drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c- Extension
.c- Size
- 21008 bytes
- Lines
- 593
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
dccg.hclk_mgr_internal.hdce100/dce_clk_mgr.hdcn20_clk_mgr.hreg_helper.hcore_types.hdm_helpers.hnavi10_ip_offset.hdcn/dcn_2_0_0_offset.hdcn/dcn_2_0_0_sh_mask.hclk/clk_11_0_0_offset.hclk/clk_11_0_0_sh_mask.h
Detected Declarations
function dentist_get_did_from_dividerfunction dcn20_update_clocks_update_dpp_dtofunction dcn20_update_clocks_update_dentistfunction dcn2_update_clocksfunction dcn2_update_clocks_fpgafunction dcn2_init_clocksfunction dcn2_enable_pme_wafunction dcn2_read_clocks_from_hw_dentistfunction dcn2_get_clockfunction dcn2_are_clock_states_equalfunction dcn2_notify_link_rate_changefunction dcn20_clk_mgr_construct
Annotated Snippet
if (dpp_clock_lowered) {
// if clock is being lowered, increase DTO before lowering refclk
dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
dcn20_update_clocks_update_dentist(clk_mgr, context);
} else {
// if clock is being raised, increase refclk before lowering DTO
if (update_dppclk || update_dispclk)
dcn20_update_clocks_update_dentist(clk_mgr, context);
// always update dtos unless clock is lowered and not safe to lower
dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
}
}
if (update_dispclk &&
dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
/*update dmcu for wait_loop count*/
dmcu->funcs->set_psr_wait_loop(dmcu,
clk_mgr_base->clks.dispclk_khz / 1000 / 7);
}
}
void dcn2_update_clocks_fpga(struct clk_mgr *clk_mgr,
struct dc_state *context,
bool safe_to_lower)
{
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
/* Min fclk = 1.2GHz since all the extra scemi logic seems to run off of it */
int fclk_adj = new_clocks->fclk_khz > 1200000 ? new_clocks->fclk_khz : 1200000;
if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr->clks.phyclk_khz)) {
clk_mgr->clks.phyclk_khz = new_clocks->phyclk_khz;
}
if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr->clks.dcfclk_khz)) {
clk_mgr->clks.dcfclk_khz = new_clocks->dcfclk_khz;
}
if (should_set_clock(safe_to_lower,
new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz)) {
clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
}
if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr->clks.socclk_khz)) {
clk_mgr->clks.socclk_khz = new_clocks->socclk_khz;
}
if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr->clks.dramclk_khz)) {
clk_mgr->clks.dramclk_khz = new_clocks->dramclk_khz;
}
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->clks.dppclk_khz)) {
clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz;
}
if (should_set_clock(safe_to_lower, fclk_adj, clk_mgr->clks.fclk_khz)) {
clk_mgr->clks.fclk_khz = fclk_adj;
}
if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr->clks.dispclk_khz)) {
clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz;
}
/* Both fclk and ref_dppclk run on the same scemi clock.
* So take the higher value since the DPP DTO is typically programmed
* such that max dppclk is 1:1 with ref_dppclk.
*/
if (clk_mgr->clks.fclk_khz > clk_mgr->clks.dppclk_khz)
clk_mgr->clks.dppclk_khz = clk_mgr->clks.fclk_khz;
if (clk_mgr->clks.dppclk_khz > clk_mgr->clks.fclk_khz)
clk_mgr->clks.fclk_khz = clk_mgr->clks.dppclk_khz;
// Both fclk and ref_dppclk run on the same scemi clock.
clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
/* TODO: set dtbclk in correct place */
clk_mgr->clks.dtbclk_en = false;
dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
}
void dcn2_init_clocks(struct clk_mgr *clk_mgr)
{
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
// Assumption is that boot state always supports pstate
clk_mgr->clks.p_state_change_support = true;
clk_mgr->clks.prev_p_state_change_support = true;
}
static void dcn2_enable_pme_wa(struct clk_mgr *clk_mgr_base)
Annotation
- Immediate include surface: `dccg.h`, `clk_mgr_internal.h`, `dce100/dce_clk_mgr.h`, `dcn20_clk_mgr.h`, `reg_helper.h`, `core_types.h`, `dm_helpers.h`, `navi10_ip_offset.h`.
- Detected declarations: `function dentist_get_did_from_divider`, `function dcn20_update_clocks_update_dpp_dto`, `function dcn20_update_clocks_update_dentist`, `function dcn2_update_clocks`, `function dcn2_update_clocks_fpga`, `function dcn2_init_clocks`, `function dcn2_enable_pme_wa`, `function dcn2_read_clocks_from_hw_dentist`, `function dcn2_get_clock`, `function dcn2_are_clock_states_equal`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
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.