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