Commit 2d3907c1 authored by Samson Tam's avatar Samson Tam Committed by Alex Deucher

drm/amd/display: fill in clock values when DPM is not enabled

[Why]
For individual feature testing, PMFW may not report all clock
values back. Driver will default them to 0 but this will
cause the BB table to be skipped and default to one state
with max clocks.

[How]
Add helper function to scan through initial clock values and
populate them with default clock limits so that BB table
can be built.
Add dpm_enabled flag to check when DPM is not enabled and
to trigger helper function.
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarJasdeep Dhillon <jdhillon@amd.com>
Signed-off-by: default avatarSamson Tam <samson.tam@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a28acf70
...@@ -156,12 +156,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) ...@@ -156,12 +156,14 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
{ {
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
unsigned int num_levels; unsigned int num_levels;
unsigned int num_dcfclk_levels, num_dtbclk_levels, num_dispclk_levels;
memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks)); memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
clk_mgr_base->clks.p_state_change_support = true; clk_mgr_base->clks.p_state_change_support = true;
clk_mgr_base->clks.prev_p_state_change_support = true; clk_mgr_base->clks.prev_p_state_change_support = true;
clk_mgr_base->clks.fclk_prev_p_state_change_support = true; clk_mgr_base->clks.fclk_prev_p_state_change_support = true;
clk_mgr->smu_present = false; clk_mgr->smu_present = false;
clk_mgr->dpm_present = false;
if (!clk_mgr_base->bw_params) if (!clk_mgr_base->bw_params)
return; return;
...@@ -179,6 +181,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) ...@@ -179,6 +181,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK, dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
&num_levels); &num_levels);
num_dcfclk_levels = num_levels;
/* SOCCLK */ /* SOCCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK, dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
...@@ -189,11 +192,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) ...@@ -189,11 +192,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK, dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
&num_levels); &num_levels);
num_dtbclk_levels = num_levels;
/* DISPCLK */ /* DISPCLK */
dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK, dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz, &clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
&num_levels); &num_levels);
num_dispclk_levels = num_levels;
if (num_dcfclk_levels && num_dtbclk_levels && num_dispclk_levels)
clk_mgr->dpm_present = true;
if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) { if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
unsigned int i; unsigned int i;
...@@ -658,6 +666,12 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) ...@@ -658,6 +666,12 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
&num_levels); &num_levels);
clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1; clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
if (clk_mgr->dpm_present && !num_levels)
clk_mgr->dpm_present = false;
if (!clk_mgr->dpm_present)
dcn32_patch_dpm_table(clk_mgr_base->bw_params);
DC_FP_START(); DC_FP_START();
/* Refresh bounding box */ /* Refresh bounding box */
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box( clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
......
...@@ -1926,6 +1926,45 @@ static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st ...@@ -1926,6 +1926,45 @@ static void remove_entry_from_table_at_index(struct _vcs_dpi_voltage_scaling_st
memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st)); memset(&table[--(*num_entries)], 0, sizeof(struct _vcs_dpi_voltage_scaling_st));
} }
void dcn32_patch_dpm_table(struct clk_bw_params *bw_params)
{
int i;
unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0,
max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 0, max_uclk_mhz = 0;
for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
max_uclk_mhz = bw_params->clk_table.entries[i].memclk_mhz;
if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz)
max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz;
if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz;
if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz;
if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
max_dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
}
/* Scan through clock values we currently have and if they are 0,
* then populate it with dcn3_2_soc.clock_limits[] value.
*
* Do it for DCFCLK, DISPCLK, DTBCLK and UCLK as any of those being
* 0, will cause it to skip building the clock table.
*/
if (max_dcfclk_mhz == 0)
bw_params->clk_table.entries[0].dcfclk_mhz = dcn3_2_soc.clock_limits[0].dcfclk_mhz;
if (max_dispclk_mhz == 0)
bw_params->clk_table.entries[0].dispclk_mhz = dcn3_2_soc.clock_limits[0].dispclk_mhz;
if (max_dtbclk_mhz == 0)
bw_params->clk_table.entries[0].dtbclk_mhz = dcn3_2_soc.clock_limits[0].dtbclk_mhz;
if (max_uclk_mhz == 0)
bw_params->clk_table.entries[0].memclk_mhz = dcn3_2_soc.clock_limits[0].dram_speed_mts / 16;
}
static int build_synthetic_soc_states(struct clk_bw_params *bw_params, static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries) struct _vcs_dpi_voltage_scaling_st *table, unsigned int *num_entries)
{ {
......
...@@ -77,4 +77,6 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc, ...@@ -77,4 +77,6 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
int pipe_cnt, int pipe_cnt,
int vlevel); int vlevel);
void dcn32_patch_dpm_table(struct clk_bw_params *bw_params);
#endif #endif
...@@ -340,6 +340,8 @@ struct clk_mgr_internal { ...@@ -340,6 +340,8 @@ struct clk_mgr_internal {
bool smu_present; bool smu_present;
void *wm_range_table; void *wm_range_table;
long long wm_range_table_addr; long long wm_range_table_addr;
bool dpm_present;
}; };
struct clk_mgr_internal_funcs { struct clk_mgr_internal_funcs {
......
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