1 /* 2 * Copyright 2012-15 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #include <linux/slab.h> 27 28 #include "dm_services.h" 29 30 #include "resource.h" 31 #include "include/irq_service_interface.h" 32 #include "link_encoder.h" 33 #include "stream_encoder.h" 34 #include "opp.h" 35 #include "timing_generator.h" 36 #include "transform.h" 37 #include "dccg.h" 38 #include "dchubbub.h" 39 #include "dpp.h" 40 #include "core_types.h" 41 #include "set_mode_types.h" 42 #include "virtual/virtual_stream_encoder.h" 43 #include "dpcd_defs.h" 44 #include "dc_link_dp.h" 45 46 #if defined(CONFIG_DRM_AMD_DC_SI) 47 #include "dce60/dce60_resource.h" 48 #endif 49 #include "dce80/dce80_resource.h" 50 #include "dce100/dce100_resource.h" 51 #include "dce110/dce110_resource.h" 52 #include "dce112/dce112_resource.h" 53 #include "dce120/dce120_resource.h" 54 #if defined(CONFIG_DRM_AMD_DC_DCN) 55 #include "dcn10/dcn10_resource.h" 56 #include "dcn20/dcn20_resource.h" 57 #include "dcn21/dcn21_resource.h" 58 #include "dcn30/dcn30_resource.h" 59 #include "dcn301/dcn301_resource.h" 60 #include "dcn302/dcn302_resource.h" 61 #include "dcn303/dcn303_resource.h" 62 #include "dcn31/dcn31_resource.h" 63 #endif 64 65 #define DC_LOGGER_INIT(logger) 66 67 enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 68 { 69 enum dce_version dc_version = DCE_VERSION_UNKNOWN; 70 switch (asic_id.chip_family) { 71 72 #if defined(CONFIG_DRM_AMD_DC_SI) 73 case FAMILY_SI: 74 if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) || 75 ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) || 76 ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev)) 77 dc_version = DCE_VERSION_6_0; 78 else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev)) 79 dc_version = DCE_VERSION_6_4; 80 else 81 dc_version = DCE_VERSION_6_1; 82 break; 83 #endif 84 case FAMILY_CI: 85 dc_version = DCE_VERSION_8_0; 86 break; 87 case FAMILY_KV: 88 if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 89 ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 90 ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 91 dc_version = DCE_VERSION_8_3; 92 else 93 dc_version = DCE_VERSION_8_1; 94 break; 95 case FAMILY_CZ: 96 dc_version = DCE_VERSION_11_0; 97 break; 98 99 case FAMILY_VI: 100 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 101 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 102 dc_version = DCE_VERSION_10_0; 103 break; 104 } 105 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 106 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 107 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 108 dc_version = DCE_VERSION_11_2; 109 } 110 if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) 111 dc_version = DCE_VERSION_11_22; 112 break; 113 case FAMILY_AI: 114 if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 115 dc_version = DCE_VERSION_12_1; 116 else 117 dc_version = DCE_VERSION_12_0; 118 break; 119 #if defined(CONFIG_DRM_AMD_DC_DCN) 120 case FAMILY_RV: 121 dc_version = DCN_VERSION_1_0; 122 if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) 123 dc_version = DCN_VERSION_1_01; 124 if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) 125 dc_version = DCN_VERSION_2_1; 126 if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev)) 127 dc_version = DCN_VERSION_2_1; 128 break; 129 130 case FAMILY_NV: 131 dc_version = DCN_VERSION_2_0; 132 if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) 133 dc_version = DCN_VERSION_3_0; 134 if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev)) 135 dc_version = DCN_VERSION_3_02; 136 if (ASICREV_IS_BEIGE_GOBY_P(asic_id.hw_internal_rev)) 137 dc_version = DCN_VERSION_3_03; 138 break; 139 140 case FAMILY_VGH: 141 dc_version = DCN_VERSION_3_01; 142 break; 143 144 case FAMILY_YELLOW_CARP: 145 if (ASICREV_IS_YELLOW_CARP(asic_id.hw_internal_rev)) 146 dc_version = DCN_VERSION_3_1; 147 break; 148 #endif 149 150 default: 151 dc_version = DCE_VERSION_UNKNOWN; 152 break; 153 } 154 return dc_version; 155 } 156 157 struct resource_pool *dc_create_resource_pool(struct dc *dc, 158 const struct dc_init_data *init_data, 159 enum dce_version dc_version) 160 { 161 struct resource_pool *res_pool = NULL; 162 163 switch (dc_version) { 164 #if defined(CONFIG_DRM_AMD_DC_SI) 165 case DCE_VERSION_6_0: 166 res_pool = dce60_create_resource_pool( 167 init_data->num_virtual_links, dc); 168 break; 169 case DCE_VERSION_6_1: 170 res_pool = dce61_create_resource_pool( 171 init_data->num_virtual_links, dc); 172 break; 173 case DCE_VERSION_6_4: 174 res_pool = dce64_create_resource_pool( 175 init_data->num_virtual_links, dc); 176 break; 177 #endif 178 case DCE_VERSION_8_0: 179 res_pool = dce80_create_resource_pool( 180 init_data->num_virtual_links, dc); 181 break; 182 case DCE_VERSION_8_1: 183 res_pool = dce81_create_resource_pool( 184 init_data->num_virtual_links, dc); 185 break; 186 case DCE_VERSION_8_3: 187 res_pool = dce83_create_resource_pool( 188 init_data->num_virtual_links, dc); 189 break; 190 case DCE_VERSION_10_0: 191 res_pool = dce100_create_resource_pool( 192 init_data->num_virtual_links, dc); 193 break; 194 case DCE_VERSION_11_0: 195 res_pool = dce110_create_resource_pool( 196 init_data->num_virtual_links, dc, 197 init_data->asic_id); 198 break; 199 case DCE_VERSION_11_2: 200 case DCE_VERSION_11_22: 201 res_pool = dce112_create_resource_pool( 202 init_data->num_virtual_links, dc); 203 break; 204 case DCE_VERSION_12_0: 205 case DCE_VERSION_12_1: 206 res_pool = dce120_create_resource_pool( 207 init_data->num_virtual_links, dc); 208 break; 209 210 #if defined(CONFIG_DRM_AMD_DC_DCN) 211 case DCN_VERSION_1_0: 212 case DCN_VERSION_1_01: 213 res_pool = dcn10_create_resource_pool(init_data, dc); 214 break; 215 case DCN_VERSION_2_0: 216 res_pool = dcn20_create_resource_pool(init_data, dc); 217 break; 218 case DCN_VERSION_2_1: 219 res_pool = dcn21_create_resource_pool(init_data, dc); 220 break; 221 case DCN_VERSION_3_0: 222 res_pool = dcn30_create_resource_pool(init_data, dc); 223 break; 224 case DCN_VERSION_3_01: 225 res_pool = dcn301_create_resource_pool(init_data, dc); 226 break; 227 case DCN_VERSION_3_02: 228 res_pool = dcn302_create_resource_pool(init_data, dc); 229 break; 230 case DCN_VERSION_3_03: 231 res_pool = dcn303_create_resource_pool(init_data, dc); 232 break; 233 case DCN_VERSION_3_1: 234 res_pool = dcn31_create_resource_pool(init_data, dc); 235 break; 236 #endif 237 default: 238 break; 239 } 240 241 if (res_pool != NULL) { 242 if (dc->ctx->dc_bios->fw_info_valid) { 243 res_pool->ref_clocks.xtalin_clock_inKhz = 244 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; 245 /* initialize with firmware data first, no all 246 * ASIC have DCCG SW component. FPGA or 247 * simulation need initialization of 248 * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz 249 * with xtalin_clock_inKhz 250 */ 251 res_pool->ref_clocks.dccg_ref_clock_inKhz = 252 res_pool->ref_clocks.xtalin_clock_inKhz; 253 res_pool->ref_clocks.dchub_ref_clock_inKhz = 254 res_pool->ref_clocks.xtalin_clock_inKhz; 255 } else 256 ASSERT_CRITICAL(false); 257 } 258 259 return res_pool; 260 } 261 262 void dc_destroy_resource_pool(struct dc *dc) 263 { 264 if (dc) { 265 if (dc->res_pool) 266 dc->res_pool->funcs->destroy(&dc->res_pool); 267 268 kfree(dc->hwseq); 269 } 270 } 271 272 static void update_num_audio( 273 const struct resource_straps *straps, 274 unsigned int *num_audio, 275 struct audio_support *aud_support) 276 { 277 aud_support->dp_audio = true; 278 aud_support->hdmi_audio_native = false; 279 aud_support->hdmi_audio_on_dongle = false; 280 281 if (straps->hdmi_disable == 0) { 282 if (straps->dc_pinstraps_audio & 0x2) { 283 aud_support->hdmi_audio_on_dongle = true; 284 aud_support->hdmi_audio_native = true; 285 } 286 } 287 288 switch (straps->audio_stream_number) { 289 case 0: /* multi streams supported */ 290 break; 291 case 1: /* multi streams not supported */ 292 *num_audio = 1; 293 break; 294 default: 295 DC_ERR("DC: unexpected audio fuse!\n"); 296 } 297 } 298 299 bool resource_construct( 300 unsigned int num_virtual_links, 301 struct dc *dc, 302 struct resource_pool *pool, 303 const struct resource_create_funcs *create_funcs) 304 { 305 struct dc_context *ctx = dc->ctx; 306 const struct resource_caps *caps = pool->res_cap; 307 int i; 308 unsigned int num_audio = caps->num_audio; 309 struct resource_straps straps = {0}; 310 311 if (create_funcs->read_dce_straps) 312 create_funcs->read_dce_straps(dc->ctx, &straps); 313 314 pool->audio_count = 0; 315 if (create_funcs->create_audio) { 316 /* find the total number of streams available via the 317 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 318 * registers (one for each pin) starting from pin 1 319 * up to the max number of audio pins. 320 * We stop on the first pin where 321 * PORT_CONNECTIVITY == 1 (as instructed by HW team). 322 */ 323 update_num_audio(&straps, &num_audio, &pool->audio_support); 324 for (i = 0; i < caps->num_audio; i++) { 325 struct audio *aud = create_funcs->create_audio(ctx, i); 326 327 if (aud == NULL) { 328 DC_ERR("DC: failed to create audio!\n"); 329 return false; 330 } 331 if (!aud->funcs->endpoint_valid(aud)) { 332 aud->funcs->destroy(&aud); 333 break; 334 } 335 pool->audios[i] = aud; 336 pool->audio_count++; 337 } 338 } 339 340 pool->stream_enc_count = 0; 341 if (create_funcs->create_stream_encoder) { 342 for (i = 0; i < caps->num_stream_encoder; i++) { 343 pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 344 if (pool->stream_enc[i] == NULL) 345 DC_ERR("DC: failed to create stream_encoder!\n"); 346 pool->stream_enc_count++; 347 } 348 } 349 350 #if defined(CONFIG_DRM_AMD_DC_DCN) 351 pool->hpo_dp_stream_enc_count = 0; 352 if (create_funcs->create_hpo_dp_stream_encoder) { 353 for (i = 0; i < caps->num_hpo_dp_stream_encoder; i++) { 354 pool->hpo_dp_stream_enc[i] = create_funcs->create_hpo_dp_stream_encoder(i+ENGINE_ID_HPO_DP_0, ctx); 355 if (pool->hpo_dp_stream_enc[i] == NULL) 356 DC_ERR("DC: failed to create HPO DP stream encoder!\n"); 357 pool->hpo_dp_stream_enc_count++; 358 359 } 360 } 361 362 pool->hpo_dp_link_enc_count = 0; 363 if (create_funcs->create_hpo_dp_link_encoder) { 364 for (i = 0; i < caps->num_hpo_dp_link_encoder; i++) { 365 pool->hpo_dp_link_enc[i] = create_funcs->create_hpo_dp_link_encoder(i, ctx); 366 if (pool->hpo_dp_link_enc[i] == NULL) 367 DC_ERR("DC: failed to create HPO DP link encoder!\n"); 368 pool->hpo_dp_link_enc_count++; 369 } 370 } 371 #endif 372 373 #if defined(CONFIG_DRM_AMD_DC_DCN) 374 for (i = 0; i < caps->num_mpc_3dlut; i++) { 375 pool->mpc_lut[i] = dc_create_3dlut_func(); 376 if (pool->mpc_lut[i] == NULL) 377 DC_ERR("DC: failed to create MPC 3dlut!\n"); 378 pool->mpc_shaper[i] = dc_create_transfer_func(); 379 if (pool->mpc_shaper[i] == NULL) 380 DC_ERR("DC: failed to create MPC shaper!\n"); 381 } 382 #endif 383 dc->caps.dynamic_audio = false; 384 if (pool->audio_count < pool->stream_enc_count) { 385 dc->caps.dynamic_audio = true; 386 } 387 for (i = 0; i < num_virtual_links; i++) { 388 pool->stream_enc[pool->stream_enc_count] = 389 virtual_stream_encoder_create( 390 ctx, ctx->dc_bios); 391 if (pool->stream_enc[pool->stream_enc_count] == NULL) { 392 DC_ERR("DC: failed to create stream_encoder!\n"); 393 return false; 394 } 395 pool->stream_enc_count++; 396 } 397 398 dc->hwseq = create_funcs->create_hwseq(ctx); 399 400 return true; 401 } 402 static int find_matching_clock_source( 403 const struct resource_pool *pool, 404 struct clock_source *clock_source) 405 { 406 407 int i; 408 409 for (i = 0; i < pool->clk_src_count; i++) { 410 if (pool->clock_sources[i] == clock_source) 411 return i; 412 } 413 return -1; 414 } 415 416 void resource_unreference_clock_source( 417 struct resource_context *res_ctx, 418 const struct resource_pool *pool, 419 struct clock_source *clock_source) 420 { 421 int i = find_matching_clock_source(pool, clock_source); 422 423 if (i > -1) 424 res_ctx->clock_source_ref_count[i]--; 425 426 if (pool->dp_clock_source == clock_source) 427 res_ctx->dp_clock_source_ref_count--; 428 } 429 430 void resource_reference_clock_source( 431 struct resource_context *res_ctx, 432 const struct resource_pool *pool, 433 struct clock_source *clock_source) 434 { 435 int i = find_matching_clock_source(pool, clock_source); 436 437 if (i > -1) 438 res_ctx->clock_source_ref_count[i]++; 439 440 if (pool->dp_clock_source == clock_source) 441 res_ctx->dp_clock_source_ref_count++; 442 } 443 444 int resource_get_clock_source_reference( 445 struct resource_context *res_ctx, 446 const struct resource_pool *pool, 447 struct clock_source *clock_source) 448 { 449 int i = find_matching_clock_source(pool, clock_source); 450 451 if (i > -1) 452 return res_ctx->clock_source_ref_count[i]; 453 454 if (pool->dp_clock_source == clock_source) 455 return res_ctx->dp_clock_source_ref_count; 456 457 return -1; 458 } 459 460 bool resource_are_vblanks_synchronizable( 461 struct dc_stream_state *stream1, 462 struct dc_stream_state *stream2) 463 { 464 uint32_t base60_refresh_rates[] = {10, 20, 5}; 465 uint8_t i; 466 uint8_t rr_count = ARRAY_SIZE(base60_refresh_rates); 467 uint64_t frame_time_diff; 468 469 if (stream1->ctx->dc->config.vblank_alignment_dto_params && 470 stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 && 471 dc_is_dp_signal(stream1->signal) && 472 dc_is_dp_signal(stream2->signal) && 473 false == stream1->has_non_synchronizable_pclk && 474 false == stream2->has_non_synchronizable_pclk && 475 stream1->timing.flags.VBLANK_SYNCHRONIZABLE && 476 stream2->timing.flags.VBLANK_SYNCHRONIZABLE) { 477 /* disable refresh rates higher than 60Hz for now */ 478 if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/ 479 stream1->timing.v_total > 60) 480 return false; 481 if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/ 482 stream2->timing.v_total > 60) 483 return false; 484 frame_time_diff = (uint64_t)10000 * 485 stream1->timing.h_total * 486 stream1->timing.v_total * 487 stream2->timing.pix_clk_100hz; 488 frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz); 489 frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total); 490 frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total); 491 for (i = 0; i < rr_count; i++) { 492 int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000; 493 494 if (diff < 0) 495 diff = -diff; 496 if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff) 497 return true; 498 } 499 } 500 return false; 501 } 502 503 bool resource_are_streams_timing_synchronizable( 504 struct dc_stream_state *stream1, 505 struct dc_stream_state *stream2) 506 { 507 if (stream1->timing.h_total != stream2->timing.h_total) 508 return false; 509 510 if (stream1->timing.v_total != stream2->timing.v_total) 511 return false; 512 513 if (stream1->timing.h_addressable 514 != stream2->timing.h_addressable) 515 return false; 516 517 if (stream1->timing.v_addressable 518 != stream2->timing.v_addressable) 519 return false; 520 521 if (stream1->timing.v_front_porch 522 != stream2->timing.v_front_porch) 523 return false; 524 525 if (stream1->timing.pix_clk_100hz 526 != stream2->timing.pix_clk_100hz) 527 return false; 528 529 if (stream1->clamping.c_depth != stream2->clamping.c_depth) 530 return false; 531 532 if (stream1->phy_pix_clk != stream2->phy_pix_clk 533 && (!dc_is_dp_signal(stream1->signal) 534 || !dc_is_dp_signal(stream2->signal))) 535 return false; 536 537 if (stream1->view_format != stream2->view_format) 538 return false; 539 540 if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) 541 return false; 542 543 return true; 544 } 545 static bool is_dp_and_hdmi_sharable( 546 struct dc_stream_state *stream1, 547 struct dc_stream_state *stream2) 548 { 549 if (stream1->ctx->dc->caps.disable_dp_clk_share) 550 return false; 551 552 if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 553 stream2->clamping.c_depth != COLOR_DEPTH_888) 554 return false; 555 556 return true; 557 558 } 559 560 static bool is_sharable_clk_src( 561 const struct pipe_ctx *pipe_with_clk_src, 562 const struct pipe_ctx *pipe) 563 { 564 if (pipe_with_clk_src->clock_source == NULL) 565 return false; 566 567 if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 568 return false; 569 570 if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 571 (dc_is_dp_signal(pipe->stream->signal) && 572 !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 573 pipe->stream))) 574 return false; 575 576 if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 577 && dc_is_dual_link_signal(pipe->stream->signal)) 578 return false; 579 580 if (dc_is_hdmi_signal(pipe->stream->signal) 581 && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 582 return false; 583 584 if (!resource_are_streams_timing_synchronizable( 585 pipe_with_clk_src->stream, pipe->stream)) 586 return false; 587 588 return true; 589 } 590 591 struct clock_source *resource_find_used_clk_src_for_sharing( 592 struct resource_context *res_ctx, 593 struct pipe_ctx *pipe_ctx) 594 { 595 int i; 596 597 for (i = 0; i < MAX_PIPES; i++) { 598 if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 599 return res_ctx->pipe_ctx[i].clock_source; 600 } 601 602 return NULL; 603 } 604 605 static enum pixel_format convert_pixel_format_to_dalsurface( 606 enum surface_pixel_format surface_pixel_format) 607 { 608 enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 609 610 switch (surface_pixel_format) { 611 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 612 dal_pixel_format = PIXEL_FORMAT_INDEX8; 613 break; 614 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 615 dal_pixel_format = PIXEL_FORMAT_RGB565; 616 break; 617 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 618 dal_pixel_format = PIXEL_FORMAT_RGB565; 619 break; 620 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 621 dal_pixel_format = PIXEL_FORMAT_ARGB8888; 622 break; 623 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 624 dal_pixel_format = PIXEL_FORMAT_ARGB8888; 625 break; 626 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 627 dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 628 break; 629 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 630 dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 631 break; 632 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 633 dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 634 break; 635 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 636 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 637 dal_pixel_format = PIXEL_FORMAT_FP16; 638 break; 639 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 640 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 641 dal_pixel_format = PIXEL_FORMAT_420BPP8; 642 break; 643 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 644 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 645 dal_pixel_format = PIXEL_FORMAT_420BPP10; 646 break; 647 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 648 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 649 default: 650 dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 651 break; 652 } 653 return dal_pixel_format; 654 } 655 656 static inline void get_vp_scan_direction( 657 enum dc_rotation_angle rotation, 658 bool horizontal_mirror, 659 bool *orthogonal_rotation, 660 bool *flip_vert_scan_dir, 661 bool *flip_horz_scan_dir) 662 { 663 *orthogonal_rotation = false; 664 *flip_vert_scan_dir = false; 665 *flip_horz_scan_dir = false; 666 if (rotation == ROTATION_ANGLE_180) { 667 *flip_vert_scan_dir = true; 668 *flip_horz_scan_dir = true; 669 } else if (rotation == ROTATION_ANGLE_90) { 670 *orthogonal_rotation = true; 671 *flip_horz_scan_dir = true; 672 } else if (rotation == ROTATION_ANGLE_270) { 673 *orthogonal_rotation = true; 674 *flip_vert_scan_dir = true; 675 } 676 677 if (horizontal_mirror) 678 *flip_horz_scan_dir = !*flip_horz_scan_dir; 679 } 680 681 int get_num_mpc_splits(struct pipe_ctx *pipe) 682 { 683 int mpc_split_count = 0; 684 struct pipe_ctx *other_pipe = pipe->bottom_pipe; 685 686 while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 687 mpc_split_count++; 688 other_pipe = other_pipe->bottom_pipe; 689 } 690 other_pipe = pipe->top_pipe; 691 while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 692 mpc_split_count++; 693 other_pipe = other_pipe->top_pipe; 694 } 695 696 return mpc_split_count; 697 } 698 699 int get_num_odm_splits(struct pipe_ctx *pipe) 700 { 701 int odm_split_count = 0; 702 struct pipe_ctx *next_pipe = pipe->next_odm_pipe; 703 while (next_pipe) { 704 odm_split_count++; 705 next_pipe = next_pipe->next_odm_pipe; 706 } 707 pipe = pipe->prev_odm_pipe; 708 while (pipe) { 709 odm_split_count++; 710 pipe = pipe->prev_odm_pipe; 711 } 712 return odm_split_count; 713 } 714 715 static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) 716 { 717 *split_count = get_num_odm_splits(pipe_ctx); 718 *split_idx = 0; 719 if (*split_count == 0) { 720 /*Check for mpc split*/ 721 struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; 722 723 *split_count = get_num_mpc_splits(pipe_ctx); 724 while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { 725 (*split_idx)++; 726 split_pipe = split_pipe->top_pipe; 727 } 728 } else { 729 /*Get odm split index*/ 730 struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; 731 732 while (split_pipe) { 733 (*split_idx)++; 734 split_pipe = split_pipe->prev_odm_pipe; 735 } 736 } 737 } 738 739 /* 740 * This is a preliminary vp size calculation to allow us to check taps support. 741 * The result is completely overridden afterwards. 742 */ 743 static void calculate_viewport_size(struct pipe_ctx *pipe_ctx) 744 { 745 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 746 747 data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width)); 748 data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height)); 749 data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width)); 750 data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height)); 751 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 752 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) { 753 swap(data->viewport.width, data->viewport.height); 754 swap(data->viewport_c.width, data->viewport_c.height); 755 } 756 } 757 758 static void calculate_recout(struct pipe_ctx *pipe_ctx) 759 { 760 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 761 const struct dc_stream_state *stream = pipe_ctx->stream; 762 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 763 struct rect surf_clip = plane_state->clip_rect; 764 bool split_tb = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 765 int split_count, split_idx; 766 767 calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 768 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 769 split_idx = 0; 770 771 /* 772 * Only the leftmost ODM pipe should be offset by a nonzero distance 773 */ 774 if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) { 775 data->recout.x = stream->dst.x; 776 if (stream->src.x < surf_clip.x) 777 data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width 778 / stream->src.width; 779 } else 780 data->recout.x = 0; 781 782 if (stream->src.x > surf_clip.x) 783 surf_clip.width -= stream->src.x - surf_clip.x; 784 data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; 785 if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) 786 data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; 787 788 data->recout.y = stream->dst.y; 789 if (stream->src.y < surf_clip.y) 790 data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height 791 / stream->src.height; 792 else if (stream->src.y > surf_clip.y) 793 surf_clip.height -= stream->src.y - surf_clip.y; 794 795 data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; 796 if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) 797 data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; 798 799 /* Handle h & v split */ 800 if (split_tb) { 801 ASSERT(data->recout.height % 2 == 0); 802 data->recout.height /= 2; 803 } else if (split_count) { 804 if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { 805 /* extra pixels in the division remainder need to go to pipes after 806 * the extra pixel index minus one(epimo) defined here as: 807 */ 808 int epimo = split_count - data->recout.width % (split_count + 1); 809 810 data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; 811 if (split_idx > epimo) 812 data->recout.x += split_idx - epimo - 1; 813 ASSERT(stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE || data->recout.width % 2 == 0); 814 data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 815 } else { 816 /* odm */ 817 if (split_idx == split_count) { 818 /* rightmost pipe is the remainder recout */ 819 data->recout.width -= data->h_active * split_count - data->recout.x; 820 821 /* ODM combine cases with MPO we can get negative widths */ 822 if (data->recout.width < 0) 823 data->recout.width = 0; 824 825 data->recout.x = 0; 826 } else 827 data->recout.width = data->h_active - data->recout.x; 828 } 829 } 830 } 831 832 static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 833 { 834 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 835 const struct dc_stream_state *stream = pipe_ctx->stream; 836 struct rect surf_src = plane_state->src_rect; 837 const int in_w = stream->src.width; 838 const int in_h = stream->src.height; 839 const int out_w = stream->dst.width; 840 const int out_h = stream->dst.height; 841 842 /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 843 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 844 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 845 swap(surf_src.height, surf_src.width); 846 847 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 848 surf_src.width, 849 plane_state->dst_rect.width); 850 pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 851 surf_src.height, 852 plane_state->dst_rect.height); 853 854 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 855 pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 856 else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 857 pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 858 859 pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 860 pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 861 pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 862 pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 863 864 pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 865 pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 866 867 if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 868 || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 869 pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 870 pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 871 } 872 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 873 pipe_ctx->plane_res.scl_data.ratios.horz, 19); 874 pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 875 pipe_ctx->plane_res.scl_data.ratios.vert, 19); 876 pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 877 pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 878 pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 879 pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 880 } 881 882 883 /* 884 * We completely calculate vp offset, size and inits here based entirely on scaling 885 * ratios and recout for pixel perfect pipe combine. 886 */ 887 static void calculate_init_and_vp( 888 bool flip_scan_dir, 889 int recout_offset_within_recout_full, 890 int recout_size, 891 int src_size, 892 int taps, 893 struct fixed31_32 ratio, 894 struct fixed31_32 *init, 895 int *vp_offset, 896 int *vp_size) 897 { 898 struct fixed31_32 temp; 899 int int_part; 900 901 /* 902 * First of the taps starts sampling pixel number <init_int_part> corresponding to recout 903 * pixel 1. Next recout pixel samples int part of <init + scaling ratio> and so on. 904 * All following calculations are based on this logic. 905 * 906 * Init calculated according to formula: 907 * init = (scaling_ratio + number_of_taps + 1) / 2 908 * init_bot = init + scaling_ratio 909 * to get pixel perfect combine add the fraction from calculating vp offset 910 */ 911 temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full); 912 *vp_offset = dc_fixpt_floor(temp); 913 temp.value &= 0xffffffff; 914 *init = dc_fixpt_truncate(dc_fixpt_add(dc_fixpt_div_int( 915 dc_fixpt_add_int(ratio, taps + 1), 2), temp), 19); 916 /* 917 * If viewport has non 0 offset and there are more taps than covered by init then 918 * we should decrease the offset and increase init so we are never sampling 919 * outside of viewport. 920 */ 921 int_part = dc_fixpt_floor(*init); 922 if (int_part < taps) { 923 int_part = taps - int_part; 924 if (int_part > *vp_offset) 925 int_part = *vp_offset; 926 *vp_offset -= int_part; 927 *init = dc_fixpt_add_int(*init, int_part); 928 } 929 /* 930 * If taps are sampling outside of viewport at end of recout and there are more pixels 931 * available in the surface we should increase the viewport size, regardless set vp to 932 * only what is used. 933 */ 934 temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1)); 935 *vp_size = dc_fixpt_floor(temp); 936 if (*vp_size + *vp_offset > src_size) 937 *vp_size = src_size - *vp_offset; 938 939 /* We did all the math assuming we are scanning same direction as display does, 940 * however mirror/rotation changes how vp scans vs how it is offset. If scan direction 941 * is flipped we simply need to calculate offset from the other side of plane. 942 * Note that outside of viewport all scaling hardware works in recout space. 943 */ 944 if (flip_scan_dir) 945 *vp_offset = src_size - *vp_offset - *vp_size; 946 } 947 948 static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx) 949 { 950 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 951 const struct dc_stream_state *stream = pipe_ctx->stream; 952 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 953 struct rect src = plane_state->src_rect; 954 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 955 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 956 int split_count, split_idx, ro_lb, ro_tb, recout_full_x, recout_full_y; 957 bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 958 959 calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 960 /* 961 * recout full is what the recout would have been if we didnt clip 962 * the source plane at all. We only care about left(ro_lb) and top(ro_tb) 963 * offsets of recout within recout full because those are the directions 964 * we scan from and therefore the only ones that affect inits. 965 */ 966 recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 967 * stream->dst.width / stream->src.width; 968 recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 969 * stream->dst.height / stream->src.height; 970 if (pipe_ctx->prev_odm_pipe && split_idx) 971 ro_lb = data->h_active * split_idx - recout_full_x; 972 else 973 ro_lb = data->recout.x - recout_full_x; 974 ro_tb = data->recout.y - recout_full_y; 975 ASSERT(ro_lb >= 0 && ro_tb >= 0); 976 977 /* 978 * Work in recout rotation since that requires less transformations 979 */ 980 get_vp_scan_direction( 981 plane_state->rotation, 982 plane_state->horizontal_mirror, 983 &orthogonal_rotation, 984 &flip_vert_scan_dir, 985 &flip_horz_scan_dir); 986 987 if (orthogonal_rotation) { 988 swap(src.width, src.height); 989 swap(flip_vert_scan_dir, flip_horz_scan_dir); 990 } 991 992 calculate_init_and_vp( 993 flip_horz_scan_dir, 994 ro_lb, 995 data->recout.width, 996 src.width, 997 data->taps.h_taps, 998 data->ratios.horz, 999 &data->inits.h, 1000 &data->viewport.x, 1001 &data->viewport.width); 1002 calculate_init_and_vp( 1003 flip_horz_scan_dir, 1004 ro_lb, 1005 data->recout.width, 1006 src.width / vpc_div, 1007 data->taps.h_taps_c, 1008 data->ratios.horz_c, 1009 &data->inits.h_c, 1010 &data->viewport_c.x, 1011 &data->viewport_c.width); 1012 calculate_init_and_vp( 1013 flip_vert_scan_dir, 1014 ro_tb, 1015 data->recout.height, 1016 src.height, 1017 data->taps.v_taps, 1018 data->ratios.vert, 1019 &data->inits.v, 1020 &data->viewport.y, 1021 &data->viewport.height); 1022 calculate_init_and_vp( 1023 flip_vert_scan_dir, 1024 ro_tb, 1025 data->recout.height, 1026 src.height / vpc_div, 1027 data->taps.v_taps_c, 1028 data->ratios.vert_c, 1029 &data->inits.v_c, 1030 &data->viewport_c.y, 1031 &data->viewport_c.height); 1032 if (orthogonal_rotation) { 1033 swap(data->viewport.x, data->viewport.y); 1034 swap(data->viewport.width, data->viewport.height); 1035 swap(data->viewport_c.x, data->viewport_c.y); 1036 swap(data->viewport_c.width, data->viewport_c.height); 1037 } 1038 data->viewport.x += src.x; 1039 data->viewport.y += src.y; 1040 ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0); 1041 data->viewport_c.x += src.x / vpc_div; 1042 data->viewport_c.y += src.y / vpc_div; 1043 } 1044 1045 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1046 { 1047 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 1048 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1049 bool res = false; 1050 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 1051 1052 pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 1053 pipe_ctx->plane_state->format); 1054 1055 /* Timing borders are part of vactive that we are also supposed to skip in addition 1056 * to any stream dst offset. Since dm logic assumes dst is in addressable 1057 * space we need to add the left and top borders to dst offsets temporarily. 1058 * TODO: fix in DM, stream dst is supposed to be in vactive 1059 */ 1060 pipe_ctx->stream->dst.x += timing->h_border_left; 1061 pipe_ctx->stream->dst.y += timing->v_border_top; 1062 1063 /* Calculate H and V active size */ 1064 pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + 1065 timing->h_border_left + timing->h_border_right; 1066 pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + 1067 timing->v_border_top + timing->v_border_bottom; 1068 if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 1069 pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 1070 1071 /* depends on h_active */ 1072 calculate_recout(pipe_ctx); 1073 /* depends on pixel format */ 1074 calculate_scaling_ratios(pipe_ctx); 1075 /* depends on scaling ratios and recout, does not calculate offset yet */ 1076 calculate_viewport_size(pipe_ctx); 1077 1078 /* Stopgap for validation of ODM + MPO on one side of screen case */ 1079 if (pipe_ctx->plane_res.scl_data.viewport.height < 1 || 1080 pipe_ctx->plane_res.scl_data.viewport.width < 1) 1081 return false; 1082 1083 /* 1084 * LB calculations depend on vp size, h/v_active and scaling ratios 1085 * Setting line buffer pixel depth to 24bpp yields banding 1086 * on certain displays, such as the Sharp 4k. 36bpp is needed 1087 * to support SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 and 1088 * SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616 with actual > 10 bpc 1089 * precision on at least DCN display engines. However, at least 1090 * Carrizo with DCE_VERSION_11_0 does not like 36 bpp lb depth, 1091 * so use only 30 bpp on DCE_VERSION_11_0. Testing with DCE 11.2 and 8.3 1092 * did not show such problems, so this seems to be the exception. 1093 */ 1094 if (plane_state->ctx->dce_version > DCE_VERSION_11_0) 1095 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_36BPP; 1096 else 1097 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 1098 1099 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; 1100 1101 if (pipe_ctx->plane_res.xfm != NULL) 1102 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 1103 pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1104 1105 if (pipe_ctx->plane_res.dpp != NULL) 1106 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1107 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1108 1109 1110 if (!res) { 1111 /* Try 24 bpp linebuffer */ 1112 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 1113 1114 if (pipe_ctx->plane_res.xfm != NULL) 1115 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 1116 pipe_ctx->plane_res.xfm, 1117 &pipe_ctx->plane_res.scl_data, 1118 &plane_state->scaling_quality); 1119 1120 if (pipe_ctx->plane_res.dpp != NULL) 1121 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1122 pipe_ctx->plane_res.dpp, 1123 &pipe_ctx->plane_res.scl_data, 1124 &plane_state->scaling_quality); 1125 } 1126 1127 /* 1128 * Depends on recout, scaling ratios, h_active and taps 1129 * May need to re-check lb size after this in some obscure scenario 1130 */ 1131 if (res) 1132 calculate_inits_and_viewports(pipe_ctx); 1133 1134 /* 1135 * Handle side by side and top bottom 3d recout offsets after vp calculation 1136 * since 3d is special and needs to calculate vp as if there is no recout offset 1137 * This may break with rotation, good thing we aren't mixing hw rotation and 3d 1138 */ 1139 if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == plane_state) { 1140 ASSERT(plane_state->rotation == ROTATION_ANGLE_0 || 1141 (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_TOP_AND_BOTTOM && 1142 pipe_ctx->stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE)); 1143 if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 1144 pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height; 1145 else if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 1146 pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width; 1147 } 1148 1149 if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE || 1150 pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) 1151 res = false; 1152 1153 DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n" 1154 "src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n", 1155 __func__, 1156 pipe_ctx->pipe_idx, 1157 pipe_ctx->plane_res.scl_data.viewport.height, 1158 pipe_ctx->plane_res.scl_data.viewport.width, 1159 pipe_ctx->plane_res.scl_data.viewport.x, 1160 pipe_ctx->plane_res.scl_data.viewport.y, 1161 pipe_ctx->plane_res.scl_data.recout.height, 1162 pipe_ctx->plane_res.scl_data.recout.width, 1163 pipe_ctx->plane_res.scl_data.recout.x, 1164 pipe_ctx->plane_res.scl_data.recout.y, 1165 pipe_ctx->plane_res.scl_data.h_active, 1166 pipe_ctx->plane_res.scl_data.v_active, 1167 plane_state->src_rect.height, 1168 plane_state->src_rect.width, 1169 plane_state->src_rect.x, 1170 plane_state->src_rect.y, 1171 plane_state->dst_rect.height, 1172 plane_state->dst_rect.width, 1173 plane_state->dst_rect.x, 1174 plane_state->dst_rect.y, 1175 plane_state->clip_rect.height, 1176 plane_state->clip_rect.width, 1177 plane_state->clip_rect.x, 1178 plane_state->clip_rect.y); 1179 1180 pipe_ctx->stream->dst.x -= timing->h_border_left; 1181 pipe_ctx->stream->dst.y -= timing->v_border_top; 1182 1183 return res; 1184 } 1185 1186 1187 enum dc_status resource_build_scaling_params_for_context( 1188 const struct dc *dc, 1189 struct dc_state *context) 1190 { 1191 int i; 1192 1193 for (i = 0; i < MAX_PIPES; i++) { 1194 if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 1195 context->res_ctx.pipe_ctx[i].stream != NULL) 1196 if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1197 return DC_FAIL_SCALING; 1198 } 1199 1200 return DC_OK; 1201 } 1202 1203 struct pipe_ctx *find_idle_secondary_pipe( 1204 struct resource_context *res_ctx, 1205 const struct resource_pool *pool, 1206 const struct pipe_ctx *primary_pipe) 1207 { 1208 int i; 1209 struct pipe_ctx *secondary_pipe = NULL; 1210 1211 /* 1212 * We add a preferred pipe mapping to avoid the chance that 1213 * MPCCs already in use will need to be reassigned to other trees. 1214 * For example, if we went with the strict, assign backwards logic: 1215 * 1216 * (State 1) 1217 * Display A on, no surface, top pipe = 0 1218 * Display B on, no surface, top pipe = 1 1219 * 1220 * (State 2) 1221 * Display A on, no surface, top pipe = 0 1222 * Display B on, surface enable, top pipe = 1, bottom pipe = 5 1223 * 1224 * (State 3) 1225 * Display A on, surface enable, top pipe = 0, bottom pipe = 5 1226 * Display B on, surface enable, top pipe = 1, bottom pipe = 4 1227 * 1228 * The state 2->3 transition requires remapping MPCC 5 from display B 1229 * to display A. 1230 * 1231 * However, with the preferred pipe logic, state 2 would look like: 1232 * 1233 * (State 2) 1234 * Display A on, no surface, top pipe = 0 1235 * Display B on, surface enable, top pipe = 1, bottom pipe = 4 1236 * 1237 * This would then cause 2->3 to not require remapping any MPCCs. 1238 */ 1239 if (primary_pipe) { 1240 int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 1241 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 1242 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 1243 secondary_pipe->pipe_idx = preferred_pipe_idx; 1244 } 1245 } 1246 1247 /* 1248 * search backwards for the second pipe to keep pipe 1249 * assignment more consistent 1250 */ 1251 if (!secondary_pipe) 1252 for (i = pool->pipe_count - 1; i >= 0; i--) { 1253 if (res_ctx->pipe_ctx[i].stream == NULL) { 1254 secondary_pipe = &res_ctx->pipe_ctx[i]; 1255 secondary_pipe->pipe_idx = i; 1256 break; 1257 } 1258 } 1259 1260 return secondary_pipe; 1261 } 1262 1263 struct pipe_ctx *resource_get_head_pipe_for_stream( 1264 struct resource_context *res_ctx, 1265 struct dc_stream_state *stream) 1266 { 1267 int i; 1268 1269 for (i = 0; i < MAX_PIPES; i++) { 1270 if (res_ctx->pipe_ctx[i].stream == stream 1271 && !res_ctx->pipe_ctx[i].top_pipe 1272 && !res_ctx->pipe_ctx[i].prev_odm_pipe) 1273 return &res_ctx->pipe_ctx[i]; 1274 } 1275 return NULL; 1276 } 1277 1278 static struct pipe_ctx *resource_get_tail_pipe( 1279 struct resource_context *res_ctx, 1280 struct pipe_ctx *head_pipe) 1281 { 1282 struct pipe_ctx *tail_pipe; 1283 1284 tail_pipe = head_pipe->bottom_pipe; 1285 1286 while (tail_pipe) { 1287 head_pipe = tail_pipe; 1288 tail_pipe = tail_pipe->bottom_pipe; 1289 } 1290 1291 return head_pipe; 1292 } 1293 1294 /* 1295 * A free_pipe for a stream is defined here as a pipe 1296 * that has no surface attached yet 1297 */ 1298 static struct pipe_ctx *acquire_free_pipe_for_head( 1299 struct dc_state *context, 1300 const struct resource_pool *pool, 1301 struct pipe_ctx *head_pipe) 1302 { 1303 int i; 1304 struct resource_context *res_ctx = &context->res_ctx; 1305 1306 if (!head_pipe->plane_state) 1307 return head_pipe; 1308 1309 /* Re-use pipe already acquired for this stream if available*/ 1310 for (i = pool->pipe_count - 1; i >= 0; i--) { 1311 if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 1312 !res_ctx->pipe_ctx[i].plane_state) { 1313 return &res_ctx->pipe_ctx[i]; 1314 } 1315 } 1316 1317 /* 1318 * At this point we have no re-useable pipe for this stream and we need 1319 * to acquire an idle one to satisfy the request 1320 */ 1321 1322 if (!pool->funcs->acquire_idle_pipe_for_layer) 1323 return NULL; 1324 1325 return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 1326 } 1327 1328 #if defined(CONFIG_DRM_AMD_DC_DCN) 1329 static int acquire_first_split_pipe( 1330 struct resource_context *res_ctx, 1331 const struct resource_pool *pool, 1332 struct dc_stream_state *stream) 1333 { 1334 int i; 1335 1336 for (i = 0; i < pool->pipe_count; i++) { 1337 struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 1338 1339 if (split_pipe->top_pipe && 1340 split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 1341 split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 1342 if (split_pipe->bottom_pipe) 1343 split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 1344 1345 if (split_pipe->top_pipe->plane_state) 1346 resource_build_scaling_params(split_pipe->top_pipe); 1347 1348 memset(split_pipe, 0, sizeof(*split_pipe)); 1349 split_pipe->stream_res.tg = pool->timing_generators[i]; 1350 split_pipe->plane_res.hubp = pool->hubps[i]; 1351 split_pipe->plane_res.ipp = pool->ipps[i]; 1352 split_pipe->plane_res.dpp = pool->dpps[i]; 1353 split_pipe->stream_res.opp = pool->opps[i]; 1354 split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 1355 split_pipe->pipe_idx = i; 1356 1357 split_pipe->stream = stream; 1358 return i; 1359 } 1360 } 1361 return -1; 1362 } 1363 #endif 1364 1365 bool dc_add_plane_to_context( 1366 const struct dc *dc, 1367 struct dc_stream_state *stream, 1368 struct dc_plane_state *plane_state, 1369 struct dc_state *context) 1370 { 1371 int i; 1372 struct resource_pool *pool = dc->res_pool; 1373 struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1374 struct dc_stream_status *stream_status = NULL; 1375 1376 for (i = 0; i < context->stream_count; i++) 1377 if (context->streams[i] == stream) { 1378 stream_status = &context->stream_status[i]; 1379 break; 1380 } 1381 if (stream_status == NULL) { 1382 dm_error("Existing stream not found; failed to attach surface!\n"); 1383 return false; 1384 } 1385 1386 1387 if (stream_status->plane_count == MAX_SURFACE_NUM) { 1388 dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 1389 plane_state, MAX_SURFACE_NUM); 1390 return false; 1391 } 1392 1393 head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 1394 1395 if (!head_pipe) { 1396 dm_error("Head pipe not found for stream_state %p !\n", stream); 1397 return false; 1398 } 1399 1400 /* retain new surface, but only once per stream */ 1401 dc_plane_state_retain(plane_state); 1402 1403 while (head_pipe) { 1404 free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 1405 1406 #if defined(CONFIG_DRM_AMD_DC_DCN) 1407 if (!free_pipe) { 1408 int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 1409 if (pipe_idx >= 0) 1410 free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 1411 } 1412 #endif 1413 if (!free_pipe) { 1414 dc_plane_state_release(plane_state); 1415 return false; 1416 } 1417 1418 free_pipe->plane_state = plane_state; 1419 1420 if (head_pipe != free_pipe) { 1421 tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 1422 ASSERT(tail_pipe); 1423 free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 1424 free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1425 free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 1426 free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1427 free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1428 free_pipe->clock_source = tail_pipe->clock_source; 1429 free_pipe->top_pipe = tail_pipe; 1430 tail_pipe->bottom_pipe = free_pipe; 1431 if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { 1432 free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; 1433 tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; 1434 } 1435 if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { 1436 free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; 1437 tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; 1438 } 1439 } 1440 head_pipe = head_pipe->next_odm_pipe; 1441 } 1442 /* assign new surfaces*/ 1443 stream_status->plane_states[stream_status->plane_count] = plane_state; 1444 1445 stream_status->plane_count++; 1446 1447 return true; 1448 } 1449 1450 bool dc_remove_plane_from_context( 1451 const struct dc *dc, 1452 struct dc_stream_state *stream, 1453 struct dc_plane_state *plane_state, 1454 struct dc_state *context) 1455 { 1456 int i; 1457 struct dc_stream_status *stream_status = NULL; 1458 struct resource_pool *pool = dc->res_pool; 1459 1460 for (i = 0; i < context->stream_count; i++) 1461 if (context->streams[i] == stream) { 1462 stream_status = &context->stream_status[i]; 1463 break; 1464 } 1465 1466 if (stream_status == NULL) { 1467 dm_error("Existing stream not found; failed to remove plane.\n"); 1468 return false; 1469 } 1470 1471 /* release pipe for plane*/ 1472 for (i = pool->pipe_count - 1; i >= 0; i--) { 1473 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1474 1475 if (pipe_ctx->plane_state == plane_state) { 1476 if (pipe_ctx->top_pipe) 1477 pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 1478 1479 /* Second condition is to avoid setting NULL to top pipe 1480 * of tail pipe making it look like head pipe in subsequent 1481 * deletes 1482 */ 1483 if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 1484 pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 1485 1486 /* 1487 * For head pipe detach surfaces from pipe for tail 1488 * pipe just zero it out 1489 */ 1490 if (!pipe_ctx->top_pipe) 1491 pipe_ctx->plane_state = NULL; 1492 else 1493 memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 1494 } 1495 } 1496 1497 1498 for (i = 0; i < stream_status->plane_count; i++) { 1499 if (stream_status->plane_states[i] == plane_state) { 1500 1501 dc_plane_state_release(stream_status->plane_states[i]); 1502 break; 1503 } 1504 } 1505 1506 if (i == stream_status->plane_count) { 1507 dm_error("Existing plane_state not found; failed to detach it!\n"); 1508 return false; 1509 } 1510 1511 stream_status->plane_count--; 1512 1513 /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1514 for (; i < stream_status->plane_count; i++) 1515 stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 1516 1517 stream_status->plane_states[stream_status->plane_count] = NULL; 1518 1519 return true; 1520 } 1521 1522 bool dc_rem_all_planes_for_stream( 1523 const struct dc *dc, 1524 struct dc_stream_state *stream, 1525 struct dc_state *context) 1526 { 1527 int i, old_plane_count; 1528 struct dc_stream_status *stream_status = NULL; 1529 struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 1530 1531 for (i = 0; i < context->stream_count; i++) 1532 if (context->streams[i] == stream) { 1533 stream_status = &context->stream_status[i]; 1534 break; 1535 } 1536 1537 if (stream_status == NULL) { 1538 dm_error("Existing stream %p not found!\n", stream); 1539 return false; 1540 } 1541 1542 old_plane_count = stream_status->plane_count; 1543 1544 for (i = 0; i < old_plane_count; i++) 1545 del_planes[i] = stream_status->plane_states[i]; 1546 1547 for (i = 0; i < old_plane_count; i++) 1548 if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 1549 return false; 1550 1551 return true; 1552 } 1553 1554 static bool add_all_planes_for_stream( 1555 const struct dc *dc, 1556 struct dc_stream_state *stream, 1557 const struct dc_validation_set set[], 1558 int set_count, 1559 struct dc_state *context) 1560 { 1561 int i, j; 1562 1563 for (i = 0; i < set_count; i++) 1564 if (set[i].stream == stream) 1565 break; 1566 1567 if (i == set_count) { 1568 dm_error("Stream %p not found in set!\n", stream); 1569 return false; 1570 } 1571 1572 for (j = 0; j < set[i].plane_count; j++) 1573 if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 1574 return false; 1575 1576 return true; 1577 } 1578 1579 bool dc_add_all_planes_for_stream( 1580 const struct dc *dc, 1581 struct dc_stream_state *stream, 1582 struct dc_plane_state * const *plane_states, 1583 int plane_count, 1584 struct dc_state *context) 1585 { 1586 struct dc_validation_set set; 1587 int i; 1588 1589 set.stream = stream; 1590 set.plane_count = plane_count; 1591 1592 for (i = 0; i < plane_count; i++) 1593 set.plane_states[i] = plane_states[i]; 1594 1595 return add_all_planes_for_stream(dc, stream, &set, 1, context); 1596 } 1597 1598 static bool is_timing_changed(struct dc_stream_state *cur_stream, 1599 struct dc_stream_state *new_stream) 1600 { 1601 if (cur_stream == NULL) 1602 return true; 1603 1604 /* If output color space is changed, need to reprogram info frames */ 1605 if (cur_stream->output_color_space != new_stream->output_color_space) 1606 return true; 1607 1608 return memcmp( 1609 &cur_stream->timing, 1610 &new_stream->timing, 1611 sizeof(struct dc_crtc_timing)) != 0; 1612 } 1613 1614 static bool are_stream_backends_same( 1615 struct dc_stream_state *stream_a, struct dc_stream_state *stream_b) 1616 { 1617 if (stream_a == stream_b) 1618 return true; 1619 1620 if (stream_a == NULL || stream_b == NULL) 1621 return false; 1622 1623 if (is_timing_changed(stream_a, stream_b)) 1624 return false; 1625 1626 if (stream_a->dpms_off != stream_b->dpms_off) 1627 return false; 1628 1629 return true; 1630 } 1631 1632 /* 1633 * dc_is_stream_unchanged() - Compare two stream states for equivalence. 1634 * 1635 * Checks if there a difference between the two states 1636 * that would require a mode change. 1637 * 1638 * Does not compare cursor position or attributes. 1639 */ 1640 bool dc_is_stream_unchanged( 1641 struct dc_stream_state *old_stream, struct dc_stream_state *stream) 1642 { 1643 1644 if (!are_stream_backends_same(old_stream, stream)) 1645 return false; 1646 1647 if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) 1648 return false; 1649 1650 return true; 1651 } 1652 1653 /* 1654 * dc_is_stream_scaling_unchanged() - Compare scaling rectangles of two streams. 1655 */ 1656 bool dc_is_stream_scaling_unchanged( 1657 struct dc_stream_state *old_stream, struct dc_stream_state *stream) 1658 { 1659 if (old_stream == stream) 1660 return true; 1661 1662 if (old_stream == NULL || stream == NULL) 1663 return false; 1664 1665 if (memcmp(&old_stream->src, 1666 &stream->src, 1667 sizeof(struct rect)) != 0) 1668 return false; 1669 1670 if (memcmp(&old_stream->dst, 1671 &stream->dst, 1672 sizeof(struct rect)) != 0) 1673 return false; 1674 1675 return true; 1676 } 1677 1678 static void update_stream_engine_usage( 1679 struct resource_context *res_ctx, 1680 const struct resource_pool *pool, 1681 struct stream_encoder *stream_enc, 1682 bool acquired) 1683 { 1684 int i; 1685 1686 for (i = 0; i < pool->stream_enc_count; i++) { 1687 if (pool->stream_enc[i] == stream_enc) 1688 res_ctx->is_stream_enc_acquired[i] = acquired; 1689 } 1690 } 1691 1692 #if defined(CONFIG_DRM_AMD_DC_DCN) 1693 static void update_hpo_dp_stream_engine_usage( 1694 struct resource_context *res_ctx, 1695 const struct resource_pool *pool, 1696 struct hpo_dp_stream_encoder *hpo_dp_stream_enc, 1697 bool acquired) 1698 { 1699 int i; 1700 1701 for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { 1702 if (pool->hpo_dp_stream_enc[i] == hpo_dp_stream_enc) 1703 res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired; 1704 } 1705 } 1706 #endif 1707 1708 /* TODO: release audio object */ 1709 void update_audio_usage( 1710 struct resource_context *res_ctx, 1711 const struct resource_pool *pool, 1712 struct audio *audio, 1713 bool acquired) 1714 { 1715 int i; 1716 for (i = 0; i < pool->audio_count; i++) { 1717 if (pool->audios[i] == audio) 1718 res_ctx->is_audio_acquired[i] = acquired; 1719 } 1720 } 1721 1722 static int acquire_first_free_pipe( 1723 struct resource_context *res_ctx, 1724 const struct resource_pool *pool, 1725 struct dc_stream_state *stream) 1726 { 1727 int i; 1728 1729 for (i = 0; i < pool->pipe_count; i++) { 1730 if (!res_ctx->pipe_ctx[i].stream) { 1731 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 1732 1733 pipe_ctx->stream_res.tg = pool->timing_generators[i]; 1734 pipe_ctx->plane_res.mi = pool->mis[i]; 1735 pipe_ctx->plane_res.hubp = pool->hubps[i]; 1736 pipe_ctx->plane_res.ipp = pool->ipps[i]; 1737 pipe_ctx->plane_res.xfm = pool->transforms[i]; 1738 pipe_ctx->plane_res.dpp = pool->dpps[i]; 1739 pipe_ctx->stream_res.opp = pool->opps[i]; 1740 if (pool->dpps[i]) 1741 pipe_ctx->plane_res.mpcc_inst = pool->dpps[i]->inst; 1742 pipe_ctx->pipe_idx = i; 1743 1744 1745 pipe_ctx->stream = stream; 1746 return i; 1747 } 1748 } 1749 return -1; 1750 } 1751 1752 #if defined(CONFIG_DRM_AMD_DC_DCN) 1753 static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for_link( 1754 struct resource_context *res_ctx, 1755 const struct resource_pool *pool, 1756 struct dc_stream_state *stream) 1757 { 1758 int i; 1759 1760 for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { 1761 if (!res_ctx->is_hpo_dp_stream_enc_acquired[i] && 1762 pool->hpo_dp_stream_enc[i]) { 1763 1764 return pool->hpo_dp_stream_enc[i]; 1765 } 1766 } 1767 1768 return NULL; 1769 } 1770 #endif 1771 1772 static struct audio *find_first_free_audio( 1773 struct resource_context *res_ctx, 1774 const struct resource_pool *pool, 1775 enum engine_id id, 1776 enum dce_version dc_version) 1777 { 1778 int i, available_audio_count; 1779 1780 available_audio_count = pool->audio_count; 1781 1782 for (i = 0; i < available_audio_count; i++) { 1783 if ((res_ctx->is_audio_acquired[i] == false) && (res_ctx->is_stream_enc_acquired[i] == true)) { 1784 /*we have enough audio endpoint, find the matching inst*/ 1785 if (id != i) 1786 continue; 1787 return pool->audios[i]; 1788 } 1789 } 1790 1791 /* use engine id to find free audio */ 1792 if ((id < available_audio_count) && (res_ctx->is_audio_acquired[id] == false)) { 1793 return pool->audios[id]; 1794 } 1795 /*not found the matching one, first come first serve*/ 1796 for (i = 0; i < available_audio_count; i++) { 1797 if (res_ctx->is_audio_acquired[i] == false) { 1798 return pool->audios[i]; 1799 } 1800 } 1801 return 0; 1802 } 1803 1804 /* 1805 * dc_add_stream_to_ctx() - Add a new dc_stream_state to a dc_state. 1806 */ 1807 enum dc_status dc_add_stream_to_ctx( 1808 struct dc *dc, 1809 struct dc_state *new_ctx, 1810 struct dc_stream_state *stream) 1811 { 1812 enum dc_status res; 1813 DC_LOGGER_INIT(dc->ctx->logger); 1814 1815 if (new_ctx->stream_count >= dc->res_pool->timing_generator_count) { 1816 DC_LOG_WARNING("Max streams reached, can't add stream %p !\n", stream); 1817 return DC_ERROR_UNEXPECTED; 1818 } 1819 1820 new_ctx->streams[new_ctx->stream_count] = stream; 1821 dc_stream_retain(stream); 1822 new_ctx->stream_count++; 1823 1824 res = dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream); 1825 if (res != DC_OK) 1826 DC_LOG_WARNING("Adding stream %p to context failed with err %d!\n", stream, res); 1827 1828 return res; 1829 } 1830 1831 /* 1832 * dc_remove_stream_from_ctx() - Remove a stream from a dc_state. 1833 */ 1834 enum dc_status dc_remove_stream_from_ctx( 1835 struct dc *dc, 1836 struct dc_state *new_ctx, 1837 struct dc_stream_state *stream) 1838 { 1839 int i; 1840 struct dc_context *dc_ctx = dc->ctx; 1841 struct pipe_ctx *del_pipe = resource_get_head_pipe_for_stream(&new_ctx->res_ctx, stream); 1842 struct pipe_ctx *odm_pipe; 1843 1844 if (!del_pipe) { 1845 DC_ERROR("Pipe not found for stream %p !\n", stream); 1846 return DC_ERROR_UNEXPECTED; 1847 } 1848 1849 odm_pipe = del_pipe->next_odm_pipe; 1850 1851 /* Release primary pipe */ 1852 ASSERT(del_pipe->stream_res.stream_enc); 1853 update_stream_engine_usage( 1854 &new_ctx->res_ctx, 1855 dc->res_pool, 1856 del_pipe->stream_res.stream_enc, 1857 false); 1858 /* Release link encoder from stream in new dc_state. */ 1859 if (dc->res_pool->funcs->link_enc_unassign) 1860 dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); 1861 1862 #if defined(CONFIG_DRM_AMD_DC_DCN) 1863 if (is_dp_128b_132b_signal(del_pipe)) { 1864 update_hpo_dp_stream_engine_usage( 1865 &new_ctx->res_ctx, dc->res_pool, 1866 del_pipe->stream_res.hpo_dp_stream_enc, 1867 false); 1868 } 1869 #endif 1870 1871 if (del_pipe->stream_res.audio) 1872 update_audio_usage( 1873 &new_ctx->res_ctx, 1874 dc->res_pool, 1875 del_pipe->stream_res.audio, 1876 false); 1877 1878 resource_unreference_clock_source(&new_ctx->res_ctx, 1879 dc->res_pool, 1880 del_pipe->clock_source); 1881 1882 if (dc->res_pool->funcs->remove_stream_from_ctx) 1883 dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream); 1884 1885 while (odm_pipe) { 1886 struct pipe_ctx *next_odm_pipe = odm_pipe->next_odm_pipe; 1887 1888 memset(odm_pipe, 0, sizeof(*odm_pipe)); 1889 odm_pipe = next_odm_pipe; 1890 } 1891 memset(del_pipe, 0, sizeof(*del_pipe)); 1892 1893 for (i = 0; i < new_ctx->stream_count; i++) 1894 if (new_ctx->streams[i] == stream) 1895 break; 1896 1897 if (new_ctx->streams[i] != stream) { 1898 DC_ERROR("Context doesn't have stream %p !\n", stream); 1899 return DC_ERROR_UNEXPECTED; 1900 } 1901 1902 dc_stream_release(new_ctx->streams[i]); 1903 new_ctx->stream_count--; 1904 1905 /* Trim back arrays */ 1906 for (; i < new_ctx->stream_count; i++) { 1907 new_ctx->streams[i] = new_ctx->streams[i + 1]; 1908 new_ctx->stream_status[i] = new_ctx->stream_status[i + 1]; 1909 } 1910 1911 new_ctx->streams[new_ctx->stream_count] = NULL; 1912 memset( 1913 &new_ctx->stream_status[new_ctx->stream_count], 1914 0, 1915 sizeof(new_ctx->stream_status[0])); 1916 1917 return DC_OK; 1918 } 1919 1920 static struct dc_stream_state *find_pll_sharable_stream( 1921 struct dc_stream_state *stream_needs_pll, 1922 struct dc_state *context) 1923 { 1924 int i; 1925 1926 for (i = 0; i < context->stream_count; i++) { 1927 struct dc_stream_state *stream_has_pll = context->streams[i]; 1928 1929 /* We are looking for non dp, non virtual stream */ 1930 if (resource_are_streams_timing_synchronizable( 1931 stream_needs_pll, stream_has_pll) 1932 && !dc_is_dp_signal(stream_has_pll->signal) 1933 && stream_has_pll->link->connector_signal 1934 != SIGNAL_TYPE_VIRTUAL) 1935 return stream_has_pll; 1936 1937 } 1938 1939 return NULL; 1940 } 1941 1942 static int get_norm_pix_clk(const struct dc_crtc_timing *timing) 1943 { 1944 uint32_t pix_clk = timing->pix_clk_100hz; 1945 uint32_t normalized_pix_clk = pix_clk; 1946 1947 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) 1948 pix_clk /= 2; 1949 if (timing->pixel_encoding != PIXEL_ENCODING_YCBCR422) { 1950 switch (timing->display_color_depth) { 1951 case COLOR_DEPTH_666: 1952 case COLOR_DEPTH_888: 1953 normalized_pix_clk = pix_clk; 1954 break; 1955 case COLOR_DEPTH_101010: 1956 normalized_pix_clk = (pix_clk * 30) / 24; 1957 break; 1958 case COLOR_DEPTH_121212: 1959 normalized_pix_clk = (pix_clk * 36) / 24; 1960 break; 1961 case COLOR_DEPTH_161616: 1962 normalized_pix_clk = (pix_clk * 48) / 24; 1963 break; 1964 default: 1965 ASSERT(0); 1966 break; 1967 } 1968 } 1969 return normalized_pix_clk; 1970 } 1971 1972 static void calculate_phy_pix_clks(struct dc_stream_state *stream) 1973 { 1974 /* update actual pixel clock on all streams */ 1975 if (dc_is_hdmi_signal(stream->signal)) 1976 stream->phy_pix_clk = get_norm_pix_clk( 1977 &stream->timing) / 10; 1978 else 1979 stream->phy_pix_clk = 1980 stream->timing.pix_clk_100hz / 10; 1981 1982 if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING) 1983 stream->phy_pix_clk *= 2; 1984 } 1985 1986 static int acquire_resource_from_hw_enabled_state( 1987 struct resource_context *res_ctx, 1988 const struct resource_pool *pool, 1989 struct dc_stream_state *stream) 1990 { 1991 struct dc_link *link = stream->link; 1992 unsigned int i, inst, tg_inst = 0; 1993 1994 /* Check for enabled DIG to identify enabled display */ 1995 if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) 1996 return -1; 1997 1998 inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); 1999 2000 if (inst == ENGINE_ID_UNKNOWN) 2001 return -1; 2002 2003 for (i = 0; i < pool->stream_enc_count; i++) { 2004 if (pool->stream_enc[i]->id == inst) { 2005 tg_inst = pool->stream_enc[i]->funcs->dig_source_otg( 2006 pool->stream_enc[i]); 2007 break; 2008 } 2009 } 2010 2011 // tg_inst not found 2012 if (i == pool->stream_enc_count) 2013 return -1; 2014 2015 if (tg_inst >= pool->timing_generator_count) 2016 return -1; 2017 2018 if (!res_ctx->pipe_ctx[tg_inst].stream) { 2019 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[tg_inst]; 2020 2021 pipe_ctx->stream_res.tg = pool->timing_generators[tg_inst]; 2022 pipe_ctx->plane_res.mi = pool->mis[tg_inst]; 2023 pipe_ctx->plane_res.hubp = pool->hubps[tg_inst]; 2024 pipe_ctx->plane_res.ipp = pool->ipps[tg_inst]; 2025 pipe_ctx->plane_res.xfm = pool->transforms[tg_inst]; 2026 pipe_ctx->plane_res.dpp = pool->dpps[tg_inst]; 2027 pipe_ctx->stream_res.opp = pool->opps[tg_inst]; 2028 2029 if (pool->dpps[tg_inst]) { 2030 pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst; 2031 2032 // Read DPP->MPCC->OPP Pipe from HW State 2033 if (pool->mpc->funcs->read_mpcc_state) { 2034 struct mpcc_state s = {0}; 2035 2036 pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s); 2037 2038 if (s.dpp_id < MAX_MPCC) 2039 pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id; 2040 2041 if (s.bot_mpcc_id < MAX_MPCC) 2042 pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot = 2043 &pool->mpc->mpcc_array[s.bot_mpcc_id]; 2044 2045 if (s.opp_id < MAX_OPP) 2046 pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id; 2047 } 2048 } 2049 pipe_ctx->pipe_idx = tg_inst; 2050 2051 pipe_ctx->stream = stream; 2052 return tg_inst; 2053 } 2054 2055 return -1; 2056 } 2057 2058 static void mark_seamless_boot_stream( 2059 const struct dc *dc, 2060 struct dc_stream_state *stream) 2061 { 2062 struct dc_bios *dcb = dc->ctx->dc_bios; 2063 2064 /* TODO: Check Linux */ 2065 if (dc->config.allow_seamless_boot_optimization && 2066 !dcb->funcs->is_accelerated_mode(dcb)) { 2067 if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) 2068 stream->apply_seamless_boot_optimization = true; 2069 } 2070 } 2071 2072 enum dc_status resource_map_pool_resources( 2073 const struct dc *dc, 2074 struct dc_state *context, 2075 struct dc_stream_state *stream) 2076 { 2077 const struct resource_pool *pool = dc->res_pool; 2078 int i; 2079 struct dc_context *dc_ctx = dc->ctx; 2080 struct pipe_ctx *pipe_ctx = NULL; 2081 int pipe_idx = -1; 2082 2083 calculate_phy_pix_clks(stream); 2084 2085 mark_seamless_boot_stream(dc, stream); 2086 2087 if (stream->apply_seamless_boot_optimization) { 2088 pipe_idx = acquire_resource_from_hw_enabled_state( 2089 &context->res_ctx, 2090 pool, 2091 stream); 2092 if (pipe_idx < 0) 2093 /* hw resource was assigned to other stream */ 2094 stream->apply_seamless_boot_optimization = false; 2095 } 2096 2097 if (pipe_idx < 0) 2098 /* acquire new resources */ 2099 pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); 2100 2101 #ifdef CONFIG_DRM_AMD_DC_DCN 2102 if (pipe_idx < 0) 2103 pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 2104 #endif 2105 2106 if (pipe_idx < 0 || context->res_ctx.pipe_ctx[pipe_idx].stream_res.tg == NULL) 2107 return DC_NO_CONTROLLER_RESOURCE; 2108 2109 pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; 2110 2111 pipe_ctx->stream_res.stream_enc = 2112 dc->res_pool->funcs->find_first_free_match_stream_enc_for_link( 2113 &context->res_ctx, pool, stream); 2114 2115 if (!pipe_ctx->stream_res.stream_enc) 2116 return DC_NO_STREAM_ENC_RESOURCE; 2117 2118 update_stream_engine_usage( 2119 &context->res_ctx, pool, 2120 pipe_ctx->stream_res.stream_enc, 2121 true); 2122 2123 #if defined(CONFIG_DRM_AMD_DC_DCN) 2124 /* Allocate DP HPO Stream Encoder based on signal, hw capabilities 2125 * and link settings 2126 */ 2127 if (dc_is_dp_signal(stream->signal) && 2128 dc->caps.dp_hpo) { 2129 struct dc_link_settings link_settings = {0}; 2130 2131 decide_link_settings(stream, &link_settings); 2132 if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING) { 2133 pipe_ctx->stream_res.hpo_dp_stream_enc = 2134 find_first_free_match_hpo_dp_stream_enc_for_link( 2135 &context->res_ctx, pool, stream); 2136 2137 if (!pipe_ctx->stream_res.hpo_dp_stream_enc) 2138 return DC_NO_STREAM_ENC_RESOURCE; 2139 2140 update_hpo_dp_stream_engine_usage( 2141 &context->res_ctx, pool, 2142 pipe_ctx->stream_res.hpo_dp_stream_enc, 2143 true); 2144 } 2145 } 2146 #endif 2147 2148 /* TODO: Add check if ASIC support and EDID audio */ 2149 if (!stream->converter_disable_audio && 2150 dc_is_audio_capable_signal(pipe_ctx->stream->signal) && 2151 stream->audio_info.mode_count && stream->audio_info.flags.all) { 2152 pipe_ctx->stream_res.audio = find_first_free_audio( 2153 &context->res_ctx, pool, pipe_ctx->stream_res.stream_enc->id, dc_ctx->dce_version); 2154 2155 /* 2156 * Audio assigned in order first come first get. 2157 * There are asics which has number of audio 2158 * resources less then number of pipes 2159 */ 2160 if (pipe_ctx->stream_res.audio) 2161 update_audio_usage(&context->res_ctx, pool, 2162 pipe_ctx->stream_res.audio, true); 2163 } 2164 2165 /* Add ABM to the resource if on EDP */ 2166 if (pipe_ctx->stream && dc_is_embedded_signal(pipe_ctx->stream->signal)) { 2167 #if defined(CONFIG_DRM_AMD_DC_DCN) 2168 if (pool->abm) 2169 pipe_ctx->stream_res.abm = pool->abm; 2170 else 2171 pipe_ctx->stream_res.abm = pool->multiple_abms[pipe_ctx->stream_res.tg->inst]; 2172 #else 2173 pipe_ctx->stream_res.abm = pool->abm; 2174 #endif 2175 } 2176 2177 for (i = 0; i < context->stream_count; i++) 2178 if (context->streams[i] == stream) { 2179 context->stream_status[i].primary_otg_inst = pipe_ctx->stream_res.tg->inst; 2180 context->stream_status[i].stream_enc_inst = pipe_ctx->stream_res.stream_enc->stream_enc_inst; 2181 context->stream_status[i].audio_inst = 2182 pipe_ctx->stream_res.audio ? pipe_ctx->stream_res.audio->inst : -1; 2183 2184 return DC_OK; 2185 } 2186 2187 DC_ERROR("Stream %p not found in new ctx!\n", stream); 2188 return DC_ERROR_UNEXPECTED; 2189 } 2190 2191 /** 2192 * dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state 2193 * Is a shallow copy. Increments refcounts on existing streams and planes. 2194 * @dc: copy out of dc->current_state 2195 * @dst_ctx: copy into this 2196 */ 2197 void dc_resource_state_copy_construct_current( 2198 const struct dc *dc, 2199 struct dc_state *dst_ctx) 2200 { 2201 dc_resource_state_copy_construct(dc->current_state, dst_ctx); 2202 } 2203 2204 2205 void dc_resource_state_construct( 2206 const struct dc *dc, 2207 struct dc_state *dst_ctx) 2208 { 2209 dst_ctx->clk_mgr = dc->clk_mgr; 2210 } 2211 2212 2213 bool dc_resource_is_dsc_encoding_supported(const struct dc *dc) 2214 { 2215 return dc->res_pool->res_cap->num_dsc > 0; 2216 } 2217 2218 2219 /** 2220 * dc_validate_global_state() - Determine if HW can support a given state 2221 * Checks HW resource availability and bandwidth requirement. 2222 * @dc: dc struct for this driver 2223 * @new_ctx: state to be validated 2224 * @fast_validate: set to true if only yes/no to support matters 2225 * 2226 * Return: DC_OK if the result can be programmed. Otherwise, an error code. 2227 */ 2228 enum dc_status dc_validate_global_state( 2229 struct dc *dc, 2230 struct dc_state *new_ctx, 2231 bool fast_validate) 2232 { 2233 enum dc_status result = DC_ERROR_UNEXPECTED; 2234 int i, j; 2235 2236 if (!new_ctx) 2237 return DC_ERROR_UNEXPECTED; 2238 #if defined(CONFIG_DRM_AMD_DC_DCN) 2239 2240 /* 2241 * Update link encoder to stream assignment. 2242 * TODO: Split out reason allocation from validation. 2243 */ 2244 if (dc->res_pool->funcs->link_encs_assign) 2245 dc->res_pool->funcs->link_encs_assign( 2246 dc, new_ctx, new_ctx->streams, new_ctx->stream_count); 2247 #endif 2248 2249 if (dc->res_pool->funcs->validate_global) { 2250 result = dc->res_pool->funcs->validate_global(dc, new_ctx); 2251 if (result != DC_OK) 2252 return result; 2253 } 2254 2255 for (i = 0; i < new_ctx->stream_count; i++) { 2256 struct dc_stream_state *stream = new_ctx->streams[i]; 2257 2258 for (j = 0; j < dc->res_pool->pipe_count; j++) { 2259 struct pipe_ctx *pipe_ctx = &new_ctx->res_ctx.pipe_ctx[j]; 2260 2261 if (pipe_ctx->stream != stream) 2262 continue; 2263 2264 if (dc->res_pool->funcs->patch_unknown_plane_state && 2265 pipe_ctx->plane_state && 2266 pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) { 2267 result = dc->res_pool->funcs->patch_unknown_plane_state(pipe_ctx->plane_state); 2268 if (result != DC_OK) 2269 return result; 2270 } 2271 2272 /* Switch to dp clock source only if there is 2273 * no non dp stream that shares the same timing 2274 * with the dp stream. 2275 */ 2276 if (dc_is_dp_signal(pipe_ctx->stream->signal) && 2277 !find_pll_sharable_stream(stream, new_ctx)) { 2278 2279 resource_unreference_clock_source( 2280 &new_ctx->res_ctx, 2281 dc->res_pool, 2282 pipe_ctx->clock_source); 2283 2284 pipe_ctx->clock_source = dc->res_pool->dp_clock_source; 2285 resource_reference_clock_source( 2286 &new_ctx->res_ctx, 2287 dc->res_pool, 2288 pipe_ctx->clock_source); 2289 } 2290 } 2291 } 2292 2293 result = resource_build_scaling_params_for_context(dc, new_ctx); 2294 2295 if (result == DC_OK) 2296 if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) 2297 result = DC_FAIL_BANDWIDTH_VALIDATE; 2298 2299 return result; 2300 } 2301 2302 static void patch_gamut_packet_checksum( 2303 struct dc_info_packet *gamut_packet) 2304 { 2305 /* For gamut we recalc checksum */ 2306 if (gamut_packet->valid) { 2307 uint8_t chk_sum = 0; 2308 uint8_t *ptr; 2309 uint8_t i; 2310 2311 /*start of the Gamut data. */ 2312 ptr = &gamut_packet->sb[3]; 2313 2314 for (i = 0; i <= gamut_packet->sb[1]; i++) 2315 chk_sum += ptr[i]; 2316 2317 gamut_packet->sb[2] = (uint8_t) (0x100 - chk_sum); 2318 } 2319 } 2320 2321 static void set_avi_info_frame( 2322 struct dc_info_packet *info_packet, 2323 struct pipe_ctx *pipe_ctx) 2324 { 2325 struct dc_stream_state *stream = pipe_ctx->stream; 2326 enum dc_color_space color_space = COLOR_SPACE_UNKNOWN; 2327 uint32_t pixel_encoding = 0; 2328 enum scanning_type scan_type = SCANNING_TYPE_NODATA; 2329 enum dc_aspect_ratio aspect = ASPECT_RATIO_NO_DATA; 2330 bool itc = false; 2331 uint8_t itc_value = 0; 2332 uint8_t cn0_cn1 = 0; 2333 unsigned int cn0_cn1_value = 0; 2334 uint8_t *check_sum = NULL; 2335 uint8_t byte_index = 0; 2336 union hdmi_info_packet hdmi_info; 2337 union display_content_support support = {0}; 2338 unsigned int vic = pipe_ctx->stream->timing.vic; 2339 enum dc_timing_3d_format format; 2340 2341 memset(&hdmi_info, 0, sizeof(union hdmi_info_packet)); 2342 2343 color_space = pipe_ctx->stream->output_color_space; 2344 if (color_space == COLOR_SPACE_UNKNOWN) 2345 color_space = (stream->timing.pixel_encoding == PIXEL_ENCODING_RGB) ? 2346 COLOR_SPACE_SRGB:COLOR_SPACE_YCBCR709; 2347 2348 /* Initialize header */ 2349 hdmi_info.bits.header.info_frame_type = HDMI_INFOFRAME_TYPE_AVI; 2350 /* InfoFrameVersion_3 is defined by CEA861F (Section 6.4), but shall 2351 * not be used in HDMI 2.0 (Section 10.1) */ 2352 hdmi_info.bits.header.version = 2; 2353 hdmi_info.bits.header.length = HDMI_AVI_INFOFRAME_SIZE; 2354 2355 /* 2356 * IDO-defined (Y2,Y1,Y0 = 1,1,1) shall not be used by devices built 2357 * according to HDMI 2.0 spec (Section 10.1) 2358 */ 2359 2360 switch (stream->timing.pixel_encoding) { 2361 case PIXEL_ENCODING_YCBCR422: 2362 pixel_encoding = 1; 2363 break; 2364 2365 case PIXEL_ENCODING_YCBCR444: 2366 pixel_encoding = 2; 2367 break; 2368 case PIXEL_ENCODING_YCBCR420: 2369 pixel_encoding = 3; 2370 break; 2371 2372 case PIXEL_ENCODING_RGB: 2373 default: 2374 pixel_encoding = 0; 2375 } 2376 2377 /* Y0_Y1_Y2 : The pixel encoding */ 2378 /* H14b AVI InfoFrame has extension on Y-field from 2 bits to 3 bits */ 2379 hdmi_info.bits.Y0_Y1_Y2 = pixel_encoding; 2380 2381 /* A0 = 1 Active Format Information valid */ 2382 hdmi_info.bits.A0 = ACTIVE_FORMAT_VALID; 2383 2384 /* B0, B1 = 3; Bar info data is valid */ 2385 hdmi_info.bits.B0_B1 = BAR_INFO_BOTH_VALID; 2386 2387 hdmi_info.bits.SC0_SC1 = PICTURE_SCALING_UNIFORM; 2388 2389 /* S0, S1 : Underscan / Overscan */ 2390 /* TODO: un-hardcode scan type */ 2391 scan_type = SCANNING_TYPE_UNDERSCAN; 2392 hdmi_info.bits.S0_S1 = scan_type; 2393 2394 /* C0, C1 : Colorimetry */ 2395 if (color_space == COLOR_SPACE_YCBCR709 || 2396 color_space == COLOR_SPACE_YCBCR709_LIMITED) 2397 hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; 2398 else if (color_space == COLOR_SPACE_YCBCR601 || 2399 color_space == COLOR_SPACE_YCBCR601_LIMITED) 2400 hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601; 2401 else { 2402 hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA; 2403 } 2404 if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE || 2405 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE || 2406 color_space == COLOR_SPACE_2020_YCBCR) { 2407 hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR; 2408 hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2409 } else if (color_space == COLOR_SPACE_ADOBERGB) { 2410 hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB; 2411 hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED; 2412 } 2413 2414 /* TODO: un-hardcode aspect ratio */ 2415 aspect = stream->timing.aspect_ratio; 2416 2417 switch (aspect) { 2418 case ASPECT_RATIO_4_3: 2419 case ASPECT_RATIO_16_9: 2420 hdmi_info.bits.M0_M1 = aspect; 2421 break; 2422 2423 case ASPECT_RATIO_NO_DATA: 2424 case ASPECT_RATIO_64_27: 2425 case ASPECT_RATIO_256_135: 2426 default: 2427 hdmi_info.bits.M0_M1 = 0; 2428 } 2429 2430 /* Active Format Aspect ratio - same as Picture Aspect Ratio. */ 2431 hdmi_info.bits.R0_R3 = ACTIVE_FORMAT_ASPECT_RATIO_SAME_AS_PICTURE; 2432 2433 /* TODO: un-hardcode cn0_cn1 and itc */ 2434 2435 cn0_cn1 = 0; 2436 cn0_cn1_value = 0; 2437 2438 itc = true; 2439 itc_value = 1; 2440 2441 support = stream->content_support; 2442 2443 if (itc) { 2444 if (!support.bits.valid_content_type) { 2445 cn0_cn1_value = 0; 2446 } else { 2447 if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GRAPHICS) { 2448 if (support.bits.graphics_content == 1) { 2449 cn0_cn1_value = 0; 2450 } 2451 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_PHOTO) { 2452 if (support.bits.photo_content == 1) { 2453 cn0_cn1_value = 1; 2454 } else { 2455 cn0_cn1_value = 0; 2456 itc_value = 0; 2457 } 2458 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_CINEMA) { 2459 if (support.bits.cinema_content == 1) { 2460 cn0_cn1_value = 2; 2461 } else { 2462 cn0_cn1_value = 0; 2463 itc_value = 0; 2464 } 2465 } else if (cn0_cn1 == DISPLAY_CONTENT_TYPE_GAME) { 2466 if (support.bits.game_content == 1) { 2467 cn0_cn1_value = 3; 2468 } else { 2469 cn0_cn1_value = 0; 2470 itc_value = 0; 2471 } 2472 } 2473 } 2474 hdmi_info.bits.CN0_CN1 = cn0_cn1_value; 2475 hdmi_info.bits.ITC = itc_value; 2476 } 2477 2478 if (stream->qs_bit == 1) { 2479 if (color_space == COLOR_SPACE_SRGB || 2480 color_space == COLOR_SPACE_2020_RGB_FULLRANGE) 2481 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; 2482 else if (color_space == COLOR_SPACE_SRGB_LIMITED || 2483 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) 2484 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; 2485 else 2486 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2487 } else 2488 hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; 2489 2490 /* TODO : We should handle YCC quantization */ 2491 /* but we do not have matrix calculation */ 2492 if (stream->qy_bit == 1) { 2493 if (color_space == COLOR_SPACE_SRGB || 2494 color_space == COLOR_SPACE_2020_RGB_FULLRANGE) 2495 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2496 else if (color_space == COLOR_SPACE_SRGB_LIMITED || 2497 color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) 2498 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2499 else 2500 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2501 } else 2502 hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; 2503 2504 ///VIC 2505 format = stream->timing.timing_3d_format; 2506 /*todo, add 3DStereo support*/ 2507 if (format != TIMING_3D_FORMAT_NONE) { 2508 // Based on HDMI specs hdmi vic needs to be converted to cea vic when 3D is enabled 2509 switch (pipe_ctx->stream->timing.hdmi_vic) { 2510 case 1: 2511 vic = 95; 2512 break; 2513 case 2: 2514 vic = 94; 2515 break; 2516 case 3: 2517 vic = 93; 2518 break; 2519 case 4: 2520 vic = 98; 2521 break; 2522 default: 2523 break; 2524 } 2525 } 2526 /* If VIC >= 128, the Source shall use AVI InfoFrame Version 3*/ 2527 hdmi_info.bits.VIC0_VIC7 = vic; 2528 if (vic >= 128) 2529 hdmi_info.bits.header.version = 3; 2530 /* If (C1, C0)=(1, 1) and (EC2, EC1, EC0)=(1, 1, 1), 2531 * the Source shall use 20 AVI InfoFrame Version 4 2532 */ 2533 if (hdmi_info.bits.C0_C1 == COLORIMETRY_EXTENDED && 2534 hdmi_info.bits.EC0_EC2 == COLORIMETRYEX_RESERVED) { 2535 hdmi_info.bits.header.version = 4; 2536 hdmi_info.bits.header.length = 14; 2537 } 2538 2539 /* pixel repetition 2540 * PR0 - PR3 start from 0 whereas pHwPathMode->mode.timing.flags.pixel 2541 * repetition start from 1 */ 2542 hdmi_info.bits.PR0_PR3 = 0; 2543 2544 /* Bar Info 2545 * barTop: Line Number of End of Top Bar. 2546 * barBottom: Line Number of Start of Bottom Bar. 2547 * barLeft: Pixel Number of End of Left Bar. 2548 * barRight: Pixel Number of Start of Right Bar. */ 2549 hdmi_info.bits.bar_top = stream->timing.v_border_top; 2550 hdmi_info.bits.bar_bottom = (stream->timing.v_total 2551 - stream->timing.v_border_bottom + 1); 2552 hdmi_info.bits.bar_left = stream->timing.h_border_left; 2553 hdmi_info.bits.bar_right = (stream->timing.h_total 2554 - stream->timing.h_border_right + 1); 2555 2556 /* Additional Colorimetry Extension 2557 * Used in conduction with C0-C1 and EC0-EC2 2558 * 0 = DCI-P3 RGB (D65) 2559 * 1 = DCI-P3 RGB (theater) 2560 */ 2561 hdmi_info.bits.ACE0_ACE3 = 0; 2562 2563 /* check_sum - Calculate AFMT_AVI_INFO0 ~ AFMT_AVI_INFO3 */ 2564 check_sum = &hdmi_info.packet_raw_data.sb[0]; 2565 2566 *check_sum = HDMI_INFOFRAME_TYPE_AVI + hdmi_info.bits.header.length + hdmi_info.bits.header.version; 2567 2568 for (byte_index = 1; byte_index <= hdmi_info.bits.header.length; byte_index++) 2569 *check_sum += hdmi_info.packet_raw_data.sb[byte_index]; 2570 2571 /* one byte complement */ 2572 *check_sum = (uint8_t) (0x100 - *check_sum); 2573 2574 /* Store in hw_path_mode */ 2575 info_packet->hb0 = hdmi_info.packet_raw_data.hb0; 2576 info_packet->hb1 = hdmi_info.packet_raw_data.hb1; 2577 info_packet->hb2 = hdmi_info.packet_raw_data.hb2; 2578 2579 for (byte_index = 0; byte_index < sizeof(hdmi_info.packet_raw_data.sb); byte_index++) 2580 info_packet->sb[byte_index] = hdmi_info.packet_raw_data.sb[byte_index]; 2581 2582 info_packet->valid = true; 2583 } 2584 2585 static void set_vendor_info_packet( 2586 struct dc_info_packet *info_packet, 2587 struct dc_stream_state *stream) 2588 { 2589 /* SPD info packet for FreeSync */ 2590 2591 /* Check if Freesync is supported. Return if false. If true, 2592 * set the corresponding bit in the info packet 2593 */ 2594 if (!stream->vsp_infopacket.valid) 2595 return; 2596 2597 *info_packet = stream->vsp_infopacket; 2598 } 2599 2600 static void set_spd_info_packet( 2601 struct dc_info_packet *info_packet, 2602 struct dc_stream_state *stream) 2603 { 2604 /* SPD info packet for FreeSync */ 2605 2606 /* Check if Freesync is supported. Return if false. If true, 2607 * set the corresponding bit in the info packet 2608 */ 2609 if (!stream->vrr_infopacket.valid) 2610 return; 2611 2612 *info_packet = stream->vrr_infopacket; 2613 } 2614 2615 static void set_hdr_static_info_packet( 2616 struct dc_info_packet *info_packet, 2617 struct dc_stream_state *stream) 2618 { 2619 /* HDR Static Metadata info packet for HDR10 */ 2620 2621 if (!stream->hdr_static_metadata.valid || 2622 stream->use_dynamic_meta) 2623 return; 2624 2625 *info_packet = stream->hdr_static_metadata; 2626 } 2627 2628 static void set_vsc_info_packet( 2629 struct dc_info_packet *info_packet, 2630 struct dc_stream_state *stream) 2631 { 2632 if (!stream->vsc_infopacket.valid) 2633 return; 2634 2635 *info_packet = stream->vsc_infopacket; 2636 } 2637 2638 void dc_resource_state_destruct(struct dc_state *context) 2639 { 2640 int i, j; 2641 2642 for (i = 0; i < context->stream_count; i++) { 2643 for (j = 0; j < context->stream_status[i].plane_count; j++) 2644 dc_plane_state_release( 2645 context->stream_status[i].plane_states[j]); 2646 2647 context->stream_status[i].plane_count = 0; 2648 dc_stream_release(context->streams[i]); 2649 context->streams[i] = NULL; 2650 } 2651 context->stream_count = 0; 2652 } 2653 2654 void dc_resource_state_copy_construct( 2655 const struct dc_state *src_ctx, 2656 struct dc_state *dst_ctx) 2657 { 2658 int i, j; 2659 struct kref refcount = dst_ctx->refcount; 2660 2661 *dst_ctx = *src_ctx; 2662 2663 for (i = 0; i < MAX_PIPES; i++) { 2664 struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 2665 2666 if (cur_pipe->top_pipe) 2667 cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 2668 2669 if (cur_pipe->bottom_pipe) 2670 cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2671 2672 if (cur_pipe->next_odm_pipe) 2673 cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2674 2675 if (cur_pipe->prev_odm_pipe) 2676 cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 2677 } 2678 2679 for (i = 0; i < dst_ctx->stream_count; i++) { 2680 dc_stream_retain(dst_ctx->streams[i]); 2681 for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 2682 dc_plane_state_retain( 2683 dst_ctx->stream_status[i].plane_states[j]); 2684 } 2685 2686 /* context refcount should not be overridden */ 2687 dst_ctx->refcount = refcount; 2688 2689 } 2690 2691 struct clock_source *dc_resource_find_first_free_pll( 2692 struct resource_context *res_ctx, 2693 const struct resource_pool *pool) 2694 { 2695 int i; 2696 2697 for (i = 0; i < pool->clk_src_count; ++i) { 2698 if (res_ctx->clock_source_ref_count[i] == 0) 2699 return pool->clock_sources[i]; 2700 } 2701 2702 return NULL; 2703 } 2704 2705 void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 2706 { 2707 enum signal_type signal = SIGNAL_TYPE_NONE; 2708 struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 2709 2710 /* default all packets to invalid */ 2711 info->avi.valid = false; 2712 info->gamut.valid = false; 2713 info->vendor.valid = false; 2714 info->spd.valid = false; 2715 info->hdrsmd.valid = false; 2716 info->vsc.valid = false; 2717 2718 signal = pipe_ctx->stream->signal; 2719 2720 /* HDMi and DP have different info packets*/ 2721 if (dc_is_hdmi_signal(signal)) { 2722 set_avi_info_frame(&info->avi, pipe_ctx); 2723 2724 set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 2725 2726 set_spd_info_packet(&info->spd, pipe_ctx->stream); 2727 2728 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2729 2730 } else if (dc_is_dp_signal(signal)) { 2731 set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 2732 2733 set_spd_info_packet(&info->spd, pipe_ctx->stream); 2734 2735 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2736 } 2737 2738 patch_gamut_packet_checksum(&info->gamut); 2739 } 2740 2741 enum dc_status resource_map_clock_resources( 2742 const struct dc *dc, 2743 struct dc_state *context, 2744 struct dc_stream_state *stream) 2745 { 2746 /* acquire new resources */ 2747 const struct resource_pool *pool = dc->res_pool; 2748 struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 2749 &context->res_ctx, stream); 2750 2751 if (!pipe_ctx) 2752 return DC_ERROR_UNEXPECTED; 2753 2754 if (dc_is_dp_signal(pipe_ctx->stream->signal) 2755 || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2756 pipe_ctx->clock_source = pool->dp_clock_source; 2757 else { 2758 pipe_ctx->clock_source = NULL; 2759 2760 if (!dc->config.disable_disp_pll_sharing) 2761 pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 2762 &context->res_ctx, 2763 pipe_ctx); 2764 2765 if (pipe_ctx->clock_source == NULL) 2766 pipe_ctx->clock_source = 2767 dc_resource_find_first_free_pll( 2768 &context->res_ctx, 2769 pool); 2770 } 2771 2772 if (pipe_ctx->clock_source == NULL) 2773 return DC_NO_CLOCK_SOURCE_RESOURCE; 2774 2775 resource_reference_clock_source( 2776 &context->res_ctx, pool, 2777 pipe_ctx->clock_source); 2778 2779 return DC_OK; 2780 } 2781 2782 /* 2783 * Note: We need to disable output if clock sources change, 2784 * since bios does optimization and doesn't apply if changing 2785 * PHY when not already disabled. 2786 */ 2787 bool pipe_need_reprogram( 2788 struct pipe_ctx *pipe_ctx_old, 2789 struct pipe_ctx *pipe_ctx) 2790 { 2791 if (!pipe_ctx_old->stream) 2792 return false; 2793 2794 if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 2795 return true; 2796 2797 if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 2798 return true; 2799 2800 if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 2801 return true; 2802 2803 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 2804 && pipe_ctx_old->stream != pipe_ctx->stream) 2805 return true; 2806 2807 if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 2808 return true; 2809 2810 if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 2811 return true; 2812 2813 if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 2814 return true; 2815 2816 if (false == pipe_ctx_old->stream->link->link_state_valid && 2817 false == pipe_ctx_old->stream->dpms_off) 2818 return true; 2819 2820 if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) 2821 return true; 2822 2823 #if defined(CONFIG_DRM_AMD_DC_DCN) 2824 if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc) 2825 return true; 2826 #endif 2827 2828 /* DIG link encoder resource assignment for stream changed. */ 2829 if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc) 2830 return true; 2831 2832 return false; 2833 } 2834 2835 void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2836 struct bit_depth_reduction_params *fmt_bit_depth) 2837 { 2838 enum dc_dither_option option = stream->dither_option; 2839 enum dc_pixel_encoding pixel_encoding = 2840 stream->timing.pixel_encoding; 2841 2842 memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2843 2844 if (option == DITHER_OPTION_DEFAULT) { 2845 switch (stream->timing.display_color_depth) { 2846 case COLOR_DEPTH_666: 2847 option = DITHER_OPTION_SPATIAL6; 2848 break; 2849 case COLOR_DEPTH_888: 2850 option = DITHER_OPTION_SPATIAL8; 2851 break; 2852 case COLOR_DEPTH_101010: 2853 option = DITHER_OPTION_SPATIAL10; 2854 break; 2855 default: 2856 option = DITHER_OPTION_DISABLE; 2857 } 2858 } 2859 2860 if (option == DITHER_OPTION_DISABLE) 2861 return; 2862 2863 if (option == DITHER_OPTION_TRUN6) { 2864 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2865 fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2866 } else if (option == DITHER_OPTION_TRUN8 || 2867 option == DITHER_OPTION_TRUN8_SPATIAL6 || 2868 option == DITHER_OPTION_TRUN8_FM6) { 2869 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2870 fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2871 } else if (option == DITHER_OPTION_TRUN10 || 2872 option == DITHER_OPTION_TRUN10_SPATIAL6 || 2873 option == DITHER_OPTION_TRUN10_SPATIAL8 || 2874 option == DITHER_OPTION_TRUN10_FM8 || 2875 option == DITHER_OPTION_TRUN10_FM6 || 2876 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2877 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2878 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2879 } 2880 2881 /* special case - Formatter can only reduce by 4 bits at most. 2882 * When reducing from 12 to 6 bits, 2883 * HW recommends we use trunc with round mode 2884 * (if we did nothing, trunc to 10 bits would be used) 2885 * note that any 12->10 bit reduction is ignored prior to DCE8, 2886 * as the input was 10 bits. 2887 */ 2888 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2889 option == DITHER_OPTION_SPATIAL6 || 2890 option == DITHER_OPTION_FM6) { 2891 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2892 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2893 fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2894 } 2895 2896 /* spatial dither 2897 * note that spatial modes 1-3 are never used 2898 */ 2899 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2900 option == DITHER_OPTION_SPATIAL6 || 2901 option == DITHER_OPTION_TRUN10_SPATIAL6 || 2902 option == DITHER_OPTION_TRUN8_SPATIAL6) { 2903 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2904 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2905 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2906 fmt_bit_depth->flags.RGB_RANDOM = 2907 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2908 } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2909 option == DITHER_OPTION_SPATIAL8 || 2910 option == DITHER_OPTION_SPATIAL8_FM6 || 2911 option == DITHER_OPTION_TRUN10_SPATIAL8 || 2912 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2913 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2914 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2915 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2916 fmt_bit_depth->flags.RGB_RANDOM = 2917 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2918 } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2919 option == DITHER_OPTION_SPATIAL10 || 2920 option == DITHER_OPTION_SPATIAL10_FM8 || 2921 option == DITHER_OPTION_SPATIAL10_FM6) { 2922 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2923 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2924 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2925 fmt_bit_depth->flags.RGB_RANDOM = 2926 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2927 } 2928 2929 if (option == DITHER_OPTION_SPATIAL6 || 2930 option == DITHER_OPTION_SPATIAL8 || 2931 option == DITHER_OPTION_SPATIAL10) { 2932 fmt_bit_depth->flags.FRAME_RANDOM = 0; 2933 } else { 2934 fmt_bit_depth->flags.FRAME_RANDOM = 1; 2935 } 2936 2937 ////////////////////// 2938 //// temporal dither 2939 ////////////////////// 2940 if (option == DITHER_OPTION_FM6 || 2941 option == DITHER_OPTION_SPATIAL8_FM6 || 2942 option == DITHER_OPTION_SPATIAL10_FM6 || 2943 option == DITHER_OPTION_TRUN10_FM6 || 2944 option == DITHER_OPTION_TRUN8_FM6 || 2945 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2946 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2947 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2948 } else if (option == DITHER_OPTION_FM8 || 2949 option == DITHER_OPTION_SPATIAL10_FM8 || 2950 option == DITHER_OPTION_TRUN10_FM8) { 2951 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2952 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2953 } else if (option == DITHER_OPTION_FM10) { 2954 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2955 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2956 } 2957 2958 fmt_bit_depth->pixel_encoding = pixel_encoding; 2959 } 2960 2961 enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 2962 { 2963 struct dc_link *link = stream->link; 2964 struct timing_generator *tg = dc->res_pool->timing_generators[0]; 2965 enum dc_status res = DC_OK; 2966 2967 calculate_phy_pix_clks(stream); 2968 2969 if (!tg->funcs->validate_timing(tg, &stream->timing)) 2970 res = DC_FAIL_CONTROLLER_VALIDATE; 2971 2972 if (res == DC_OK) { 2973 if (!link->link_enc->funcs->validate_output_with_stream( 2974 link->link_enc, stream)) 2975 res = DC_FAIL_ENC_VALIDATE; 2976 } 2977 2978 /* TODO: validate audio ASIC caps, encoder */ 2979 2980 if (res == DC_OK) 2981 res = dc_link_validate_mode_timing(stream, 2982 link, 2983 &stream->timing); 2984 2985 return res; 2986 } 2987 2988 enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 2989 { 2990 enum dc_status res = DC_OK; 2991 2992 /* TODO For now validates pixel format only */ 2993 if (dc->res_pool->funcs->validate_plane) 2994 return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 2995 2996 return res; 2997 } 2998 2999 unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 3000 { 3001 switch (format) { 3002 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 3003 return 8; 3004 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 3005 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 3006 return 12; 3007 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 3008 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 3009 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 3010 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 3011 return 16; 3012 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 3013 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 3014 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 3015 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 3016 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 3017 #if defined(CONFIG_DRM_AMD_DC_DCN) 3018 case SURFACE_PIXEL_FORMAT_GRPH_RGBE: 3019 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: 3020 #endif 3021 return 32; 3022 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 3023 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: 3024 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 3025 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 3026 return 64; 3027 default: 3028 ASSERT_CRITICAL(false); 3029 return -1; 3030 } 3031 } 3032 static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) 3033 { 3034 if (modes) { 3035 if (modes->sample_rates.rate.RATE_192) 3036 return 192000; 3037 if (modes->sample_rates.rate.RATE_176_4) 3038 return 176400; 3039 if (modes->sample_rates.rate.RATE_96) 3040 return 96000; 3041 if (modes->sample_rates.rate.RATE_88_2) 3042 return 88200; 3043 if (modes->sample_rates.rate.RATE_48) 3044 return 48000; 3045 if (modes->sample_rates.rate.RATE_44_1) 3046 return 44100; 3047 if (modes->sample_rates.rate.RATE_32) 3048 return 32000; 3049 } 3050 /*original logic when no audio info*/ 3051 return 441000; 3052 } 3053 3054 void get_audio_check(struct audio_info *aud_modes, 3055 struct audio_check *audio_chk) 3056 { 3057 unsigned int i; 3058 unsigned int max_sample_rate = 0; 3059 3060 if (aud_modes) { 3061 audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/ 3062 3063 audio_chk->max_audiosample_rate = 0; 3064 for (i = 0; i < aud_modes->mode_count; i++) { 3065 max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]); 3066 if (audio_chk->max_audiosample_rate < max_sample_rate) 3067 audio_chk->max_audiosample_rate = max_sample_rate; 3068 /*dts takes the same as type 2: AP = 0.25*/ 3069 } 3070 /*check which one take more bandwidth*/ 3071 if (audio_chk->max_audiosample_rate > 192000) 3072 audio_chk->audio_packet_type = 0x9;/*AP =1*/ 3073 audio_chk->acat = 0;/*not support*/ 3074 } 3075 } 3076 3077 #if defined(CONFIG_DRM_AMD_DC_DCN) 3078 struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( 3079 const struct resource_pool *pool) 3080 { 3081 uint8_t i; 3082 struct hpo_dp_link_encoder *enc = NULL; 3083 3084 ASSERT(pool->hpo_dp_link_enc_count <= MAX_HPO_DP2_LINK_ENCODERS); 3085 3086 for (i = 0; i < pool->hpo_dp_link_enc_count; i++) { 3087 if (pool->hpo_dp_link_enc[i]->transmitter == TRANSMITTER_UNKNOWN) { 3088 enc = pool->hpo_dp_link_enc[i]; 3089 break; 3090 } 3091 } 3092 3093 return enc; 3094 } 3095 #endif 3096