xref: /linux/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c (revision badcb0896bdb4c6148564331c4b24ba7635efa94)
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4 
5 #include "dml21_wrapper.h"
6 #include "dml2_core_dcn4_calcs.h"
7 #include "dml2_internal_shared_types.h"
8 #include "dml2_internal_types.h"
9 #include "dml21_utils.h"
10 #include "dml21_translation_helper.h"
11 #include "soc_and_ip_translator.h"
12 
13 static void dml21_populate_pmo_options(struct dml2_pmo_options *pmo_options,
14 		const struct dc *in_dc,
15 		const struct dml2_configuration_options *config)
16 {
17 	bool disable_fams2 = !in_dc->debug.fams2_config.bits.enable;
18 
19 	/* ODM options */
20 	pmo_options->disable_dyn_odm = !config->minimize_dispclk_using_odm;
21 	pmo_options->disable_dyn_odm_for_multi_stream = true;
22 	pmo_options->disable_dyn_odm_for_stream_with_svp = true;
23 
24 	pmo_options->disable_vblank = ((in_dc->debug.dml21_disable_pstate_method_mask >> 1) & 1);
25 
26 	/* NOTE: DRR and SubVP Require FAMS2 */
27 	pmo_options->disable_svp = ((in_dc->debug.dml21_disable_pstate_method_mask >> 2) & 1) ||
28 			in_dc->debug.force_disable_subvp ||
29 			disable_fams2;
30 	pmo_options->disable_drr_clamped = ((in_dc->debug.dml21_disable_pstate_method_mask >> 3) & 1) ||
31 			disable_fams2;
32 	pmo_options->disable_drr_var = ((in_dc->debug.dml21_disable_pstate_method_mask >> 4) & 1) ||
33 			disable_fams2;
34 	pmo_options->disable_fams2 = disable_fams2;
35 
36 	pmo_options->disable_drr_var_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE ||
37 			in_dc->debug.disable_fams_gaming == INGAME_FAMS_MULTI_DISP_CLAMPED_ONLY;
38 	pmo_options->disable_drr_clamped_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE;
39 
40 	pmo_options->force_mandatory_uclk_pstate_support = config->pmo.force_mandatory_uclk_pstate_support;
41 }
42 
43 static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_version dcn_version)
44 {
45 	enum dml2_project_id project_id;
46 	switch (dcn_version) {
47 	case DCN_VERSION_4_01:
48 		project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
49 		break;
50 	case DCN_VERSION_4_2:
51 	case DCN_VERSION_4_2B:
52 		project_id = dml2_project_dcn42;
53 		break;
54 	default:
55 		project_id = dml2_project_invalid;
56 		DC_ERR("unsupported dcn version for DML21!");
57 		break;
58 	}
59 
60 	return project_id;
61 }
62 
63 void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_init,
64 		const struct dml2_configuration_options *config,
65 		const struct dc *in_dc)
66 {
67 	dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc->ctx->dce_version);
68 
69 	if (config->use_native_soc_bb_construction) {
70 		in_dc->soc_and_ip_translator->translator_funcs->get_soc_bb(&dml_init->soc_bb, in_dc, config);
71 		in_dc->soc_and_ip_translator->translator_funcs->get_ip_caps(&dml_init->ip_caps);
72 	} else {
73 		dml_init->soc_bb = config->external_socbb_ip_params->soc_bb;
74 		dml_init->ip_caps = config->external_socbb_ip_params->ip_params;
75 	}
76 
77 	dml21_populate_pmo_options(&dml_init->options.pmo_options, in_dc, config);
78 }
79 
80 static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
81 {
82 	unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
83 
84 	if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
85 		max_hw_v_total -= stream->timing.v_front_porch + 1;
86 	}
87 
88 	return max_hw_v_total;
89 }
90 
91 static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing,
92 		struct dc_stream_state *stream,
93 		struct pipe_ctx *pipe_ctx,
94 		struct dml2_context *dml_ctx)
95 {
96 	const unsigned int min_v_front_porch = (stream->timing.flags.INTERLACE != 0) ? 2 : 1;
97 
98 	unsigned int hblank_start, vblank_start;
99 	uint64_t min_hardware_refresh_in_uhz;
100 	uint32_t pix_clk_100hz;
101 
102 	timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->dsc_padding_params.dsc_hactive_padding;
103 	timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
104 	timing->h_front_porch = stream->timing.h_front_porch;
105 	timing->v_front_porch = stream->timing.v_front_porch > min_v_front_porch ?
106 			stream->timing.v_front_porch : min_v_front_porch;
107 	timing->pixel_clock_khz = stream->timing.pix_clk_100hz / 10;
108 	if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0)
109 		timing->pixel_clock_khz = pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz / 10;
110 	if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
111 		timing->pixel_clock_khz *= 2;
112 	timing->h_total = stream->timing.h_total + pipe_ctx->dsc_padding_params.dsc_htotal_padding;
113 	timing->v_total = stream->timing.v_total;
114 	timing->h_sync_width = stream->timing.h_sync_width;
115 	timing->interlaced = (stream->timing.flags.INTERLACE != 0);
116 
117 	hblank_start = stream->timing.h_total - stream->timing.h_front_porch;
118 
119 	timing->h_blank_end = hblank_start - stream->timing.h_addressable - pipe_ctx->dsc_padding_params.dsc_hactive_padding
120 		- stream->timing.h_border_left - stream->timing.h_border_right;
121 
122 	if (hblank_start < stream->timing.h_addressable)
123 		timing->h_blank_end = 0;
124 
125 	vblank_start = timing->v_total - timing->v_front_porch;
126 
127 	timing->v_blank_end = vblank_start - stream->timing.v_addressable
128 		- stream->timing.v_border_top - stream->timing.v_border_bottom;
129 
130 	timing->drr_config.enabled = stream->ignore_msa_timing_param;
131 	timing->drr_config.drr_active_variable = stream->vrr_active_variable;
132 	timing->drr_config.drr_active_fixed = stream->vrr_active_fixed;
133 	timing->drr_config.disallowed = !stream->allow_freesync;
134 
135 	/* limit min refresh rate to DC cap */
136 	min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz;
137 	if (stream->ctx->dc->caps.max_v_total != 0) {
138 		if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0) {
139 			pix_clk_100hz = pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz;
140 		} else {
141 			pix_clk_100hz = stream->timing.pix_clk_100hz;
142 		}
143 		min_hardware_refresh_in_uhz = div64_u64((pix_clk_100hz * 100000000ULL),
144 				(timing->h_total * (long long)calc_max_hardware_v_total(stream)));
145 	}
146 
147 	{
148 		uint64_t min_refresh = max((uint64_t)stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz);
149 		ASSERT(min_refresh <= ULONG_MAX);
150 		timing->drr_config.min_refresh_uhz = (unsigned long)min_refresh;
151 	}
152 
153 	if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
154 			stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
155 		timing->drr_config.max_instant_vtotal_delta = dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase(stream, false);
156 	else
157 		timing->drr_config.max_instant_vtotal_delta = 0;
158 
159 	if (stream->timing.flags.DSC) {
160 		timing->dsc.enable = dml2_dsc_enable;
161 		timing->dsc.overrides.num_slices = stream->timing.dsc_cfg.num_slices_h;
162 		timing->dsc.dsc_compressed_bpp_x16 = stream->timing.dsc_cfg.bits_per_pixel;
163 	} else
164 		timing->dsc.enable = dml2_dsc_disable;
165 
166 	switch (stream->timing.display_color_depth) {
167 	case COLOR_DEPTH_666:
168 		timing->bpc = 6;
169 		break;
170 	case COLOR_DEPTH_888:
171 		timing->bpc = 8;
172 		break;
173 	case COLOR_DEPTH_101010:
174 		timing->bpc = 10;
175 		break;
176 	case COLOR_DEPTH_121212:
177 		timing->bpc = 12;
178 		break;
179 	case COLOR_DEPTH_141414:
180 		timing->bpc = 14;
181 		break;
182 	case COLOR_DEPTH_161616:
183 		timing->bpc = 16;
184 		break;
185 	case COLOR_DEPTH_999:
186 		timing->bpc = 9;
187 		break;
188 	case COLOR_DEPTH_111111:
189 		timing->bpc = 11;
190 		break;
191 	default:
192 		timing->bpc = 8;
193 		break;
194 	}
195 
196 	timing->vblank_nom = timing->v_total - timing->v_active;
197 }
198 
199 static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output,
200 		struct dc_stream_state *stream, const struct pipe_ctx *pipe)
201 {
202 	output->output_dp_lane_count = 4;
203 
204 	switch (stream->signal) {
205 	case SIGNAL_TYPE_DISPLAY_PORT_MST:
206 	case SIGNAL_TYPE_DISPLAY_PORT:
207 		output->output_encoder = dml2_dp;
208 		if (check_dp2p0_output_encoder(pipe))
209 			output->output_encoder = dml2_dp2p0;
210 		break;
211 	case SIGNAL_TYPE_EDP:
212 		output->output_encoder = dml2_edp;
213 		break;
214 	case SIGNAL_TYPE_HDMI_TYPE_A:
215 	case SIGNAL_TYPE_DVI_SINGLE_LINK:
216 	case SIGNAL_TYPE_DVI_DUAL_LINK:
217 		output->output_encoder = dml2_hdmi;
218 		break;
219 	case SIGNAL_TYPE_HDMI_FRL:
220 		output->output_encoder = dml2_hdmifrl;
221 		break;
222 	default:
223 			output->output_encoder = dml2_dp;
224 	}
225 
226 	switch (stream->timing.pixel_encoding) {
227 	case PIXEL_ENCODING_RGB:
228 	case PIXEL_ENCODING_YCBCR444:
229 		output->output_format = dml2_444;
230 		break;
231 	case PIXEL_ENCODING_YCBCR420:
232 		output->output_format = dml2_420;
233 		break;
234 	case PIXEL_ENCODING_YCBCR422:
235 		if (stream->timing.flags.DSC && !stream->timing.dsc_cfg.ycbcr422_simple)
236 			output->output_format = dml2_n422;
237 		else
238 			output->output_format = dml2_s422;
239 		break;
240 	default:
241 		output->output_format = dml2_444;
242 		break;
243 	}
244 
245 	switch (stream->signal) {
246 	case SIGNAL_TYPE_NONE:
247 	case SIGNAL_TYPE_DVI_SINGLE_LINK:
248 	case SIGNAL_TYPE_DVI_DUAL_LINK:
249 	case SIGNAL_TYPE_HDMI_TYPE_A:
250 	case SIGNAL_TYPE_LVDS:
251 	case SIGNAL_TYPE_RGB:
252 	case SIGNAL_TYPE_DISPLAY_PORT:
253 	case SIGNAL_TYPE_DISPLAY_PORT_MST:
254 	case SIGNAL_TYPE_EDP:
255 	case SIGNAL_TYPE_VIRTUAL:
256 	case SIGNAL_TYPE_HDMI_FRL:
257 	default:
258 		output->output_dp_link_rate = dml2_dp_rate_na;
259 		break;
260 	}
261 
262 	output->audio_sample_layout = stream->audio_info.modes->sample_size;
263 	output->audio_sample_rate = stream->audio_info.modes->max_bit_rate;
264 	output->output_disabled = true;
265 
266 	//TODO : New to DML2.1. How do we populate this ?
267 	// output->validate_output
268 }
269 
270 static void populate_dml21_stream_overrides_from_stream_state(
271 		struct dml2_stream_parameters *stream_desc,
272 		struct dc_stream_state *stream,
273 		struct dc_stream_status *stream_status)
274 {
275 	switch (stream->debug.force_odm_combine_segments) {
276 	case 0:
277 		stream_desc->overrides.odm_mode = dml2_odm_mode_auto;
278 		break;
279 	case 1:
280 		stream_desc->overrides.odm_mode = dml2_odm_mode_bypass;
281 		break;
282 	case 2:
283 		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_2to1;
284 		break;
285 	case 3:
286 		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_3to1;
287 		break;
288 	case 4:
289 		stream_desc->overrides.odm_mode = dml2_odm_mode_combine_4to1;
290 		break;
291 	default:
292 		stream_desc->overrides.odm_mode =  dml2_odm_mode_auto;
293 		break;
294 	}
295 	if (!stream->ctx->dc->debug.enable_single_display_2to1_odm_policy ||
296 			stream->debug.force_odm_combine_segments > 0)
297 		stream_desc->overrides.disable_dynamic_odm = true;
298 	stream_desc->overrides.disable_subvp = stream->ctx->dc->debug.force_disable_subvp ||
299 			stream->hw_cursor_req ||
300 			stream_status->mall_stream_config.cursor_size_limit_subvp;
301 }
302 
303 static enum dml2_swizzle_mode gfx_addr3_to_dml2_swizzle_mode(enum swizzle_mode_addr3_values addr3_mode)
304 {
305 	enum dml2_swizzle_mode dml2_mode = dml2_sw_linear;
306 
307 	switch (addr3_mode) {
308 	case DC_ADDR3_SW_LINEAR:
309 		dml2_mode = dml2_sw_linear;
310 		break;
311 	case DC_ADDR3_SW_256B_2D:
312 		dml2_mode = dml2_sw_256b_2d;
313 		break;
314 	case DC_ADDR3_SW_4KB_2D:
315 		dml2_mode = dml2_sw_4kb_2d;
316 		break;
317 	case DC_ADDR3_SW_64KB_2D:
318 		dml2_mode = dml2_sw_64kb_2d;
319 		break;
320 	case DC_ADDR3_SW_256KB_2D:
321 		dml2_mode = dml2_sw_256kb_2d;
322 		break;
323 	default:
324 		/* invalid swizzle mode for DML2.1 */
325 		ASSERT(false);
326 		dml2_mode = dml2_sw_linear;
327 	}
328 
329 	return dml2_mode;
330 }
331 
332 static enum dml2_swizzle_mode gfx9_to_dml2_swizzle_mode(enum swizzle_mode_values gfx9_mode)
333 {
334 	enum dml2_swizzle_mode dml2_mode = dml2_sw_64kb_2d;
335 
336 	switch (gfx9_mode) {
337 	case DC_SW_LINEAR:
338 		dml2_mode = dml2_sw_linear;
339 		break;
340 	case DC_SW_256_D:
341 	case DC_SW_256_R:
342 		dml2_mode = dml2_sw_256b_2d;
343 		break;
344 	case DC_SW_4KB_D:
345 	case DC_SW_4KB_R:
346 	case DC_SW_4KB_R_X:
347 		dml2_mode = dml2_sw_4kb_2d;
348 		break;
349 	case DC_SW_64KB_D:
350 	case DC_SW_64KB_D_X:
351 	case DC_SW_64KB_R:
352 	case DC_SW_64KB_R_X:
353 		dml2_mode = dml2_sw_64kb_2d;
354 		break;
355 	case DC_SW_256B_S:
356 	case DC_SW_4KB_S:
357 	case DC_SW_64KB_S:
358 	case DC_SW_VAR_S:
359 	case DC_SW_VAR_D:
360 	case DC_SW_VAR_R:
361 	case DC_SW_64KB_S_T:
362 	case DC_SW_64KB_D_T:
363 	case DC_SW_4KB_S_X:
364 	case DC_SW_4KB_D_X:
365 	case DC_SW_64KB_S_X:
366 	case DC_SW_VAR_S_X:
367 	case DC_SW_VAR_D_X:
368 	case DC_SW_VAR_R_X:
369 	default:
370 		/*
371 		 * invalid swizzle mode for DML2.1. This could happen because
372 		 * DML21 is not intended to be used by N-1 in production. To
373 		 * properly filter out unsupported swizzle modes, we will need
374 		 * to fix capability reporting when DML2.1 is used for N-1 in
375 		 * dc. So DML will only receive DML21 supported swizzle modes.
376 		 * This implementation is not added and has a low value because
377 		 * the supported swizzle modes should already cover most of our
378 		 * N-1 test cases.
379 		 */
380 		return dml2_sw_64kb_2d;
381 	}
382 
383 	return dml2_mode;
384 }
385 
386 static void populate_dml21_dummy_surface_cfg(struct dml2_surface_cfg *surface, const struct dc_stream_state *stream)
387 {
388 	surface->plane0.width = stream->timing.h_addressable;
389 	surface->plane0.height = stream->timing.v_addressable;
390 	surface->plane1.width = stream->timing.h_addressable;
391 	surface->plane1.height = stream->timing.v_addressable;
392 	surface->plane0.pitch = ((surface->plane0.width + 127) / 128) * 128;
393 	surface->plane1.pitch = 0;
394 	surface->dcc.enable = false;
395 	surface->dcc.informative.dcc_rate_plane0 = 1.0;
396 	surface->dcc.informative.dcc_rate_plane1 = 1.0;
397 	surface->dcc.informative.fraction_of_zero_size_request_plane0 = 0;
398 	surface->dcc.informative.fraction_of_zero_size_request_plane1 = 0;
399 	surface->tiling = dml2_sw_64kb_2d;
400 }
401 
402 static void populate_dml21_dummy_plane_cfg(struct dml2_plane_parameters *plane,
403 					   const struct dc_stream_state *stream,
404 					   const struct dml2_soc_bb *soc_bb)
405 {
406 	unsigned int width, height;
407 
408 	if (stream->timing.h_addressable > 3840)
409 		width = 3840;
410 	else
411 		width = stream->timing.h_addressable;	// 4K max
412 
413 	if (stream->timing.v_addressable > 2160)
414 		height = 2160;
415 	else
416 		height = stream->timing.v_addressable;	// 4K max
417 
418 	plane->cursor.cursor_bpp = 32;
419 
420 	plane->cursor.cursor_width = 256;
421 	plane->cursor.num_cursors = 1;
422 
423 	plane->composition.viewport.plane0.width = width;
424 	plane->composition.viewport.plane0.height = height;
425 	plane->composition.viewport.plane1.width = 0;
426 	plane->composition.viewport.plane1.height = 0;
427 
428 	plane->composition.viewport.stationary = false;
429 	plane->composition.viewport.plane0.x_start = 0;
430 	plane->composition.viewport.plane0.y_start = 0;
431 	plane->composition.viewport.plane1.x_start = 0;
432 	plane->composition.viewport.plane1.y_start = 0;
433 
434 	plane->composition.scaler_info.enabled = false;
435 	plane->composition.rotation_angle = dml2_rotation_0;
436 	plane->composition.scaler_info.plane0.h_ratio = 1.0;
437 	plane->composition.scaler_info.plane0.v_ratio = 1.0;
438 	plane->composition.scaler_info.plane1.h_ratio = 0;
439 	plane->composition.scaler_info.plane1.v_ratio = 0;
440 	plane->composition.scaler_info.plane0.h_taps = 1;
441 	plane->composition.scaler_info.plane0.v_taps = 1;
442 	plane->composition.scaler_info.plane1.h_taps = 0;
443 	plane->composition.scaler_info.plane1.v_taps = 0;
444 	plane->composition.scaler_info.rect_out_width = width;
445 	plane->pixel_format = dml2_444_32;
446 
447 	plane->dynamic_meta_data.enable = false;
448 	plane->overrides.gpuvm_min_page_size_kbytes = soc_bb->gpuvm_min_page_size_kbytes;
449 	plane->overrides.hostvm_min_page_size_kbytes = soc_bb->hostvm_min_page_size_kbytes;
450 }
451 
452 static void populate_dml21_surface_config_from_plane_state(
453 		const struct dc *in_dc,
454 		struct dml2_surface_cfg *surface,
455 		const struct dc_plane_state *plane_state)
456 {
457 	(void)in_dc;
458 	surface->plane0.pitch = plane_state->plane_size.surface_pitch;
459 	surface->plane1.pitch = plane_state->plane_size.chroma_pitch;
460 	surface->plane0.height = plane_state->plane_size.surface_size.height;
461 	surface->plane0.width = plane_state->plane_size.surface_size.width;
462 	surface->plane1.height = plane_state->plane_size.chroma_size.height;
463 	surface->plane1.width = plane_state->plane_size.chroma_size.width;
464 	surface->dcc.enable = plane_state->dcc.enable;
465 	surface->dcc.informative.dcc_rate_plane0 = 1.0;
466 	surface->dcc.informative.dcc_rate_plane1 = 1.0;
467 	surface->dcc.informative.fraction_of_zero_size_request_plane0 = plane_state->dcc.independent_64b_blks;
468 	surface->dcc.informative.fraction_of_zero_size_request_plane1 = plane_state->dcc.independent_64b_blks_c;
469 	surface->dcc.plane0.pitch = plane_state->dcc.meta_pitch;
470 	surface->dcc.plane1.pitch = plane_state->dcc.meta_pitch_c;
471 
472 	// Update swizzle / array mode based on the gfx_format
473 	switch (plane_state->tiling_info.gfxversion) {
474 	case DcGfxVersion7:
475 	case DcGfxVersion8:
476 		break;
477 	case DcGfxVersion9:
478 	case DcGfxVersion10:
479 	case DcGfxVersion11:
480 		surface->tiling = gfx9_to_dml2_swizzle_mode(plane_state->tiling_info.gfx9.swizzle);
481 		break;
482 	case DcGfxAddr3:
483 		surface->tiling = gfx_addr3_to_dml2_swizzle_mode(plane_state->tiling_info.gfx_addr3.swizzle);
484 		break;
485 	}
486 }
487 
488 static const struct scaler_data *get_scaler_data_for_plane(
489 		struct dml2_context *dml_ctx,
490 		const struct dc_plane_state *in,
491 		const struct dc_state *context)
492 {
493 	int i;
494 	struct pipe_ctx *temp_pipe = &dml_ctx->v21.scratch.temp_pipe;
495 
496 	memset(temp_pipe, 0, sizeof(struct pipe_ctx));
497 
498 	for (i = 0; i < MAX_PIPES; i++)	{
499 		const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
500 
501 		if (pipe->plane_state == in && !pipe->prev_odm_pipe) {
502 			temp_pipe->stream = pipe->stream;
503 			temp_pipe->plane_state = pipe->plane_state;
504 			temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
505 			temp_pipe->stream_res = pipe->stream_res;
506 			temp_pipe->dsc_padding_params.dsc_hactive_padding = pipe->dsc_padding_params.dsc_hactive_padding;
507 			temp_pipe->dsc_padding_params.dsc_htotal_padding = pipe->dsc_padding_params.dsc_htotal_padding;
508 			temp_pipe->dsc_padding_params.dsc_pix_clk_100hz = pipe->dsc_padding_params.dsc_pix_clk_100hz;
509 			dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
510 			break;
511 		}
512 	}
513 
514 	ASSERT(i < MAX_PIPES);
515 	return &temp_pipe->plane_res.scl_data;
516 }
517 
518 static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dml_ctx,
519 		struct dml2_plane_parameters *plane, const struct dc_plane_state *plane_state,
520 		const struct dc_state *context, unsigned int stream_index, const struct dml2_soc_bb *soc_bb)
521 {
522 	const struct scaler_data *scaler_data = get_scaler_data_for_plane(dml_ctx, plane_state, context);
523 	struct dc_stream_state *stream = context->streams[stream_index];
524 
525 	plane->cursor.cursor_bpp = 32;
526 	plane->cursor.cursor_width = 256;
527 	plane->cursor.num_cursors = 1;
528 
529 	switch (plane_state->format) {
530 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
531 	case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
532 		plane->pixel_format = dml2_420_8;
533 		break;
534 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
535 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
536 		plane->pixel_format = dml2_420_10;
537 		break;
538 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
539 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
540 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
541 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
542 		plane->pixel_format = dml2_444_64;
543 		break;
544 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
545 	case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
546 		plane->pixel_format = dml2_444_16;
547 		break;
548 	case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
549 		plane->pixel_format = dml2_444_8;
550 		break;
551 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
552 		plane->pixel_format = dml2_rgbe_alpha;
553 		break;
554 	default:
555 		plane->pixel_format = dml2_444_32;
556 		break;
557 	}
558 
559 	plane->composition.viewport.plane0.height = scaler_data->viewport.height;
560 	plane->composition.viewport.plane0.width = scaler_data->viewport.width;
561 	plane->composition.viewport.plane1.height = scaler_data->viewport_c.height;
562 	plane->composition.viewport.plane1.width = scaler_data->viewport_c.width;
563 	plane->composition.viewport.plane0.x_start = scaler_data->viewport.x;
564 	plane->composition.viewport.plane0.y_start = scaler_data->viewport.y;
565 	plane->composition.viewport.plane1.x_start = scaler_data->viewport_c.x;
566 	plane->composition.viewport.plane1.y_start = scaler_data->viewport_c.y;
567 	plane->composition.viewport.stationary = false;
568 	plane->composition.scaler_info.enabled = scaler_data->ratios.horz.value != dc_fixpt_one.value ||
569 		scaler_data->ratios.horz_c.value != dc_fixpt_one.value ||
570 		scaler_data->ratios.vert.value != dc_fixpt_one.value ||
571 		scaler_data->ratios.vert_c.value != dc_fixpt_one.value;
572 
573 	if (!scaler_data->taps.h_taps) {
574 		/* Above logic determines scaling should be enabled even when there are no taps for
575 		 * certain cases. Hence do corrective active and disable scaling.
576 		 */
577 		plane->composition.scaler_info.enabled = false;
578 	} else if ((plane_state->ctx->dc->config.use_spl == true) &&
579 		(plane->composition.scaler_info.enabled == false)) {
580 		/* To enable sharpener for 1:1, scaler must be enabled.  If use_spl is set, then
581 		 *  allow case where ratio is 1 but taps > 1
582 		 */
583 		if ((scaler_data->taps.h_taps > 1) || (scaler_data->taps.v_taps > 1) ||
584 			(scaler_data->taps.h_taps_c > 1) || (scaler_data->taps.v_taps_c > 1))
585 			plane->composition.scaler_info.enabled = true;
586 	}
587 
588 	/* always_scale is only used for debug purposes not used in production but has to be
589 	 * maintained for certain complainces. */
590 	if (plane_state->ctx->dc->debug.always_scale == true) {
591 		plane->composition.scaler_info.enabled = true;
592 	}
593 
594 	if (plane->composition.scaler_info.enabled == false) {
595 		plane->composition.scaler_info.plane0.h_ratio = 1.0;
596 		plane->composition.scaler_info.plane0.v_ratio = 1.0;
597 		plane->composition.scaler_info.plane1.h_ratio = 1.0;
598 		plane->composition.scaler_info.plane1.v_ratio = 1.0;
599 	} else {
600 		plane->composition.scaler_info.plane0.h_ratio = (double)scaler_data->ratios.horz.value / (1ULL << 32);
601 		plane->composition.scaler_info.plane0.v_ratio = (double)scaler_data->ratios.vert.value / (1ULL << 32);
602 		plane->composition.scaler_info.plane1.h_ratio = (double)scaler_data->ratios.horz_c.value / (1ULL << 32);
603 		plane->composition.scaler_info.plane1.v_ratio = (double)scaler_data->ratios.vert_c.value / (1ULL << 32);
604 	}
605 
606 	if (!scaler_data->taps.h_taps) {
607 		plane->composition.scaler_info.plane0.h_taps = 1;
608 		plane->composition.scaler_info.plane1.h_taps = 1;
609 	} else {
610 		plane->composition.scaler_info.plane0.h_taps = scaler_data->taps.h_taps;
611 		plane->composition.scaler_info.plane1.h_taps = scaler_data->taps.h_taps_c;
612 	}
613 	if (!scaler_data->taps.v_taps) {
614 		plane->composition.scaler_info.plane0.v_taps = 1;
615 		plane->composition.scaler_info.plane1.v_taps = 1;
616 	} else {
617 		plane->composition.scaler_info.plane0.v_taps = scaler_data->taps.v_taps;
618 		plane->composition.scaler_info.plane1.v_taps = scaler_data->taps.v_taps_c;
619 	}
620 
621 	plane->composition.viewport.stationary = false;
622 
623 #ifndef TRIM_CM2
624 	if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
625 		plane->tdlut.setup_for_tdlut = true;
626 
627 		switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.layout) {
628 		case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
629 		case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
630 			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_sw_linear;
631 			break;
632 		case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
633 			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
634 			break;
635 		}
636 
637 		switch (plane_state->mcm_luts.lut3d_data.gpu_mem_params.size) {
638 		case DC_CM2_GPU_MEM_SIZE_171717:
639 			plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
640 			break;
641 		case DC_CM2_GPU_MEM_SIZE_333333:
642 			plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube;
643 			break;
644 		// handling when use case and HW support available
645 		case DC_CM2_GPU_MEM_SIZE_454545:
646 		case DC_CM2_GPU_MEM_SIZE_656565:
647 			break;
648 		case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
649 		default:
650 			//plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
651 			break;
652 		}
653 	}
654 #else
655 	if (plane_state->cm.flags.bits.lut3d_dma_enable) {
656 		plane->tdlut.setup_for_tdlut = true;
657 
658 		switch (plane_state->cm.lut3d_dma.swizzle) {
659 		case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
660 		case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
661 			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_sw_linear;
662 			break;
663 		case CM_LUT_1D_PACKED_LINEAR:
664 			plane->tdlut.tdlut_addressing_mode = dml2_tdlut_simple_linear;
665 			break;
666 		}
667 
668 		switch (plane_state->cm.lut3d_dma.size) {
669 		case CM_LUT_SIZE_171717:
670 			plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
671 			break;
672 		case CM_LUT_SIZE_333333:
673 			plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube;
674 			break;
675 		// handling when use case and HW support available
676 		case CM_LUT_SIZE_454545:
677 		case CM_LUT_SIZE_656565:
678 			break;
679 		case CM_LUT_SIZE_NONE:
680 		case CM_LUT_SIZE_999:
681 		default:
682 			//plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
683 			break;
684 		}
685 	}
686 #endif // TRIM_CM2
687 	plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable;
688 
689 	plane->dynamic_meta_data.enable = false;
690 	plane->dynamic_meta_data.lines_before_active_required = 0;
691 	plane->dynamic_meta_data.transmitted_bytes = 0;
692 
693 	plane->composition.scaler_info.rect_out_width = plane_state->dst_rect.width;
694 	plane->composition.rotation_angle = (enum dml2_rotation_angle) plane_state->rotation;
695 	plane->stream_index = stream_index;
696 
697 	plane->overrides.gpuvm_min_page_size_kbytes = soc_bb->gpuvm_min_page_size_kbytes;
698 	plane->overrides.hostvm_min_page_size_kbytes = soc_bb->hostvm_min_page_size_kbytes;
699 
700 	//Always true for DAL, we want to validate the worst case scenario as we have to switch b/w the two without possibility of failure.
701 	plane->immediate_flip = true;
702 
703 	plane->composition.rect_out_height_spans_vactive =
704 		plane_state->dst_rect.height >= stream->src.height &&
705 		stream->dst.height >= stream->timing.v_addressable;
706 }
707 
708 //TODO : Could be possibly moved to a common helper layer.
709 static bool dml21_wrapper_get_plane_id(const struct dc_state *context, unsigned int stream_id, const struct dc_plane_state *plane, unsigned int *plane_id)
710 {
711 	int i, j;
712 
713 	if (!plane_id)
714 		return false;
715 
716 	for (i = 0; i < context->stream_count; i++) {
717 		if (context->streams[i]->stream_id == stream_id) {
718 			for (j = 0; j < context->stream_status[i].plane_count; j++) {
719 				if (context->stream_status[i].plane_states[j] == plane) {
720 					*plane_id = (i << 16) | j;
721 					return true;
722 				}
723 			}
724 		}
725 	}
726 
727 	return false;
728 }
729 
730 static unsigned int map_stream_to_dml21_display_cfg(const struct dml2_context *dml_ctx, const struct dc_stream_state *stream)
731 {
732 	int i = 0;
733 	int location = -1;
734 
735 	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
736 		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) {
737 			location = i;
738 			break;
739 		}
740 	}
741 
742 	return location;
743 }
744 
745 unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id,
746 		const struct dc_plane_state *plane, const struct dc_state *context)
747 {
748 	unsigned int plane_id;
749 	int i = 0;
750 	int location = -1;
751 
752 	if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) {
753 		ASSERT(false);
754 		return UINT_MAX;
755 	}
756 
757 	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
758 		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) {
759 			location = i;
760 			break;
761 		}
762 	}
763 
764 	return location;
765 }
766 
767 static enum dml2_uclk_pstate_change_strategy dml21_force_pstate_method_to_uclk_state_change_strategy(enum dml2_force_pstate_methods force_pstate_method)
768 {
769 	enum dml2_uclk_pstate_change_strategy val = dml2_uclk_pstate_change_strategy_auto;
770 
771 	switch (force_pstate_method) {
772 	case dml2_force_pstate_method_vactive:
773 		val = dml2_uclk_pstate_change_strategy_force_vactive;
774 		break;
775 	case dml2_force_pstate_method_vblank:
776 		val = dml2_uclk_pstate_change_strategy_force_vblank;
777 		break;
778 	case dml2_force_pstate_method_drr:
779 		val = dml2_uclk_pstate_change_strategy_force_drr;
780 		break;
781 	case dml2_force_pstate_method_subvp:
782 		val = dml2_uclk_pstate_change_strategy_force_mall_svp;
783 		break;
784 	case dml2_force_pstate_method_auto:
785 	default:
786 		val = dml2_uclk_pstate_change_strategy_auto;
787 	}
788 
789 	return val;
790 }
791 
792 bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
793 {
794 	int stream_index, plane_index;
795 	int disp_cfg_stream_location, disp_cfg_plane_location;
796 	struct dml2_display_cfg *dml_dispcfg = &dml_ctx->v21.display_config;
797 	unsigned int plane_count = 0;
798 
799 	memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
800 
801 	dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable;
802 	if (dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels)
803 		dml_dispcfg->gpuvm_max_page_table_levels = dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels;
804 	else
805 		dml_dispcfg->gpuvm_max_page_table_levels = 4;
806 	dml_dispcfg->hostvm_enable = dml_ctx->config.hostvm_enable;
807 	dml_dispcfg->hostvm_max_non_cached_page_table_levels = dml_ctx->v21.dml_init.soc_bb.hostvm_max_non_cached_page_table_levels;
808 	dml_dispcfg->minimize_det_reallocation = true;
809 	dml_dispcfg->overrides.enable_subvp_implicit_pmo = true;
810 
811 	if (in_dc->debug.disable_unbounded_requesting) {
812 		dml_dispcfg->overrides.hw.force_unbounded_requesting.enable = true;
813 		dml_dispcfg->overrides.hw.force_unbounded_requesting.value = false;
814 	}
815 
816 	for (stream_index = 0; stream_index < context->stream_count; stream_index++) {
817 		disp_cfg_stream_location = map_stream_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]);
818 
819 		if (disp_cfg_stream_location < 0)
820 			disp_cfg_stream_location = dml_dispcfg->num_streams++;
821 
822 		ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__);
823 		populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index], dml_ctx);
824 		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]);
825 		populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index], &context->stream_status[stream_index]);
826 
827 		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.fclk_pstate = dml2_twait_budgeting_setting_if_needed;
828 		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.uclk_pstate = dml2_twait_budgeting_setting_if_needed;
829 		dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.stutter_enter_exit = dml2_twait_budgeting_setting_if_needed;
830 
831 		dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id[disp_cfg_stream_location] = context->streams[stream_index]->stream_id;
832 		dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_stream_id_valid[disp_cfg_stream_location] = true;
833 
834 		if (context->stream_status[stream_index].plane_count == 0) {
835 			disp_cfg_plane_location = dml_dispcfg->num_planes++;
836 			populate_dml21_dummy_surface_cfg(&dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->streams[stream_index]);
837 			populate_dml21_dummy_plane_cfg(
838 				&dml_dispcfg->plane_descriptors[disp_cfg_plane_location],
839 				context->streams[stream_index], &dml_ctx->v21.dml_init.soc_bb);
840 			dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
841 		} else {
842 			for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) {
843 				disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], context);
844 
845 				if (disp_cfg_plane_location < 0)
846 					disp_cfg_plane_location = dml_dispcfg->num_planes++;
847 
848 				ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__);
849 
850 				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]);
851 				populate_dml21_plane_config_from_plane_state(
852 					dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location],
853 					context->stream_status[stream_index].plane_states[plane_index],
854 					context, stream_index, &dml_ctx->v21.dml_init.soc_bb);
855 				dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;
856 
857 				if (dml21_wrapper_get_plane_id(context, context->streams[stream_index]->stream_id, 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]))
858 					dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true;
859 
860 				/* apply forced pstate policy */
861 				if (dml_ctx->config.pmo.force_pstate_method_enable) {
862 					dml_dispcfg->plane_descriptors[disp_cfg_plane_location].overrides.uclk_pstate_change_strategy =
863 							dml21_force_pstate_method_to_uclk_state_change_strategy(dml_ctx->config.pmo.force_pstate_method_values[stream_index]);
864 				}
865 
866 				plane_count++;
867 			}
868 		}
869 	}
870 
871 	if (plane_count == 0) {
872 		dml_dispcfg->overrides.all_streams_blanked = true;
873 	}
874 
875 	return true;
876 }
877 
878 void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state *context)
879 {
880 	/* TODO these should be the max of active, svp prefetch and idle should be tracked seperately */
881 	context->bw_ctx.bw.dcn.clk.dispclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dispclk_khz;
882 	context->bw_ctx.bw.dcn.clk.dcfclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.dcfclk_khz;
883 	context->bw_ctx.bw.dcn.clk.dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.uclk_khz;
884 	context->bw_ctx.bw.dcn.clk.fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.active.fclk_khz;
885 	context->bw_ctx.bw.dcn.clk.idle_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.uclk_khz;
886 	context->bw_ctx.bw.dcn.clk.idle_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.idle.fclk_khz;
887 	context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.deepsleep_dcfclk_khz;
888 	context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = in_ctx->v21.mode_programming.programming->fclk_pstate_supported;
889 	context->bw_ctx.bw.dcn.clk.p_state_change_support = in_ctx->v21.mode_programming.programming->uclk_pstate_supported;
890 	context->bw_ctx.bw.dcn.clk.dtbclk_en = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz > 0;
891 	context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.dtbrefclk_khz;
892 	context->bw_ctx.bw.dcn.clk.socclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.socclk_khz;
893 	context->bw_ctx.bw.dcn.clk.subvp_prefetch_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.uclk_khz;
894 	context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
895 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency;
896 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency;
897 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency;
898 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period = (int)in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_period;
899 	context->bw_ctx.bw.dcn.clk.zstate_support = in_ctx->v21.mode_programming.programming->z8_stutter.supported_in_blank; /*ignore meets_eco since it is not used*/
900 }
901 
902 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)
903 {
904 	struct dml2_dchub_watermark_regs *wm_regs = NULL;
905 
906 	switch (wm_index) {
907 	case DML2_DCHUB_WATERMARK_SET_A:
908 		wm_regs = &watermarks->dcn4x.a;
909 		break;
910 	case DML2_DCHUB_WATERMARK_SET_B:
911 		wm_regs = &watermarks->dcn4x.b;
912 		break;
913 	case DML2_DCHUB_WATERMARK_SET_C:
914 		wm_regs = &watermarks->dcn4x.c;
915 		break;
916 	case DML2_DCHUB_WATERMARK_SET_D:
917 		wm_regs = &watermarks->dcn4x.d;
918 		break;
919 	case DML2_DCHUB_WATERMARK_SET_NUM:
920 	default:
921 		/* invalid wm set index */
922 		wm_regs = NULL;
923 	}
924 
925 	return wm_regs;
926 }
927 
928 void dml21_extract_watermark_sets(const struct dc *in_dc, union dcn_watermark_set *watermarks, struct dml2_context *in_ctx)
929 {
930 	(void)in_dc;
931 	const struct dml2_display_cfg_programming *programming = in_ctx->v21.mode_programming.programming;
932 
933 	unsigned int wm_index;
934 
935 	/* copy watermark sets from DML */
936 	for (wm_index = 0; wm_index < programming->global_regs.num_watermark_sets; wm_index++) {
937 		struct dml2_dchub_watermark_regs *wm_regs = wm_set_index_to_dc_wm_set(watermarks, wm_index);
938 
939 		if (wm_regs)
940 			memcpy(wm_regs,
941 				&programming->global_regs.wm_regs[wm_index],
942 				sizeof(struct dml2_dchub_watermark_regs));
943 	}
944 }
945 
946 void dml21_map_hw_resources(struct dml2_context *dml_ctx)
947 {
948 	unsigned int i = 0;
949 
950 	for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
951 		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];
952 		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[i] = true;
953 		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];
954 		dml_ctx->v21.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[i] = true;
955 	}
956 
957 }
958 
959 void dml21_get_pipe_mcache_config(
960 	struct dc_state *context,
961 	struct pipe_ctx *pipe_ctx,
962 	struct dml2_per_plane_programming *pln_prog,
963 	struct dml2_pipe_configuration_descriptor *mcache_pipe_config)
964 {
965 	(void)context;
966 	mcache_pipe_config->plane0.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x;
967 	mcache_pipe_config->plane0.viewport_width = pipe_ctx->plane_res.scl_data.viewport.width;
968 
969 	mcache_pipe_config->plane1.viewport_x_start = pipe_ctx->plane_res.scl_data.viewport_c.x;
970 	mcache_pipe_config->plane1.viewport_width = pipe_ctx->plane_res.scl_data.viewport_c.width;
971 
972 	mcache_pipe_config->plane1_enabled =
973 			dml21_is_plane1_enabled(pln_prog->plane_descriptor->pixel_format);
974 }
975 
976 void dml21_set_dc_p_state_type(
977 		struct pipe_ctx *pipe_ctx,
978 		struct dml2_per_stream_programming *stream_programming,
979 		bool sub_vp_enabled)
980 {
981 	switch (stream_programming->uclk_pstate_method) {
982 	case dml2_pstate_method_vactive:
983 	case dml2_pstate_method_fw_vactive_drr:
984 		pipe_ctx->p_state_type = P_STATE_V_ACTIVE;
985 		break;
986 	case dml2_pstate_method_vblank:
987 	case dml2_pstate_method_fw_vblank_drr:
988 		if (sub_vp_enabled)
989 			pipe_ctx->p_state_type = P_STATE_V_BLANK_SUB_VP;
990 		else
991 			pipe_ctx->p_state_type = P_STATE_V_BLANK;
992 		break;
993 	case dml2_pstate_method_fw_svp:
994 	case dml2_pstate_method_fw_svp_drr:
995 		pipe_ctx->p_state_type = P_STATE_SUB_VP;
996 		break;
997 	case dml2_pstate_method_fw_drr:
998 		if (sub_vp_enabled)
999 			pipe_ctx->p_state_type = P_STATE_DRR_SUB_VP;
1000 		else
1001 			pipe_ctx->p_state_type = P_STATE_FPO;
1002 		break;
1003 	default:
1004 		pipe_ctx->p_state_type = P_STATE_UNKNOWN;
1005 		break;
1006 	}
1007 }
1008 
1009 void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_state *context)
1010 {
1011 	unsigned int lowest_dpm_state_index = 0;
1012 	struct dc_clocks *min_clocks = &context->bw_ctx.bw.dcn.clk;
1013 
1014 	min_clocks->dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[lowest_dpm_state_index];
1015 	min_clocks->dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[lowest_dpm_state_index];
1016 	min_clocks->dcfclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dcfclk.clk_values_khz[lowest_dpm_state_index];
1017 	min_clocks->dramclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.uclk.clk_values_khz[lowest_dpm_state_index];
1018 	min_clocks->fclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.fclk.clk_values_khz[lowest_dpm_state_index];
1019 	min_clocks->idle_dramclk_khz = 0;
1020 	min_clocks->idle_fclk_khz = 0;
1021 	min_clocks->dcfclk_deep_sleep_khz = 0;
1022 	min_clocks->fclk_p_state_change_support = true;
1023 	min_clocks->p_state_change_support = true;
1024 	min_clocks->dtbclk_en = false;
1025 	min_clocks->ref_dtbclk_khz = 0;
1026 	min_clocks->socclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.socclk.clk_values_khz[lowest_dpm_state_index];
1027 	min_clocks->subvp_prefetch_dramclk_khz = 0;
1028 	min_clocks->subvp_prefetch_fclk_khz = 0;
1029 	min_clocks->phyclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.phyclk.clk_values_khz[lowest_dpm_state_index];
1030 	min_clocks->stutter_efficiency.base_efficiency = 1;
1031 	min_clocks->stutter_efficiency.low_power_efficiency = 1;
1032 	min_clocks->stutter_efficiency.z8_stutter_efficiency = 1;
1033 	min_clocks->stutter_efficiency.z8_stutter_period = 100000;
1034 	min_clocks->zstate_support = DCN_ZSTATE_SUPPORT_ALLOW;
1035 }
1036 
1037