From: Austin Zheng <[email protected]>

[Why/How]
1. DPMM also needs to consider the per-DPM derate when calculating the
clocks
that will be used by mode programming.
Otherwise DPMM calculations can result in rounding up to the next DPM
anyways.

clk index value used by mode support is not reliable when trying to
determine the actual
per-dpm derate.

2. Also update how per-dpm derates are stored so each derate applies until
an upper bound.
Upperbound of 0 signifies this derate is used for the remaining DPMs.

To simplify logic, all derates for all clocks should have the same number
of entries
and the last entry should have an upperbound of 0.

3. Deprecate system_active_average derates from the derate table and move
them to the per-DPM structure
The remaining derates (urgent, dcn_mall, system idle) are unchanged

Reviewed-by: Dillon Varone <[email protected]>
Signed-off-by: Austin Zheng <[email protected]>
Signed-off-by: James Lin <[email protected]>
---
 .../dml21/inc/bounding_boxes/dcn42_soc_bb.h   |  25 ++---
 .../dml21/inc/bounding_boxes/dcn42b_soc_bb.h  |  25 ++---
 .../dml21/inc/bounding_boxes/dcn4_soc_bb.h    |  25 ++---
 .../dml21/inc/dml_top_soc_parameter_types.h   |  44 +++++++-
 .../src/dml2_core/dml2_core_dcn4_calcs.c      |  19 ++--
 .../dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c      | 106 +++++++++++++++++-
 .../src/inc/dml2_internal_shared_types.h      |   1 +
 7 files changed, 181 insertions(+), 64 deletions(-)

diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h
index b21beebc52bd..52f906e41fb4 100644
--- 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h
+++ 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h
@@ -16,13 +16,6 @@ static const struct dml2_soc_qos_parameters 
dml_dcn42_variant_a_soc_qos_params =
                        .fclk_derate_percent = 80,
                        .dcfclk_derate_percent = 80,
                },
-               .system_active_average = {
-                       .dram_derate_percent_pixel = 30,
-                       .dram_derate_percent_vm = 30,
-                       .dram_derate_percent_pixel_and_vm = 30,
-                       .fclk_derate_percent = 60,
-                       .dcfclk_derate_percent = 60,
-               },
                .dcn_mall_prefetch_urgent = {
                        .dram_derate_percent_pixel = 65,
                        .dram_derate_percent_vm = 30,
@@ -45,6 +38,17 @@ static const struct dml2_soc_qos_parameters 
dml_dcn42_variant_a_soc_qos_params =
                        .dcfclk_derate_percent = 60,
                },
        },
+       .derate_table_per_dpm = {
+               .dram_per_dpm_derate_pixel = {
+                       {.derate_percent = 30, .clk_upperbound_threshold_khz = 
0},
+               },
+               .fclk_per_dpm_derate = {
+                       {.derate_percent = 60, .clk_upperbound_threshold_khz = 
0},
+               },
+               .dcfclk_per_dpm_derate = {
+                       {.derate_percent = 60, .clk_upperbound_threshold_khz = 
0},
+               },
+       },
        .writeback = {
                .base_latency_us = 12,
                .scaling_factor_us = 0,
@@ -134,13 +138,6 @@ static const struct dml2_soc_bb dml2_socbb_dcn42 = {
                                .fclk_derate_percent = 80,
                                .dcfclk_derate_percent = 80,
                        },
-                       .system_active_average = {
-                               .dram_derate_percent_pixel = 30,
-                               .dram_derate_percent_vm = 30,
-                               .dram_derate_percent_pixel_and_vm = 30,
-                               .fclk_derate_percent = 60,
-                               .dcfclk_derate_percent = 60,
-                       },
                        .dcn_mall_prefetch_urgent = {
                                .dram_derate_percent_pixel = 65,
                                .dram_derate_percent_vm = 30,
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42b_soc_bb.h
 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42b_soc_bb.h
index 5d844ff4b671..33eb583e3365 100644
--- 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42b_soc_bb.h
+++ 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42b_soc_bb.h
@@ -17,13 +17,6 @@ static const struct dml2_soc_qos_parameters 
dml_dcn42b_variant_a_soc_qos_params
                        .fclk_derate_percent = 80,
                        .dcfclk_derate_percent = 80,
                },
-               .system_active_average = {
-                       .dram_derate_percent_pixel = 30,
-                       .dram_derate_percent_vm = 30,
-                       .dram_derate_percent_pixel_and_vm = 30,
-                       .fclk_derate_percent = 60,
-                       .dcfclk_derate_percent = 60,
-               },
                .dcn_mall_prefetch_urgent = {
                        .dram_derate_percent_pixel = 65,
                        .dram_derate_percent_vm = 30,
@@ -46,6 +39,17 @@ static const struct dml2_soc_qos_parameters 
dml_dcn42b_variant_a_soc_qos_params
                        .dcfclk_derate_percent = 60,
                },
        },
+       .derate_table_per_dpm = {
+               .dram_per_dpm_derate_pixel = {
+                       {.derate_percent = 30, .clk_upperbound_threshold_khz = 
0},
+               },
+               .fclk_per_dpm_derate = {
+                       {.derate_percent = 60, .clk_upperbound_threshold_khz = 
0},
+               },
+               .dcfclk_per_dpm_derate = {
+                       {.derate_percent = 60, .clk_upperbound_threshold_khz = 
0},
+               },
+       },
        .writeback = {
                .base_latency_us = 12,
                .scaling_factor_us = 0,
@@ -134,13 +138,6 @@ static const struct dml2_soc_bb dml2_socbb_dcn42b = {
                                .fclk_derate_percent = 80,
                                .dcfclk_derate_percent = 80,
                        },
-                       .system_active_average = {
-                               .dram_derate_percent_pixel = 30,
-                               .dram_derate_percent_vm = 30,
-                               .dram_derate_percent_pixel_and_vm = 30,
-                               .fclk_derate_percent = 60,
-                               .dcfclk_derate_percent = 60,
-                       },
                        .dcn_mall_prefetch_urgent = {
                                .dram_derate_percent_pixel = 65,
                                .dram_derate_percent_vm = 30,
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h
index 16a4f97bca4e..f26366ebeeda 100644
--- 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h
+++ 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn4_soc_bb.h
@@ -16,13 +16,6 @@ static const struct dml2_soc_qos_parameters 
dml_dcn4_variant_a_soc_qos_params =
                        .fclk_derate_percent = 76,
                        .dcfclk_derate_percent = 100,
                },
-               .system_active_average = {
-                       .dram_derate_percent_pixel = 17,
-                       .dram_derate_percent_vm = 0,
-                       .dram_derate_percent_pixel_and_vm = 0,
-                       .fclk_derate_percent = 57,
-                       .dcfclk_derate_percent = 75,
-               },
                .dcn_mall_prefetch_urgent = {
                        .dram_derate_percent_pixel = 40,
                        .dram_derate_percent_vm = 0,
@@ -45,6 +38,17 @@ static const struct dml2_soc_qos_parameters 
dml_dcn4_variant_a_soc_qos_params =
                        .dcfclk_derate_percent = 100,
                },
        },
+       .derate_table_per_dpm = {
+               .dram_per_dpm_derate_pixel = {
+                       {.derate_percent = 17, .clk_upperbound_threshold_khz = 
0},
+               },
+               .fclk_per_dpm_derate = {
+                       {.derate_percent = 57, .clk_upperbound_threshold_khz = 
0},
+               },
+               .dcfclk_per_dpm_derate = {
+                       {.derate_percent = 75, .clk_upperbound_threshold_khz = 
0},
+               },
+       },
        .writeback = {
                .base_latency_us = 12,
                .scaling_factor_us = 0,
@@ -142,13 +146,6 @@ static const struct dml2_soc_bb dml2_socbb_dcn401 = {
                                .fclk_derate_percent = 76,
                                .dcfclk_derate_percent = 100,
                        },
-                       .system_active_average = {
-                               .dram_derate_percent_pixel = 15,
-                               .dram_derate_percent_vm = 0,
-                               .dram_derate_percent_pixel_and_vm = 0,
-                               .fclk_derate_percent = 57,
-                               .dcfclk_derate_percent = 75,
-                       },
                        .dcn_mall_prefetch_urgent = {
                                .dram_derate_percent_pixel = 40,
                                .dram_derate_percent_vm = 0,
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
index b830e95b27c8..45208f804d2b 100644
--- 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
+++ 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
@@ -20,7 +20,6 @@ struct dml2_soc_derate_values {
 
 struct dml2_soc_derates {
        struct dml2_soc_derate_values system_active_urgent;
-       struct dml2_soc_derate_values system_active_average;
        struct dml2_soc_derate_values dcn_mall_prefetch_urgent;
        struct dml2_soc_derate_values dcn_mall_prefetch_average;
        struct dml2_soc_derate_values system_idle_average;
@@ -71,8 +70,22 @@ enum dml2_qos_param_type {
        dml2_qos_param_type_dcn4x
 };
 
-//Indicies mapped to DPM level
-// Unpopulated indicies should fallback to the global derate value.
+// Per-DPM derate structure: each element pairs a derate percentage with its 
clock threshold
+// Requirements:
+// - Index 0 must always be populated (the base/default derate)
+// - Last populated entry must have clk_upperbound_threshold_khz = 0
+// - All clock arrays within a power state should have the same number of 
entries
+// - If a non-zero DPM index has derate_percent = 0, fall back to index 0
+// Unpopulated derates should fallback to the global derate value.
+// Each element pairs a derate percentage with its threshold
+struct dml2_soc_derate_values_per_dpm_v2 {
+       unsigned int derate_percent;
+       unsigned int clk_upperbound_threshold_khz;
+};
+
+// Legacy structure - for backward compatibility as driver debug values can 
override the values. (will temporarily break driver overrides)
+// Per-DPM derate arrays for system_active_average (the only power state that 
varies by DPM)
+// Urgent derates are constant across DPMs and come from 
derate_table.system_active_urgent
 struct dml2_soc_derate_values_per_dpm {
        unsigned int dram_derate_percent_pixel[DML_MAX_CLK_TABLE_SIZE];
        unsigned int fclk_derate_percent[DML_MAX_CLK_TABLE_SIZE];
@@ -80,12 +93,31 @@ struct dml2_soc_derate_values_per_dpm {
 };
 
 struct dml2_soc_derates_per_dpm {
-       struct dml2_soc_derate_values_per_dpm system_active_derates_per_dpm;
+       // Union allows both layouts to coexist without increasing struct size
+       // Anonymous structs allow direct member access without .v1 or .v2 
prefix
+       union {
+               // Legacy layout - used by soc_and_ip_translator (unchanged 
access pattern)
+               // TODO: Remove after soc_and_ip_translator migration is 
complete
+               struct {
+                       struct dml2_soc_derate_values_per_dpm 
system_active_derates_per_dpm;
+                       unsigned int 
min_uclk_khz_threshold[DML_MAX_CLK_TABLE_SIZE];
+                       unsigned int 
min_fclk_khz_threshold[DML_MAX_CLK_TABLE_SIZE];
+                       unsigned int 
min_dcfclk_khz_threshold[DML_MAX_CLK_TABLE_SIZE];
+               };
+
+               // New layout - used by DML internally
+               // Arrays of derate/threshold pairs, one per DPM level
+               struct {
+                       struct dml2_soc_derate_values_per_dpm_v2 
dram_per_dpm_derate_pixel[DML_MAX_CLK_TABLE_SIZE];
+                       struct dml2_soc_derate_values_per_dpm_v2 
fclk_per_dpm_derate[DML_MAX_CLK_TABLE_SIZE];
+                       struct dml2_soc_derate_values_per_dpm_v2 
dcfclk_per_dpm_derate[DML_MAX_CLK_TABLE_SIZE];
+               };
+       };
 };
 
 struct dml2_soc_qos_parameters {
-       struct dml2_soc_derates derate_table;
-       struct dml2_soc_derates_per_dpm derate_table_per_dpm;
+       struct dml2_soc_derates derate_table; // Single-value derates (source 
of truth for urgent, idle, mall_prefetch)
+       struct dml2_soc_derates_per_dpm derate_table_per_dpm; // Per-DPM 
derates for system_active_average only
        struct {
                unsigned int base_latency_us;
                unsigned int scaling_factor_us;
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index d943cc8bf60e..475bdeb39d21 100644
--- 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -2739,16 +2739,15 @@ static double dml_get_return_bandwidth_available(
                        derate_fabric_factor = 
soc->qos_parameters.derate_table.dcn_mall_prefetch_average.fclk_derate_percent 
/ 100.0;
                        derate_dram_factor = 
soc->qos_parameters.derate_table.dcn_mall_prefetch_average.dram_derate_percent_pixel
 / 100.0;
                } else { // just assume sys_active
-                       // use per dpm derates if the values are populated. 
Otherwise use global derates
-                       derate_sdp_factor = 
soc->qos_parameters.derate_table_per_dpm.system_active_derates_per_dpm.dcfclk_derate_percent[uclk_dpm_level]
 != 0 ?
-                               
soc->qos_parameters.derate_table_per_dpm.system_active_derates_per_dpm.dcfclk_derate_percent[uclk_dpm_level]
 / 100.0 :
-                               
soc->qos_parameters.derate_table.system_active_average.dcfclk_derate_percent / 
100.0;
-                       derate_fabric_factor = 
soc->qos_parameters.derate_table_per_dpm.system_active_derates_per_dpm.fclk_derate_percent[uclk_dpm_level]
 != 0 ?
-                               
soc->qos_parameters.derate_table_per_dpm.system_active_derates_per_dpm.fclk_derate_percent[uclk_dpm_level]
 / 100.0 :
-                               
soc->qos_parameters.derate_table.system_active_average.fclk_derate_percent / 
100.0;
-                       derate_dram_factor = 
soc->qos_parameters.derate_table_per_dpm.system_active_derates_per_dpm.dram_derate_percent_pixel[uclk_dpm_level]
 != 0 ?
-                               
soc->qos_parameters.derate_table_per_dpm.system_active_derates_per_dpm.dram_derate_percent_pixel[uclk_dpm_level]
 / 100.0 :
-                               
soc->qos_parameters.derate_table.system_active_average.dram_derate_percent_pixel
 / 100.0;
+                       derate_sdp_factor = 
(soc->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[uclk_dpm_level].derate_percent
 != 0 ?
+                               
soc->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[uclk_dpm_level].derate_percent
 :
+                               
soc->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[0].derate_percent)
 / 100.0;
+                       derate_fabric_factor = 
(soc->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[uclk_dpm_level].derate_percent
 != 0 ?
+                               
soc->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[uclk_dpm_level].derate_percent
 :
+                               
soc->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[0].derate_percent) 
/ 100.0;
+                       derate_dram_factor = 
(soc->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[uclk_dpm_level].derate_percent
 != 0 ?
+                               
soc->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[uclk_dpm_level].derate_percent
 :
+                               
soc->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[0].derate_percent)
 / 100.0;
                }
        } else { // urgent bw
                if (state_type == dml2_core_internal_soc_state_svp_prefetch) {
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
index 22c757cdac07..54a1f9c13dbf 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
@@ -6,6 +6,8 @@
 #include "dml2_internal_shared_types.h"
 #include "dml_top_types.h"
 #include "lib_float_math.h"
+#include "dml2_debug.h"
+
 
 static double dram_bw_kbps_to_uclk_khz(unsigned long long bandwidth_kbps, 
const struct dml2_dram_params *dram_config, struct 
dml2_mcg_dram_bw_to_min_clk_table *dram_bw_table)
 {
@@ -55,16 +57,101 @@ static unsigned long dml_round_up(double a)
        return (unsigned long)a;
 }
 
+/* Calculate DPM index to use for per-DPM derates
+ * Iterates through DPM levels - if calculated clocks exceed thresholds 
increment to next DPM level
+ */
+static void calculate_derate_index(struct 
dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out)
+{
+       const struct dml2_core_mode_support_result *mode_support_result = 
&in_out->display_cfg->mode_support_result;
+       double required_bw_dram_kbps, required_bw_sdp_kbps;
+       int i;
+
+       /* Default to DPM 0 (lowest power state) */
+       in_out->derate_dpm_index = 0;
+
+       /* Get required bandwidths from mode support */
+       required_bw_dram_kbps = 
mode_support_result->global.active.average_bw_dram_kbps;
+       required_bw_sdp_kbps = 
mode_support_result->global.active.average_bw_sdp_kbps;
+
+       /* Iterate through DPM levels from lowest to highest to find the first 
level
+        * whose available bandwidth can satisfy the requirements.
+        */
+       for (i = 0; i < DML_MAX_CLK_TABLE_SIZE; i++) {
+               unsigned int dram_threshold = 
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[i].clk_upperbound_threshold_khz;
+               unsigned int fclk_threshold = 
in_out->soc_bb->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[i].clk_upperbound_threshold_khz;
+               unsigned int dcfclk_threshold = 
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[i].clk_upperbound_threshold_khz;
+               unsigned int uclk_derate = 
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[i].derate_percent;
+               unsigned int fclk_derate = 
in_out->soc_bb->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[i].derate_percent;
+               unsigned int dcfclk_derate = 
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[i].derate_percent;
+               double max_dram_bw_for_dpm = 0, max_fclk_bw_for_dpm = 0, 
max_dcfclk_bw_for_dpm = 0;
+
+               /* Skip entries with 0 derate (use fallback logic) */
+               if (uclk_derate == 0 || fclk_derate == 0 || dcfclk_derate == 0) 
{
+                       DML_ASSERT(0); // derate should be populated (at least 
1 entry in the per_dpm table that can be applied for all DPMs
+               }
+
+               /* Threshold of 0 indicates last entry - this DPM level handles 
all higher bandwidths */
+               if (dram_threshold == 0 && fclk_threshold == 0 && 
dcfclk_threshold == 0) {
+                       in_out->derate_dpm_index = i;
+                       break;
+               }
+
+               /* Calculate maximum available bandwidth at this DPM level
+                       * Available BW = max_clock_at_threshold * derate * 
conversion_factor */
+
+                       /* For DRAM: convert threshold clock to bandwidth */
+               if 
(!in_out->soc_bb->clk_table.dram_config.alt_clock_bw_conversion) {
+                       unsigned long uclk_bytes_per_tick = 
in_out->soc_bb->clk_table.dram_config.channel_count
+                               * 
in_out->soc_bb->clk_table.dram_config.channel_width_bytes
+                               * 
in_out->soc_bb->clk_table.dram_config.transactions_per_clock;
+                       max_dram_bw_for_dpm = (double)dram_threshold * 
uclk_bytes_per_tick * ((double)uclk_derate / 100.0);
+               } else {
+                       /* use pre-computed table - find bandwidth at threshold 
clock */
+                       for (unsigned int j = 0; j < 
in_out->min_clk_table->dram_bw_table.num_entries; j++) {
+                               if 
(in_out->min_clk_table->dram_bw_table.entries[j].min_uclk_khz >= 
dram_threshold) {
+                                       max_dram_bw_for_dpm = 
(double)in_out->min_clk_table->dram_bw_table.entries[j].pre_derate_dram_bw_kbps;
+                                       break;
+                               }
+                       }
+               }
+
+               max_fclk_bw_for_dpm = (double)fclk_threshold
+                       * 
in_out->soc_bb->fabric_datapath_to_dcn_data_return_bytes
+                       * ((double)fclk_derate / 100.0);
+
+               max_dcfclk_bw_for_dpm = (double)dcfclk_threshold
+                       * in_out->soc_bb->return_bus_width_bytes
+                       * ((double)dcfclk_derate / 100.0);
+
+               /* Check if this DPM level's available bandwidth satisfies all 
requirements
+                       * All bandwidth paths must be satisfied to use this DPM 
level */
+               if (((dram_threshold == 0) || (required_bw_dram_kbps <= 
max_dram_bw_for_dpm)) &&
+                       ((fclk_threshold == 0) || (required_bw_sdp_kbps <= 
max_fclk_bw_for_dpm)) &&
+                       ((dcfclk_threshold == 0) || (required_bw_sdp_kbps <= 
max_dcfclk_bw_for_dpm))) {
+                       in_out->derate_dpm_index = i;
+                       break;
+               }
+       }
+}
+
 static void calculate_system_active_minimums(struct 
dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out)
 {
        double min_uclk_avg, min_uclk_urgent, min_uclk_bw;
        double min_fclk_avg, min_fclk_urgent, min_fclk_bw;
        double min_dcfclk_avg, min_dcfclk_urgent, min_dcfclk_bw;
        double min_uclk_latency, min_fclk_latency, min_dcfclk_latency;
+       int dpm_index, uclk_avg_derate_percent, fclk_avg_derate_percent, 
dcfclk_avg_derate_percent;
        const struct dml2_core_mode_support_result *mode_support_result = 
&in_out->display_cfg->mode_support_result;
 
+       dpm_index = in_out->derate_dpm_index;
+
+       /* Get average derates from system_active_average per-DPM table */
+       uclk_avg_derate_percent = 
(in_out->soc_bb->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[dpm_index].derate_percent
 != 0 || dpm_index == 0) ?
+               
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[dpm_index].derate_percent
 :
+               
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[0].derate_percent;
+
        min_uclk_avg = dram_bw_kbps_to_uclk_khz((unsigned long 
long)(mode_support_result->global.active.average_bw_dram_kbps
-                                                                               
        / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_average.dram_derate_percent_pixel
 / 100)),
+                                                                               
        / ((double)uclk_avg_derate_percent / 100)),
                                                        
&in_out->soc_bb->clk_table.dram_config, &in_out->min_clk_table->dram_bw_table);
 
        if (in_out->display_cfg->display_config.hostvm_enable)
@@ -78,16 +165,22 @@ static void calculate_system_active_minimums(struct 
dml2_dpmm_map_mode_to_soc_dp
 
        min_uclk_bw = min_uclk_urgent > min_uclk_avg ? min_uclk_urgent : 
min_uclk_avg;
 
+       fclk_avg_derate_percent = 
(in_out->soc_bb->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[dpm_index].derate_percent
 != 0 || dpm_index == 0) ?
+               
in_out->soc_bb->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[dpm_index].derate_percent
 :
+               
in_out->soc_bb->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[0].derate_percent;
        min_fclk_avg = 
(double)mode_support_result->global.active.average_bw_sdp_kbps / 
in_out->soc_bb->fabric_datapath_to_dcn_data_return_bytes;
-       min_fclk_avg = (double)min_fclk_avg / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_average.fclk_derate_percent
 / 100);
+       min_fclk_avg = (double)min_fclk_avg / ((double)fclk_avg_derate_percent 
/ 100);
 
        min_fclk_urgent = 
(double)mode_support_result->global.active.urgent_bw_sdp_kbps / 
in_out->soc_bb->fabric_datapath_to_dcn_data_return_bytes;
        min_fclk_urgent = (double)min_fclk_urgent / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_urgent.fclk_derate_percent
 / 100);
 
        min_fclk_bw = min_fclk_urgent > min_fclk_avg ? min_fclk_urgent : 
min_fclk_avg;
 
+       dcfclk_avg_derate_percent = 
(in_out->soc_bb->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[dpm_index].derate_percent
 != 0 || dpm_index == 0) ?
+               
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[dpm_index].derate_percent
 :
+               
in_out->soc_bb->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[0].derate_percent;
        min_dcfclk_avg = 
(double)mode_support_result->global.active.average_bw_sdp_kbps / 
in_out->soc_bb->return_bus_width_bytes;
-       min_dcfclk_avg = (double)min_dcfclk_avg / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_average.dcfclk_derate_percent
 / 100);
+       min_dcfclk_avg = (double)min_dcfclk_avg / 
((double)dcfclk_avg_derate_percent / 100);
 
        min_dcfclk_urgent = 
(double)mode_support_result->global.active.urgent_bw_sdp_kbps / 
in_out->soc_bb->return_bus_width_bytes;
        min_dcfclk_urgent = (double)min_dcfclk_urgent / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_urgent.dcfclk_derate_percent
 / 100);
@@ -145,7 +238,7 @@ static void calculate_svp_prefetch_minimums(struct 
dml2_dpmm_map_mode_to_soc_dpm
 
        /* assumes DF throttling is disabled */
        min_uclk_avg = dram_bw_kbps_to_uclk_khz((unsigned long 
long)(mode_support_result->global.svp_prefetch.average_bw_dram_kbps
-                                                                               
/ 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_average.dram_derate_percent_pixel
 / 100)),
+                                                                               
/ 
((double)in_out->soc_bb->qos_parameters.derate_table_per_dpm.dram_per_dpm_derate_pixel[in_out->derate_dpm_index].derate_percent
 / 100)),
                                                                
&in_out->soc_bb->clk_table.dram_config, &in_out->min_clk_table->dram_bw_table);
 
        min_uclk_urgent = dram_bw_kbps_to_uclk_khz((unsigned long 
long)(mode_support_result->global.svp_prefetch.urgent_bw_dram_kbps
@@ -155,7 +248,7 @@ static void calculate_svp_prefetch_minimums(struct 
dml2_dpmm_map_mode_to_soc_dpm
        min_uclk_bw = min_uclk_urgent > min_uclk_avg ? min_uclk_urgent : 
min_uclk_avg;
 
        min_fclk_avg = 
(double)mode_support_result->global.svp_prefetch.average_bw_sdp_kbps / 
in_out->soc_bb->fabric_datapath_to_dcn_data_return_bytes;
-       min_fclk_avg = (double)min_fclk_avg / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_average.fclk_derate_percent
 / 100);
+       min_fclk_avg = (double)min_fclk_avg / 
((double)in_out->soc_bb->qos_parameters.derate_table_per_dpm.fclk_per_dpm_derate[in_out->derate_dpm_index].derate_percent
 / 100);
 
        min_fclk_urgent = 
(double)mode_support_result->global.svp_prefetch.urgent_bw_sdp_kbps / 
in_out->soc_bb->fabric_datapath_to_dcn_data_return_bytes;
        min_fclk_urgent = (double)min_fclk_urgent / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_urgent.fclk_derate_percent
 / 100);
@@ -163,7 +256,7 @@ static void calculate_svp_prefetch_minimums(struct 
dml2_dpmm_map_mode_to_soc_dpm
        min_fclk_bw = min_fclk_urgent > min_fclk_avg ? min_fclk_urgent : 
min_fclk_avg;
 
        min_dcfclk_avg = 
(double)mode_support_result->global.svp_prefetch.average_bw_sdp_kbps / 
in_out->soc_bb->return_bus_width_bytes;
-       min_dcfclk_avg = (double)min_dcfclk_avg / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_average.dcfclk_derate_percent
 / 100);
+       min_dcfclk_avg = (double)min_dcfclk_avg / 
((double)in_out->soc_bb->qos_parameters.derate_table_per_dpm.dcfclk_per_dpm_derate[in_out->derate_dpm_index].derate_percent
 / 100);
 
        min_dcfclk_urgent = 
(double)mode_support_result->global.svp_prefetch.urgent_bw_sdp_kbps / 
in_out->soc_bb->return_bus_width_bytes;
        min_dcfclk_urgent = (double)min_dcfclk_urgent / 
((double)in_out->soc_bb->qos_parameters.derate_table.system_active_urgent.dcfclk_derate_percent
 / 100);
@@ -633,6 +726,7 @@ static bool map_mode_to_soc_dpm(struct 
dml2_dpmm_map_mode_to_soc_dpm_params_in_o
        double dispclk_khz;
        const struct dml2_core_mode_support_result *mode_support_result = 
&in_out->display_cfg->mode_support_result;
 
+       calculate_derate_index(in_out);
        calculate_system_active_minimums(in_out);
        calculate_svp_prefetch_minimums(in_out);
        calculate_idle_minimums(in_out);
diff --git 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
index a18f067fe53f..8ddf58da2eed 100644
--- 
a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
+++ 
b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
@@ -246,6 +246,7 @@ struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out {
        * Output
        */
        struct dml2_display_cfg_programming *programming;
+       int derate_dpm_index;
 };
 
 struct dml2_dpmm_map_watermarks_params_in_out {
-- 
2.43.0

Reply via email to