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 = &params->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 = &params->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 = &params->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 = &params->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 = &params->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 = &params->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 = &params->display_config->display_config;
89 	l->optimize_mcache.optimize_mcache_params.optimized_display_cfg = &params->optimized_display_config->display_config;
90 	l->optimize_mcache.optimize_mcache_params.cfg_support_info = &params->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 = &params->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 = &params->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 = &params->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 = &params->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 = &params->dml->core_instance;
173 			l->mode_support_params.display_cfg = &l->next_candidate_display_cfg;
174 			l->mode_support_params.min_clk_table = &params->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 = &params->dml->core_instance;
227 		l->mode_support_params.display_cfg = &l->cur_candidate_display_cfg;
228 		l->mode_support_params.min_clk_table = &params->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 = &params->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 = &params->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 = &params->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 = &params->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 = &params->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 = &params->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