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