drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c- Extension
.c- Size
- 39983 bytes
- Lines
- 1121
- 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
dcn42_clk_mgr.hdccg.hclk_mgr_internal.hdce100/dce_clk_mgr.hdcn20/dcn20_clk_mgr.hreg_helper.hcore_types.hdcn42_smu.hdm_helpers.hdcn30/dcn30_clk_mgr.hdcn31/dcn31_clk_mgr.hdcn35/dcn35_clk_mgr.hdc_dmub_srv.hlink_service.hlogger_types.hclk/clk_15_0_0_offset.hclk/clk_15_0_0_sh_mask.hdcn/dcn_4_2_0_offset.hdcn/dcn_4_2_0_sh_mask.h
Detected Declarations
function dcn42_has_active_displayfunction dcn42_get_clock_freq_from_clkipfunction dcn42_update_clocks_update_dtb_dtofunction dcn42_update_clocks_update_dpp_dtofunction dcn42_update_clocksfunction dcn42bfunction should_set_clockfunction dcn42_enable_pme_wafunction dcn42_are_clock_states_equalfunction dcn42_dump_clk_registers_internalfunction dcn42_dump_clk_registersfunction dcn42_is_spll_ssc_enabledfunction init_clk_statesfunction dcn42_get_dpm_table_from_smufunction dcn42_init_single_clockfunction dcn42_convert_wck_ratiofunction dcn42_init_clocksfunction dcn42_read_ss_info_from_lutfunction dcn42_build_watermark_rangesfunction dcn42_notify_wm_rangesfunction dcn42_set_low_power_statefunction dcn42_exit_low_power_statefunction dcn42_init_clocks_fpgafunction dcn42_update_clocks_fpgafunction dcn42_get_max_clock_khzfunction dcn42_get_dispclk_from_dentistfunction dcn42_is_smu_presentfunction dcn42_get_smu_clocksfunction dcn42_clk_mgr_constructfunction dcn42_clk_mgr_destroy
Annotated Snippet
else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) {
/* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting.
* In this case just continue in loop
*/
continue;
} else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) {
/* The software state is not valid if dpp resource is NULL and
* dppclk_khz > 0.
*/
ASSERT(false);
continue;
}
prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];
if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
clk_mgr->dccg->funcs->update_dpp_dto(
clk_mgr->dccg, dpp_inst, dppclk_khz);
dppclk_active[dpp_inst] = true;
}
if (safe_to_lower)
for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
struct dpp *old_dpp = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.dpp;
if (old_dpp && !dppclk_active[old_dpp->inst])
clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, old_dpp->inst, 0);
}
}
void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
struct dc_state *context,
bool safe_to_lower)
{
union dmub_rb_cmd cmd;
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
struct dc *dc = clk_mgr_base->ctx->dc;
bool update_dppclk = false;
bool update_dispclk = false;
bool dpp_clock_lowered = false;
bool has_active_display;
if (dc->work_arounds.skip_clock_update)
return;
has_active_display = dcn42_has_active_display(dc, context);
if (new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz < 590000)
new_clocks->ref_dtbclk_khz = 600000;
/*
* if it is safe to lower, but we are already in the lower state, we don't have to do anything
* also if safe to lower is false, we just go in the higher state
*/
if (safe_to_lower) {
if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn42_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk)
dcn42_smu_set_dtbclk(clk_mgr, false);
clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
}
/* check that we're not already in lower */
if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
/* if we can go lower, go lower */
if (has_active_display == false)
clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
}
} else {
if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
}
/* Only attempt to enable dtbclk if currently disabled AND new state requests it.
* For dcn42b (no dtbclk hardware), init_clk_states sets dtbclk_en=false and
* new_clocks->dtbclk_en should always be false, so this block never executes.
*/
if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
int actual_dtbclk = 0;
dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
dcn42_smu_set_dtbclk(clk_mgr, true);
actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk);
if (actual_dtbclk > 590000) {
clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
Annotation
- Immediate include surface: `dcn42_clk_mgr.h`, `dccg.h`, `clk_mgr_internal.h`, `dce100/dce_clk_mgr.h`, `dcn20/dcn20_clk_mgr.h`, `reg_helper.h`, `core_types.h`, `dcn42_smu.h`.
- Detected declarations: `function dcn42_has_active_display`, `function dcn42_get_clock_freq_from_clkip`, `function dcn42_update_clocks_update_dtb_dto`, `function dcn42_update_clocks_update_dpp_dto`, `function dcn42_update_clocks`, `function dcn42b`, `function should_set_clock`, `function dcn42_enable_pme_wa`, `function dcn42_are_clock_states_equal`, `function dcn42_dump_clk_registers_internal`.
- 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.