From: Joshua Aberback <joshua.aberb...@amd.com>

[WHY]
If there are no DC clock limits present, or if the DC limits are the same
as the AC limits, we can disable the AC/DC codepath as there won't be any
validation differences between the two modes.

[HOW]
When all DC power mode clock limits are the same as the max clock
values, there won't be any difference between AC mode and DC mode. Zero
out DC limits that equal max and provide a new cap to indicate the
presence of any non-zero DC mode limit. In summary:
 - zero out DC limits that are the same as max clock value
 - new dc cap to indicate the presence of DC mode limits
 - set limits present if any clock has distinct AC and DC values from SMU

Acked-by: Alex Hung <alex.h...@amd.com>
Reviewed-by: Rodrigo Siqueira <rodrigo.sique...@amd.com>
Signed-off-by: Joshua Aberback <joshua.aberb...@amd.com>
---
 .../dc/clk_mgr/dcn401/dcn401_clk_mgr.c        | 28 ++++++++++++++-----
 drivers/gpu/drm/amd/display/dc/dc.h           |  1 +
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 12 +++++++-
 3 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
index 1cf750cfed66..bd74ff47fb37 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
@@ -180,7 +180,6 @@ static void dcn401_build_wm_range_table(struct clk_mgr 
*clk_mgr)
 void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
 {
        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
-       unsigned int num_levels;
        struct clk_limit_num_entries *num_entries_per_clk = 
&clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
        unsigned int i;
 
@@ -208,34 +207,43 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
                        
&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
                        &num_entries_per_clk->num_dcfclk_levels);
        clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz = 
dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DCFCLK);
+       if (num_entries_per_clk->num_dcfclk_levels && 
clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz ==
+                       
clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dcfclk_levels
 - 1].dcfclk_mhz)
+               clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz = 0;
 
        /* SOCCLK */
        dcn401_init_single_clock(clk_mgr, PPCLK_SOCCLK,
                                        
&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
                                        
&num_entries_per_clk->num_socclk_levels);
        clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz = 
dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_SOCCLK);
+       if (num_entries_per_clk->num_socclk_levels && 
clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz ==
+                       
clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_socclk_levels
 - 1].socclk_mhz)
+               clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz = 0;
 
        /* DTBCLK */
        if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch) {
                dcn401_init_single_clock(clk_mgr, PPCLK_DTBCLK,
                                
&clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
                                &num_entries_per_clk->num_dtbclk_levels);
-               clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz =
-                       dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, 
PPCLK_DTBCLK);
+               clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = 
dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DTBCLK);
+               if (num_entries_per_clk->num_dtbclk_levels && 
clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz ==
+                               
clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dtbclk_levels
 - 1].dtbclk_mhz)
+                       clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = 0;
        }
 
        /* DISPCLK */
        dcn401_init_single_clock(clk_mgr, PPCLK_DISPCLK,
                        
&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
                        &num_entries_per_clk->num_dispclk_levels);
-       num_levels = num_entries_per_clk->num_dispclk_levels;
        clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = 
dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DISPCLK);
+       if (num_entries_per_clk->num_dispclk_levels && 
clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz ==
+                       
clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dispclk_levels
 - 1].dispclk_mhz)
+               clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = 0;
 
        /* DPPCLK */
        dcn401_init_single_clock(clk_mgr, PPCLK_DPPCLK,
                        
&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz,
                        &num_entries_per_clk->num_dppclk_levels);
-       num_levels = num_entries_per_clk->num_dppclk_levels;
 
        if (num_entries_per_clk->num_dcfclk_levels &&
                        num_entries_per_clk->num_dtbclk_levels &&
@@ -243,7 +251,7 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
                clk_mgr->dpm_present = true;
 
        if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
-               for (i = 0; i < num_levels; i++)
+               for (i = 0; i < num_entries_per_clk->num_dispclk_levels; i++)
                        if 
(clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz
                                        < 
khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz))
                                
clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz
@@ -251,7 +259,7 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base)
        }
 
        if (clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz) {
-               for (i = 0; i < num_levels; i++)
+               for (i = 0; i < num_entries_per_clk->num_dppclk_levels; i++)
                        if 
(clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz
                                        < 
khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz))
                                
clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz
@@ -842,12 +850,18 @@ static void dcn401_get_memclk_states_from_smu(struct 
clk_mgr *clk_mgr_base)
        }
 
        clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = 
dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK);
+       if (num_entries_per_clk->num_memclk_levels && 
clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz ==
+                       
clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_memclk_levels
 - 1].memclk_mhz)
+               clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = 0;
        clk_mgr_base->bw_params->dc_mode_softmax_memclk = 
clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz;
 
        dcn401_init_single_clock(clk_mgr, PPCLK_FCLK,
                        &clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
                        &num_entries_per_clk->num_fclk_levels);
        clk_mgr_base->bw_params->dc_mode_limit.fclk_mhz = 
dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_FCLK);
+       if (num_entries_per_clk->num_fclk_levels && 
clk_mgr_base->bw_params->dc_mode_limit.fclk_mhz ==
+                       
clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_fclk_levels 
- 1].fclk_mhz)
+               clk_mgr_base->bw_params->dc_mode_limit.fclk_mhz = 0;
 
        if (num_entries_per_clk->num_memclk_levels >= 
num_entries_per_clk->num_fclk_levels) {
                num_levels = num_entries_per_clk->num_memclk_levels;
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h 
b/drivers/gpu/drm/amd/display/dc/dc.h
index 8698db8f3e45..2fce8c0303fa 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -290,6 +290,7 @@ struct dc_caps {
        uint32_t max_disp_clock_khz_at_vmin;
        uint8_t subvp_drr_vblank_start_margin_us;
        bool cursor_not_scaled;
+       bool dcmode_power_limits_present;
 };
 
 struct dc_bug_wa {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c 
b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index d9a3d6c2da1f..3b74c4a9c2a8 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -212,9 +212,19 @@ void dcn401_init_hw(struct dc *dc)
        uint32_t backlight = MAX_BACKLIGHT_LEVEL;
        uint32_t user_level = MAX_BACKLIGHT_LEVEL;
 
-       if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
+       if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) {
                dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
 
+               // mark dcmode limits present if any clock has distinct AC and 
DC values from SMU
+               dc->caps.dcmode_power_limits_present =
+                               
(dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels && 
dc->clk_mgr->bw_params->dc_mode_limit.dcfclk_mhz) ||
+                               
(dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels && 
dc->clk_mgr->bw_params->dc_mode_limit.dispclk_mhz) ||
+                               
(dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels && 
dc->clk_mgr->bw_params->dc_mode_limit.dtbclk_mhz) ||
+                               
(dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels && 
dc->clk_mgr->bw_params->dc_mode_limit.fclk_mhz) ||
+                               
(dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels && 
dc->clk_mgr->bw_params->dc_mode_limit.memclk_mhz) ||
+                               
(dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels && 
dc->clk_mgr->bw_params->dc_mode_limit.socclk_mhz);
+       }
+
        // Initialize the dccg
        if (res_pool->dccg->funcs->dccg_init)
                res_pool->dccg->funcs->dccg_init(res_pool->dccg);
-- 
2.34.1

Reply via email to