]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: update dpp/disp clock from smu clock table
authorPaul Hsieh <Paul.Hsieh@amd.com>
Wed, 23 Jul 2025 03:51:42 +0000 (11:51 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 4 Aug 2025 18:38:59 +0000 (14:38 -0400)
[Why]
The reason some high-resolution monitors fail to display properly
is that this platform does not support sufficiently high DPP and
DISP clock frequencies

[How]
Update DISP and DPP clocks from the smu clock table then DML can
filter these mode if not support.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Paul Hsieh <Paul.Hsieh@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c

index 9e2ef0e724fcf6f166d3d30a14d6a00bac01bba2..7aee02d56292380b53f8ec890bb83b166e9852a8 100644 (file)
@@ -563,6 +563,7 @@ static void vg_clk_mgr_helper_populate_bw_params(
 {
        int i, j;
        struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
+       uint32_t max_dispclk = 0, max_dppclk = 0;
 
        j = -1;
 
@@ -584,6 +585,15 @@ static void vg_clk_mgr_helper_populate_bw_params(
                return;
        }
 
+       /* dispclk and dppclk can be max at any voltage, same number of levels for both */
+       if (clock_table->NumDispClkLevelsEnabled <= VG_NUM_DISPCLK_DPM_LEVELS &&
+           clock_table->NumDispClkLevelsEnabled <= VG_NUM_DPPCLK_DPM_LEVELS) {
+               max_dispclk = find_max_clk_value(clock_table->DispClocks, clock_table->NumDispClkLevelsEnabled);
+               max_dppclk = find_max_clk_value(clock_table->DppClocks, clock_table->NumDispClkLevelsEnabled);
+       } else {
+               ASSERT(0);
+       }
+
        bw_params->clk_table.num_entries = j + 1;
 
        for (i = 0; i < bw_params->clk_table.num_entries - 1; i++, j--) {
@@ -591,11 +601,17 @@ static void vg_clk_mgr_helper_populate_bw_params(
                bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk;
                bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage;
                bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->DfPstateTable[j].voltage);
+
+               /* Now update clocks we do read */
+               bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
+               bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
        }
        bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].fclk;
        bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk;
        bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage;
        bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, VG_NUM_DCFCLK_DPM_LEVELS);
+       bw_params->clk_table.entries[i].dispclk_mhz = find_max_clk_value(clock_table->DispClocks, VG_NUM_DISPCLK_DPM_LEVELS);
+       bw_params->clk_table.entries[i].dppclk_mhz = find_max_clk_value(clock_table->DppClocks, VG_NUM_DPPCLK_DPM_LEVELS);
 
        bw_params->vram_type = bios_info->memory_type;
        bw_params->num_channels = bios_info->ma_channel_number;
index 0c0b2d67c9cd93af3c505bf4eaccaf66e834f172..2066a65c69bbcca463bf4423a5f2e681e2d4c527 100644 (file)
@@ -326,7 +326,7 @@ void dcn301_fpu_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_p
        struct dcn301_resource_pool *pool = TO_DCN301_RES_POOL(dc->res_pool);
        struct clk_limit_table *clk_table = &bw_params->clk_table;
        unsigned int i, closest_clk_lvl;
-       int j;
+       int j = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0;
 
        dc_assert_fp_enabled();
 
@@ -338,6 +338,15 @@ void dcn301_fpu_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_p
        dcn3_01_soc.num_chans = bw_params->num_channels;
 
        ASSERT(clk_table->num_entries);
+
+       /* Prepass to find max clocks independent of voltage level. */
+       for (i = 0; i < clk_table->num_entries; ++i) {
+               if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz)
+                       max_dispclk_mhz = clk_table->entries[i].dispclk_mhz;
+               if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz)
+                       max_dppclk_mhz = clk_table->entries[i].dppclk_mhz;
+       }
+
        for (i = 0; i < clk_table->num_entries; i++) {
                /* loop backwards*/
                for (closest_clk_lvl = 0, j = dcn3_01_soc.num_states - 1; j >= 0; j--) {
@@ -353,8 +362,13 @@ void dcn301_fpu_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_p
                s[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
                s[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2;
 
-               s[i].dispclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
-               s[i].dppclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+               /* Clocks independent of voltage level. */
+               s[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz :
+                       dcn3_01_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+
+               s[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz :
+                       dcn3_01_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+
                s[i].dram_bw_per_chan_gbps =
                        dcn3_01_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
                s[i].dscclk_mhz = dcn3_01_soc.clock_limits[closest_clk_lvl].dscclk_mhz;