1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4 
5 
6 #include "dml2_internal_types.h"
7 #include "dml_top.h"
8 #include "dml2_core_dcn4_calcs.h"
9 #include "dml2_internal_shared_types.h"
10 #include "dml21_utils.h"
11 #include "dml21_translation_helper.h"
12 #include "dml2_dc_resource_mgmt.h"
13 
14 static bool dml21_allocate_memory(struct dml2_context **dml_ctx)
15 {
16 	*dml_ctx = kzalloc(sizeof(struct dml2_context), GFP_KERNEL);
17 	if (!(*dml_ctx))
18 		return false;
19 
20 	(*dml_ctx)->v21.dml_init.dml2_instance = kzalloc(sizeof(struct dml2_instance), GFP_KERNEL);
21 	if (!((*dml_ctx)->v21.dml_init.dml2_instance))
22 		return false;
23 
24 	(*dml_ctx)->v21.mode_support.dml2_instance = (*dml_ctx)->v21.dml_init.dml2_instance;
25 	(*dml_ctx)->v21.mode_programming.dml2_instance = (*dml_ctx)->v21.dml_init.dml2_instance;
26 
27 	(*dml_ctx)->v21.mode_support.display_config = &(*dml_ctx)->v21.display_config;
28 	(*dml_ctx)->v21.mode_programming.display_config = (*dml_ctx)->v21.mode_support.display_config;
29 
30 	(*dml_ctx)->v21.mode_programming.programming = kzalloc(sizeof(struct dml2_display_cfg_programming), GFP_KERNEL);
31 	if (!((*dml_ctx)->v21.mode_programming.programming))
32 		return false;
33 
34 	return true;
35 }
36 
37 static void dml21_apply_debug_options(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
38 {
39 	bool disable_fams2;
40 	struct dml2_pmo_options *pmo_options = &dml_ctx->v21.dml_init.options.pmo_options;
41 
42 	/* ODM options */
43 	pmo_options->disable_dyn_odm = !config->minimize_dispclk_using_odm;
44 	pmo_options->disable_dyn_odm_for_multi_stream = true;
45 	pmo_options->disable_dyn_odm_for_stream_with_svp = true;
46 
47 	/* UCLK P-State options */
48 	if (in_dc->debug.dml21_force_pstate_method) {
49 		dml_ctx->config.pmo.force_pstate_method_enable = true;
50 		for (int i = 0; i < MAX_PIPES; i++)
51 			dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i];
52 	} else {
53 		dml_ctx->config.pmo.force_pstate_method_enable = false;
54 	}
55 
56 	pmo_options->disable_vblank = ((in_dc->debug.dml21_disable_pstate_method_mask >> 1) & 1);
57 
58 	/* NOTE: DRR and SubVP Require FAMS2 */
59 	disable_fams2 = !in_dc->debug.fams2_config.bits.enable;
60 	pmo_options->disable_svp = ((in_dc->debug.dml21_disable_pstate_method_mask >> 2) & 1) ||
61 			in_dc->debug.force_disable_subvp ||
62 			disable_fams2;
63 	pmo_options->disable_drr_clamped = ((in_dc->debug.dml21_disable_pstate_method_mask >> 3) & 1) ||
64 			disable_fams2;
65 	pmo_options->disable_drr_var = ((in_dc->debug.dml21_disable_pstate_method_mask >> 4) & 1) ||
66 			disable_fams2;
67 	pmo_options->disable_fams2 = disable_fams2;
68 
69 	pmo_options->disable_drr_var_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE ||
70 			in_dc->debug.disable_fams_gaming == INGAME_FAMS_MULTI_DISP_CLAMPED_ONLY;
71 	pmo_options->disable_drr_clamped_when_var_active = in_dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE;
72 }
73 
74 static void dml21_init(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config)
75 {
76 	switch (in_dc->ctx->dce_version) {
77 	case DCN_VERSION_4_01:
78 		(*dml_ctx)->v21.dml_init.options.project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
79 		break;
80 	default:
81 		(*dml_ctx)->v21.dml_init.options.project_id = dml2_project_invalid;
82 	}
83 
84 	(*dml_ctx)->architecture = dml2_architecture_21;
85 
86 	/* Store configuration options */
87 	(*dml_ctx)->config = *config;
88 
89 	DC_FP_START();
90 
91 	/*Initialize SOCBB and DCNIP params */
92 	dml21_initialize_soc_bb_params(&(*dml_ctx)->v21.dml_init, config, in_dc);
93 	dml21_initialize_ip_params(&(*dml_ctx)->v21.dml_init, config, in_dc);
94 	dml21_apply_soc_bb_overrides(&(*dml_ctx)->v21.dml_init, config, in_dc);
95 
96 	/* apply debug overrides */
97 	dml21_apply_debug_options(in_dc, *dml_ctx, config);
98 
99 	/*Initialize DML21 instance */
100 	dml2_initialize_instance(&(*dml_ctx)->v21.dml_init);
101 
102 	DC_FP_END();
103 }
104 
105 bool dml21_create(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config)
106 {
107 	/* Allocate memory for initializing DML21 instance */
108 	if (!dml21_allocate_memory(dml_ctx))
109 		return false;
110 
111 	dml21_init(in_dc, dml_ctx, config);
112 
113 	return true;
114 }
115 
116 void dml21_destroy(struct dml2_context *dml2)
117 {
118 	kfree(dml2->v21.dml_init.dml2_instance);
119 	kfree(dml2->v21.mode_programming.programming);
120 }
121 
122 static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state,
123 	struct dml2_context *in_ctx, unsigned int pipe_cnt)
124 {
125 	unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0;
126 	struct dml2_per_plane_programming *pln_prog = NULL;
127 	struct dml2_per_stream_programming *stream_prog = NULL;
128 	struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
129 	struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
130 	int num_pipes;
131 	unsigned int dml_phantom_prog_idx;
132 
133 	context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
134 
135 	/* copy global DCHUBBUB arbiter registers */
136 	memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs));
137 
138 	/* legacy only */
139 	context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64;
140 
141 	context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0;
142 	context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0;
143 	context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0;
144 
145 	/* phantom's start after main planes */
146 	dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes;
147 
148 	for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) {
149 		pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
150 
151 		if (!pln_prog->plane_descriptor)
152 			continue;
153 
154 		stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index];
155 		num_dpps_required = pln_prog->num_dpps_required;
156 
157 		if (num_dpps_required == 0) {
158 			continue;
159 		}
160 		num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
161 
162 		if (num_pipes <= 0)
163 			continue;
164 
165 		/* program each pipe */
166 		for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
167 			dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog);
168 
169 			if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) {
170 				dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog);
171 			}
172 		}
173 
174 		/* copy per plane mcache allocation */
175 		memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));
176 		if (pln_prog->phantom_plane.valid) {
177 			memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx],
178 					&pln_prog->phantom_plane.mcache_allocation,
179 					sizeof(struct dml2_mcache_surface_allocation));
180 
181 			dml_phantom_prog_idx++;
182 		}
183 	}
184 
185 	/* assign global clocks */
186 	context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
187 	context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
188 	if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
189 		context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
190 			in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
191 	} else {
192 		context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
193 	}
194 
195 	if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
196 		context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
197 			in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
198 	} else {
199 		context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
200 	}
201 
202 	/* get global mall allocation */
203 	if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) {
204 		context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes);
205 	} else {
206 		context->bw_ctx.bw.dcn.clk.num_ways = 0;
207 	}
208 }
209 
210 static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
211 {
212 	bool result = false;
213 	struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming;
214 
215 	memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
216 	memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
217 	memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out));
218 
219 	if (!context)
220 		return true;
221 
222 	if (context->stream_count == 0) {
223 		dml21_build_fams2_programming(in_dc, context, dml_ctx);
224 		return true;
225 	}
226 
227 	/* scrub phantom's from current dc_state */
228 	dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
229 	dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
230 
231 	/* Populate stream, plane mappings and other fields in display config. */
232 	result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
233 	if (!result)
234 		return false;
235 
236 	result = dml2_build_mode_programming(mode_programming);
237 	if (!result)
238 		return false;
239 
240 	/* Check and map HW resources */
241 	if (result && !dml_ctx->config.skip_hw_state_mapping) {
242 		dml21_map_hw_resources(dml_ctx);
243 		dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state);
244 		/* if subvp phantoms are present, expand them into dc context */
245 		dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx);
246 	}
247 
248 	/* Copy DML CLK, WM and REG outputs to bandwidth context */
249 	if (result && !dml_ctx->config.skip_hw_state_mapping) {
250 		dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
251 		dml21_copy_clocks_to_dc_state(dml_ctx, context);
252 		dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
253 		dml21_build_fams2_programming(in_dc, context, dml_ctx);
254 	}
255 
256 	return true;
257 }
258 
259 static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
260 {
261 	bool is_supported = false;
262 	struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init;
263 	struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support;
264 
265 	memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
266 	memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
267 	memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out));
268 
269 	if (!context || context->stream_count == 0)
270 		return true;
271 
272 	/* Scrub phantom's from current dc_state */
273 	dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
274 	dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
275 
276 	mode_support->dml2_instance = dml_init->dml2_instance;
277 	dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
278 	dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
279 	is_supported = dml2_check_mode_supported(mode_support);
280 	if (!is_supported)
281 		return false;
282 
283 	return true;
284 }
285 
286 bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx, bool fast_validate)
287 {
288 	bool out = false;
289 
290 	DC_FP_START();
291 
292 	/* Use dml_validate_only for fast_validate path */
293 	if (fast_validate)
294 		out = dml21_check_mode_support(in_dc, context, dml_ctx);
295 	else
296 		out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
297 
298 	DC_FP_END();
299 
300 	return out;
301 }
302 
303 void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
304 {
305 	unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
306 	int num_pipes;
307 	struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
308 	struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
309 
310 	struct dml2_per_plane_programming *pln_prog = NULL;
311 	struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL;
312 	struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals;
313 
314 	if (context->stream_count == 0) {
315 		return;
316 	}
317 
318 	memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out));
319 	l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance;
320 
321 	/* phantom's start after main planes */
322 	dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes;
323 
324 	/* Build mcache programming parameters per plane per pipe */
325 	for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
326 		pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
327 
328 		mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx];
329 		memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
330 		mcache_config->plane_descriptor = pln_prog->plane_descriptor;
331 		mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx];
332 		mcache_config->num_pipes = pln_prog->num_dpps_required;
333 		l->build_mcache_programming_params.num_configurations++;
334 
335 		if (pln_prog->num_dpps_required == 0) {
336 			continue;
337 		}
338 
339 		num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
340 		if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
341 		    dc_main_pipes[0]->plane_state == NULL)
342 			continue;
343 
344 		/* get config for each pipe */
345 		for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
346 			ASSERT(dc_main_pipes[dc_pipe_index]);
347 			dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
348 		}
349 
350 		/* get config for each phantom pipe */
351 		if (pln_prog->phantom_plane.valid &&
352 				dc_phantom_pipes[0] &&
353 				dc_main_pipes[0]->stream &&
354 				dc_phantom_pipes[0]->plane_state) {
355 			mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx];
356 			memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
357 			mcache_config->plane_descriptor = pln_prog->plane_descriptor;
358 			mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx];
359 			mcache_config->num_pipes = pln_prog->num_dpps_required;
360 			l->build_mcache_programming_params.num_configurations++;
361 
362 			for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
363 				ASSERT(dc_phantom_pipes[dc_pipe_index]);
364 				dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
365 			}
366 
367 			/* increment phantom index */
368 			dml_phantom_prog_idx++;
369 		}
370 	}
371 
372 	/* Call to generate mcache programming per plane per pipe for the given display configuration */
373 	dml2_build_mcache_programming(&l->build_mcache_programming_params);
374 
375 	/* get per plane per pipe mcache programming */
376 	for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
377 		pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
378 
379 		num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
380 		if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
381 		    dc_main_pipes[0]->plane_state == NULL)
382 			continue;
383 
384 		/* get config for each pipe */
385 		for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
386 			ASSERT(dc_main_pipes[dc_pipe_index]);
387 			if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) {
388 				memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs,
389 						l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index],
390 						sizeof(struct dml2_hubp_pipe_mcache_regs));
391 			}
392 		}
393 
394 		/* get config for each phantom pipe */
395 		if (pln_prog->phantom_plane.valid &&
396 				dc_phantom_pipes[0] &&
397 				dc_main_pipes[0]->stream &&
398 				dc_phantom_pipes[0]->plane_state) {
399 			for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
400 				ASSERT(dc_phantom_pipes[dc_pipe_index]);
401 				if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) {
402 					memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs,
403 							l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index],
404 							sizeof(struct dml2_hubp_pipe_mcache_regs));
405 				}
406 			}
407 			/* increment phantom index */
408 			dml_phantom_prog_idx++;
409 		}
410 	}
411 }
412 
413 void dml21_copy(struct dml2_context *dst_dml_ctx,
414 	struct dml2_context *src_dml_ctx)
415 {
416 	/* Preserve references to internals */
417 	struct dml2_instance *dst_dml2_instance = dst_dml_ctx->v21.dml_init.dml2_instance;
418 	struct dml2_display_cfg_programming *dst_dml2_programming = dst_dml_ctx->v21.mode_programming.programming;
419 
420 	/* Copy context */
421 	memcpy(dst_dml_ctx, src_dml_ctx, sizeof(struct dml2_context));
422 
423 	/* Copy Internals */
424 	memcpy(dst_dml2_instance, src_dml_ctx->v21.dml_init.dml2_instance, sizeof(struct dml2_instance));
425 	memcpy(dst_dml2_programming, src_dml_ctx->v21.mode_programming.programming, sizeof(struct dml2_display_cfg_programming));
426 
427 	/* Restore references to internals */
428 	dst_dml_ctx->v21.dml_init.dml2_instance = dst_dml2_instance;
429 
430 	dst_dml_ctx->v21.mode_support.dml2_instance = dst_dml2_instance;
431 	dst_dml_ctx->v21.mode_programming.dml2_instance = dst_dml2_instance;
432 
433 	dst_dml_ctx->v21.mode_support.display_config = &dst_dml_ctx->v21.display_config;
434 	dst_dml_ctx->v21.mode_programming.display_config = dst_dml_ctx->v21.mode_support.display_config;
435 
436 	dst_dml_ctx->v21.mode_programming.programming = dst_dml2_programming;
437 
438 	DC_FP_START();
439 
440 	/* need to initialize copied instance for internal references to be correct */
441 	dml2_initialize_instance(&dst_dml_ctx->v21.dml_init);
442 
443 	DC_FP_END();
444 }
445 
446 bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
447 	struct dml2_context *src_dml_ctx)
448 {
449 	/* Allocate memory for initializing DML21 instance */
450 	if (!dml21_allocate_memory(dst_dml_ctx))
451 		return false;
452 
453 	dml21_copy(*dst_dml_ctx, src_dml_ctx);
454 
455 	return true;
456 }
457 
458 void dml21_reinit(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config)
459 {
460 	dml21_init(in_dc, dml_ctx, config);
461 }
462 
463