summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
diff options
context:
space:
mode:
authorIlya Bakoulin <Ilya.Bakoulin@amd.com>2021-04-26 14:27:38 -0400
committerAlex Deucher <alexander.deucher@amd.com>2021-05-10 18:10:49 -0400
commitc31bef1cb1203b26f901a511a3246204cfaf8a57 (patch)
tree68af19ffec33060e5c94fc84ad4f8136104de60e /drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
parentebc22cbdc058d474210343ec87955711546183ad (diff)
drm/amd/display: Fix clock table filling logic
[Why] Currently, the code that fills the clock table can miss filling information about some of the higher voltage states advertised by the SMU. This, in turn, may cause some of the higher pixel clock modes (e.g. 8k60) to fail validation. [How] Fill the table with one entry per DCFCLK level instead of one entry per FCLK level. This is needed because the maximum FCLK does not necessarily need maximum voltage, whereas DCFCLK values from SMU cover the full voltage range. Signed-off-by: Ilya Bakoulin <Ilya.Bakoulin@amd.com> Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Stylon Wang <stylon.wang@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c80
1 files changed, 53 insertions, 27 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index 887a54246bde..c2d0f68dbdcc 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -797,46 +797,67 @@ static struct wm_table lpddr4_wm_table_rn = {
},
}
};
-static unsigned int find_socclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
+
+static unsigned int find_max_fclk_for_voltage(struct dpm_clocks *clock_table,
+ unsigned int voltage)
{
int i;
+ uint32_t max_clk = 0;
- for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) {
- if (clock_table->SocClocks[i].Vol == voltage)
- return clock_table->SocClocks[i].Freq;
+ for (i = 0; i < PP_SMU_NUM_FCLK_DPM_LEVELS; i++) {
+ if (clock_table->FClocks[i].Vol <= voltage) {
+ max_clk = clock_table->FClocks[i].Freq > max_clk ?
+ clock_table->FClocks[i].Freq : max_clk;
+ }
}
- ASSERT(0);
- return 0;
+ return max_clk;
}
-static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
+
+static unsigned int find_max_memclk_for_voltage(struct dpm_clocks *clock_table,
+ unsigned int voltage)
{
int i;
+ uint32_t max_clk = 0;
- for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; i++) {
- if (clock_table->DcfClocks[i].Vol == voltage)
- return clock_table->DcfClocks[i].Freq;
+ for (i = 0; i < PP_SMU_NUM_MEMCLK_DPM_LEVELS; i++) {
+ if (clock_table->MemClocks[i].Vol <= voltage) {
+ max_clk = clock_table->MemClocks[i].Freq > max_clk ?
+ clock_table->MemClocks[i].Freq : max_clk;
+ }
}
- ASSERT(0);
- return 0;
+ return max_clk;
+}
+
+static unsigned int find_max_socclk_for_voltage(struct dpm_clocks *clock_table,
+ unsigned int voltage)
+{
+ int i;
+ uint32_t max_clk = 0;
+
+ for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) {
+ if (clock_table->SocClocks[i].Vol <= voltage) {
+ max_clk = clock_table->SocClocks[i].Freq > max_clk ?
+ clock_table->SocClocks[i].Freq : max_clk;
+ }
+ }
+
+ return max_clk;
}
static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info)
{
int i, j = 0;
+ unsigned int volt;
j = -1;
- ASSERT(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL);
-
- /* Find lowest DPM, FCLK is filled in reverse order*/
-
- for (i = PP_SMU_NUM_FCLK_DPM_LEVELS - 1; i >= 0; i--) {
- if (clock_table->FClocks[i].Freq != 0 && clock_table->FClocks[i].Vol != 0) {
+ /* Find max DPM */
+ for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; ++i) {
+ if (clock_table->DcfClocks[i].Freq != 0 &&
+ clock_table->DcfClocks[i].Vol != 0)
j = i;
- break;
- }
}
if (j == -1) {
@@ -847,13 +868,18 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
bw_params->clk_table.num_entries = j + 1;
- for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) {
- bw_params->clk_table.entries[i].fclk_mhz = clock_table->FClocks[j].Freq;
- bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemClocks[j].Freq;
- bw_params->clk_table.entries[i].voltage = clock_table->FClocks[j].Vol;
- bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol);
- bw_params->clk_table.entries[i].socclk_mhz = find_socclk_for_voltage(clock_table,
- bw_params->clk_table.entries[i].voltage);
+ for (i = 0; i < bw_params->clk_table.num_entries; i++) {
+ volt = clock_table->DcfClocks[i].Vol;
+
+ bw_params->clk_table.entries[i].voltage = volt;
+ bw_params->clk_table.entries[i].dcfclk_mhz =
+ clock_table->DcfClocks[i].Freq;
+ bw_params->clk_table.entries[i].fclk_mhz =
+ find_max_fclk_for_voltage(clock_table, volt);
+ bw_params->clk_table.entries[i].memclk_mhz =
+ find_max_memclk_for_voltage(clock_table, volt);
+ bw_params->clk_table.entries[i].socclk_mhz =
+ find_max_socclk_for_voltage(clock_table, volt);
}
bw_params->vram_type = bios_info->memory_type;