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