From: Austin Zheng <[email protected]> [Why] Currently only a singular de-rate is used for all DPM levels. The intent was to limit the bandwidth utilization at high DPMs so the display requirements are not competing with other engines for bandwidth. At lower DPMs, the de-rates could be more lenient so more bandwidth can be utilized without the need to increase the DPM level and result in potential power savings. i.e. DPM0 could be achieved on certain display configs instead of DPM1 if de-rates were a couple percentage points higher
The system average de-rates can be adjusted as needed as only urgent de-rates are defined for the SOC. [How] Update QOS parameters to have a table of derates with a per-DPM granularity If the per-DPM value is provided, that will value be used. Otherwise use the global value if there is no DPM specific value. Reviewed-by: Jun Lei <[email protected]> Signed-off-by: Austin Zheng <[email protected]> Signed-off-by: George Zhang <[email protected]> --- .../dml21/inc/dml_top_soc_parameter_types.h | 13 ++++++ .../src/dml2_core/dml2_core_dcn4_calcs.c | 41 +++++++++++++------ 2 files changed, 41 insertions(+), 13 deletions(-) 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 6152155d6073..672b96a3da74 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 @@ -71,8 +71,21 @@ enum dml2_qos_param_type { dml2_qos_param_type_dcn4x }; +//Indicies mapped to DPM level +// Unpopulated indicies should fallback to the global derate value. +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]; + unsigned int dcfclk_derate_percent[DML_MAX_CLK_TABLE_SIZE]; +}; + +struct dml2_soc_derates_per_dpm { + struct dml2_soc_derate_values_per_dpm system_active_derates_per_dpm; +}; + struct dml2_soc_qos_parameters { struct dml2_soc_derates derate_table; + struct dml2_soc_derates_per_dpm derate_table_per_dpm; 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 f338e733318e..51a66e1be7a1 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 @@ -2701,7 +2701,8 @@ static double dml_get_return_bandwidth_available( bool is_hvm_only, double dcfclk_mhz, double fclk_mhz, - double dram_bw_mbps) + double dram_bw_mbps, + unsigned int uclk_dpm_level) { double return_bw_mbps = 0.; double ideal_sdp_bandwidth = (double)soc->return_bus_width_bytes * dcfclk_mhz; @@ -2722,9 +2723,16 @@ 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 - derate_sdp_factor = soc->qos_parameters.derate_table.system_active_average.dcfclk_derate_percent / 100.0; - derate_fabric_factor = soc->qos_parameters.derate_table.system_active_average.fclk_derate_percent / 100.0; - derate_dram_factor = soc->qos_parameters.derate_table.system_active_average.dram_derate_percent_pixel / 100.0; + // 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; } } else { // urgent bw if (state_type == dml2_core_internal_soc_state_svp_prefetch) { @@ -2778,6 +2786,7 @@ static double dml_get_return_bandwidth_available( DML_LOG_VERBOSE("DML::%s: derate_fabric_bandwidth = %f (derate %f)\n", __func__, derate_fabric_bandwidth, derate_fabric_factor); DML_LOG_VERBOSE("DML::%s: derate_dram_bandwidth = %f (derate %f)\n", __func__, derate_dram_bandwidth, derate_dram_factor); DML_LOG_VERBOSE("DML::%s: return_bw_mbps = %f\n", __func__, return_bw_mbps); + DML_LOG_VERBOSE("DML::%s: uclk_dpm_level = %u\n", __func__, uclk_dpm_level); return return_bw_mbps; } @@ -2793,7 +2802,8 @@ static noinline_for_stack void calculate_bandwidth_available( bool HostVMEnable, double dcfclk_mhz, double fclk_mhz, - double dram_bw_mbps) + double dram_bw_mbps, + unsigned int uclk_dpm_level) { unsigned int n, m; @@ -2812,9 +2822,10 @@ static noinline_for_stack void calculate_bandwidth_available( 0, // hvm_only dcfclk_mhz, fclk_mhz, - dram_bw_mbps); + dram_bw_mbps, + uclk_dpm_level); - urg_bandwidth_available[m][n] = dml_get_return_bandwidth_available(soc, m, n, 0, HostVMEnable, 0, dcfclk_mhz, fclk_mhz, dram_bw_mbps); + urg_bandwidth_available[m][n] = dml_get_return_bandwidth_available(soc, m, n, 0, HostVMEnable, 0, dcfclk_mhz, fclk_mhz, dram_bw_mbps, uclk_dpm_level); #ifdef __DML_VBA_DEBUG__ @@ -2824,8 +2835,8 @@ static noinline_for_stack void calculate_bandwidth_available( // urg_bandwidth_available_vm_only is indexed by soc_state if (n == dml2_core_internal_bw_dram) { - urg_bandwidth_available_vm_only[m] = dml_get_return_bandwidth_available(soc, m, n, 0, HostVMEnable, 1, dcfclk_mhz, fclk_mhz, dram_bw_mbps); - urg_bandwidth_available_pixel_and_vm[m] = dml_get_return_bandwidth_available(soc, m, n, 0, HostVMEnable, 0, dcfclk_mhz, fclk_mhz, dram_bw_mbps); + urg_bandwidth_available_vm_only[m] = dml_get_return_bandwidth_available(soc, m, n, 0, HostVMEnable, 1, dcfclk_mhz, fclk_mhz, dram_bw_mbps, uclk_dpm_level); + urg_bandwidth_available_pixel_and_vm[m] = dml_get_return_bandwidth_available(soc, m, n, 0, HostVMEnable, 0, dcfclk_mhz, fclk_mhz, dram_bw_mbps, uclk_dpm_level); } } @@ -9483,7 +9494,8 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out display_cfg->hostvm_enable, mode_lib->ms.DCFCLK, mode_lib->ms.FabricClock, - mode_lib->ms.dram_bw_mbps); + mode_lib->ms.dram_bw_mbps, + mode_lib->ms.active_min_uclk_dpm_index); calculate_bandwidth_available( mode_lib->ms.support.avg_bandwidth_available_min, @@ -9498,10 +9510,12 @@ static bool dml_core_mode_support(struct dml2_core_calcs_mode_support_ex *in_out mode_lib->ms.MaxDCFCLK, mode_lib->ms.MaxFabricClock, #ifdef DML_MODE_SUPPORT_USE_DPM_DRAM_BW - mode_lib->ms.dram_bw_mbps); + mode_lib->ms.dram_bw_mbps, #else - mode_lib->ms.max_dram_bw_mbps); + mode_lib->ms.max_dram_bw_mbps, #endif + mode_lib->ms.active_min_uclk_dpm_index); + // Average BW support check calculate_avg_bandwidth_required( @@ -10958,7 +10972,8 @@ static bool dml_core_mode_programming(struct dml2_core_calcs_mode_programming_ex display_cfg->hostvm_enable, mode_lib->mp.Dcfclk, mode_lib->mp.FabricClock, - mode_lib->mp.dram_bw_mbps); + mode_lib->mp.dram_bw_mbps, + mode_lib->mp.active_min_uclk_dpm_index); calculate_hostvm_inefficiency_factor( -- 2.54.0
