[PATCH 09/41] drm/amd/display: Ensure dtbclk is enabled
<[email protected]> Fri, 31 Jul 2026 17:12:30 -0400
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Charlene Liu <[email protected]> [why] ensure dtbclk is enabled before hdmistreamclk_en pmfw could stop dtbclk on idle. driver needs to ensure dtbclk enabled is enabled before hdmistreamclk_en also disable debounce timer on dcn42. Reviewed-by: Chris Park <[email protected]> Reviewed-by: Leo Chen <[email protected]> Signed-off-by: Charlene Liu <[email protected]> Signed-off-by: Roman Li <[email protected]> --- .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c | 28 +++++++++++++++++-- .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h | 1 + .../drm/amd/display/dc/dce/dce_clock_source.c | 4 +++ .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 1 + .../display/dc/link/protocols/link_hdmi_frl.c | 18 ++++++++++-- 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c index c7b9bad93a93..19ef0b92e8e6 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c @@ -220,6 +220,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base, bool update_dispclk = false; bool dpp_clock_lowered = false; bool has_active_display; + int actual_dtbclk = 0; if (dc->work_arounds.skip_clock_update) return; @@ -260,8 +261,9 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base, * 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; + actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk); + + if (new_clocks->dtbclk_en && actual_dtbclk < 590000) { dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); dcn42_smu_set_dtbclk(clk_mgr, true); @@ -343,7 +345,6 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base, dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz); clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz; } - if (dpp_clock_lowered) { // increase per DPP DTO before lowering global dppclk dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); @@ -1051,7 +1052,27 @@ void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int) dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART, smu_dpm_clks.dpm_clks); } +void dcn42_request_dtbclk(struct clk_mgr *clk_mgr_base, bool enable) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + /*pmfw might turn off dtblck based on allow_dtbstop*/ + clk_mgr_base->clks.dtbclk_en = false; + if (enable) { + int actual_dtbclk = 0; + + 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 = actual_dtbclk; + clk_mgr_base->clks.dtbclk_en = true; + } + } else { + clk_mgr_base->clks.dtbclk_en = false; + dcn42_smu_set_dtbclk(clk_mgr, false); + } +} static struct clk_mgr_funcs dcn42_funcs = { .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, @@ -1065,6 +1086,7 @@ static struct clk_mgr_funcs dcn42_funcs = { .get_max_clock_khz = dcn42_get_max_clock_khz, .get_dispclk_from_dentist = dcn42_get_dispclk_from_dentist, .is_smu_present = dcn42_is_smu_present, + .request_dtbclk = dcn42_request_dtbclk, .notify_cstate_disable = dcn42_notify_cstate_disable, }; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h index 330242747fff..f90c6e2e85c2 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h @@ -84,4 +84,5 @@ void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct dcn42 void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int); void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, struct dc_state *context, bool safe_to_lower); int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base); +void dcn42_request_dtbclk(struct clk_mgr *clk_mgr_base, bool enable); #endif //__DCN42_CLK_MGR_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index e52fb7248a88..47ec08071ceb 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -1118,6 +1118,10 @@ static bool dcn401_program_pix_clk( if (clock_source->ctx->dc->caps.is_apu && pix_clk_params->requested_pix_clk_100hz && dc_is_hdmi_frl_signal(pix_clk_params->signal_type)) { + //make sure dtbclk is enabled + if (clock_source->ctx->dc->clk_mgr->funcs->request_dtbclk) + clock_source->ctx->dc->clk_mgr->funcs->request_dtbclk( + clock_source->ctx->dc->clk_mgr, true); /*need hdmistreamclk before vpg block register access*/ clock_source->ctx->dc->res_pool->dccg->funcs->set_hdmistreamclk( clock_source->ctx->dc->res_pool->dccg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index ec678bd249ef..614beb5924fd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -427,6 +427,7 @@ struct clk_mgr_funcs { struct block_sequence_state *seq_state); void (*execute_clk_mgr_block_sequence)(struct clk_mgr *clk_mgr); + void (*request_dtbclk)(struct clk_mgr *clk_mgr_base, bool enable); }; struct clk_mgr { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c index 75ec3b701d81..714168e1ece6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c @@ -415,6 +415,18 @@ void hdmi_frl_LTS_clear_Link_Setting(struct ddc_service *ddc_service) } +static uint8_t hdmi_frl_get_max_ffe_level(struct dc_link *link, + struct dc_hdmi_frl_link_settings *link_settings) +{ + uint8_t max_ffe_level = + (link_settings->frl_link_rate > HDMI_FRL_LINK_RATE_12GBPS) ? 7 : 3; + + if ((uint8_t)link->dc->debug.limit_ffe < max_ffe_level) + max_ffe_level = (uint8_t)link->dc->debug.limit_ffe; + + return max_ffe_level; +} + static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_service, struct dc_hdmi_frl_link_settings *link_settings) { @@ -436,7 +448,7 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s struct hpo_frl_link_encoder *hpo_frl_link_enc = ddc_service->link->hpo_frl_link_enc; struct link_encoder *dio_link_enc = ddc_service->link->link_enc; uint8_t sink_version = 0; - uint8_t FFE_Levels = (uint8_t)ddc_service->link->dc->debug.limit_ffe; + uint8_t FFE_Levels = hdmi_frl_get_max_ffe_level(ddc_service->link, link_settings); uint8_t current_FFE = 0; bool override_FFE = false; bool flt_no_timeout = false; @@ -616,7 +628,7 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s } current_FFE++; override_FFE = true; - if (current_FFE > 3) + if (current_FFE > FFE_Levels) current_FFE = 0; if (flt_no_timeout) current_FFE = 0; @@ -642,7 +654,7 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s } current_FFE++; override_FFE = true; - if (current_FFE > 3) + if (current_FFE > FFE_Levels) current_FFE = 0; if (flt_no_timeout) current_FFE = 0; -- 2.34.1