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