1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4
5 #include "dml2_top_optimization.h"
6 #include "dml2_internal_shared_types.h"
7 #include "dml_top_mcache.h"
8
copy_display_configuration_with_meta(struct display_configuation_with_meta * dst,const struct display_configuation_with_meta * src)9 static void copy_display_configuration_with_meta(struct display_configuation_with_meta *dst, const struct display_configuation_with_meta *src)
10 {
11 memcpy(dst, src, sizeof(struct display_configuation_with_meta));
12 }
13
dml2_top_optimization_init_function_min_clk_for_latency(const struct optimization_init_function_params * params)14 bool dml2_top_optimization_init_function_min_clk_for_latency(const struct optimization_init_function_params *params)
15 {
16 struct dml2_optimization_stage1_state *state = ¶ms->display_config->stage1;
17
18 state->performed = true;
19
20 return true;
21 }
22
dml2_top_optimization_test_function_min_clk_for_latency(const struct optimization_test_function_params * params)23 bool dml2_top_optimization_test_function_min_clk_for_latency(const struct optimization_test_function_params *params)
24 {
25 struct dml2_optimization_stage1_state *state = ¶ms->display_config->stage1;
26
27 return state->min_clk_index_for_latency == 0;
28 }
29
dml2_top_optimization_optimize_function_min_clk_for_latency(const struct optimization_optimize_function_params * params)30 bool dml2_top_optimization_optimize_function_min_clk_for_latency(const struct optimization_optimize_function_params *params)
31 {
32 bool result = false;
33
34 if (params->display_config->stage1.min_clk_index_for_latency > 0) {
35 copy_display_configuration_with_meta(params->optimized_display_config, params->display_config);
36 params->optimized_display_config->stage1.min_clk_index_for_latency--;
37 result = true;
38 }
39
40 return result;
41 }
42
dml2_top_optimization_test_function_mcache(const struct optimization_test_function_params * params)43 bool dml2_top_optimization_test_function_mcache(const struct optimization_test_function_params *params)
44 {
45 struct dml2_optimization_test_function_locals *l = params->locals;
46 bool mcache_success = false;
47 bool result = false;
48
49 memset(l, 0, sizeof(struct dml2_optimization_test_function_locals));
50
51 l->test_mcache.calc_mcache_count_params.dml2_instance = params->dml;
52 l->test_mcache.calc_mcache_count_params.display_config = ¶ms->display_config->display_config;
53 l->test_mcache.calc_mcache_count_params.mcache_allocations = params->display_config->stage2.mcache_allocations;
54
55 result = dml2_top_mcache_calc_mcache_count_and_offsets(&l->test_mcache.calc_mcache_count_params); // use core to get the basic mcache_allocations
56
57 if (result) {
58 l->test_mcache.assign_global_mcache_ids_params.allocations = params->display_config->stage2.mcache_allocations;
59 l->test_mcache.assign_global_mcache_ids_params.num_allocations = params->display_config->display_config.num_planes;
60
61 dml2_top_mcache_assign_global_mcache_ids(&l->test_mcache.assign_global_mcache_ids_params);
62
63 l->test_mcache.validate_admissibility_params.dml2_instance = params->dml;
64 l->test_mcache.validate_admissibility_params.display_cfg = ¶ms->display_config->display_config;
65 l->test_mcache.validate_admissibility_params.mcache_allocations = params->display_config->stage2.mcache_allocations;
66 l->test_mcache.validate_admissibility_params.cfg_support_info = ¶ms->display_config->mode_support_result.cfg_support_info;
67
68 mcache_success = dml2_top_mcache_validate_admissability(&l->test_mcache.validate_admissibility_params); // also find the shift to make mcache allocation works
69
70 memcpy(params->display_config->stage2.per_plane_mcache_support, l->test_mcache.validate_admissibility_params.per_plane_status, sizeof(bool) * DML2_MAX_PLANES);
71 }
72
73 return mcache_success;
74 }
75
dml2_top_optimization_optimize_function_mcache(const struct optimization_optimize_function_params * params)76 bool dml2_top_optimization_optimize_function_mcache(const struct optimization_optimize_function_params *params)
77 {
78 struct dml2_optimization_optimize_function_locals *l = params->locals;
79 bool optimize_success = false;
80
81 if (params->last_candidate_supported == false)
82 return false;
83
84 copy_display_configuration_with_meta(params->optimized_display_config, params->display_config);
85
86 l->optimize_mcache.optimize_mcache_params.instance = ¶ms->dml->pmo_instance;
87 l->optimize_mcache.optimize_mcache_params.dcc_mcache_supported = params->display_config->stage2.per_plane_mcache_support;
88 l->optimize_mcache.optimize_mcache_params.display_config = ¶ms->display_config->display_config;
89 l->optimize_mcache.optimize_mcache_params.optimized_display_cfg = ¶ms->optimized_display_config->display_config;
90 l->optimize_mcache.optimize_mcache_params.cfg_support_info = ¶ms->optimized_display_config->mode_support_result.cfg_support_info;
91
92 optimize_success = params->dml->pmo_instance.optimize_dcc_mcache(&l->optimize_mcache.optimize_mcache_params);
93
94 return optimize_success;
95 }
96
dml2_top_optimization_init_function_vmin(const struct optimization_init_function_params * params)97 bool dml2_top_optimization_init_function_vmin(const struct optimization_init_function_params *params)
98 {
99 struct dml2_optimization_init_function_locals *l = params->locals;
100
101 l->vmin.init_params.instance = ¶ms->dml->pmo_instance;
102 l->vmin.init_params.base_display_config = params->display_config;
103 return params->dml->pmo_instance.init_for_vmin(&l->vmin.init_params);
104 }
105
dml2_top_optimization_test_function_vmin(const struct optimization_test_function_params * params)106 bool dml2_top_optimization_test_function_vmin(const struct optimization_test_function_params *params)
107 {
108 struct dml2_optimization_test_function_locals *l = params->locals;
109
110 l->test_vmin.pmo_test_vmin_params.instance = ¶ms->dml->pmo_instance;
111 l->test_vmin.pmo_test_vmin_params.display_config = params->display_config;
112 l->test_vmin.pmo_test_vmin_params.vmin_limits = ¶ms->dml->soc_bbox.vmin_limit;
113 return params->dml->pmo_instance.test_for_vmin(&l->test_vmin.pmo_test_vmin_params);
114 }
115
dml2_top_optimization_optimize_function_vmin(const struct optimization_optimize_function_params * params)116 bool dml2_top_optimization_optimize_function_vmin(const struct optimization_optimize_function_params *params)
117 {
118 struct dml2_optimization_optimize_function_locals *l = params->locals;
119
120 if (params->last_candidate_supported == false)
121 return false;
122
123 l->optimize_vmin.pmo_optimize_vmin_params.instance = ¶ms->dml->pmo_instance;
124 l->optimize_vmin.pmo_optimize_vmin_params.base_display_config = params->display_config;
125 l->optimize_vmin.pmo_optimize_vmin_params.optimized_display_config = params->optimized_display_config;
126 return params->dml->pmo_instance.optimize_for_vmin(&l->optimize_vmin.pmo_optimize_vmin_params);
127 }
128
dml2_top_optimization_perform_optimization_phase(struct dml2_optimization_phase_locals * l,const struct optimization_phase_params * params)129 bool dml2_top_optimization_perform_optimization_phase(struct dml2_optimization_phase_locals *l, const struct optimization_phase_params *params)
130 {
131 bool test_passed = false;
132 bool optimize_succeeded = true;
133 bool candidate_validation_passed = true;
134 struct optimization_init_function_params init_params = { 0 };
135 struct optimization_test_function_params test_params = { 0 };
136 struct optimization_optimize_function_params optimize_params = { 0 };
137
138 if (!params->dml ||
139 !params->optimize_function ||
140 !params->test_function ||
141 !params->display_config ||
142 !params->optimized_display_config)
143 return false;
144
145 copy_display_configuration_with_meta(&l->cur_candidate_display_cfg, params->display_config);
146
147 init_params.locals = &l->init_function_locals;
148 init_params.dml = params->dml;
149 init_params.display_config = &l->cur_candidate_display_cfg;
150
151 if (params->init_function && !params->init_function(&init_params))
152 return false;
153
154 test_params.locals = &l->test_function_locals;
155 test_params.dml = params->dml;
156 test_params.display_config = &l->cur_candidate_display_cfg;
157
158 test_passed = params->test_function(&test_params);
159
160 while (!test_passed && optimize_succeeded) {
161 memset(&optimize_params, 0, sizeof(struct optimization_optimize_function_params));
162
163 optimize_params.locals = &l->optimize_function_locals;
164 optimize_params.dml = params->dml;
165 optimize_params.display_config = &l->cur_candidate_display_cfg;
166 optimize_params.optimized_display_config = &l->next_candidate_display_cfg;
167 optimize_params.last_candidate_supported = candidate_validation_passed;
168
169 optimize_succeeded = params->optimize_function(&optimize_params);
170
171 if (optimize_succeeded) {
172 l->mode_support_params.instance = ¶ms->dml->core_instance;
173 l->mode_support_params.display_cfg = &l->next_candidate_display_cfg;
174 l->mode_support_params.min_clk_table = ¶ms->dml->min_clk_table;
175
176 if (l->next_candidate_display_cfg.stage3.performed)
177 l->mode_support_params.min_clk_index = l->next_candidate_display_cfg.stage3.min_clk_index_for_latency;
178 else
179 l->mode_support_params.min_clk_index = l->next_candidate_display_cfg.stage1.min_clk_index_for_latency;
180
181 candidate_validation_passed = params->dml->core_instance.mode_support(&l->mode_support_params);
182
183 l->next_candidate_display_cfg.mode_support_result = l->mode_support_params.mode_support_result;
184 }
185
186 if (optimize_succeeded && candidate_validation_passed) {
187 memset(&test_params, 0, sizeof(struct optimization_test_function_params));
188 test_params.locals = &l->test_function_locals;
189 test_params.dml = params->dml;
190 test_params.display_config = &l->next_candidate_display_cfg;
191 test_passed = params->test_function(&test_params);
192
193 copy_display_configuration_with_meta(&l->cur_candidate_display_cfg, &l->next_candidate_display_cfg);
194
195 // If optimization is not all or nothing, then store partial progress in output
196 if (!params->all_or_nothing)
197 copy_display_configuration_with_meta(params->optimized_display_config, &l->next_candidate_display_cfg);
198 }
199 }
200
201 if (test_passed)
202 copy_display_configuration_with_meta(params->optimized_display_config, &l->cur_candidate_display_cfg);
203
204 return test_passed;
205 }
206
dml2_top_optimization_perform_optimization_phase_1(struct dml2_optimization_phase_locals * l,const struct optimization_phase_params * params)207 bool dml2_top_optimization_perform_optimization_phase_1(struct dml2_optimization_phase_locals *l, const struct optimization_phase_params *params)
208 {
209 int highest_state, lowest_state, cur_state;
210 bool supported = false;
211
212 if (!params->dml ||
213 !params->optimize_function ||
214 !params->test_function ||
215 !params->display_config ||
216 !params->optimized_display_config)
217 return false;
218
219 copy_display_configuration_with_meta(&l->cur_candidate_display_cfg, params->display_config);
220 highest_state = l->cur_candidate_display_cfg.stage1.min_clk_index_for_latency;
221 lowest_state = 0;
222
223 while (highest_state > lowest_state) {
224 cur_state = (highest_state + lowest_state) / 2;
225
226 l->mode_support_params.instance = ¶ms->dml->core_instance;
227 l->mode_support_params.display_cfg = &l->cur_candidate_display_cfg;
228 l->mode_support_params.min_clk_table = ¶ms->dml->min_clk_table;
229 l->mode_support_params.min_clk_index = cur_state;
230
231 supported = params->dml->core_instance.mode_support(&l->mode_support_params);
232
233 if (supported) {
234 l->cur_candidate_display_cfg.mode_support_result = l->mode_support_params.mode_support_result;
235 highest_state = cur_state;
236 } else {
237 lowest_state = cur_state + 1;
238 }
239 }
240 l->cur_candidate_display_cfg.stage1.min_clk_index_for_latency = lowest_state;
241
242 copy_display_configuration_with_meta(params->optimized_display_config, &l->cur_candidate_display_cfg);
243
244 return true;
245 }
246
dml2_top_optimization_init_function_uclk_pstate(const struct optimization_init_function_params * params)247 bool dml2_top_optimization_init_function_uclk_pstate(const struct optimization_init_function_params *params)
248 {
249 struct dml2_optimization_init_function_locals *l = params->locals;
250
251 l->uclk_pstate.init_params.instance = ¶ms->dml->pmo_instance;
252 l->uclk_pstate.init_params.base_display_config = params->display_config;
253
254 return params->dml->pmo_instance.init_for_uclk_pstate(&l->uclk_pstate.init_params);
255 }
256
dml2_top_optimization_test_function_uclk_pstate(const struct optimization_test_function_params * params)257 bool dml2_top_optimization_test_function_uclk_pstate(const struct optimization_test_function_params *params)
258 {
259 struct dml2_optimization_test_function_locals *l = params->locals;
260
261 l->uclk_pstate.test_params.instance = ¶ms->dml->pmo_instance;
262 l->uclk_pstate.test_params.base_display_config = params->display_config;
263
264 return params->dml->pmo_instance.test_for_uclk_pstate(&l->uclk_pstate.test_params);
265 }
266
dml2_top_optimization_optimize_function_uclk_pstate(const struct optimization_optimize_function_params * params)267 bool dml2_top_optimization_optimize_function_uclk_pstate(const struct optimization_optimize_function_params *params)
268 {
269 struct dml2_optimization_optimize_function_locals *l = params->locals;
270
271 l->uclk_pstate.optimize_params.instance = ¶ms->dml->pmo_instance;
272 l->uclk_pstate.optimize_params.base_display_config = params->display_config;
273 l->uclk_pstate.optimize_params.optimized_display_config = params->optimized_display_config;
274 l->uclk_pstate.optimize_params.last_candidate_failed = !params->last_candidate_supported;
275
276 return params->dml->pmo_instance.optimize_for_uclk_pstate(&l->uclk_pstate.optimize_params);
277 }
278
dml2_top_optimization_init_function_stutter(const struct optimization_init_function_params * params)279 bool dml2_top_optimization_init_function_stutter(const struct optimization_init_function_params *params)
280 {
281 struct dml2_optimization_init_function_locals *l = params->locals;
282
283 l->uclk_pstate.init_params.instance = ¶ms->dml->pmo_instance;
284 l->uclk_pstate.init_params.base_display_config = params->display_config;
285
286 return params->dml->pmo_instance.init_for_stutter(&l->stutter.stutter_params);
287 }
288
dml2_top_optimization_test_function_stutter(const struct optimization_test_function_params * params)289 bool dml2_top_optimization_test_function_stutter(const struct optimization_test_function_params *params)
290 {
291 struct dml2_optimization_test_function_locals *l = params->locals;
292
293 l->stutter.stutter_params.instance = ¶ms->dml->pmo_instance;
294 l->stutter.stutter_params.base_display_config = params->display_config;
295 return params->dml->pmo_instance.test_for_stutter(&l->stutter.stutter_params);
296 }
297
dml2_top_optimization_optimize_function_stutter(const struct optimization_optimize_function_params * params)298 bool dml2_top_optimization_optimize_function_stutter(const struct optimization_optimize_function_params *params)
299 {
300 struct dml2_optimization_optimize_function_locals *l = params->locals;
301
302 l->stutter.stutter_params.instance = ¶ms->dml->pmo_instance;
303 l->stutter.stutter_params.base_display_config = params->display_config;
304 l->stutter.stutter_params.optimized_display_config = params->optimized_display_config;
305 l->stutter.stutter_params.last_candidate_failed = !params->last_candidate_supported;
306 return params->dml->pmo_instance.optimize_for_stutter(&l->stutter.stutter_params);
307 }
308