drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c- Extension
.c- Size
- 47044 bytes
- Lines
- 1250
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
dccg.hclk_mgr_internal.hdcn32/dcn32_clk_mgr_smu_msg.hdcn20/dcn20_clk_mgr.hdce100/dce_clk_mgr.hdcn31/dcn31_clk_mgr.hdcn32/dcn32_clk_mgr.hreg_helper.hcore_types.hdm_helpers.hlink_service.hdc_state_priv.hatomfirmware.hdcn32_smu13_driver_if.hdcn/dcn_3_2_0_offset.hdcn/dcn_3_2_0_sh_mask.hdml/dcn32/dcn32_fpu.h
Detected Declarations
function dcn32_init_single_clockfunction dcn32_build_wm_range_tablefunction dcn32_init_clocksfunction dcn32_update_clocks_update_dtb_dtofunction dcn32_update_dppclk_dispclk_freqfunction dcn32_update_clocks_update_dpp_dtofunction dcn32_update_clocks_update_dentistfunction dcn32_get_dispclk_from_dentistfunction dcn32_check_native_scalingfunction dcn32_auto_dpm_test_logfunction dcn32_update_clocksfunction should_set_clockfunction dcn32_get_vco_frequency_from_regfunction dcn32_dump_clk_registersfunction dcn32_clock_read_ss_infofunction dcn32_notify_wm_rangesfunction dcn32_set_hard_min_memclkfunction dcn32_set_hard_max_memclkfunction dcn32_get_memclk_states_from_smufunction dcn32_are_clock_states_equalfunction dcn32_enable_pme_wafunction dcn32_is_smu_presentfunction dcn32_set_max_memclkfunction dcn32_set_min_memclkfunction dcn32_clk_mgr_constructfunction dcn32_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);
}
}
static void dcn32_update_clocks_update_dentist(
struct clk_mgr_internal *clk_mgr,
struct dc_state *context)
{
uint32_t new_disp_divider = 0;
uint32_t new_dispclk_wdivider = 0;
uint32_t old_dispclk_wdivider = 0;
uint32_t i;
uint32_t dentist_dispclk_wdivider_readback = 0;
struct dc *dc = clk_mgr->base.ctx->dc;
if (clk_mgr->base.clks.dispclk_khz == 0)
return;
new_disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
* clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dispclk_khz;
new_dispclk_wdivider = dentist_get_did_from_divider(new_disp_divider);
REG_GET(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, &old_dispclk_wdivider);
/* When changing divider to or from 127, some extra programming is required to prevent corruption */
if (old_dispclk_wdivider == 127 && new_dispclk_wdivider != 127) {
for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
uint32_t fifo_level;
struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg;
struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
int32_t N;
int32_t j;
if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER))
continue;
/* Virtual encoders don't have this function */
if (!stream_enc->funcs->get_fifo_cal_average_level)
continue;
fifo_level = stream_enc->funcs->get_fifo_cal_average_level(
stream_enc);
N = fifo_level / 4;
dccg->funcs->set_fifo_errdet_ovr_en(
dccg,
true);
for (j = 0; j < N - 4; j++)
dccg->funcs->otg_drop_pixel(
dccg,
pipe_ctx->stream_res.tg->inst);
dccg->funcs->set_fifo_errdet_ovr_en(
dccg,
false);
}
} else if (new_dispclk_wdivider == 127 && old_dispclk_wdivider != 127) {
/* request clock with 126 divider first */
uint32_t temp_disp_divider = dentist_get_divider_from_did(126);
uint32_t temp_dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / temp_disp_divider;
if (clk_mgr->smu_present)
/*
* SMU uses discrete dispclk presets. We applied
* the same formula to increase our dppclk_khz
* to the next matching discrete value. By
* contract, we should use the preset dispclk
* floored in Mhz to describe the intended clock.
*/
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK,
(uint16_t)khz_to_mhz_floor(temp_dispclk_khz));
if (dc->debug.override_dispclk_programming) {
REG_GET(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, &dentist_dispclk_wdivider_readback);
Annotation
- Immediate include surface: `dccg.h`, `clk_mgr_internal.h`, `dcn32/dcn32_clk_mgr_smu_msg.h`, `dcn20/dcn20_clk_mgr.h`, `dce100/dce_clk_mgr.h`, `dcn31/dcn31_clk_mgr.h`, `dcn32/dcn32_clk_mgr.h`, `reg_helper.h`.
- Detected declarations: `function dcn32_init_single_clock`, `function dcn32_build_wm_range_table`, `function dcn32_init_clocks`, `function dcn32_update_clocks_update_dtb_dto`, `function dcn32_update_dppclk_dispclk_freq`, `function dcn32_update_clocks_update_dpp_dto`, `function dcn32_update_clocks_update_dentist`, `function dcn32_get_dispclk_from_dentist`, `function dcn32_check_native_scaling`, `function dcn32_auto_dpm_test_log`.
- 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.