Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amd/display: Add DCN42 PMO policy for DML2.1

[Why]
The MinTTU policy in DML2.1 does not guarantee that we support p-state
in blank. This is a delta vs dml2 and earlier revisions as the prefetch
mode override has been removed in favor of a more configurable pstate
optimizer.

[How]
Split off DCN42 with its own PMO helpers so that we can use a simpler
strategy of only allowing the mode if we support p-state in vblank and
if vactive has enough latency hiding.

The actual hookup to use these helpers in the PMO factory will be
done in a later patch to satisfy build system requirements.

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Nicholas Kazlauskas and committed by
Alex Deucher
bcfeed17 136d15b0

+229 -7
+1
drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
··· 100 100 DML21 += src/dml2_pmo/dml2_pmo_dcn3.o 101 101 DML21 += src/dml2_pmo/dml2_pmo_factory.o 102 102 DML21 += src/dml2_pmo/dml2_pmo_dcn4_fams2.o 103 + DML21 += src/dml2_pmo/dml2_pmo_dcn42.o 103 104 DML21 += src/dml2_standalone_libraries/lib_float_math.o 104 105 DML21 += dml21_translation_helper.o 105 106 DML21 += dml21_wrapper.o
+192
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.c
··· 1 + // SPDX-License-Identifier: MIT 2 + // 3 + // Copyright 2026 Advanced Micro Devices, Inc. 4 + 5 + #include "dml2_pmo_dcn42.h" 6 + #include "lib_float_math.h" 7 + #include "dml2_debug.h" 8 + #include "dml2_pmo_dcn4_fams2.h" 9 + 10 + /* 11 + * DCN42 PMO Policy Implementation 12 + * This implementation provides VBlank-only strategies for 1, 2, 3, and 4 display 13 + * configurations, ensuring p-state watermark support in the blank period only. 14 + */ 15 + 16 + static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_1_display[] = { 17 + // VBlank only 18 + { 19 + .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na }, 20 + .allow_state_increase = true, 21 + }, 22 + }; 23 + 24 + static const int dcn42_strategy_list_1_display_size = sizeof(dcn42_strategy_list_1_display) / sizeof(struct dml2_pmo_pstate_strategy); 25 + 26 + static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_2_display[] = { 27 + // VBlank only for both displays 28 + { 29 + .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na }, 30 + .allow_state_increase = true, 31 + }, 32 + }; 33 + 34 + static const int dcn42_strategy_list_2_display_size = sizeof(dcn42_strategy_list_2_display) / sizeof(struct dml2_pmo_pstate_strategy); 35 + 36 + static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_3_display[] = { 37 + // VBlank only for all three displays 38 + { 39 + .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_na }, 40 + .allow_state_increase = true, 41 + }, 42 + }; 43 + 44 + static const int dcn42_strategy_list_3_display_size = sizeof(dcn42_strategy_list_3_display) / sizeof(struct dml2_pmo_pstate_strategy); 45 + 46 + static const struct dml2_pmo_pstate_strategy dcn42_strategy_list_4_display[] = { 47 + // VBlank only for all four displays 48 + { 49 + .per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_vblank, dml2_pstate_method_vblank }, 50 + .allow_state_increase = true, 51 + }, 52 + }; 53 + 54 + static const int dcn42_strategy_list_4_display_size = sizeof(dcn42_strategy_list_4_display) / sizeof(struct dml2_pmo_pstate_strategy); 55 + 56 + bool pmo_dcn42_test_for_pstate_support(struct dml2_pmo_test_for_pstate_support_in_out *in_out) 57 + { 58 + const struct dml2_pmo_scratch *s = &in_out->instance->scratch; 59 + const int REQUIRED_RESERVED_TIME = 60 + (int)in_out->instance->soc_bb->power_management_parameters.dram_clk_change_blackout_us; 61 + bool p_state_supported = true; 62 + unsigned int stream_index; 63 + 64 + if (in_out->base_display_config->display_config.overrides.all_streams_blanked) 65 + return true; 66 + 67 + if (s->pmo_dcn4.cur_pstate_candidate < 0) 68 + return false; 69 + 70 + for (stream_index = 0; stream_index < in_out->base_display_config->display_config.num_streams; stream_index++) { 71 + if (s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].per_stream_pstate_method[stream_index] == dml2_pstate_method_vblank) { 72 + if (dcn4_get_minimum_reserved_time_us_for_planes(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < REQUIRED_RESERVED_TIME || 73 + dcn4_get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) > 0) { 74 + p_state_supported = false; 75 + break; 76 + } 77 + } else { 78 + p_state_supported = false; 79 + break; 80 + } 81 + } 82 + 83 + return p_state_supported; 84 + } 85 + 86 + bool pmo_dcn42_initialize(struct dml2_pmo_initialize_in_out *in_out) 87 + { 88 + int i = 0; 89 + struct dml2_pmo_instance *pmo = in_out->instance; 90 + 91 + unsigned int base_list_size = 0; 92 + const struct dml2_pmo_pstate_strategy *base_list = NULL; 93 + unsigned int *expanded_list_size = NULL; 94 + struct dml2_pmo_pstate_strategy *expanded_list = NULL; 95 + 96 + DML_LOG_COMP_IF_ENTER(); 97 + 98 + pmo->soc_bb = in_out->soc_bb; 99 + pmo->ip_caps = in_out->ip_caps; 100 + pmo->mpc_combine_limit = 2; 101 + pmo->odm_combine_limit = 4; 102 + pmo->mcg_clock_table_size = in_out->mcg_clock_table_size; 103 + 104 + /* 105 + * DCN42 does not support FAMS features like SubVP and DRR. 106 + * These parameters are initialized to safe values but won't be used 107 + * since our strategies only use VBlank. 108 + */ 109 + pmo->fams_params.v2.subvp.refresh_rate_limit_max = 0; 110 + pmo->fams_params.v2.subvp.refresh_rate_limit_min = 0; 111 + pmo->fams_params.v2.drr.refresh_rate_limit_max = 0; 112 + pmo->fams_params.v2.drr.refresh_rate_limit_min = 0; 113 + 114 + pmo->options = in_out->options; 115 + 116 + /* Generate permutations of p-state configs from base strategy list */ 117 + for (i = 0; i < PMO_DCN4_MAX_DISPLAYS; i++) { 118 + switch (i+1) { 119 + case 1: 120 + if (pmo->options->override_strategy_lists[i] && pmo->options->num_override_strategies_per_list[i]) { 121 + base_list = pmo->options->override_strategy_lists[i]; 122 + base_list_size = pmo->options->num_override_strategies_per_list[i]; 123 + } else { 124 + base_list = dcn42_strategy_list_1_display; 125 + base_list_size = dcn42_strategy_list_1_display_size; 126 + } 127 + 128 + expanded_list_size = &pmo->init_data.pmo_dcn4.num_expanded_strategies_per_list[i]; 129 + expanded_list = pmo->init_data.pmo_dcn4.expanded_strategy_list_1_display; 130 + 131 + break; 132 + case 2: 133 + if (pmo->options->override_strategy_lists[i] && pmo->options->num_override_strategies_per_list[i]) { 134 + base_list = pmo->options->override_strategy_lists[i]; 135 + base_list_size = pmo->options->num_override_strategies_per_list[i]; 136 + } else { 137 + base_list = dcn42_strategy_list_2_display; 138 + base_list_size = dcn42_strategy_list_2_display_size; 139 + } 140 + 141 + expanded_list_size = &pmo->init_data.pmo_dcn4.num_expanded_strategies_per_list[i]; 142 + expanded_list = pmo->init_data.pmo_dcn4.expanded_strategy_list_2_display; 143 + 144 + break; 145 + case 3: 146 + if (pmo->options->override_strategy_lists[i] && pmo->options->num_override_strategies_per_list[i]) { 147 + base_list = pmo->options->override_strategy_lists[i]; 148 + base_list_size = pmo->options->num_override_strategies_per_list[i]; 149 + } else { 150 + base_list = dcn42_strategy_list_3_display; 151 + base_list_size = dcn42_strategy_list_3_display_size; 152 + } 153 + 154 + expanded_list_size = &pmo->init_data.pmo_dcn4.num_expanded_strategies_per_list[i]; 155 + expanded_list = pmo->init_data.pmo_dcn4.expanded_strategy_list_3_display; 156 + 157 + break; 158 + case 4: 159 + if (pmo->options->override_strategy_lists[i] && pmo->options->num_override_strategies_per_list[i]) { 160 + base_list = pmo->options->override_strategy_lists[i]; 161 + base_list_size = pmo->options->num_override_strategies_per_list[i]; 162 + } else { 163 + base_list = dcn42_strategy_list_4_display; 164 + base_list_size = dcn42_strategy_list_4_display_size; 165 + } 166 + 167 + expanded_list_size = &pmo->init_data.pmo_dcn4.num_expanded_strategies_per_list[i]; 168 + expanded_list = pmo->init_data.pmo_dcn4.expanded_strategy_list_4_display; 169 + 170 + break; 171 + } 172 + 173 + DML_ASSERT(base_list_size <= PMO_DCN4_MAX_BASE_STRATEGIES); 174 + 175 + /* 176 + * Populate list using DCN4 FAMS2 expansion function. 177 + * Since our strategies only contain VBlank methods, the expansion 178 + * will not introduce any FAMS-specific logic. 179 + */ 180 + pmo_dcn4_fams2_expand_base_pstate_strategies( 181 + base_list, 182 + base_list_size, 183 + i + 1, 184 + expanded_list, 185 + expanded_list_size); 186 + } 187 + 188 + DML_LOG_DEBUG("%s exit with true\n", __func__); 189 + DML_LOG_COMP_IF_EXIT(); 190 + 191 + return true; 192 + }
+17
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn42.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright 2026 Advanced Micro Devices, Inc. 4 + */ 5 + 6 + #ifndef __DML2_PMO_DCN42_H__ 7 + #define __DML2_PMO_DCN42_H__ 8 + 9 + #include "dml2_internal_shared_types.h" 10 + 11 + struct dml2_pmo_initialize_in_out; 12 + struct dml2_pmo_test_for_pstate_support_in_out; 13 + 14 + bool pmo_dcn42_initialize(struct dml2_pmo_initialize_in_out *in_out); 15 + bool pmo_dcn42_test_for_pstate_support(struct dml2_pmo_test_for_pstate_support_in_out *in_out); 16 + 17 + #endif /* __DML2_PMO_DCN42_H__ */
+9 -7
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
··· 1662 1662 return is_config_schedulable(pmo, display_cfg, pstate_strategy); 1663 1663 } 1664 1664 1665 - static int get_vactive_pstate_margin(const struct display_configuation_with_meta *display_cfg, int plane_mask) 1665 + int dcn4_get_vactive_pstate_margin(const struct display_configuation_with_meta *display_cfg, int plane_mask) 1666 1666 { 1667 1667 unsigned int i; 1668 1668 int min_vactive_margin_us = 0xFFFFFFF; ··· 1907 1907 1908 1908 // Figure out which streams can do vactive, and also build up implicit SVP and FAMS2 meta 1909 1909 for (stream_index = 0; stream_index < display_config->display_config.num_streams; stream_index++) { 1910 - if (get_vactive_pstate_margin(display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) >= (int)(MIN_VACTIVE_MARGIN_PCT * pmo->soc_bb->power_management_parameters.dram_clk_change_blackout_us)) 1910 + if (dcn4_get_vactive_pstate_margin(display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) >= (int)(MIN_VACTIVE_MARGIN_PCT * pmo->soc_bb->power_management_parameters.dram_clk_change_blackout_us)) 1911 1911 set_bit_in_bitfield(&s->pmo_dcn4.stream_vactive_capability_mask, stream_index); 1912 1912 1913 1913 /* FAMS2 meta */ ··· 2182 2182 return success; 2183 2183 } 2184 2184 2185 - static int get_minimum_reserved_time_us_for_planes(struct display_configuation_with_meta *display_config, int plane_mask) 2185 + int dcn4_get_minimum_reserved_time_us_for_planes( 2186 + const struct display_configuation_with_meta *display_config, 2187 + int plane_mask) 2186 2188 { 2187 2189 int min_time_us = 0xFFFFFF; 2188 2190 unsigned int plane_index = 0; ··· 2224 2222 2225 2223 if (s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].per_stream_pstate_method[stream_index] == dml2_pstate_method_vactive || 2226 2224 s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_vactive_drr) { 2227 - if (get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < (MIN_VACTIVE_MARGIN_PCT * in_out->instance->soc_bb->power_management_parameters.dram_clk_change_blackout_us) || 2225 + if (dcn4_get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < (MIN_VACTIVE_MARGIN_PCT * in_out->instance->soc_bb->power_management_parameters.dram_clk_change_blackout_us) || 2228 2226 get_vactive_det_fill_latency_delay_us(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) > stream_pstate_meta->method_vactive.max_vactive_det_fill_delay_us) { 2229 2227 p_state_supported = false; 2230 2228 break; 2231 2229 } 2232 2230 } else if (s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].per_stream_pstate_method[stream_index] == dml2_pstate_method_vblank || 2233 2231 s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_vblank_drr) { 2234 - if (get_minimum_reserved_time_us_for_planes(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < 2232 + if (dcn4_get_minimum_reserved_time_us_for_planes(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < 2235 2233 REQUIRED_RESERVED_TIME || 2236 - get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < MIN_VACTIVE_MARGIN_VBLANK) { 2234 + dcn4_get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < MIN_VACTIVE_MARGIN_VBLANK) { 2237 2235 p_state_supported = false; 2238 2236 break; 2239 2237 } ··· 2245 2243 } 2246 2244 } else if (s->pmo_dcn4.pstate_strategy_candidates[s->pmo_dcn4.cur_pstate_candidate].per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_drr) { 2247 2245 if (!all_planes_match_method(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index], dml2_pstate_method_fw_drr) || 2248 - get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < MIN_VACTIVE_MARGIN_DRR) { 2246 + dcn4_get_vactive_pstate_margin(in_out->base_display_config, s->pmo_dcn4.stream_plane_mask[stream_index]) < MIN_VACTIVE_MARGIN_DRR) { 2249 2247 p_state_supported = false; 2250 2248 break; 2251 2249 }
+10
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.h
··· 7 7 8 8 #include "dml2_internal_shared_types.h" 9 9 10 + struct display_configuation_with_meta; 11 + 12 + int dcn4_get_vactive_pstate_margin( 13 + const struct display_configuation_with_meta *display_cfg, 14 + int plane_mask); 15 + 16 + int dcn4_get_minimum_reserved_time_us_for_planes( 17 + const struct display_configuation_with_meta *display_config, 18 + int plane_mask); 19 + 10 20 bool pmo_dcn4_fams2_initialize(struct dml2_pmo_initialize_in_out *in_out); 11 21 12 22 bool pmo_dcn4_fams2_optimize_dcc_mcache(struct dml2_pmo_optimize_dcc_mcache_in_out *in_out);