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