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