From: Sung Lee <sung....@amd.com>

[WHY]
DF PState and Voltage State are coupled such that one cannot be
raised without raising the other. This uses more power than
is necessary in high bandwidth scenarios.

[HOW]
Add logic to create a new bounding box state that allows for
DF PState to be low while Voltage State is high. Watermarks
vlevel calculation logic was also udpated to assume
state 1 contains the new optimized state.

Signed-off-by: Sung Lee <sung....@amd.com>
Acked-by: Aurabindo Pillai <aurabindo.pil...@amd.com>
---
 .../drm/amd/display/dc/dcn21/dcn21_resource.c | 71 ++++++++++++++-----
 1 file changed, 53 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
index 686e1d47faa4..72cbc13ce3da 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -1154,12 +1154,12 @@ void dcn21_calculate_wm(
                                                &context->bw_ctx.dml, pipes, 
pipe_cnt);
        /* WM Set C */
        table_entry = &bw_params->wm_table.entries[WM_C];
-       vlevel = MIN(MAX(vlevel_req, 2), vlevel_max);
+       vlevel = MIN(MAX(vlevel_req, 3), vlevel_max);
        calculate_wm_set_for_vlevel(vlevel, table_entry, 
&context->bw_ctx.bw.dcn.watermarks.c,
                                                &context->bw_ctx.dml, pipes, 
pipe_cnt);
        /* WM Set B */
        table_entry = &bw_params->wm_table.entries[WM_B];
-       vlevel = MIN(MAX(vlevel_req, 1), vlevel_max);
+       vlevel = MIN(MAX(vlevel_req, 2), vlevel_max);
        calculate_wm_set_for_vlevel(vlevel, table_entry, 
&context->bw_ctx.bw.dcn.watermarks.b,
                                                &context->bw_ctx.dml, pipes, 
pipe_cnt);
 
@@ -1385,12 +1385,39 @@ struct display_stream_compressor *dcn21_dsc_create(
        return &dsc->base;
 }
 
+static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct 
clk_limit_table *clk_table, unsigned int high_voltage_lvl)
+{
+       struct _vcs_dpi_voltage_scaling_st low_pstate_lvl;
+       int i;
+
+       low_pstate_lvl.state = 1;
+       low_pstate_lvl.dcfclk_mhz = clk_table->entries[0].dcfclk_mhz;
+       low_pstate_lvl.fabricclk_mhz = clk_table->entries[0].fclk_mhz;
+       low_pstate_lvl.socclk_mhz = clk_table->entries[0].socclk_mhz;
+       low_pstate_lvl.dram_speed_mts = clk_table->entries[0].memclk_mhz * 2;
+
+       low_pstate_lvl.dispclk_mhz = 
dcn2_1_soc.clock_limits[high_voltage_lvl].dispclk_mhz;
+       low_pstate_lvl.dppclk_mhz = 
dcn2_1_soc.clock_limits[high_voltage_lvl].dppclk_mhz;
+       low_pstate_lvl.dram_bw_per_chan_gbps = 
dcn2_1_soc.clock_limits[high_voltage_lvl].dram_bw_per_chan_gbps;
+       low_pstate_lvl.dscclk_mhz = 
dcn2_1_soc.clock_limits[high_voltage_lvl].dscclk_mhz;
+       low_pstate_lvl.dtbclk_mhz = 
dcn2_1_soc.clock_limits[high_voltage_lvl].dtbclk_mhz;
+       low_pstate_lvl.phyclk_d18_mhz = 
dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_d18_mhz;
+       low_pstate_lvl.phyclk_mhz = 
dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_mhz;
+
+       for (i = clk_table->num_entries; i > 1; i--)
+               clk_table->entries[i] = clk_table->entries[i-1];
+       clk_table->entries[1] = clk_table->entries[0];
+       clk_table->num_entries++;
+
+       return low_pstate_lvl;
+}
+
 static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params 
*bw_params)
 {
        struct dcn21_resource_pool *pool = TO_DCN21_RES_POOL(dc->res_pool);
        struct clk_limit_table *clk_table = &bw_params->clk_table;
        struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES];
-       unsigned int i, closest_clk_lvl;
+       unsigned int i, closest_clk_lvl = 0, k = 0;
        int j;
 
        dcn2_1_ip.max_num_otg = pool->base.res_cap->num_timing_generator;
@@ -1407,27 +1434,35 @@ static void update_bw_bounding_box(struct dc *dc, 
struct clk_bw_params *bw_param
                        }
                }
 
-               clock_limits[i].state = i;
-               clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
-               clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
-               clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz;
-               clock_limits[i].dram_speed_mts = 
clk_table->entries[i].memclk_mhz * 2;
-
-               clock_limits[i].dispclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
-               clock_limits[i].dppclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
-               clock_limits[i].dram_bw_per_chan_gbps = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
-               clock_limits[i].dscclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
-               clock_limits[i].dtbclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
-               clock_limits[i].phyclk_d18_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
-               clock_limits[i].phyclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+               /* clk_table[1] is reserved for min DF PState.  skip here to 
fill in later. */
+               if (i == 1)
+                       k++;
+
+               clock_limits[k].state = k;
+               clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz;
+               clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz;
+               clock_limits[k].socclk_mhz = clk_table->entries[i].socclk_mhz;
+               clock_limits[k].dram_speed_mts = 
clk_table->entries[i].memclk_mhz * 2;
+
+               clock_limits[k].dispclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz;
+               clock_limits[k].dppclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz;
+               clock_limits[k].dram_bw_per_chan_gbps = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps;
+               clock_limits[k].dscclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz;
+               clock_limits[k].dtbclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz;
+               clock_limits[k].phyclk_d18_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz;
+               clock_limits[k].phyclk_mhz = 
dcn2_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz;
+
+               k++;
        }
-       for (i = 0; i < clk_table->num_entries; i++)
+       for (i = 0; i < clk_table->num_entries + 1; i++)
                dcn2_1_soc.clock_limits[i] = clock_limits[i];
        if (clk_table->num_entries) {
-               dcn2_1_soc.num_states = clk_table->num_entries;
+               dcn2_1_soc.num_states = clk_table->num_entries + 1;
                /* duplicate last level */
                dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = 
dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1];
                dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = 
dcn2_1_soc.num_states;
+               /* fill in min DF PState */
+               dcn2_1_soc.clock_limits[1] = 
construct_low_pstate_lvl(clk_table, closest_clk_lvl);
        }
 
        dml_init_instance(&dc->dml, &dcn2_1_soc, &dcn2_1_ip, DML_PROJECT_DCN21);
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to