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