drm/amd/display: Disable AC/DC codepath when unnecessary
authorJoshua Aberback <joshua.aberback@amd.com>
Thu, 28 Mar 2024 17:43:36 +0000 (13:43 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 13 May 2024 19:45:55 +0000 (15:45 -0400)
[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.hung@amd.com>
Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Joshua Aberback <joshua.aberback@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/dcn401/dcn401_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c

index 1cf750cfed66d04049c5057fbad9206284b06bba..bd74ff47fb375083ed5beecc24859756d0cdf0bc 100644 (file)
@@ -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;
index 8698db8f3e45606fbf4540b8dbf53361e84d86b4..2fce8c0303fac4e9ccec8d95de05333900f133d7 100644 (file)
@@ -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 {
index d9a3d6c2da1f9507c5c7fb4926d4433ed8b5124b..3b74c4a9c2a86b9420a42779a0c2c9c7955167a6 100644 (file)
@@ -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);