Commit 7bd571b2 authored by Alvin Lee's avatar Alvin Lee Committed by Alex Deucher

drm/amd/display: DAL to program DISPCLK WDIVIDER if PMFW doesn't

[Why & How]
- If for any reason PMFW fails to set the expected (or valid)
  DISPCLK WDIVIDER, then DAL will program DENTIST DISPCLK
  WDIVIDER to correct for this issue
Reviewed-by: default avatarSamson Tam <Samson.Tam@amd.com>
Acked-by: default avatarQingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: default avatarAlvin Lee <Alvin.Lee2@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 6ed373b0
...@@ -257,25 +257,24 @@ static void dcn32_update_dppclk_dispclk_freq(struct clk_mgr_internal *clk_mgr, s ...@@ -257,25 +257,24 @@ static void dcn32_update_dppclk_dispclk_freq(struct clk_mgr_internal *clk_mgr, s
static void dcn32_update_clocks_update_dentist( static void dcn32_update_clocks_update_dentist(
struct clk_mgr_internal *clk_mgr, struct clk_mgr_internal *clk_mgr,
struct dc_state *context, struct dc_state *context)
uint32_t old_dispclk_khz)
{ {
uint32_t new_disp_divider = 0; uint32_t new_disp_divider = 0;
uint32_t old_disp_divider = 0;
uint32_t new_dispclk_wdivider = 0; uint32_t new_dispclk_wdivider = 0;
uint32_t old_dispclk_wdivider = 0; uint32_t old_dispclk_wdivider = 0;
uint32_t i; uint32_t i;
uint32_t dentist_dispclk_wdivider_readback = 0;
struct dc *dc = clk_mgr->base.ctx->dc;
if (old_dispclk_khz == 0 || clk_mgr->base.clks.dispclk_khz == 0) if (clk_mgr->base.clks.dispclk_khz == 0)
return; return;
new_disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR new_disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
* clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dispclk_khz; * clk_mgr->base.dentist_vco_freq_khz / clk_mgr->base.clks.dispclk_khz;
old_disp_divider = DENTIST_DIVIDER_RANGE_SCALE_FACTOR
* clk_mgr->base.dentist_vco_freq_khz / old_dispclk_khz;
new_dispclk_wdivider = dentist_get_did_from_divider(new_disp_divider); new_dispclk_wdivider = dentist_get_did_from_divider(new_disp_divider);
old_dispclk_wdivider = dentist_get_did_from_divider(old_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 */ /* When changing divider to or from 127, some extra programming is required to prevent corruption */
if (old_dispclk_wdivider == 127 && new_dispclk_wdivider != 127) { if (old_dispclk_wdivider == 127 && new_dispclk_wdivider != 127) {
...@@ -314,6 +313,17 @@ static void dcn32_update_clocks_update_dentist( ...@@ -314,6 +313,17 @@ static void dcn32_update_clocks_update_dentist(
if (clk_mgr->smu_present) if (clk_mgr->smu_present)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(temp_dispclk_khz)); dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(temp_dispclk_khz));
if (dc->debug.override_dispclk_programming) {
REG_GET(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, &dentist_dispclk_wdivider_readback);
if (dentist_dispclk_wdivider_readback != 126) {
REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, 126);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
}
}
for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { 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]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg; struct dccg *dccg = clk_mgr->base.ctx->dc->res_pool->dccg;
...@@ -341,6 +351,18 @@ static void dcn32_update_clocks_update_dentist( ...@@ -341,6 +351,18 @@ static void dcn32_update_clocks_update_dentist(
/* do requested DISPCLK updates*/ /* do requested DISPCLK updates*/
if (clk_mgr->smu_present) if (clk_mgr->smu_present)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr->base.clks.dispclk_khz)); dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr->base.clks.dispclk_khz));
if (dc->debug.override_dispclk_programming) {
REG_GET(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, &dentist_dispclk_wdivider_readback);
if (dentist_dispclk_wdivider_readback > new_dispclk_wdivider) {
REG_UPDATE(DENTIST_DISPCLK_CNTL,
DENTIST_DISPCLK_WDIVIDER, new_dispclk_wdivider);
REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);
}
}
} }
static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
...@@ -361,7 +383,6 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, ...@@ -361,7 +383,6 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
bool p_state_change_support; bool p_state_change_support;
bool fclk_p_state_change_support; bool fclk_p_state_change_support;
int total_plane_count; int total_plane_count;
int old_dispclk_khz = clk_mgr_base->clks.dispclk_khz;
if (dc->work_arounds.skip_clock_update) if (dc->work_arounds.skip_clock_update)
return; return;
...@@ -504,13 +525,13 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, ...@@ -504,13 +525,13 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
if (dpp_clock_lowered) { if (dpp_clock_lowered) {
/* if clock is being lowered, increase DTO before lowering refclk */ /* 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_dpp_dto(clk_mgr, context, safe_to_lower);
dcn32_update_clocks_update_dentist(clk_mgr, context, old_dispclk_khz); dcn32_update_clocks_update_dentist(clk_mgr, context);
if (clk_mgr->smu_present) if (clk_mgr->smu_present)
dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz)); dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
} else { } else {
/* if clock is being raised, increase refclk before lowering DTO */ /* if clock is being raised, increase refclk before lowering DTO */
if (update_dppclk || update_dispclk) if (update_dppclk || update_dispclk)
dcn32_update_clocks_update_dentist(clk_mgr, context, old_dispclk_khz); dcn32_update_clocks_update_dentist(clk_mgr, context);
/* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures /* There is a check inside dcn20_update_clocks_update_dpp_dto which ensures
* that we do not lower dto when it is not safe to lower. We do not need to * that we do not lower dto when it is not safe to lower. We do not need to
* compare the current and new dppclk before calling this function. * compare the current and new dppclk before calling this function.
......
...@@ -874,6 +874,7 @@ struct dc_debug_options { ...@@ -874,6 +874,7 @@ struct dc_debug_options {
bool disable_unbounded_requesting; bool disable_unbounded_requesting;
bool dig_fifo_off_in_blank; bool dig_fifo_off_in_blank;
bool temp_mst_deallocation_sequence; bool temp_mst_deallocation_sequence;
bool override_dispclk_programming;
}; };
struct gpu_info_soc_bounding_box_v1_0; struct gpu_info_soc_bounding_box_v1_0;
......
...@@ -726,6 +726,7 @@ static const struct dc_debug_options debug_defaults_drv = { ...@@ -726,6 +726,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.alloc_extra_way_for_cursor = true, .alloc_extra_way_for_cursor = true,
.min_prefetch_in_strobe_ns = 60000, // 60us .min_prefetch_in_strobe_ns = 60000, // 60us
.disable_unbounded_requesting = false, .disable_unbounded_requesting = false,
.override_dispclk_programming = true,
}; };
static const struct dc_debug_options debug_defaults_diags = { static const struct dc_debug_options debug_defaults_diags = {
......
...@@ -724,6 +724,7 @@ static const struct dc_debug_options debug_defaults_drv = { ...@@ -724,6 +724,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.alloc_extra_way_for_cursor = true, .alloc_extra_way_for_cursor = true,
.min_prefetch_in_strobe_ns = 60000, // 60us .min_prefetch_in_strobe_ns = 60000, // 60us
.disable_unbounded_requesting = false, .disable_unbounded_requesting = false,
.override_dispclk_programming = true,
}; };
static const struct dc_debug_options debug_defaults_diags = { static const struct dc_debug_options debug_defaults_diags = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment