1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4 
5 
6 #include "dml21_wrapper.h"
7 #include "dml2_core_dcn4_calcs.h"
8 #include "dml2_internal_shared_types.h"
9 #include "dml2_internal_types.h"
10 #include "dml21_utils.h"
11 #include "dml21_translation_helper.h"
12 #include "bounding_boxes/dcn4_soc_bb.h"
13 #include "bounding_boxes/dcn3_soc_bb.h"
14 
dml21_init_socbb_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)15 static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_init,
16 		const struct dml2_configuration_options *config,
17 		const struct dc *in_dc)
18 {
19 	const struct dml2_soc_bb *soc_bb;
20 	const struct dml2_soc_qos_parameters *qos_params;
21 
22 	switch (in_dc->ctx->dce_version) {
23 	case DCN_VERSION_3_2:	// TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
24 		soc_bb = &dml2_socbb_dcn31;
25 		qos_params = &dml_dcn31_soc_qos_params;
26 		break;
27 	case DCN_VERSION_4_01:
28 	default:
29 		if (config->bb_from_dmub)
30 			soc_bb = config->bb_from_dmub;
31 		else
32 			soc_bb = &dml2_socbb_dcn401;
33 
34 		qos_params = &dml_dcn4_variant_a_soc_qos_params;
35 	}
36 
37 	/* patch soc bb */
38 	memcpy(&dml_init->soc_bb, soc_bb, sizeof(struct dml2_soc_bb));
39 
40 	/* patch qos params */
41 	memcpy(&dml_init->soc_bb.qos_parameters, qos_params, sizeof(struct dml2_soc_qos_parameters));
42 }
43 
dml21_external_socbb_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config)44 static void dml21_external_socbb_params(struct dml2_initialize_instance_in_out *dml_init,
45 		const struct dml2_configuration_options *config)
46 {
47 	memcpy(&dml_init->soc_bb, &config->external_socbb_ip_params->soc_bb, sizeof(struct dml2_soc_bb));
48 }
49 
dml21_external_ip_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config)50 static void dml21_external_ip_params(struct dml2_initialize_instance_in_out *dml_init,
51 		const struct dml2_configuration_options *config)
52 {
53 	memcpy(&dml_init->ip_caps, &config->external_socbb_ip_params->ip_params, sizeof(struct dml2_ip_capabilities));
54 }
55 
dml21_init_ip_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)56 static void dml21_init_ip_params(struct dml2_initialize_instance_in_out *dml_init,
57 		const struct dml2_configuration_options *config,
58 		const struct dc *in_dc)
59 {
60 	const struct dml2_ip_capabilities *ip_caps;
61 
62 	switch (in_dc->ctx->dce_version) {
63 	case DCN_VERSION_3_2:	// TODO : Temporary for N-1 validation. Remove this after N-1 validation phase is complete.
64 		ip_caps = &dml2_dcn31_max_ip_caps;
65 		break;
66 	case DCN_VERSION_4_01:
67 	default:
68 		ip_caps = &dml2_dcn401_max_ip_caps;
69 	}
70 
71 	memcpy(&dml_init->ip_caps, ip_caps, sizeof(struct dml2_ip_capabilities));
72 }
73 
dml21_initialize_soc_bb_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)74 void dml21_initialize_soc_bb_params(struct dml2_initialize_instance_in_out *dml_init,
75 		const struct dml2_configuration_options *config,
76 		const struct dc *in_dc)
77 {
78 	if (config->use_native_soc_bb_construction)
79 		dml21_init_socbb_params(dml_init, config, in_dc);
80 	else
81 		dml21_external_socbb_params(dml_init, config);
82 }
83 
dml21_initialize_ip_params(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)84 void dml21_initialize_ip_params(struct dml2_initialize_instance_in_out *dml_init,
85 		const struct dml2_configuration_options *config,
86 		const struct dc *in_dc)
87 {
88 	if (config->use_native_soc_bb_construction)
89 		dml21_init_ip_params(dml_init, config, in_dc);
90 	else
91 		dml21_external_ip_params(dml_init, config);
92 }
93 
dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out * dml_init,const struct dml2_configuration_options * config,const struct dc * in_dc)94 void dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out *dml_init,
95 		const struct dml2_configuration_options *config, const struct dc *in_dc)
96 {
97 	int i;
98 
99 	const struct clk_bw_params *dc_bw_params = in_dc->clk_mgr->bw_params;
100 	const struct clk_limit_table *dc_clk_table = &dc_bw_params->clk_table;
101 	struct dml2_soc_bb *dml_soc_bb = &dml_init->soc_bb;
102 	struct dml2_soc_state_table *dml_clk_table = &dml_soc_bb->clk_table;
103 
104 	/* override clocks if smu is present */
105 	if (in_dc->clk_mgr->funcs->is_smu_present && in_dc->clk_mgr->funcs->is_smu_present(in_dc->clk_mgr)) {
106 		/* dcfclk */
107 		if (dc_clk_table->num_entries_per_clk.num_dcfclk_levels) {
108 			dml_clk_table->dcfclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dcfclk_levels;
109 			for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
110 				if (i < dml_clk_table->dcfclk.num_clk_values) {
111 					if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dcfclk_mhz &&
112 							dc_clk_table->entries[i].dcfclk_mhz > dc_bw_params->dc_mode_limit.dcfclk_mhz) {
113 						if (i == 0 || dc_clk_table->entries[i-1].dcfclk_mhz < dc_bw_params->dc_mode_limit.dcfclk_mhz) {
114 							dml_clk_table->dcfclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dcfclk_mhz * 1000;
115 							dml_clk_table->dcfclk.num_clk_values = i + 1;
116 						} else {
117 							dml_clk_table->dcfclk.clk_values_khz[i] = 0;
118 							dml_clk_table->dcfclk.num_clk_values = i;
119 						}
120 					} else {
121 						dml_clk_table->dcfclk.clk_values_khz[i] = dc_clk_table->entries[i].dcfclk_mhz * 1000;
122 					}
123 				} else {
124 					dml_clk_table->dcfclk.clk_values_khz[i] = 0;
125 				}
126 			}
127 		}
128 
129 		/* fclk */
130 		if (dc_clk_table->num_entries_per_clk.num_fclk_levels) {
131 			dml_clk_table->fclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_fclk_levels;
132 			for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
133 				if (i < dml_clk_table->fclk.num_clk_values) {
134 					if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.fclk_mhz &&
135 							dc_clk_table->entries[i].fclk_mhz > dc_bw_params->dc_mode_limit.fclk_mhz) {
136 						if (i == 0 || dc_clk_table->entries[i-1].fclk_mhz < dc_bw_params->dc_mode_limit.fclk_mhz) {
137 							dml_clk_table->fclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.fclk_mhz * 1000;
138 							dml_clk_table->fclk.num_clk_values = i + 1;
139 						} else {
140 							dml_clk_table->fclk.clk_values_khz[i] = 0;
141 							dml_clk_table->fclk.num_clk_values = i;
142 						}
143 					} else {
144 						dml_clk_table->fclk.clk_values_khz[i] = dc_clk_table->entries[i].fclk_mhz * 1000;
145 					}
146 				} else {
147 					dml_clk_table->fclk.clk_values_khz[i] = 0;
148 				}
149 			}
150 		}
151 
152 		/* uclk */
153 		if (dc_clk_table->num_entries_per_clk.num_memclk_levels) {
154 			dml_clk_table->uclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_memclk_levels;
155 			for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
156 				if (i < dml_clk_table->uclk.num_clk_values) {
157 					if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.memclk_mhz &&
158 							dc_clk_table->entries[i].memclk_mhz > dc_bw_params->dc_mode_limit.memclk_mhz) {
159 						if (i == 0 || dc_clk_table->entries[i-1].memclk_mhz < dc_bw_params->dc_mode_limit.memclk_mhz) {
160 							dml_clk_table->uclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.memclk_mhz * 1000;
161 							dml_clk_table->uclk.num_clk_values = i + 1;
162 						} else {
163 							dml_clk_table->uclk.clk_values_khz[i] = 0;
164 							dml_clk_table->uclk.num_clk_values = i;
165 						}
166 					} else {
167 						dml_clk_table->uclk.clk_values_khz[i] = dc_clk_table->entries[i].memclk_mhz * 1000;
168 					}
169 				} else {
170 					dml_clk_table->uclk.clk_values_khz[i] = 0;
171 				}
172 			}
173 		}
174 
175 		/* dispclk */
176 		if (dc_clk_table->num_entries_per_clk.num_dispclk_levels) {
177 			dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels;
178 			for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
179 				if (i < dml_clk_table->dispclk.num_clk_values) {
180 					if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dispclk_mhz &&
181 							dc_clk_table->entries[i].dispclk_mhz > dc_bw_params->dc_mode_limit.dispclk_mhz) {
182 						if (i == 0 || dc_clk_table->entries[i-1].dispclk_mhz < dc_bw_params->dc_mode_limit.dispclk_mhz) {
183 							dml_clk_table->dispclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dispclk_mhz * 1000;
184 							dml_clk_table->dispclk.num_clk_values = i + 1;
185 						} else {
186 							dml_clk_table->dispclk.clk_values_khz[i] = 0;
187 							dml_clk_table->dispclk.num_clk_values = i;
188 						}
189 					} else {
190 						dml_clk_table->dispclk.clk_values_khz[i] = dc_clk_table->entries[i].dispclk_mhz * 1000;
191 					}
192 				} else {
193 					dml_clk_table->dispclk.clk_values_khz[i] = 0;
194 				}
195 			}
196 		}
197 
198 		/* dppclk */
199 		if (dc_clk_table->num_entries_per_clk.num_dppclk_levels) {
200 			dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels;
201 			for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
202 				if (i < dml_clk_table->dppclk.num_clk_values) {
203 					if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dppclk_mhz &&
204 							dc_clk_table->entries[i].dppclk_mhz > dc_bw_params->dc_mode_limit.dppclk_mhz) {
205 						if (i == 0 || dc_clk_table->entries[i-1].dppclk_mhz < dc_bw_params->dc_mode_limit.dppclk_mhz) {
206 							dml_clk_table->dppclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dppclk_mhz * 1000;
207 							dml_clk_table->dppclk.num_clk_values = i + 1;
208 						} else {
209 							dml_clk_table->dppclk.clk_values_khz[i] = 0;
210 							dml_clk_table->dppclk.num_clk_values = i;
211 						}
212 					} else {
213 						dml_clk_table->dppclk.clk_values_khz[i] = dc_clk_table->entries[i].dppclk_mhz * 1000;
214 					}
215 				} else {
216 					dml_clk_table->dppclk.clk_values_khz[i] = 0;
217 				}
218 			}
219 		}
220 
221 		/* dtbclk */
222 		if (dc_clk_table->num_entries_per_clk.num_dtbclk_levels) {
223 			dml_clk_table->dtbclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dtbclk_levels;
224 			for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
225 				if (i < dml_clk_table->dtbclk.num_clk_values) {
226 					if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.dtbclk_mhz &&
227 							dc_clk_table->entries[i].dtbclk_mhz > dc_bw_params->dc_mode_limit.dtbclk_mhz) {
228 						if (i == 0 || dc_clk_table->entries[i-1].dtbclk_mhz < dc_bw_params->dc_mode_limit.dtbclk_mhz) {
229 							dml_clk_table->dtbclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.dtbclk_mhz * 1000;
230 							dml_clk_table->dtbclk.num_clk_values = i + 1;
231 						} else {
232 							dml_clk_table->dtbclk.clk_values_khz[i] = 0;
233 							dml_clk_table->dtbclk.num_clk_values = i;
234 						}
235 					} else {
236 						dml_clk_table->dtbclk.clk_values_khz[i] = dc_clk_table->entries[i].dtbclk_mhz * 1000;
237 					}
238 				} else {
239 					dml_clk_table->dtbclk.clk_values_khz[i] = 0;
240 				}
241 			}
242 		}
243 
244 		/* socclk */
245 		if (dc_clk_table->num_entries_per_clk.num_socclk_levels) {
246 			dml_clk_table->socclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_socclk_levels;
247 			for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
248 				if (i < dml_clk_table->socclk.num_clk_values) {
249 					if (config->use_clock_dc_limits && dc_bw_params->dc_mode_limit.socclk_mhz &&
250 							dc_clk_table->entries[i].socclk_mhz > dc_bw_params->dc_mode_limit.socclk_mhz) {
251 						if (i == 0 || dc_clk_table->entries[i-1].socclk_mhz < dc_bw_params->dc_mode_limit.socclk_mhz) {
252 							dml_clk_table->socclk.clk_values_khz[i] = dc_bw_params->dc_mode_limit.socclk_mhz * 1000;
253 							dml_clk_table->socclk.num_clk_values = i + 1;
254 						} else {
255 							dml_clk_table->socclk.clk_values_khz[i] = 0;
256 							dml_clk_table->socclk.num_clk_values = i;
257 						}
258 					} else {
259 						dml_clk_table->socclk.clk_values_khz[i] = dc_clk_table->entries[i].socclk_mhz * 1000;
260 					}
261 				} else {
262 					dml_clk_table->socclk.clk_values_khz[i] = 0;
263 				}
264 			}
265 		}
266 
267 		/* do not override phyclks for now */
268 		/* phyclk */
269 		// dml_clk_table->phyclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_phyclk_levels;
270 		// for (i = 0; i < DML_MAX_CLK_TABLE_SIZE; i++) {
271 		// 	dml_clk_table->phyclk.clk_values_khz[i] = dc_clk_table->entries[i].phyclk_mhz * 1000;
272 		// }
273 
274 		/* phyclk_d18 */
275 		// dml_clk_table->phyclk_d18.num_clk_values = dc_clk_table->num_entries_per_clk.num_phyclk_d18_levels;
276 		// for (i = 0; i < DML_MAX_CLK_TABLE_SIZE; i++) {
277 		// 	dml_clk_table->phyclk_d18.clk_values_khz[i] = dc_clk_table->entries[i].phyclk_d18_mhz * 1000;
278 		// }
279 
280 		/* phyclk_d32 */
281 		// dml_clk_table->phyclk_d32.num_clk_values = dc_clk_table->num_entries_per_clk.num_phyclk_d32_levels;
282 		// for (i = 0; i < DML_MAX_CLK_TABLE_SIZE; i++) {
283 		// 	dml_clk_table->phyclk_d32.clk_values_khz[i] = dc_clk_table->entries[i].phyclk_d32_mhz * 1000;
284 		// }
285 	}
286 
287 	dml_soc_bb->dchub_refclk_mhz = in_dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
288 	dml_soc_bb->dprefclk_mhz = in_dc->clk_mgr->dprefclk_khz / 1000;
289 	dml_soc_bb->xtalclk_mhz = in_dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency / 1000;
290 	dml_soc_bb->dispclk_dppclk_vco_speed_mhz = in_dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
291 
292 	/* override bounding box paramters from VBIOS */
293 	if (in_dc->ctx->dc_bios->bb_info.dram_clock_change_latency_100ns > 0)
294 		dml_soc_bb->power_management_parameters.dram_clk_change_blackout_us =
295 				(in_dc->ctx->dc_bios->bb_info.dram_clock_change_latency_100ns + 9) / 10;
296 
297 	if (in_dc->ctx->dc_bios->bb_info.dram_sr_enter_exit_latency_100ns > 0)
298 		dml_soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us =
299 				(in_dc->ctx->dc_bios->bb_info.dram_sr_enter_exit_latency_100ns + 9) / 10;
300 
301 	if (in_dc->ctx->dc_bios->bb_info.dram_sr_exit_latency_100ns > 0)
302 		dml_soc_bb->power_management_parameters.stutter_exit_latency_us =
303 			(in_dc->ctx->dc_bios->bb_info.dram_sr_exit_latency_100ns + 9) / 10;
304 
305 	if (in_dc->ctx->dc_bios->vram_info.num_chans) {
306 		dml_clk_table->dram_config.channel_count = in_dc->ctx->dc_bios->vram_info.num_chans;
307 		dml_soc_bb->mall_allocated_for_dcn_mbytes = in_dc->caps.mall_size_total / 1048576;
308 	}
309 
310 	if (in_dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) {
311 		dml_clk_table->dram_config.channel_width_bytes = in_dc->ctx->dc_bios->vram_info.dram_channel_width_bytes;
312 	}
313 
314 	/* override bounding box paramters from DC config */
315 	if (in_dc->bb_overrides.sr_exit_time_ns) {
316 		dml_soc_bb->power_management_parameters.stutter_exit_latency_us =
317 				in_dc->bb_overrides.sr_exit_time_ns / 1000.0;
318 	}
319 
320 	if (in_dc->bb_overrides.sr_enter_plus_exit_time_ns) {
321 		dml_soc_bb->power_management_parameters.stutter_enter_plus_exit_latency_us =
322 				in_dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
323 	}
324 
325 	if (in_dc->bb_overrides.dram_clock_change_latency_ns) {
326 		dml_soc_bb->power_management_parameters.dram_clk_change_blackout_us =
327 				in_dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
328 	}
329 
330 	if (in_dc->bb_overrides.fclk_clock_change_latency_ns) {
331 		dml_soc_bb->power_management_parameters.fclk_change_blackout_us =
332 				in_dc->bb_overrides.fclk_clock_change_latency_ns / 1000.0;
333 	}
334 
335 	//TODO
336 	// if (in_dc->bb_overrides.dummy_clock_change_latency_ns) {
337 	// 	dml_soc_bb->power_management_parameters.dram_clk_change_blackout_us =
338 	// 			in_dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
339 	// }
340 }
341 
populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg * timing,struct dc_stream_state * stream,struct dml2_context * dml_ctx)342 static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing,
343 		struct dc_stream_state *stream,
344 		struct dml2_context *dml_ctx)
345 {
346 	unsigned int hblank_start, vblank_start;
347 
348 	timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
349 	timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
350 	timing->h_front_porch = stream->timing.h_front_porch;
351 	timing->v_front_porch = stream->timing.v_front_porch;
352 	timing->pixel_clock_khz = stream->timing.pix_clk_100hz / 10;
353 	if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
354 		timing->pixel_clock_khz *= 2;
355 	timing->h_total = stream->timing.h_total;
356 	timing->v_total = stream->timing.v_total;
357 	timing->h_sync_width = stream->timing.h_sync_width;
358 	timing->interlaced = stream->timing.flags.INTERLACE;
359 
360 	hblank_start = stream->timing.h_total - stream->timing.h_front_porch;
361 
362 	timing->h_blank_end = hblank_start - stream->timing.h_addressable
363 		- stream->timing.h_border_left - stream->timing.h_border_right;
364 
365 	if (hblank_start < stream->timing.h_addressable)
366 		timing->h_blank_end = 0;
367 
368 	vblank_start = stream->timing.v_total - stream->timing.v_front_porch;
369 
370 	timing->v_blank_end = vblank_start - stream->timing.v_addressable
371 		- stream->timing.v_border_top - stream->timing.v_border_bottom;
372 
373 	timing->drr_config.enabled = stream->ignore_msa_timing_param;
374 	timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
375 	timing->drr_config.drr_active_variable = stream->vrr_active_variable;
376 	timing->drr_config.drr_active_fixed = stream->vrr_active_fixed;
377 	timing->drr_config.disallowed = !stream->allow_freesync;
378 
379 	if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
380 			stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
381 		timing->drr_config.max_instant_vtotal_delta = dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase(stream, false);
382 	else
383 		timing->drr_config.max_instant_vtotal_delta = 0;
384 
385 	if (stream->timing.flags.DSC) {
386 		timing->dsc.enable = dml2_dsc_enable;
387 		timing->dsc.overrides.num_slices = stream->timing.dsc_cfg.num_slices_h;
388 		timing->dsc.dsc_compressed_bpp_x16 = stream->timing.dsc_cfg.bits_per_pixel;
389 	} else
390 		timing->dsc.enable = dml2_dsc_disable;
391 
392 	switch (stream->timing.display_color_depth) {
393 	case COLOR_DEPTH_666:
394 		timing->bpc = 6;
395 		break;
396 	case COLOR_DEPTH_888:
397 		timing->bpc = 8;
398 		break;
399 	case COLOR_DEPTH_101010:
400 		timing->bpc = 10;
401 		break;
402 	case COLOR_DEPTH_121212:
403 		timing->bpc = 12;
404 		break;
405 	case COLOR_DEPTH_141414:
406 		timing->bpc = 14;
407 		break;
408 	case COLOR_DEPTH_161616:
409 		timing->bpc = 16;
410 		break;
411 	case COLOR_DEPTH_999:
412 		timing->bpc = 9;
413 		break;
414 	case COLOR_DEPTH_111111:
415 		timing->bpc = 11;
416 		break;
417 	default:
418 		timing->bpc = 8;
419 		break;
420 	}
421 
422 	timing->vblank_nom = timing->v_total - timing->v_active;
423 }
424 
populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg * output,struct dc_stream_state * stream,const struct pipe_ctx * pipe)425 static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output,
426 		struct dc_stream_state *stream, const struct pipe_ctx *pipe)
427 {
428 	output->output_dp_lane_count = 4;
429 
430 	switch (stream->signal) {
431 	case SIGNAL_TYPE_DISPLAY_PORT_MST:
432 	case SIGNAL_TYPE_DISPLAY_PORT:
433 		output->output_encoder = dml2_dp;
434 		if (check_dp2p0_output_encoder(pipe))
435 			output->output_encoder = dml2_dp2p0;
436 		break;
437 	case SIGNAL_TYPE_EDP:
438 		output->output_encoder = dml2_edp;
439 		break;
440 	case SIGNAL_TYPE_HDMI_TYPE_A:
441 	case SIGNAL_TYPE_DVI_SINGLE_LINK:
442 	case SIGNAL_TYPE_DVI_DUAL_LINK:
443 		output->output_encoder = dml2_hdmi;
444 		break;
445 	default:
446 			output->output_encoder = dml2_dp;
447 	}
448 
449 	switch (stream->timing.pixel_encoding) {
450 	case PIXEL_ENCODING_RGB:
451 	case PIXEL_ENCODING_YCBCR444:
452 		output->output_format = dml2_444;
453 		break;
454 	case PIXEL_ENCODING_YCBCR420:
455 		output->output_format = dml2_420;
456 		break;
457 	case PIXEL_ENCODING_YCBCR422:
458 		if (stream->timing.flags.DSC && !stream->timing.dsc_cfg.ycbcr422_simple)
459 			output->output_format = dml2_n422;
460 		else
461 			output->output_format = dml2_s422;
462 		break;
463 	default:
464 		output->output_format = dml2_444;
465 		break;
466 	}
467 
468 	switch (stream->signal) {
469 	case SIGNAL_TYPE_NONE:
470 	case SIGNAL_TYPE_DVI_SINGLE_LINK:
471 	case SIGNAL_TYPE_DVI_DUAL_LINK:
472 	case SIGNAL_TYPE_HDMI_TYPE_A:
473 	case SIGNAL_TYPE_LVDS:
474 	case SIGNAL_TYPE_RGB:
475 	case SIGNAL_TYPE_DISPLAY_PORT:
476 	case SIGNAL_TYPE_DISPLAY_PORT_MST:
477 	case SIGNAL_TYPE_EDP:
478 	case SIGNAL_TYPE_VIRTUAL:
479 	default:
480 		output->output_dp_link_rate = dml2_dp_rate_na;
481 		break;
482 	}
483 
484 	output->audio_sample_layout = stream->audio_info.modes->sample_size;
485 	output->audio_sample_rate = stream->audio_info.modes->max_bit_rate;
486 	output->output_disabled = true;
487 
488 	//TODO : New to DML2.1. How do we populate this ?
489 	// output->validate_output
490 }
491 
populate_dml21_stream_overrides_from_stream_state(struct dml2_stream_parameters * stream_desc,struct dc_stream_state * stream)492 static void populate_dml21_stream_overrides_from_stream_state(
493 		struct dml2_stream_parameters *stream_desc,
494 		struct dc_stream_state *stream)
495 {
496 	switch (stream->debug.force_odm_combine_segments) {
497 	case 0:
498 		stream_desc->overrides.odm_mode = dml2_odm_mode_auto;
499 		break;
500 	case 1:
501 		stream_desc->overrides.odm_mode = dml2_odm_mode_bypass;
502 		break;
503 	case 2:
504 		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_2to1;
505 		break;
506 	case 3:
507 		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_3to1;
508 		break;
509 	case 4:
510 		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_4to1;
511 		break;
512 	default:
513 		stream_desc->overrides.odm_mode =  dml2_odm_mode_auto;
514 		break;
515 	}
516 	if (!stream->ctx->dc->debug.enable_single_display_2to1_odm_policy ||
517 			stream->debug.force_odm_combine_segments > 0)
518 		stream_desc->overrides.disable_dynamic_odm = true;
519 	stream_desc->overrides.disable_subvp = stream->ctx->dc->debug.force_disable_subvp || stream->hw_cursor_req;
520 }
521 
gfx_addr3_to_dml2_swizzle_mode(enum swizzle_mode_addr3_values addr3_mode)522 static enum dml2_swizzle_mode gfx_addr3_to_dml2_swizzle_mode(enum swizzle_mode_addr3_values addr3_mode)
523 {
524 	enum dml2_swizzle_mode dml2_mode = dml2_sw_linear;
525 
526 	switch (addr3_mode) {
527 	case DC_ADDR3_SW_LINEAR:
528 		dml2_mode = dml2_sw_linear;
529 		break;
530 	case DC_ADDR3_SW_256B_2D:
531 		dml2_mode = dml2_sw_256b_2d;
532 		break;
533 	case DC_ADDR3_SW_4KB_2D:
534 		dml2_mode = dml2_sw_4kb_2d;
535 		break;
536 	case DC_ADDR3_SW_64KB_2D:
537 		dml2_mode = dml2_sw_64kb_2d;
538 		break;
539 	case DC_ADDR3_SW_256KB_2D:
540 		dml2_mode = dml2_sw_256kb_2d;
541 		break;
542 	default:
543 		/* invalid swizzle mode for DML2.1 */
544 		ASSERT(false);
545 		dml2_mode = dml2_sw_linear;
546 	}
547 
548 	return dml2_mode;
549 }
550 
gfx9_to_dml2_swizzle_mode(enum swizzle_mode_values gfx9_mode)551 static enum dml2_swizzle_mode gfx9_to_dml2_swizzle_mode(enum swizzle_mode_values gfx9_mode)
552 {
553 	enum dml2_swizzle_mode dml2_mode = dml2_sw_64kb_2d;
554 
555 	switch (gfx9_mode) {
556 	case DC_SW_LINEAR:
557 		dml2_mode = dml2_sw_linear;
558 		break;
559 	case DC_SW_256_D:
560 	case DC_SW_256_R:
561 		dml2_mode = dml2_sw_256b_2d;
562 		break;
563 	case DC_SW_4KB_D:
564 	case DC_SW_4KB_R:
565 	case DC_SW_4KB_R_X:
566 		dml2_mode = dml2_sw_4kb_2d;
567 		break;
568 	case DC_SW_64KB_D:
569 	case DC_SW_64KB_D_X:
570 	case DC_SW_64KB_R:
571 	case DC_SW_64KB_R_X:
572 		dml2_mode = dml2_sw_64kb_2d;
573 		break;
574 	case DC_SW_256B_S:
575 	case DC_SW_4KB_S:
576 	case DC_SW_64KB_S:
577 	case DC_SW_VAR_S:
578 	case DC_SW_VAR_D:
579 	case DC_SW_VAR_R:
580 	case DC_SW_64KB_S_T:
581 	case DC_SW_64KB_D_T:
582 	case DC_SW_4KB_S_X:
583 	case DC_SW_4KB_D_X:
584 	case DC_SW_64KB_S_X:
585 	case DC_SW_VAR_S_X:
586 	case DC_SW_VAR_D_X:
587 	case DC_SW_VAR_R_X:
588 	default:
589 		/*
590 		 * invalid swizzle mode for DML2.1. This could happen because
591 		 * DML21 is not intended to be used by N-1 in production. To
592 		 * properly filter out unsupported swizzle modes, we will need
593 		 * to fix capability reporting when DML2.1 is used for N-1 in
594 		 * dc. So DML will only receive DML21 supported swizzle modes.
595 		 * This implementation is not added and has a low value because
596 		 * the supported swizzle modes should already cover most of our
597 		 * N-1 test cases.
598 		 */
599 		return dml2_sw_64kb_2d;
600 	}
601 
602 	return dml2_mode;
603 }
604 
populate_dml21_dummy_surface_cfg(struct dml2_surface_cfg * surface,const struct dc_stream_state * stream)605 static void populate_dml21_dummy_surface_cfg(struct dml2_surface_cfg *surface, const struct dc_stream_state *stream)
606 {
607 	surface->plane0.width = stream->timing.h_addressable;
608 	surface->plane0.height = stream->timing.v_addressable;
609 	surface->plane1.width = stream->timing.h_addressable;
610 	surface->plane1.height = stream->timing.v_addressable;
611 	surface->plane0.pitch = ((surface->plane0.width + 127) / 128) * 128;
612 	surface->plane1.pitch = 0;
613 	surface->dcc.enable = false;
614 	surface->dcc.informative.dcc_rate_plane0 = 1.0;
615 	surface->dcc.informative.dcc_rate_plane1 = 1.0;
616 	surface->dcc.informative.fraction_of_zero_size_request_plane0 = 0;
617 	surface->dcc.informative.fraction_of_zero_size_request_plane1 = 0;
618 	surface->tiling = dml2_sw_64kb_2d;
619 }
620 
populate_dml21_dummy_plane_cfg(struct dml2_plane_parameters * plane,const struct dc_stream_state * stream)621 static void populate_dml21_dummy_plane_cfg(struct dml2_plane_parameters *plane, const struct dc_stream_state *stream)
622 {
623 	unsigned int width, height;
624 
625 	if (stream->timing.h_addressable > 3840)
626 		width = 3840;
627 	else
628 		width = stream->timing.h_addressable;	// 4K max
629 
630 	if (stream->timing.v_addressable > 2160)
631 		height = 2160;
632 	else
633 		height = stream->timing.v_addressable;	// 4K max
634 
635 	plane->cursor.cursor_bpp = 32;
636 
637 	plane->cursor.cursor_width = 256;
638 	plane->cursor.num_cursors = 1;
639 
640 	plane->composition.viewport.plane0.width = width;
641 	plane->composition.viewport.plane0.height = height;
642 	plane->composition.viewport.plane1.width = 0;
643 	plane->composition.viewport.plane1.height = 0;
644 
645 	plane->composition.viewport.stationary = false;
646 	plane->composition.viewport.plane0.x_start = 0;
647 	plane->composition.viewport.plane0.y_start = 0;
648 	plane->composition.viewport.plane1.x_start = 0;
649 	plane->composition.viewport.plane1.y_start = 0;
650 
651 	plane->composition.scaler_info.enabled = false;
652 	plane->composition.rotation_angle = dml2_rotation_0;
653 	plane->composition.scaler_info.plane0.h_ratio = 1.0;
654 	plane->composition.scaler_info.plane0.v_ratio = 1.0;
655 	plane->composition.scaler_info.plane1.h_ratio = 0;
656 	plane->composition.scaler_info.plane1.v_ratio = 0;
657 	plane->composition.scaler_info.plane0.h_taps = 1;
658 	plane->composition.scaler_info.plane0.v_taps = 1;
659 	plane->composition.scaler_info.plane1.h_taps = 0;
660 	plane->composition.scaler_info.plane1.v_taps = 0;
661 	plane->composition.scaler_info.rect_out_width = width;
662 	plane->pixel_format = dml2_444_32;
663 
664 	plane->dynamic_meta_data.enable = false;
665 	plane->overrides.gpuvm_min_page_size_kbytes = 256;
666 }
667 
populate_dml21_surface_config_from_plane_state(const struct dc * in_dc,struct dml2_surface_cfg * surface,const struct dc_plane_state * plane_state)668 static void populate_dml21_surface_config_from_plane_state(
669 		const struct dc *in_dc,
670 		struct dml2_surface_cfg *surface,
671 		const struct dc_plane_state *plane_state)
672 {
673 	surface->plane0.pitch = plane_state->plane_size.surface_pitch;
674 	surface->plane1.pitch = plane_state->plane_size.chroma_pitch;
675 	surface->plane0.height = plane_state->plane_size.surface_size.height;
676 	surface->plane0.width = plane_state->plane_size.surface_size.width;
677 	surface->plane1.height = plane_state->plane_size.chroma_size.height;
678 	surface->plane1.width = plane_state->plane_size.chroma_size.width;
679 	surface->dcc.enable = plane_state->dcc.enable;
680 	surface->dcc.informative.dcc_rate_plane0 = 1.0;
681 	surface->dcc.informative.dcc_rate_plane1 = 1.0;
682 	surface->dcc.informative.fraction_of_zero_size_request_plane0 = plane_state->dcc.independent_64b_blks;
683 	surface->dcc.informative.fraction_of_zero_size_request_plane1 = plane_state->dcc.independent_64b_blks_c;
684 	surface->dcc.plane0.pitch = plane_state->dcc.meta_pitch;
685 	surface->dcc.plane1.pitch = plane_state->dcc.meta_pitch_c;
686 	if (in_dc->ctx->dce_version < DCN_VERSION_4_01) {
687 		/* needed for N-1 testing */
688 		surface->tiling = gfx9_to_dml2_swizzle_mode(plane_state->tiling_info.gfx9.swizzle);
689 	} else {
690 		surface->tiling = gfx_addr3_to_dml2_swizzle_mode(plane_state->tiling_info.gfx_addr3.swizzle);
691 	}
692 }
693 
get_scaler_data_for_plane(struct dml2_context * dml_ctx,const struct dc_plane_state * in,const struct dc_state * context)694 static const struct scaler_data *get_scaler_data_for_plane(
695 		struct dml2_context *dml_ctx,
696 		const struct dc_plane_state *in,
697 		const struct dc_state *context)
698 {
699 	int i;
700 	struct pipe_ctx *temp_pipe = &dml_ctx->v21.scratch.temp_pipe;
701 
702 	memset(temp_pipe, 0, sizeof(struct pipe_ctx));
703 
704 	for (i = 0; i < MAX_PIPES; i++)	{
705 		const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
706 
707 		if (pipe->plane_state == in && !pipe->prev_odm_pipe) {
708 			temp_pipe->stream = pipe->stream;
709 			temp_pipe->plane_state = pipe->plane_state;
710 			temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
711 			temp_pipe->stream_res = pipe->stream_res;
712 			dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
713 			break;
714 		}
715 	}
716 
717 	ASSERT(i < MAX_PIPES);
718 	return &temp_pipe->plane_res.scl_data;
719 }
720 
populate_dml21_plane_config_from_plane_state(struct dml2_context * dml_ctx,struct dml2_plane_parameters * plane,const struct dc_plane_state * plane_state,const struct dc_state * context,unsigned int stream_index)721 static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dml_ctx,
722 		struct dml2_plane_parameters *plane, const struct dc_plane_state *plane_state,
723 		const struct dc_state *context, unsigned int stream_index)
724 {
725 	const struct scaler_data *scaler_data = get_scaler_data_for_plane(dml_ctx, plane_state, context);
726 	struct dc_stream_state *stream = context->streams[stream_index];
727 
728 	plane->cursor.cursor_bpp = 32;
729 	plane->cursor.cursor_width = 256;
730 	plane->cursor.num_cursors = 1;
731 
732 	switch (plane_state->format) {
733 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
734 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
735 		plane->pixel_format = dml2_420_8;
736 		break;
737 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
738 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
739 		plane->pixel_format = dml2_420_10;
740 		break;
741 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
742 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
743 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
744 		plane->pixel_format = dml2_444_64;
745 		break;
746 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
747 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
748 		plane->pixel_format = dml2_444_16;
749 		break;
750 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
751 		plane->pixel_format = dml2_444_8;
752 		break;
753 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
754 		plane->pixel_format = dml2_rgbe_alpha;
755 		break;
756 	default:
757 		plane->pixel_format = dml2_444_32;
758 		break;
759 	}
760 
761 	plane->composition.viewport.plane0.height = scaler_data->viewport.height;
762 	plane->composition.viewport.plane0.width = scaler_data->viewport.width;
763 	plane->composition.viewport.plane1.height = scaler_data->viewport_c.height;
764 	plane->composition.viewport.plane1.width = scaler_data->viewport_c.width;
765 	plane->composition.viewport.plane0.x_start = scaler_data->viewport.x;
766 	plane->composition.viewport.plane0.y_start = scaler_data->viewport.y;
767 	plane->composition.viewport.plane1.x_start = scaler_data->viewport_c.x;
768 	plane->composition.viewport.plane1.y_start = scaler_data->viewport_c.y;
769 	plane->composition.viewport.stationary = false;
770 	plane->composition.scaler_info.enabled = scaler_data->ratios.horz.value != dc_fixpt_one.value ||
771 		scaler_data->ratios.horz_c.value != dc_fixpt_one.value ||
772 		scaler_data->ratios.vert.value != dc_fixpt_one.value ||
773 		scaler_data->ratios.vert_c.value != dc_fixpt_one.value;
774 
775 	if (!scaler_data->taps.h_taps) {
776 		/* Above logic determines scaling should be enabled even when there are no taps for
777 		 * certain cases. Hence do corrective active and disable scaling.
778 		 */
779 		plane->composition.scaler_info.enabled = false;
780 	} else if ((plane_state->ctx->dc->config.use_spl == true) &&
781 		(plane->composition.scaler_info.enabled == false)) {
782 		/* To enable sharpener for 1:1, scaler must be enabled.  If use_spl is set, then
783 		 *  allow case where ratio is 1 but taps > 1
784 		 */
785 		if ((scaler_data->taps.h_taps > 1) || (scaler_data->taps.v_taps > 1) ||
786 			(scaler_data->taps.h_taps_c > 1) || (scaler_data->taps.v_taps_c > 1))
787 			plane->composition.scaler_info.enabled = true;
788 	}
789 
790 	/* always_scale is only used for debug purposes not used in production but has to be
791 	 * maintained for certain complainces. */
792 	if (plane_state->ctx->dc->debug.always_scale == true) {
793 		plane->composition.scaler_info.enabled = true;
794 	}
795 
796 	if (plane->composition.scaler_info.enabled == false) {
797 		plane->composition.scaler_info.plane0.h_ratio = 1.0;
798 		plane->composition.scaler_info.plane0.v_ratio = 1.0;
799 		plane->composition.scaler_info.plane1.h_ratio = 1.0;
800 		plane->composition.scaler_info.plane1.v_ratio = 1.0;
801 	} else {
802 		plane->composition.scaler_info.plane0.h_ratio = (double)scaler_data->ratios.horz.value / (1ULL << 32);
803 		plane->composition.scaler_info.plane0.v_ratio = (double)scaler_data->ratios.vert.value / (1ULL << 32);
804 		plane->composition.scaler_info.plane1.h_ratio = (double)scaler_data->ratios.horz_c.value / (1ULL << 32);
805 		plane->composition.scaler_info.plane1.v_ratio = (double)scaler_data->ratios.vert_c.value / (1ULL << 32);
806 	}
807 
808 	if (!scaler_data->taps.h_taps) {
809 		plane->composition.scaler_info.plane0.h_taps = 1;
810 		plane->composition.scaler_info.plane1.h_taps = 1;
811 	} else {
812 		plane->composition.scaler_info.plane0.h_taps = scaler_data->taps.h_taps;
813 		plane->composition.scaler_info.plane1.h_taps = scaler_data->taps.h_taps_c;
814 	}
815 	if (!scaler_data->taps.v_taps) {
816 		plane->composition.scaler_info.plane0.v_taps = 1;
817 		plane->composition.scaler_info.plane1.v_taps = 1;
818 	} else {
819 		plane->composition.scaler_info.plane0.v_taps = scaler_data->taps.v_taps;
820 		plane->composition.scaler_info.plane1.v_taps = scaler_data->taps.v_taps_c;
821 	}
822 
823 	plane->composition.viewport.stationary = false;
824 
825 	if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
826 		plane->tdlut.setup_for_tdlut = true;
827 
828 		switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.layout) {
829 		case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
830 		case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
831 			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_sw_linear;
832 			break;
833 		case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
834 			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
835 			break;
836 		}
837 
838 		switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.size) {
839 		case DC_CM2_GPU_MEM_SIZE_171717:
840 			plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
841 			break;
842 		case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
843 			//plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
844 			break;
845 		}
846 	}
847 	plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable;
848 
849 	plane->dynamic_meta_data.enable = false;
850 	plane->dynamic_meta_data.lines_before_active_required = 0;
851 	plane->dynamic_meta_data.transmitted_bytes = 0;
852 
853 	plane->composition.scaler_info.rect_out_width = plane_state->dst_rect.width;
854 	plane->composition.rotation_angle = (enum dml2_rotation_angle) plane_state->rotation;
855 	plane->stream_index = stream_index;
856 
857 	plane->overrides.gpuvm_min_page_size_kbytes = 256;
858 
859 	plane->immediate_flip = plane_state->flip_immediate;
860 
861 	plane->composition.rect_out_height_spans_vactive =
862 		plane_state->dst_rect.height >= stream->timing.v_addressable &&
863 		stream->dst.height >= stream->timing.v_addressable;
864 }
865 
866 //TODO : Could be possibly moved to a common helper layer.
dml21_wrapper_get_plane_id(const struct dc_state * context,const struct dc_plane_state * plane,unsigned int * plane_id)867 static bool dml21_wrapper_get_plane_id(const struct dc_state *context, const struct dc_plane_state *plane, unsigned int *plane_id)
868 {
869 	int i, j;
870 
871 	if (!plane_id)
872 		return false;
873 
874 	for (i = 0; i < context->stream_count; i++) {
875 		for (j = 0; j < context->stream_status[i].plane_count; j++) {
876 			if (context->stream_status[i].plane_states[j] == plane) {
877 				*plane_id = (i << 16) | j;
878 				return true;
879 			}
880 		}
881 	}
882 
883 	return false;
884 }
885 
map_stream_to_dml21_display_cfg(const struct dml2_context * dml_ctx,const struct dc_stream_state * stream)886 static unsigned int map_stream_to_dml21_display_cfg(const struct dml2_context *dml_ctx, const struct dc_stream_state *stream)
887 {
888 	int i = 0;
889 	int location = -1;
890 
891 	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
892 		if (dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[i] && dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i] == stream->stream_id) {
893 			location = i;
894 			break;
895 		}
896 	}
897 
898 	return location;
899 }
900 
map_plane_to_dml21_display_cfg(const struct dml2_context * dml_ctx,const struct dc_plane_state * plane,const struct dc_state * context)901 static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx,
902 		const struct dc_plane_state *plane, const struct dc_state *context)
903 {
904 	unsigned int plane_id;
905 	int i = 0;
906 	int location = -1;
907 
908 	if (!dml21_wrapper_get_plane_id(context, plane, &plane_id)) {
909 		ASSERT(false);
910 		return -1;
911 	}
912 
913 	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
914 		if (dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[i] && dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i] == plane_id) {
915 			location = i;
916 			break;
917 		}
918 	}
919 
920 	return location;
921 }
922 
dml21_force_pstate_method_to_uclk_state_change_strategy(enum dml2_force_pstate_methods force_pstate_method)923 static enum dml2_uclk_pstate_change_strategy dml21_force_pstate_method_to_uclk_state_change_strategy(enum dml2_force_pstate_methods force_pstate_method)
924 {
925 	enum dml2_uclk_pstate_change_strategy val = dml2_uclk_pstate_change_strategy_auto;
926 
927 	switch (force_pstate_method) {
928 	case dml2_force_pstate_method_vactive:
929 		val = dml2_uclk_pstate_change_strategy_force_vactive;
930 		break;
931 	case dml2_force_pstate_method_vblank:
932 		val = dml2_uclk_pstate_change_strategy_force_vblank;
933 		break;
934 	case dml2_force_pstate_method_drr:
935 		val = dml2_uclk_pstate_change_strategy_force_drr;
936 		break;
937 	case dml2_force_pstate_method_subvp:
938 		val = dml2_uclk_pstate_change_strategy_force_mall_svp;
939 		break;
940 	case dml2_force_pstate_method_auto:
941 	default:
942 		val = dml2_uclk_pstate_change_strategy_auto;
943 	}
944 
945 	return val;
946 }
947 
dml21_map_dc_state_into_dml_display_cfg(const struct dc * in_dc,struct dc_state * context,struct dml2_context * dml_ctx)948 bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
949 {
950 	int stream_index, plane_index;
951 	int disp_cfg_stream_location, disp_cfg_plane_location;
952 	struct dml2_display_cfg *dml_dispcfg = &dml_ctx->v21.display_config;
953 	unsigned int plane_count = 0;
954 
955 	memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
956 
957 	dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable;
958 	dml_dispcfg->gpuvm_max_page_table_levels = 4;
959 	dml_dispcfg->hostvm_enable = false;
960 	dml_dispcfg->minimize_det_reallocation = true;
961 	dml_dispcfg->overrides.enable_subvp_implicit_pmo = true;
962 
963 	if (in_dc->debug.disable_unbounded_requesting) {
964 		dml_dispcfg->overrides.hw.force_unbounded_requesting.enable = true;
965 		dml_dispcfg->overrides.hw.force_unbounded_requesting.value = false;
966 	}
967 
968 	for (stream_index = 0; stream_index < context->stream_count; stream_index++) {
969 		disp_cfg_stream_location = map_stream_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]);
970 
971 		if (disp_cfg_stream_location < 0)
972 			disp_cfg_stream_location = dml_dispcfg->num_streams++;
973 
974 		ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);
975 		populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx);
976 		populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]);
977 		populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index]);
978 
979 		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.fclk_pstate = dml2_twait_budgeting_setting_if_needed;
980 		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.uclk_pstate = dml2_twait_budgeting_setting_if_needed;
981 		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.stutter_enter_exit = dml2_twait_budgeting_setting_if_needed;
982 
983 		dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[disp_cfg_stream_location] = context->streams[stream_index]->stream_id;
984 		dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[disp_cfg_stream_location] = true;
985 
986 		if (context->stream_status[stream_index].plane_count == 0) {
987 			disp_cfg_plane_location = dml_dispcfg->num_planes++;
988 			populate_dml21_dummy_surface_cfg(&dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->streams[stream_index]);
989 			populate_dml21_dummy_plane_cfg(&dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->streams[stream_index]);
990 			dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
991 		} else {
992 			for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) {
993 				disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->stream_status[stream_index].plane_states[plane_index], context);
994 
995 				if (disp_cfg_plane_location < 0)
996 					disp_cfg_plane_location = dml_dispcfg->num_planes++;
997 
998 				ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);
999 
1000 				populate_dml21_surface_config_from_plane_state(in_dc, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->stream_status[stream_index].plane_states[plane_index]);
1001 				populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index);
1002 				dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
1003 
1004 				if (dml21_wrapper_get_plane_id(context, context->stream_status[stream_index].plane_states[plane_index], &dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location]))
1005 					dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true;
1006 
1007 				/* apply forced pstate policy */
1008 				if (dml_ctx->config.pmo.force_pstate_method_enable) {
1009 					dml_dispcfg->plane_descriptors[disp_cfg_plane_location].overrides.uclk_pstate_change_strategy =
1010 							dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_values[stream_index]);
1011 				}
1012 
1013 				plane_count++;
1014 			}
1015 		}
1016 	}
1017 
1018 	if (plane_count == 0) {
1019 		dml_dispcfg->overrides.all_streams_blanked = true;
1020 	}
1021 
1022 	return true;
1023 }
1024 
dml21_copy_clocks_to_dc_state(struct dml2_context * in_ctx,struct dc_state * context)1025 void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state *context)
1026 {
1027 	/* TODO these should be the max of active, svp prefetch and idle should be tracked seperately */
1028 	context->bw_ctx.bw.dcn.clk.dispclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dispclk_khz;
1029 	context->bw_ctx.bw.dcn.clk.dcfclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.dcfclk_khz;
1030 	context->bw_ctx.bw.dcn.clk.dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.uclk_khz;
1031 	context->bw_ctx.bw.dcn.clk.fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.fclk_khz;
1032 	context->bw_ctx.bw.dcn.clk.idle_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.uclk_khz;
1033 	context->bw_ctx.bw.dcn.clk.idle_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.fclk_khz;
1034 	context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.deepsleep_dcfclk_khz;
1035 	context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = in_ctx->v21.mode_programming.programming->fclk_pstate_supported;
1036 	context->bw_ctx.bw.dcn.clk.p_state_change_support = in_ctx->v21.mode_programming.programming->uclk_pstate_supported;
1037 	context->bw_ctx.bw.dcn.clk.dtbclk_en = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz > 0;
1038 	context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz;
1039 }
1040 
dml21_extract_legacy_watermark_set(const struct dc * in_dc,struct dcn_watermarks * watermark,enum dml2_dchub_watermark_reg_set_index reg_set_idx,struct dml2_context * in_ctx)1041 void dml21_extract_legacy_watermark_set(const struct dc *in_dc, struct dcn_watermarks *watermark, enum dml2_dchub_watermark_reg_set_index reg_set_idx, struct dml2_context *in_ctx)
1042 {
1043 	struct dml2_core_internal_display_mode_lib *mode_lib = &in_ctx->v21.dml_init.dml2_instance->core_instance.clean_me_up.mode_lib;
1044 	double refclk_freq_in_mhz = (in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz > 0) ? (double)in_ctx->v21.display_config.overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
1045 
1046 	if (reg_set_idx >= DML2_DCHUB_WATERMARK_SET_NUM) {
1047 		/* invalid register set index */
1048 		return;
1049 	}
1050 
1051 	/* convert to legacy format (time in ns) */
1052 	watermark->urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
1053 	watermark->pte_meta_urgent_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
1054 	watermark->cstate_pstate.cstate_enter_plus_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_enter / refclk_freq_in_mhz) * 1000.0;
1055 	watermark->cstate_pstate.cstate_exit_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].sr_exit / refclk_freq_in_mhz) * 1000.0;
1056 	watermark->cstate_pstate.pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].uclk_pstate / refclk_freq_in_mhz) * 1000.0;
1057 	watermark->urgent_latency_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].urgent / refclk_freq_in_mhz) * 1000.0;
1058 	watermark->cstate_pstate.fclk_pstate_change_ns = ((double)in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].fclk_pstate / refclk_freq_in_mhz) * 1000.0;
1059 	watermark->frac_urg_bw_flip = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_flip;
1060 	watermark->frac_urg_bw_nom = in_ctx->v21.mode_programming.programming->global_regs.wm_regs[reg_set_idx].frac_urg_bw_nom;
1061 }
1062 
wm_set_index_to_dc_wm_set(union dcn_watermark_set * watermarks,const enum dml2_dchub_watermark_reg_set_index wm_index)1063 static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
1064 {
1065 	struct dml2_dchub_watermark_regs *wm_regs = NULL;
1066 
1067 	switch (wm_index) {
1068 	case DML2_DCHUB_WATERMARK_SET_A:
1069 		wm_regs = &watermarks->dcn4x.a;
1070 		break;
1071 	case DML2_DCHUB_WATERMARK_SET_B:
1072 		wm_regs = &watermarks->dcn4x.b;
1073 		break;
1074 	case DML2_DCHUB_WATERMARK_SET_C:
1075 		wm_regs = &watermarks->dcn4x.c;
1076 		break;
1077 	case DML2_DCHUB_WATERMARK_SET_D:
1078 		wm_regs = &watermarks->dcn4x.d;
1079 		break;
1080 	case DML2_DCHUB_WATERMARK_SET_NUM:
1081 	default:
1082 		/* invalid wm set index */
1083 		wm_regs = NULL;
1084 	}
1085 
1086 	return wm_regs;
1087 }
1088 
dml21_extract_watermark_sets(const struct dc * in_dc,union dcn_watermark_set * watermarks,struct dml2_context * in_ctx)1089 void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_set *watermarks, struct dml2_context *in_ctx)
1090 {
1091 	const struct dml2_display_cfg_programming *programming = in_ctx->v21.mode_programming.programming;
1092 
1093 	unsigned int wm_index;
1094 
1095 	/* copy watermark sets from DML */
1096 	for (wm_index = 0; wm_index < programming->global_regs.num_watermark_sets; wm_index++) {
1097 		struct dml2_dchub_watermark_regs *wm_regs = wm_set_index_to_dc_wm_set(watermarks, wm_index);
1098 
1099 		if (wm_regs)
1100 			memcpy(wm_regs,
1101 				&programming->global_regs.wm_regs[wm_index],
1102 				sizeof(struct dml2_dchub_watermark_regs));
1103 	}
1104 }
1105 
1106 
dml21_populate_pipe_ctx_dlg_params(struct dml2_context * dml_ctx,struct dc_state * context,struct pipe_ctx * pipe_ctx,struct dml2_per_stream_programming * stream_programming)1107 void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming)
1108 {
1109 	unsigned int hactive, vactive, hblank_start, vblank_start, hblank_end, vblank_end;
1110 	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1111 	union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
1112 
1113 	hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right;
1114 	vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
1115 	hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
1116 	vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;
1117 
1118 	hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right;
1119 	vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
1120 
1121 	if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
1122 		/* phantom has its own global sync */
1123 		global_sync = &stream_programming->phantom_stream.global_sync;
1124 	}
1125 
1126 	pipe_ctx->pipe_dlg_param.vstartup_start = global_sync->dcn4x.vstartup_lines;
1127 	pipe_ctx->pipe_dlg_param.vupdate_offset = global_sync->dcn4x.vupdate_offset_pixels;
1128 	pipe_ctx->pipe_dlg_param.vupdate_width = global_sync->dcn4x.vupdate_vupdate_width_pixels;
1129 	pipe_ctx->pipe_dlg_param.vready_offset = global_sync->dcn4x.vready_offset_pixels;
1130 	pipe_ctx->pipe_dlg_param.pstate_keepout = global_sync->dcn4x.pstate_keepout_start_lines;
1131 
1132 	pipe_ctx->pipe_dlg_param.otg_inst = pipe_ctx->stream_res.tg->inst;
1133 
1134 	pipe_ctx->pipe_dlg_param.hactive = hactive;
1135 	pipe_ctx->pipe_dlg_param.vactive = vactive;
1136 	pipe_ctx->pipe_dlg_param.htotal = pipe_ctx->stream->timing.h_total;
1137 	pipe_ctx->pipe_dlg_param.vtotal = pipe_ctx->stream->timing.v_total;
1138 	pipe_ctx->pipe_dlg_param.hblank_end = hblank_end;
1139 	pipe_ctx->pipe_dlg_param.vblank_end = vblank_end;
1140 	pipe_ctx->pipe_dlg_param.hblank_start = hblank_start;
1141 	pipe_ctx->pipe_dlg_param.vblank_start = vblank_start;
1142 	pipe_ctx->pipe_dlg_param.vfront_porch = pipe_ctx->stream->timing.v_front_porch;
1143 	pipe_ctx->pipe_dlg_param.pixel_rate_mhz = pipe_ctx->stream->timing.pix_clk_100hz / 10000.00;
1144 	pipe_ctx->pipe_dlg_param.refresh_rate = ((timing->pix_clk_100hz * 100) / timing->h_total) / timing->v_total;
1145 	pipe_ctx->pipe_dlg_param.vtotal_max = pipe_ctx->stream->adjust.v_total_max;
1146 	pipe_ctx->pipe_dlg_param.vtotal_min = pipe_ctx->stream->adjust.v_total_min;
1147 	pipe_ctx->pipe_dlg_param.recout_height = pipe_ctx->plane_res.scl_data.recout.height;
1148 	pipe_ctx->pipe_dlg_param.recout_width = pipe_ctx->plane_res.scl_data.recout.width;
1149 	pipe_ctx->pipe_dlg_param.full_recout_height = pipe_ctx->plane_res.scl_data.recout.height;
1150 	pipe_ctx->pipe_dlg_param.full_recout_width = pipe_ctx->plane_res.scl_data.recout.width;
1151 }
1152 
dml21_map_hw_resources(struct dml2_context * dml_ctx)1153 void dml21_map_hw_resources(struct dml2_context *dml_ctx)
1154 {
1155 	unsigned int i = 0;
1156 
1157 	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
1158 		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[i] = dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[i];
1159 		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[i] = true;
1160 		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[i] = dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[i];
1161 		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[i] = true;
1162 	}
1163 
1164 }
1165 
dml21_get_pipe_mcache_config(struct dc_state * context,struct pipe_ctx * pipe_ctx,struct dml2_per_plane_programming * pln_prog,struct dml2_pipe_configuration_descriptor * mcache_pipe_config)1166 void dml21_get_pipe_mcache_config(
1167 	struct dc_state *context,
1168 	struct pipe_ctx *pipe_ctx,
1169 	struct dml2_per_plane_programming *pln_prog,
1170 	struct dml2_pipe_configuration_descriptor *mcache_pipe_config)
1171 {
1172 	mcache_pipe_config->plane0.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x;
1173 	mcache_pipe_config->plane0.viewport_width = pipe_ctx->plane_res.scl_data.viewport.width;
1174 
1175 	mcache_pipe_config->plane1.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport_c.x;
1176 	mcache_pipe_config->plane1.viewport_width = pipe_ctx->plane_res.scl_data.viewport_c.width;
1177 
1178 	mcache_pipe_config->plane1_enabled =
1179 			dml21_is_plane1_enabled(pln_prog->plane_descriptor->pixel_format);
1180 }
1181 
dml21_set_dc_p_state_type(struct pipe_ctx * pipe_ctx,struct dml2_per_stream_programming * stream_programming,bool sub_vp_enabled)1182 void dml21_set_dc_p_state_type(
1183 		struct pipe_ctx *pipe_ctx,
1184 		struct dml2_per_stream_programming *stream_programming,
1185 		bool sub_vp_enabled)
1186 {
1187 	switch (stream_programming->uclk_pstate_method) {
1188 	case dml2_uclk_pstate_support_method_vactive:
1189 	case dml2_uclk_pstate_support_method_fw_vactive_drr:
1190 		pipe_ctx->p_state_type = P_STATE_V_ACTIVE;
1191 		break;
1192 	case dml2_uclk_pstate_support_method_vblank:
1193 	case dml2_uclk_pstate_support_method_fw_vblank_drr:
1194 		if (sub_vp_enabled)
1195 			pipe_ctx->p_state_type = P_STATE_V_BLANK_SUB_VP;
1196 		else
1197 			pipe_ctx->p_state_type = P_STATE_V_BLANK;
1198 		break;
1199 	case dml2_uclk_pstate_support_method_fw_subvp_phantom:
1200 	case dml2_uclk_pstate_support_method_fw_subvp_phantom_drr:
1201 		pipe_ctx->p_state_type = P_STATE_SUB_VP;
1202 		break;
1203 	case dml2_uclk_pstate_support_method_fw_drr:
1204 		if (sub_vp_enabled)
1205 			pipe_ctx->p_state_type = P_STATE_DRR_SUB_VP;
1206 		else
1207 			pipe_ctx->p_state_type = P_STATE_FPO;
1208 		break;
1209 	default:
1210 		pipe_ctx->p_state_type = P_STATE_UNKNOWN;
1211 		break;
1212 	}
1213 }
1214 
1215