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