drivers/gpu/drm/pl111/pl111_display.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/pl111/pl111_display.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/pl111/pl111_display.c- Extension
.c- Size
- 15830 bytes
- Lines
- 601
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/delay.hlinux/dma-buf.hlinux/media-bus-format.hlinux/of_graph.hdrm/drm_fb_dma_helper.hdrm/drm_fourcc.hdrm/drm_framebuffer.hdrm/drm_gem_atomic_helper.hdrm/drm_gem_dma_helper.hdrm/drm_print.hdrm/drm_vblank.hpl111_drm.h
Detected Declarations
function Copyrightfunction pl111_mode_validfunction pl111_display_checkfunction pl111_display_enablefunction PL110function pl111_display_disablefunction pl111_display_updatefunction pl111_display_enable_vblankfunction pl111_display_disable_vblankfunction pl111_clk_div_choose_divfunction pl111_clk_div_determine_ratefunction pl111_clk_div_recalc_ratefunction pl111_clk_div_set_ratefunction pl111_init_clock_dividerfunction pl111_display_init
Annotated Snippet
if (diff < best_diff) {
best_div = div;
best_diff = diff;
best_prate = this_prate;
}
}
*prate = best_prate;
return best_div;
}
static int pl111_clk_div_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
int div = pl111_clk_div_choose_div(hw, req->rate,
&req->best_parent_rate, true);
req->rate = DIV_ROUND_UP_ULL(req->best_parent_rate, div);
return 0;
}
static unsigned long pl111_clk_div_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct pl111_drm_dev_private *priv =
container_of(hw, struct pl111_drm_dev_private, clk_div);
u32 tim2 = readl(priv->regs + CLCD_TIM2);
int div;
if (tim2 & TIM2_BCD)
return prate;
div = tim2 & TIM2_PCD_LO_MASK;
div |= (tim2 & TIM2_PCD_HI_MASK) >>
(TIM2_PCD_HI_SHIFT - TIM2_PCD_LO_BITS);
div += 2;
return DIV_ROUND_UP_ULL(prate, div);
}
static int pl111_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
struct pl111_drm_dev_private *priv =
container_of(hw, struct pl111_drm_dev_private, clk_div);
int div = pl111_clk_div_choose_div(hw, rate, &prate, false);
u32 tim2;
spin_lock(&priv->tim2_lock);
tim2 = readl(priv->regs + CLCD_TIM2);
tim2 &= ~(TIM2_BCD | TIM2_PCD_LO_MASK | TIM2_PCD_HI_MASK);
if (div == 1) {
tim2 |= TIM2_BCD;
} else {
div -= 2;
tim2 |= div & TIM2_PCD_LO_MASK;
tim2 |= (div >> TIM2_PCD_LO_BITS) << TIM2_PCD_HI_SHIFT;
}
writel(tim2, priv->regs + CLCD_TIM2);
spin_unlock(&priv->tim2_lock);
return 0;
}
static const struct clk_ops pl111_clk_div_ops = {
.recalc_rate = pl111_clk_div_recalc_rate,
.determine_rate = pl111_clk_div_determine_rate,
.set_rate = pl111_clk_div_set_rate,
};
static int
pl111_init_clock_divider(struct drm_device *drm)
{
struct pl111_drm_dev_private *priv = drm->dev_private;
struct clk *parent = devm_clk_get(drm->dev, "clcdclk");
struct clk_hw *div = &priv->clk_div;
const char *parent_name;
struct clk_init_data init = {
.name = "pl111_div",
.ops = &pl111_clk_div_ops,
.parent_names = &parent_name,
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
};
int ret;
if (IS_ERR(parent)) {
Annotation
- Immediate include surface: `linux/clk.h`, `linux/delay.h`, `linux/dma-buf.h`, `linux/media-bus-format.h`, `linux/of_graph.h`, `drm/drm_fb_dma_helper.h`, `drm/drm_fourcc.h`, `drm/drm_framebuffer.h`.
- Detected declarations: `function Copyright`, `function pl111_mode_valid`, `function pl111_display_check`, `function pl111_display_enable`, `function PL110`, `function pl111_display_disable`, `function pl111_display_update`, `function pl111_display_enable_vblank`, `function pl111_display_disable_vblank`, `function pl111_clk_div_choose_div`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.