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 #endif 61 62 #define DC_LOGGER_INIT(logger) 63 64 enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 65 { 66 enum dce_version dc_version = DCE_VERSION_UNKNOWN; 67 switch (asic_id.chip_family) { 68 69 #if defined(CONFIG_DRM_AMD_DC_SI) 70 case FAMILY_SI: 71 if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) || 72 ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) || 73 ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev)) 74 dc_version = DCE_VERSION_6_0; 75 else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev)) 76 dc_version = DCE_VERSION_6_4; 77 else 78 dc_version = DCE_VERSION_6_1; 79 break; 80 #endif 81 case FAMILY_CI: 82 dc_version = DCE_VERSION_8_0; 83 break; 84 case FAMILY_KV: 85 if (ASIC_REV_IS_KALINDI(asic_id.hw_internal_rev) || 86 ASIC_REV_IS_BHAVANI(asic_id.hw_internal_rev) || 87 ASIC_REV_IS_GODAVARI(asic_id.hw_internal_rev)) 88 dc_version = DCE_VERSION_8_3; 89 else 90 dc_version = DCE_VERSION_8_1; 91 break; 92 case FAMILY_CZ: 93 dc_version = DCE_VERSION_11_0; 94 break; 95 96 case FAMILY_VI: 97 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 98 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 99 dc_version = DCE_VERSION_10_0; 100 break; 101 } 102 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 103 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 104 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 105 dc_version = DCE_VERSION_11_2; 106 } 107 if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) 108 dc_version = DCE_VERSION_11_22; 109 break; 110 case FAMILY_AI: 111 if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 112 dc_version = DCE_VERSION_12_1; 113 else 114 dc_version = DCE_VERSION_12_0; 115 break; 116 #if defined(CONFIG_DRM_AMD_DC_DCN) 117 case FAMILY_RV: 118 dc_version = DCN_VERSION_1_0; 119 if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) 120 dc_version = DCN_VERSION_1_01; 121 if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) 122 dc_version = DCN_VERSION_2_1; 123 if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev)) 124 dc_version = DCN_VERSION_2_1; 125 break; 126 127 case FAMILY_NV: 128 dc_version = DCN_VERSION_2_0; 129 if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) 130 dc_version = DCN_VERSION_3_0; 131 if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev)) 132 dc_version = DCN_VERSION_3_02; 133 break; 134 135 case FAMILY_VGH: 136 dc_version = DCN_VERSION_3_01; 137 break; 138 #endif 139 default: 140 dc_version = DCE_VERSION_UNKNOWN; 141 break; 142 } 143 return dc_version; 144 } 145 146 struct resource_pool *dc_create_resource_pool(struct dc *dc, 147 const struct dc_init_data *init_data, 148 enum dce_version dc_version) 149 { 150 struct resource_pool *res_pool = NULL; 151 152 switch (dc_version) { 153 #if defined(CONFIG_DRM_AMD_DC_SI) 154 case DCE_VERSION_6_0: 155 res_pool = dce60_create_resource_pool( 156 init_data->num_virtual_links, dc); 157 break; 158 case DCE_VERSION_6_1: 159 res_pool = dce61_create_resource_pool( 160 init_data->num_virtual_links, dc); 161 break; 162 case DCE_VERSION_6_4: 163 res_pool = dce64_create_resource_pool( 164 init_data->num_virtual_links, dc); 165 break; 166 #endif 167 case DCE_VERSION_8_0: 168 res_pool = dce80_create_resource_pool( 169 init_data->num_virtual_links, dc); 170 break; 171 case DCE_VERSION_8_1: 172 res_pool = dce81_create_resource_pool( 173 init_data->num_virtual_links, dc); 174 break; 175 case DCE_VERSION_8_3: 176 res_pool = dce83_create_resource_pool( 177 init_data->num_virtual_links, dc); 178 break; 179 case DCE_VERSION_10_0: 180 res_pool = dce100_create_resource_pool( 181 init_data->num_virtual_links, dc); 182 break; 183 case DCE_VERSION_11_0: 184 res_pool = dce110_create_resource_pool( 185 init_data->num_virtual_links, dc, 186 init_data->asic_id); 187 break; 188 case DCE_VERSION_11_2: 189 case DCE_VERSION_11_22: 190 res_pool = dce112_create_resource_pool( 191 init_data->num_virtual_links, dc); 192 break; 193 case DCE_VERSION_12_0: 194 case DCE_VERSION_12_1: 195 res_pool = dce120_create_resource_pool( 196 init_data->num_virtual_links, dc); 197 break; 198 199 #if defined(CONFIG_DRM_AMD_DC_DCN) 200 case DCN_VERSION_1_0: 201 case DCN_VERSION_1_01: 202 res_pool = dcn10_create_resource_pool(init_data, dc); 203 break; 204 case DCN_VERSION_2_0: 205 res_pool = dcn20_create_resource_pool(init_data, dc); 206 break; 207 case DCN_VERSION_2_1: 208 res_pool = dcn21_create_resource_pool(init_data, dc); 209 break; 210 case DCN_VERSION_3_0: 211 res_pool = dcn30_create_resource_pool(init_data, dc); 212 break; 213 case DCN_VERSION_3_01: 214 res_pool = dcn301_create_resource_pool(init_data, dc); 215 break; 216 case DCN_VERSION_3_02: 217 res_pool = dcn302_create_resource_pool(init_data, dc); 218 break; 219 #endif 220 default: 221 break; 222 } 223 224 if (res_pool != NULL) { 225 if (dc->ctx->dc_bios->fw_info_valid) { 226 res_pool->ref_clocks.xtalin_clock_inKhz = 227 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency; 228 /* initialize with firmware data first, no all 229 * ASIC have DCCG SW component. FPGA or 230 * simulation need initialization of 231 * dccg_ref_clock_inKhz, dchub_ref_clock_inKhz 232 * with xtalin_clock_inKhz 233 */ 234 res_pool->ref_clocks.dccg_ref_clock_inKhz = 235 res_pool->ref_clocks.xtalin_clock_inKhz; 236 res_pool->ref_clocks.dchub_ref_clock_inKhz = 237 res_pool->ref_clocks.xtalin_clock_inKhz; 238 } else 239 ASSERT_CRITICAL(false); 240 } 241 242 return res_pool; 243 } 244 245 void dc_destroy_resource_pool(struct dc *dc) 246 { 247 if (dc) { 248 if (dc->res_pool) 249 dc->res_pool->funcs->destroy(&dc->res_pool); 250 251 kfree(dc->hwseq); 252 } 253 } 254 255 static void update_num_audio( 256 const struct resource_straps *straps, 257 unsigned int *num_audio, 258 struct audio_support *aud_support) 259 { 260 aud_support->dp_audio = true; 261 aud_support->hdmi_audio_native = false; 262 aud_support->hdmi_audio_on_dongle = false; 263 264 if (straps->hdmi_disable == 0) { 265 if (straps->dc_pinstraps_audio & 0x2) { 266 aud_support->hdmi_audio_on_dongle = true; 267 aud_support->hdmi_audio_native = true; 268 } 269 } 270 271 switch (straps->audio_stream_number) { 272 case 0: /* multi streams supported */ 273 break; 274 case 1: /* multi streams not supported */ 275 *num_audio = 1; 276 break; 277 default: 278 DC_ERR("DC: unexpected audio fuse!\n"); 279 } 280 } 281 282 bool resource_construct( 283 unsigned int num_virtual_links, 284 struct dc *dc, 285 struct resource_pool *pool, 286 const struct resource_create_funcs *create_funcs) 287 { 288 struct dc_context *ctx = dc->ctx; 289 const struct resource_caps *caps = pool->res_cap; 290 int i; 291 unsigned int num_audio = caps->num_audio; 292 struct resource_straps straps = {0}; 293 294 if (create_funcs->read_dce_straps) 295 create_funcs->read_dce_straps(dc->ctx, &straps); 296 297 pool->audio_count = 0; 298 if (create_funcs->create_audio) { 299 /* find the total number of streams available via the 300 * AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 301 * registers (one for each pin) starting from pin 1 302 * up to the max number of audio pins. 303 * We stop on the first pin where 304 * PORT_CONNECTIVITY == 1 (as instructed by HW team). 305 */ 306 update_num_audio(&straps, &num_audio, &pool->audio_support); 307 for (i = 0; i < caps->num_audio; i++) { 308 struct audio *aud = create_funcs->create_audio(ctx, i); 309 310 if (aud == NULL) { 311 DC_ERR("DC: failed to create audio!\n"); 312 return false; 313 } 314 if (!aud->funcs->endpoint_valid(aud)) { 315 aud->funcs->destroy(&aud); 316 break; 317 } 318 pool->audios[i] = aud; 319 pool->audio_count++; 320 } 321 } 322 323 pool->stream_enc_count = 0; 324 if (create_funcs->create_stream_encoder) { 325 for (i = 0; i < caps->num_stream_encoder; i++) { 326 pool->stream_enc[i] = create_funcs->create_stream_encoder(i, ctx); 327 if (pool->stream_enc[i] == NULL) 328 DC_ERR("DC: failed to create stream_encoder!\n"); 329 pool->stream_enc_count++; 330 } 331 } 332 333 #if defined(CONFIG_DRM_AMD_DC_DCN) 334 for (i = 0; i < caps->num_mpc_3dlut; i++) { 335 pool->mpc_lut[i] = dc_create_3dlut_func(); 336 if (pool->mpc_lut[i] == NULL) 337 DC_ERR("DC: failed to create MPC 3dlut!\n"); 338 pool->mpc_shaper[i] = dc_create_transfer_func(); 339 if (pool->mpc_shaper[i] == NULL) 340 DC_ERR("DC: failed to create MPC shaper!\n"); 341 } 342 #endif 343 dc->caps.dynamic_audio = false; 344 if (pool->audio_count < pool->stream_enc_count) { 345 dc->caps.dynamic_audio = true; 346 } 347 for (i = 0; i < num_virtual_links; i++) { 348 pool->stream_enc[pool->stream_enc_count] = 349 virtual_stream_encoder_create( 350 ctx, ctx->dc_bios); 351 if (pool->stream_enc[pool->stream_enc_count] == NULL) { 352 DC_ERR("DC: failed to create stream_encoder!\n"); 353 return false; 354 } 355 pool->stream_enc_count++; 356 } 357 358 dc->hwseq = create_funcs->create_hwseq(ctx); 359 360 return true; 361 } 362 static int find_matching_clock_source( 363 const struct resource_pool *pool, 364 struct clock_source *clock_source) 365 { 366 367 int i; 368 369 for (i = 0; i < pool->clk_src_count; i++) { 370 if (pool->clock_sources[i] == clock_source) 371 return i; 372 } 373 return -1; 374 } 375 376 void resource_unreference_clock_source( 377 struct resource_context *res_ctx, 378 const struct resource_pool *pool, 379 struct clock_source *clock_source) 380 { 381 int i = find_matching_clock_source(pool, clock_source); 382 383 if (i > -1) 384 res_ctx->clock_source_ref_count[i]--; 385 386 if (pool->dp_clock_source == clock_source) 387 res_ctx->dp_clock_source_ref_count--; 388 } 389 390 void resource_reference_clock_source( 391 struct resource_context *res_ctx, 392 const struct resource_pool *pool, 393 struct clock_source *clock_source) 394 { 395 int i = find_matching_clock_source(pool, clock_source); 396 397 if (i > -1) 398 res_ctx->clock_source_ref_count[i]++; 399 400 if (pool->dp_clock_source == clock_source) 401 res_ctx->dp_clock_source_ref_count++; 402 } 403 404 int resource_get_clock_source_reference( 405 struct resource_context *res_ctx, 406 const struct resource_pool *pool, 407 struct clock_source *clock_source) 408 { 409 int i = find_matching_clock_source(pool, clock_source); 410 411 if (i > -1) 412 return res_ctx->clock_source_ref_count[i]; 413 414 if (pool->dp_clock_source == clock_source) 415 return res_ctx->dp_clock_source_ref_count; 416 417 return -1; 418 } 419 420 bool resource_are_vblanks_synchronizable( 421 struct dc_stream_state *stream1, 422 struct dc_stream_state *stream2) 423 { 424 uint32_t base60_refresh_rates[] = {10, 20, 5}; 425 uint8_t i; 426 uint8_t rr_count = sizeof(base60_refresh_rates)/sizeof(base60_refresh_rates[0]); 427 uint64_t frame_time_diff; 428 429 if (stream1->ctx->dc->config.vblank_alignment_dto_params && 430 stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0 && 431 dc_is_dp_signal(stream1->signal) && 432 dc_is_dp_signal(stream2->signal) && 433 false == stream1->has_non_synchronizable_pclk && 434 false == stream2->has_non_synchronizable_pclk && 435 stream1->timing.flags.VBLANK_SYNCHRONIZABLE && 436 stream2->timing.flags.VBLANK_SYNCHRONIZABLE) { 437 /* disable refresh rates higher than 60Hz for now */ 438 if (stream1->timing.pix_clk_100hz*100/stream1->timing.h_total/ 439 stream1->timing.v_total > 60) 440 return false; 441 if (stream2->timing.pix_clk_100hz*100/stream2->timing.h_total/ 442 stream2->timing.v_total > 60) 443 return false; 444 frame_time_diff = (uint64_t)10000 * 445 stream1->timing.h_total * 446 stream1->timing.v_total * 447 stream2->timing.pix_clk_100hz; 448 frame_time_diff = div_u64(frame_time_diff, stream1->timing.pix_clk_100hz); 449 frame_time_diff = div_u64(frame_time_diff, stream2->timing.h_total); 450 frame_time_diff = div_u64(frame_time_diff, stream2->timing.v_total); 451 for (i = 0; i < rr_count; i++) { 452 int64_t diff = (int64_t)div_u64(frame_time_diff * base60_refresh_rates[i], 10) - 10000; 453 454 if (diff < 0) 455 diff = -diff; 456 if (diff < stream1->ctx->dc->config.vblank_alignment_max_frame_time_diff) 457 return true; 458 } 459 } 460 return false; 461 } 462 463 bool resource_are_streams_timing_synchronizable( 464 struct dc_stream_state *stream1, 465 struct dc_stream_state *stream2) 466 { 467 if (stream1->timing.h_total != stream2->timing.h_total) 468 return false; 469 470 if (stream1->timing.v_total != stream2->timing.v_total) 471 return false; 472 473 if (stream1->timing.h_addressable 474 != stream2->timing.h_addressable) 475 return false; 476 477 if (stream1->timing.v_addressable 478 != stream2->timing.v_addressable) 479 return false; 480 481 if (stream1->timing.v_front_porch 482 != stream2->timing.v_front_porch) 483 return false; 484 485 if (stream1->timing.pix_clk_100hz 486 != stream2->timing.pix_clk_100hz) 487 return false; 488 489 if (stream1->clamping.c_depth != stream2->clamping.c_depth) 490 return false; 491 492 if (stream1->phy_pix_clk != stream2->phy_pix_clk 493 && (!dc_is_dp_signal(stream1->signal) 494 || !dc_is_dp_signal(stream2->signal))) 495 return false; 496 497 if (stream1->view_format != stream2->view_format) 498 return false; 499 500 if (stream1->ignore_msa_timing_param || stream2->ignore_msa_timing_param) 501 return false; 502 503 return true; 504 } 505 static bool is_dp_and_hdmi_sharable( 506 struct dc_stream_state *stream1, 507 struct dc_stream_state *stream2) 508 { 509 if (stream1->ctx->dc->caps.disable_dp_clk_share) 510 return false; 511 512 if (stream1->clamping.c_depth != COLOR_DEPTH_888 || 513 stream2->clamping.c_depth != COLOR_DEPTH_888) 514 return false; 515 516 return true; 517 518 } 519 520 static bool is_sharable_clk_src( 521 const struct pipe_ctx *pipe_with_clk_src, 522 const struct pipe_ctx *pipe) 523 { 524 if (pipe_with_clk_src->clock_source == NULL) 525 return false; 526 527 if (pipe_with_clk_src->stream->signal == SIGNAL_TYPE_VIRTUAL) 528 return false; 529 530 if (dc_is_dp_signal(pipe_with_clk_src->stream->signal) || 531 (dc_is_dp_signal(pipe->stream->signal) && 532 !is_dp_and_hdmi_sharable(pipe_with_clk_src->stream, 533 pipe->stream))) 534 return false; 535 536 if (dc_is_hdmi_signal(pipe_with_clk_src->stream->signal) 537 && dc_is_dual_link_signal(pipe->stream->signal)) 538 return false; 539 540 if (dc_is_hdmi_signal(pipe->stream->signal) 541 && dc_is_dual_link_signal(pipe_with_clk_src->stream->signal)) 542 return false; 543 544 if (!resource_are_streams_timing_synchronizable( 545 pipe_with_clk_src->stream, pipe->stream)) 546 return false; 547 548 return true; 549 } 550 551 struct clock_source *resource_find_used_clk_src_for_sharing( 552 struct resource_context *res_ctx, 553 struct pipe_ctx *pipe_ctx) 554 { 555 int i; 556 557 for (i = 0; i < MAX_PIPES; i++) { 558 if (is_sharable_clk_src(&res_ctx->pipe_ctx[i], pipe_ctx)) 559 return res_ctx->pipe_ctx[i].clock_source; 560 } 561 562 return NULL; 563 } 564 565 static enum pixel_format convert_pixel_format_to_dalsurface( 566 enum surface_pixel_format surface_pixel_format) 567 { 568 enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 569 570 switch (surface_pixel_format) { 571 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 572 dal_pixel_format = PIXEL_FORMAT_INDEX8; 573 break; 574 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 575 dal_pixel_format = PIXEL_FORMAT_RGB565; 576 break; 577 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 578 dal_pixel_format = PIXEL_FORMAT_RGB565; 579 break; 580 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 581 dal_pixel_format = PIXEL_FORMAT_ARGB8888; 582 break; 583 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 584 dal_pixel_format = PIXEL_FORMAT_ARGB8888; 585 break; 586 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 587 dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 588 break; 589 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 590 dal_pixel_format = PIXEL_FORMAT_ARGB2101010; 591 break; 592 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 593 dal_pixel_format = PIXEL_FORMAT_ARGB2101010_XRBIAS; 594 break; 595 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 596 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 597 dal_pixel_format = PIXEL_FORMAT_FP16; 598 break; 599 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 600 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 601 dal_pixel_format = PIXEL_FORMAT_420BPP8; 602 break; 603 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 604 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 605 dal_pixel_format = PIXEL_FORMAT_420BPP10; 606 break; 607 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 608 default: 609 dal_pixel_format = PIXEL_FORMAT_UNKNOWN; 610 break; 611 } 612 return dal_pixel_format; 613 } 614 615 static inline void get_vp_scan_direction( 616 enum dc_rotation_angle rotation, 617 bool horizontal_mirror, 618 bool *orthogonal_rotation, 619 bool *flip_vert_scan_dir, 620 bool *flip_horz_scan_dir) 621 { 622 *orthogonal_rotation = false; 623 *flip_vert_scan_dir = false; 624 *flip_horz_scan_dir = false; 625 if (rotation == ROTATION_ANGLE_180) { 626 *flip_vert_scan_dir = true; 627 *flip_horz_scan_dir = true; 628 } else if (rotation == ROTATION_ANGLE_90) { 629 *orthogonal_rotation = true; 630 *flip_horz_scan_dir = true; 631 } else if (rotation == ROTATION_ANGLE_270) { 632 *orthogonal_rotation = true; 633 *flip_vert_scan_dir = true; 634 } 635 636 if (horizontal_mirror) 637 *flip_horz_scan_dir = !*flip_horz_scan_dir; 638 } 639 640 int get_num_mpc_splits(struct pipe_ctx *pipe) 641 { 642 int mpc_split_count = 0; 643 struct pipe_ctx *other_pipe = pipe->bottom_pipe; 644 645 while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 646 mpc_split_count++; 647 other_pipe = other_pipe->bottom_pipe; 648 } 649 other_pipe = pipe->top_pipe; 650 while (other_pipe && other_pipe->plane_state == pipe->plane_state) { 651 mpc_split_count++; 652 other_pipe = other_pipe->top_pipe; 653 } 654 655 return mpc_split_count; 656 } 657 658 int get_num_odm_splits(struct pipe_ctx *pipe) 659 { 660 int odm_split_count = 0; 661 struct pipe_ctx *next_pipe = pipe->next_odm_pipe; 662 while (next_pipe) { 663 odm_split_count++; 664 next_pipe = next_pipe->next_odm_pipe; 665 } 666 pipe = pipe->prev_odm_pipe; 667 while (pipe) { 668 odm_split_count++; 669 pipe = pipe->prev_odm_pipe; 670 } 671 return odm_split_count; 672 } 673 674 static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) 675 { 676 *split_count = get_num_odm_splits(pipe_ctx); 677 *split_idx = 0; 678 if (*split_count == 0) { 679 /*Check for mpc split*/ 680 struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; 681 682 *split_count = get_num_mpc_splits(pipe_ctx); 683 while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { 684 (*split_idx)++; 685 split_pipe = split_pipe->top_pipe; 686 } 687 } else { 688 /*Get odm split index*/ 689 struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; 690 691 while (split_pipe) { 692 (*split_idx)++; 693 split_pipe = split_pipe->prev_odm_pipe; 694 } 695 } 696 } 697 698 static void calculate_viewport(struct pipe_ctx *pipe_ctx) 699 { 700 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 701 const struct dc_stream_state *stream = pipe_ctx->stream; 702 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 703 struct rect surf_src = plane_state->src_rect; 704 struct rect clip, dest; 705 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 706 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 707 int split_count = 0; 708 int split_idx = 0; 709 bool orthogonal_rotation, flip_y_start, flip_x_start; 710 711 calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 712 713 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || 714 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { 715 split_count = 0; 716 split_idx = 0; 717 } 718 719 /* The actual clip is an intersection between stream 720 * source and surface clip 721 */ 722 dest = plane_state->dst_rect; 723 clip.x = stream->src.x > plane_state->clip_rect.x ? 724 stream->src.x : plane_state->clip_rect.x; 725 726 clip.width = stream->src.x + stream->src.width < 727 plane_state->clip_rect.x + plane_state->clip_rect.width ? 728 stream->src.x + stream->src.width - clip.x : 729 plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ; 730 731 clip.y = stream->src.y > plane_state->clip_rect.y ? 732 stream->src.y : plane_state->clip_rect.y; 733 734 clip.height = stream->src.y + stream->src.height < 735 plane_state->clip_rect.y + plane_state->clip_rect.height ? 736 stream->src.y + stream->src.height - clip.y : 737 plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ; 738 739 /* 740 * Need to calculate how scan origin is shifted in vp space 741 * to correctly rotate clip and dst 742 */ 743 get_vp_scan_direction( 744 plane_state->rotation, 745 plane_state->horizontal_mirror, 746 &orthogonal_rotation, 747 &flip_y_start, 748 &flip_x_start); 749 750 if (orthogonal_rotation) { 751 swap(clip.x, clip.y); 752 swap(clip.width, clip.height); 753 swap(dest.x, dest.y); 754 swap(dest.width, dest.height); 755 } 756 if (flip_x_start) { 757 clip.x = dest.x + dest.width - clip.x - clip.width; 758 dest.x = 0; 759 } 760 if (flip_y_start) { 761 clip.y = dest.y + dest.height - clip.y - clip.height; 762 dest.y = 0; 763 } 764 765 /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio 766 * num_pixels = clip.num_pix * scl_ratio 767 */ 768 data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width; 769 data->viewport.width = clip.width * surf_src.width / dest.width; 770 771 data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height; 772 data->viewport.height = clip.height * surf_src.height / dest.height; 773 774 /* Handle split */ 775 if (split_count) { 776 /* extra pixels in the division remainder need to go to pipes after 777 * the extra pixel index minus one(epimo) defined here as: 778 */ 779 int epimo = 0; 780 781 if (orthogonal_rotation) { 782 if (flip_y_start) 783 split_idx = split_count - split_idx; 784 785 epimo = split_count - data->viewport.height % (split_count + 1); 786 787 data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx; 788 if (split_idx > epimo) 789 data->viewport.y += split_idx - epimo - 1; 790 data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0); 791 } else { 792 if (flip_x_start) 793 split_idx = split_count - split_idx; 794 795 epimo = split_count - data->viewport.width % (split_count + 1); 796 797 data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx; 798 if (split_idx > epimo) 799 data->viewport.x += split_idx - epimo - 1; 800 data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 801 } 802 } 803 804 /* Round down, compensate in init */ 805 data->viewport_c.x = data->viewport.x / vpc_div; 806 data->viewport_c.y = data->viewport.y / vpc_div; 807 data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 808 data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_zero; 809 810 /* Round up, assume original video size always even dimensions */ 811 data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; 812 data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; 813 814 data->viewport_unadjusted = data->viewport; 815 data->viewport_c_unadjusted = data->viewport_c; 816 } 817 818 static void calculate_recout(struct pipe_ctx *pipe_ctx) 819 { 820 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 821 const struct dc_stream_state *stream = pipe_ctx->stream; 822 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 823 struct rect surf_clip = plane_state->clip_rect; 824 bool pri_split_tb = pipe_ctx->bottom_pipe && 825 pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state && 826 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 827 bool sec_split_tb = pipe_ctx->top_pipe && 828 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state && 829 stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; 830 int split_count = 0; 831 int split_idx = 0; 832 833 calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); 834 835 /* 836 * Only the leftmost ODM pipe should be offset by a nonzero distance 837 */ 838 if (!pipe_ctx->prev_odm_pipe) { 839 data->recout.x = stream->dst.x; 840 if (stream->src.x < surf_clip.x) 841 data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width 842 / stream->src.width; 843 844 } else 845 data->recout.x = 0; 846 847 if (stream->src.x > surf_clip.x) 848 surf_clip.width -= stream->src.x - surf_clip.x; 849 data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; 850 if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) 851 data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; 852 853 data->recout.y = stream->dst.y; 854 if (stream->src.y < surf_clip.y) 855 data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height 856 / stream->src.height; 857 else if (stream->src.y > surf_clip.y) 858 surf_clip.height -= stream->src.y - surf_clip.y; 859 860 data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; 861 if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) 862 data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; 863 864 /* Handle h & v split, handle rotation using viewport */ 865 if (sec_split_tb) { 866 data->recout.y += data->recout.height / 2; 867 /* Floor primary pipe, ceil 2ndary pipe */ 868 data->recout.height = (data->recout.height + 1) / 2; 869 } else if (pri_split_tb) 870 data->recout.height /= 2; 871 else if (split_count) { 872 /* extra pixels in the division remainder need to go to pipes after 873 * the extra pixel index minus one(epimo) defined here as: 874 */ 875 int epimo = split_count - data->recout.width % (split_count + 1); 876 877 /*no recout offset due to odm */ 878 if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { 879 data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; 880 if (split_idx > epimo) 881 data->recout.x += split_idx - epimo - 1; 882 } 883 data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); 884 } 885 } 886 887 static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) 888 { 889 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 890 const struct dc_stream_state *stream = pipe_ctx->stream; 891 struct rect surf_src = plane_state->src_rect; 892 const int in_w = stream->src.width; 893 const int in_h = stream->src.height; 894 const int out_w = stream->dst.width; 895 const int out_h = stream->dst.height; 896 897 /*Swap surf_src height and width since scaling ratios are in recout rotation*/ 898 if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 || 899 pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) 900 swap(surf_src.height, surf_src.width); 901 902 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_from_fraction( 903 surf_src.width, 904 plane_state->dst_rect.width); 905 pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_from_fraction( 906 surf_src.height, 907 plane_state->dst_rect.height); 908 909 if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE) 910 pipe_ctx->plane_res.scl_data.ratios.horz.value *= 2; 911 else if (stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) 912 pipe_ctx->plane_res.scl_data.ratios.vert.value *= 2; 913 914 pipe_ctx->plane_res.scl_data.ratios.vert.value = div64_s64( 915 pipe_ctx->plane_res.scl_data.ratios.vert.value * in_h, out_h); 916 pipe_ctx->plane_res.scl_data.ratios.horz.value = div64_s64( 917 pipe_ctx->plane_res.scl_data.ratios.horz.value * in_w, out_w); 918 919 pipe_ctx->plane_res.scl_data.ratios.horz_c = pipe_ctx->plane_res.scl_data.ratios.horz; 920 pipe_ctx->plane_res.scl_data.ratios.vert_c = pipe_ctx->plane_res.scl_data.ratios.vert; 921 922 if (pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP8 923 || pipe_ctx->plane_res.scl_data.format == PIXEL_FORMAT_420BPP10) { 924 pipe_ctx->plane_res.scl_data.ratios.horz_c.value /= 2; 925 pipe_ctx->plane_res.scl_data.ratios.vert_c.value /= 2; 926 } 927 pipe_ctx->plane_res.scl_data.ratios.horz = dc_fixpt_truncate( 928 pipe_ctx->plane_res.scl_data.ratios.horz, 19); 929 pipe_ctx->plane_res.scl_data.ratios.vert = dc_fixpt_truncate( 930 pipe_ctx->plane_res.scl_data.ratios.vert, 19); 931 pipe_ctx->plane_res.scl_data.ratios.horz_c = dc_fixpt_truncate( 932 pipe_ctx->plane_res.scl_data.ratios.horz_c, 19); 933 pipe_ctx->plane_res.scl_data.ratios.vert_c = dc_fixpt_truncate( 934 pipe_ctx->plane_res.scl_data.ratios.vert_c, 19); 935 } 936 937 static inline void adjust_vp_and_init_for_seamless_clip( 938 bool flip_scan_dir, 939 int recout_skip, 940 int src_size, 941 int taps, 942 struct fixed31_32 ratio, 943 struct fixed31_32 *init, 944 int *vp_offset, 945 int *vp_size) 946 { 947 if (!flip_scan_dir) { 948 /* Adjust for viewport end clip-off */ 949 if ((*vp_offset + *vp_size) < src_size) { 950 int vp_clip = src_size - *vp_size - *vp_offset; 951 int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 952 953 int_part = int_part > 0 ? int_part : 0; 954 *vp_size += int_part < vp_clip ? int_part : vp_clip; 955 } 956 957 /* Adjust for non-0 viewport offset */ 958 if (*vp_offset) { 959 int int_part; 960 961 *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 962 int_part = dc_fixpt_floor(*init) - *vp_offset; 963 if (int_part < taps) { 964 int int_adj = *vp_offset >= (taps - int_part) ? 965 (taps - int_part) : *vp_offset; 966 *vp_offset -= int_adj; 967 *vp_size += int_adj; 968 int_part += int_adj; 969 } else if (int_part > taps) { 970 *vp_offset += int_part - taps; 971 *vp_size -= int_part - taps; 972 int_part = taps; 973 } 974 init->value &= 0xffffffff; 975 *init = dc_fixpt_add_int(*init, int_part); 976 } 977 } else { 978 /* Adjust for non-0 viewport offset */ 979 if (*vp_offset) { 980 int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio)); 981 982 int_part = int_part > 0 ? int_part : 0; 983 *vp_size += int_part < *vp_offset ? int_part : *vp_offset; 984 *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset; 985 } 986 987 /* Adjust for viewport end clip-off */ 988 if ((*vp_offset + *vp_size) < src_size) { 989 int int_part; 990 int end_offset = src_size - *vp_offset - *vp_size; 991 992 /* 993 * this is init if vp had no offset, keep in mind this is from the 994 * right side of vp due to scan direction 995 */ 996 *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip)); 997 /* 998 * this is the difference between first pixel of viewport available to read 999 * and init position, takning into account scan direction 1000 */ 1001 int_part = dc_fixpt_floor(*init) - end_offset; 1002 if (int_part < taps) { 1003 int int_adj = end_offset >= (taps - int_part) ? 1004 (taps - int_part) : end_offset; 1005 *vp_size += int_adj; 1006 int_part += int_adj; 1007 } else if (int_part > taps) { 1008 *vp_size += int_part - taps; 1009 int_part = taps; 1010 } 1011 init->value &= 0xffffffff; 1012 *init = dc_fixpt_add_int(*init, int_part); 1013 } 1014 } 1015 } 1016 1017 static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) 1018 { 1019 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 1020 const struct dc_stream_state *stream = pipe_ctx->stream; 1021 struct pipe_ctx *odm_pipe = pipe_ctx; 1022 struct scaler_data *data = &pipe_ctx->plane_res.scl_data; 1023 struct rect src = pipe_ctx->plane_state->src_rect; 1024 int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 1025 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 1026 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; 1027 bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; 1028 int odm_idx = 0; 1029 1030 /* 1031 * Need to calculate the scan direction for viewport to make adjustments 1032 */ 1033 get_vp_scan_direction( 1034 plane_state->rotation, 1035 plane_state->horizontal_mirror, 1036 &orthogonal_rotation, 1037 &flip_vert_scan_dir, 1038 &flip_horz_scan_dir); 1039 1040 /* Calculate src rect rotation adjusted to recout space */ 1041 surf_size_h = src.x + src.width; 1042 surf_size_v = src.y + src.height; 1043 if (flip_horz_scan_dir) 1044 src.x = 0; 1045 if (flip_vert_scan_dir) 1046 src.y = 0; 1047 if (orthogonal_rotation) { 1048 swap(src.x, src.y); 1049 swap(src.width, src.height); 1050 } 1051 1052 /*modified recout_skip_h calculation due to odm having no recout offset*/ 1053 while (odm_pipe->prev_odm_pipe) { 1054 odm_idx++; 1055 odm_pipe = odm_pipe->prev_odm_pipe; 1056 } 1057 /*odm_pipe is the leftmost pipe in the ODM group*/ 1058 recout_skip_h = odm_idx * data->recout.width; 1059 1060 /* Recout matching initial vp offset = recout_offset - (stream dst offset + 1061 * ((surf dst offset - stream src offset) * 1/ stream scaling ratio) 1062 * - (surf surf_src offset * 1/ full scl ratio)) 1063 */ 1064 recout_skip_h += odm_pipe->plane_res.scl_data.recout.x 1065 - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x) 1066 * stream->dst.width / stream->src.width - 1067 src.x * plane_state->dst_rect.width / src.width 1068 * stream->dst.width / stream->src.width); 1069 1070 1071 recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) 1072 * stream->dst.height / stream->src.height - 1073 src.y * plane_state->dst_rect.height / src.height 1074 * stream->dst.height / stream->src.height); 1075 if (orthogonal_rotation) 1076 swap(recout_skip_h, recout_skip_v); 1077 /* 1078 * Init calculated according to formula: 1079 * init = (scaling_ratio + number_of_taps + 1) / 2 1080 * init_bot = init + scaling_ratio 1081 * init_c = init + truncated_vp_c_offset(from calculate viewport) 1082 */ 1083 data->inits.h = dc_fixpt_truncate(dc_fixpt_div_int( 1084 dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19); 1085 1086 data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int( 1087 dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19); 1088 1089 data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int( 1090 dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19); 1091 1092 data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int( 1093 dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19); 1094 1095 /* 1096 * Taps, inits and scaling ratios are in recout space need to rotate 1097 * to viewport rotation before adjustment 1098 */ 1099 adjust_vp_and_init_for_seamless_clip( 1100 flip_horz_scan_dir, 1101 recout_skip_h, 1102 surf_size_h, 1103 orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps, 1104 orthogonal_rotation ? data->ratios.vert : data->ratios.horz, 1105 orthogonal_rotation ? &data->inits.v : &data->inits.h, 1106 &data->viewport.x, 1107 &data->viewport.width); 1108 adjust_vp_and_init_for_seamless_clip( 1109 flip_horz_scan_dir, 1110 recout_skip_h, 1111 surf_size_h / vpc_div, 1112 orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c, 1113 orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c, 1114 orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c, 1115 &data->viewport_c.x, 1116 &data->viewport_c.width); 1117 adjust_vp_and_init_for_seamless_clip( 1118 flip_vert_scan_dir, 1119 recout_skip_v, 1120 surf_size_v, 1121 orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps, 1122 orthogonal_rotation ? data->ratios.horz : data->ratios.vert, 1123 orthogonal_rotation ? &data->inits.h : &data->inits.v, 1124 &data->viewport.y, 1125 &data->viewport.height); 1126 adjust_vp_and_init_for_seamless_clip( 1127 flip_vert_scan_dir, 1128 recout_skip_v, 1129 surf_size_v / vpc_div, 1130 orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c, 1131 orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c, 1132 orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c, 1133 &data->viewport_c.y, 1134 &data->viewport_c.height); 1135 1136 /* Interlaced inits based on final vert inits */ 1137 data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert); 1138 data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c); 1139 1140 } 1141 1142 /* 1143 * When handling 270 rotation in mixed SLS mode, we have 1144 * stream->timing.h_border_left that is non zero. If we are doing 1145 * pipe-splitting, this h_border_left value gets added to recout.x and when it 1146 * calls calculate_inits_and_adj_vp() and 1147 * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a 1148 * pipe to be incorrect. 1149 * 1150 * To fix this, instead of using stream->timing.h_border_left, we can use 1151 * stream->dst.x to represent the border instead. So we will set h_border_left 1152 * to 0 and shift the appropriate amount in stream->dst.x. We will then 1153 * perform all calculations in resource_build_scaling_params() based on this 1154 * and then restore the h_border_left and stream->dst.x to their original 1155 * values. 1156 * 1157 * shift_border_left_to_dst() will shift the amount of h_border_left to 1158 * stream->dst.x and set h_border_left to 0. restore_border_left_from_dst() 1159 * will restore h_border_left and stream->dst.x back to their original values 1160 * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the 1161 * original h_border_left value in its calculation. 1162 */ 1163 static int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx) 1164 { 1165 int store_h_border_left = pipe_ctx->stream->timing.h_border_left; 1166 1167 if (store_h_border_left) { 1168 pipe_ctx->stream->timing.h_border_left = 0; 1169 pipe_ctx->stream->dst.x += store_h_border_left; 1170 } 1171 return store_h_border_left; 1172 } 1173 1174 static void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx, 1175 int store_h_border_left) 1176 { 1177 pipe_ctx->stream->dst.x -= store_h_border_left; 1178 pipe_ctx->stream->timing.h_border_left = store_h_border_left; 1179 } 1180 1181 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) 1182 { 1183 const struct dc_plane_state *plane_state = pipe_ctx->plane_state; 1184 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1185 bool res = false; 1186 int store_h_border_left = shift_border_left_to_dst(pipe_ctx); 1187 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); 1188 /* Important: scaling ratio calculation requires pixel format, 1189 * lb depth calculation requires recout and taps require scaling ratios. 1190 * Inits require viewport, taps, ratios and recout of split pipe 1191 */ 1192 pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( 1193 pipe_ctx->plane_state->format); 1194 1195 calculate_scaling_ratios(pipe_ctx); 1196 1197 calculate_viewport(pipe_ctx); 1198 1199 if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE || 1200 pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) { 1201 if (store_h_border_left) { 1202 restore_border_left_from_dst(pipe_ctx, 1203 store_h_border_left); 1204 } 1205 return false; 1206 } 1207 1208 calculate_recout(pipe_ctx); 1209 1210 /** 1211 * Setting line buffer pixel depth to 24bpp yields banding 1212 * on certain displays, such as the Sharp 4k 1213 */ 1214 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; 1215 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; 1216 1217 pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left; 1218 pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top; 1219 1220 pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable + 1221 store_h_border_left + timing->h_border_right; 1222 pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + 1223 timing->v_border_top + timing->v_border_bottom; 1224 if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) 1225 pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; 1226 1227 /* Taps calculations */ 1228 if (pipe_ctx->plane_res.xfm != NULL) 1229 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 1230 pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1231 1232 if (pipe_ctx->plane_res.dpp != NULL) 1233 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1234 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality); 1235 1236 1237 if (!res) { 1238 /* Try 24 bpp linebuffer */ 1239 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_24BPP; 1240 1241 if (pipe_ctx->plane_res.xfm != NULL) 1242 res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps( 1243 pipe_ctx->plane_res.xfm, 1244 &pipe_ctx->plane_res.scl_data, 1245 &plane_state->scaling_quality); 1246 1247 if (pipe_ctx->plane_res.dpp != NULL) 1248 res = pipe_ctx->plane_res.dpp->funcs->dpp_get_optimal_number_of_taps( 1249 pipe_ctx->plane_res.dpp, 1250 &pipe_ctx->plane_res.scl_data, 1251 &plane_state->scaling_quality); 1252 } 1253 1254 if (res) 1255 /* May need to re-check lb size after this in some obscure scenario */ 1256 calculate_inits_and_adj_vp(pipe_ctx); 1257 1258 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" 1259 "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", 1260 __func__, 1261 pipe_ctx->pipe_idx, 1262 pipe_ctx->plane_res.scl_data.viewport.height, 1263 pipe_ctx->plane_res.scl_data.viewport.width, 1264 pipe_ctx->plane_res.scl_data.viewport.x, 1265 pipe_ctx->plane_res.scl_data.viewport.y, 1266 pipe_ctx->plane_res.scl_data.recout.height, 1267 pipe_ctx->plane_res.scl_data.recout.width, 1268 pipe_ctx->plane_res.scl_data.recout.x, 1269 pipe_ctx->plane_res.scl_data.recout.y, 1270 pipe_ctx->plane_res.scl_data.h_active, 1271 pipe_ctx->plane_res.scl_data.v_active, 1272 plane_state->src_rect.height, 1273 plane_state->src_rect.width, 1274 plane_state->src_rect.x, 1275 plane_state->src_rect.y, 1276 plane_state->dst_rect.height, 1277 plane_state->dst_rect.width, 1278 plane_state->dst_rect.x, 1279 plane_state->dst_rect.y, 1280 plane_state->clip_rect.height, 1281 plane_state->clip_rect.width, 1282 plane_state->clip_rect.x, 1283 plane_state->clip_rect.y); 1284 1285 if (store_h_border_left) 1286 restore_border_left_from_dst(pipe_ctx, store_h_border_left); 1287 1288 return res; 1289 } 1290 1291 1292 enum dc_status resource_build_scaling_params_for_context( 1293 const struct dc *dc, 1294 struct dc_state *context) 1295 { 1296 int i; 1297 1298 for (i = 0; i < MAX_PIPES; i++) { 1299 if (context->res_ctx.pipe_ctx[i].plane_state != NULL && 1300 context->res_ctx.pipe_ctx[i].stream != NULL) 1301 if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) 1302 return DC_FAIL_SCALING; 1303 } 1304 1305 return DC_OK; 1306 } 1307 1308 struct pipe_ctx *find_idle_secondary_pipe( 1309 struct resource_context *res_ctx, 1310 const struct resource_pool *pool, 1311 const struct pipe_ctx *primary_pipe) 1312 { 1313 int i; 1314 struct pipe_ctx *secondary_pipe = NULL; 1315 1316 /* 1317 * We add a preferred pipe mapping to avoid the chance that 1318 * MPCCs already in use will need to be reassigned to other trees. 1319 * For example, if we went with the strict, assign backwards logic: 1320 * 1321 * (State 1) 1322 * Display A on, no surface, top pipe = 0 1323 * Display B on, no surface, top pipe = 1 1324 * 1325 * (State 2) 1326 * Display A on, no surface, top pipe = 0 1327 * Display B on, surface enable, top pipe = 1, bottom pipe = 5 1328 * 1329 * (State 3) 1330 * Display A on, surface enable, top pipe = 0, bottom pipe = 5 1331 * Display B on, surface enable, top pipe = 1, bottom pipe = 4 1332 * 1333 * The state 2->3 transition requires remapping MPCC 5 from display B 1334 * to display A. 1335 * 1336 * However, with the preferred pipe logic, state 2 would look like: 1337 * 1338 * (State 2) 1339 * Display A on, no surface, top pipe = 0 1340 * Display B on, surface enable, top pipe = 1, bottom pipe = 4 1341 * 1342 * This would then cause 2->3 to not require remapping any MPCCs. 1343 */ 1344 if (primary_pipe) { 1345 int preferred_pipe_idx = (pool->pipe_count - 1) - primary_pipe->pipe_idx; 1346 if (res_ctx->pipe_ctx[preferred_pipe_idx].stream == NULL) { 1347 secondary_pipe = &res_ctx->pipe_ctx[preferred_pipe_idx]; 1348 secondary_pipe->pipe_idx = preferred_pipe_idx; 1349 } 1350 } 1351 1352 /* 1353 * search backwards for the second pipe to keep pipe 1354 * assignment more consistent 1355 */ 1356 if (!secondary_pipe) 1357 for (i = pool->pipe_count - 1; i >= 0; i--) { 1358 if (res_ctx->pipe_ctx[i].stream == NULL) { 1359 secondary_pipe = &res_ctx->pipe_ctx[i]; 1360 secondary_pipe->pipe_idx = i; 1361 break; 1362 } 1363 } 1364 1365 return secondary_pipe; 1366 } 1367 1368 struct pipe_ctx *resource_get_head_pipe_for_stream( 1369 struct resource_context *res_ctx, 1370 struct dc_stream_state *stream) 1371 { 1372 int i; 1373 1374 for (i = 0; i < MAX_PIPES; i++) { 1375 if (res_ctx->pipe_ctx[i].stream == stream 1376 && !res_ctx->pipe_ctx[i].top_pipe 1377 && !res_ctx->pipe_ctx[i].prev_odm_pipe) 1378 return &res_ctx->pipe_ctx[i]; 1379 } 1380 return NULL; 1381 } 1382 1383 static struct pipe_ctx *resource_get_tail_pipe( 1384 struct resource_context *res_ctx, 1385 struct pipe_ctx *head_pipe) 1386 { 1387 struct pipe_ctx *tail_pipe; 1388 1389 tail_pipe = head_pipe->bottom_pipe; 1390 1391 while (tail_pipe) { 1392 head_pipe = tail_pipe; 1393 tail_pipe = tail_pipe->bottom_pipe; 1394 } 1395 1396 return head_pipe; 1397 } 1398 1399 /* 1400 * A free_pipe for a stream is defined here as a pipe 1401 * that has no surface attached yet 1402 */ 1403 static struct pipe_ctx *acquire_free_pipe_for_head( 1404 struct dc_state *context, 1405 const struct resource_pool *pool, 1406 struct pipe_ctx *head_pipe) 1407 { 1408 int i; 1409 struct resource_context *res_ctx = &context->res_ctx; 1410 1411 if (!head_pipe->plane_state) 1412 return head_pipe; 1413 1414 /* Re-use pipe already acquired for this stream if available*/ 1415 for (i = pool->pipe_count - 1; i >= 0; i--) { 1416 if (res_ctx->pipe_ctx[i].stream == head_pipe->stream && 1417 !res_ctx->pipe_ctx[i].plane_state) { 1418 return &res_ctx->pipe_ctx[i]; 1419 } 1420 } 1421 1422 /* 1423 * At this point we have no re-useable pipe for this stream and we need 1424 * to acquire an idle one to satisfy the request 1425 */ 1426 1427 if (!pool->funcs->acquire_idle_pipe_for_layer) 1428 return NULL; 1429 1430 return pool->funcs->acquire_idle_pipe_for_layer(context, pool, head_pipe->stream); 1431 } 1432 1433 #if defined(CONFIG_DRM_AMD_DC_DCN) 1434 static int acquire_first_split_pipe( 1435 struct resource_context *res_ctx, 1436 const struct resource_pool *pool, 1437 struct dc_stream_state *stream) 1438 { 1439 int i; 1440 1441 for (i = 0; i < pool->pipe_count; i++) { 1442 struct pipe_ctx *split_pipe = &res_ctx->pipe_ctx[i]; 1443 1444 if (split_pipe->top_pipe && 1445 split_pipe->top_pipe->plane_state == split_pipe->plane_state) { 1446 split_pipe->top_pipe->bottom_pipe = split_pipe->bottom_pipe; 1447 if (split_pipe->bottom_pipe) 1448 split_pipe->bottom_pipe->top_pipe = split_pipe->top_pipe; 1449 1450 if (split_pipe->top_pipe->plane_state) 1451 resource_build_scaling_params(split_pipe->top_pipe); 1452 1453 memset(split_pipe, 0, sizeof(*split_pipe)); 1454 split_pipe->stream_res.tg = pool->timing_generators[i]; 1455 split_pipe->plane_res.hubp = pool->hubps[i]; 1456 split_pipe->plane_res.ipp = pool->ipps[i]; 1457 split_pipe->plane_res.dpp = pool->dpps[i]; 1458 split_pipe->stream_res.opp = pool->opps[i]; 1459 split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst; 1460 split_pipe->pipe_idx = i; 1461 1462 split_pipe->stream = stream; 1463 return i; 1464 } 1465 } 1466 return -1; 1467 } 1468 #endif 1469 1470 bool dc_add_plane_to_context( 1471 const struct dc *dc, 1472 struct dc_stream_state *stream, 1473 struct dc_plane_state *plane_state, 1474 struct dc_state *context) 1475 { 1476 int i; 1477 struct resource_pool *pool = dc->res_pool; 1478 struct pipe_ctx *head_pipe, *tail_pipe, *free_pipe; 1479 struct dc_stream_status *stream_status = NULL; 1480 1481 for (i = 0; i < context->stream_count; i++) 1482 if (context->streams[i] == stream) { 1483 stream_status = &context->stream_status[i]; 1484 break; 1485 } 1486 if (stream_status == NULL) { 1487 dm_error("Existing stream not found; failed to attach surface!\n"); 1488 return false; 1489 } 1490 1491 1492 if (stream_status->plane_count == MAX_SURFACE_NUM) { 1493 dm_error("Surface: can not attach plane_state %p! Maximum is: %d\n", 1494 plane_state, MAX_SURFACE_NUM); 1495 return false; 1496 } 1497 1498 head_pipe = resource_get_head_pipe_for_stream(&context->res_ctx, stream); 1499 1500 if (!head_pipe) { 1501 dm_error("Head pipe not found for stream_state %p !\n", stream); 1502 return false; 1503 } 1504 1505 /* retain new surface, but only once per stream */ 1506 dc_plane_state_retain(plane_state); 1507 1508 while (head_pipe) { 1509 free_pipe = acquire_free_pipe_for_head(context, pool, head_pipe); 1510 1511 #if defined(CONFIG_DRM_AMD_DC_DCN) 1512 if (!free_pipe) { 1513 int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream); 1514 if (pipe_idx >= 0) 1515 free_pipe = &context->res_ctx.pipe_ctx[pipe_idx]; 1516 } 1517 #endif 1518 if (!free_pipe) { 1519 dc_plane_state_release(plane_state); 1520 return false; 1521 } 1522 1523 free_pipe->plane_state = plane_state; 1524 1525 if (head_pipe != free_pipe) { 1526 tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe); 1527 ASSERT(tail_pipe); 1528 free_pipe->stream_res.tg = tail_pipe->stream_res.tg; 1529 free_pipe->stream_res.abm = tail_pipe->stream_res.abm; 1530 free_pipe->stream_res.opp = tail_pipe->stream_res.opp; 1531 free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; 1532 free_pipe->stream_res.audio = tail_pipe->stream_res.audio; 1533 free_pipe->clock_source = tail_pipe->clock_source; 1534 free_pipe->top_pipe = tail_pipe; 1535 tail_pipe->bottom_pipe = free_pipe; 1536 if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { 1537 free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; 1538 tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; 1539 } 1540 if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { 1541 free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; 1542 tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; 1543 } 1544 } 1545 head_pipe = head_pipe->next_odm_pipe; 1546 } 1547 /* assign new surfaces*/ 1548 stream_status->plane_states[stream_status->plane_count] = plane_state; 1549 1550 stream_status->plane_count++; 1551 1552 return true; 1553 } 1554 1555 bool dc_remove_plane_from_context( 1556 const struct dc *dc, 1557 struct dc_stream_state *stream, 1558 struct dc_plane_state *plane_state, 1559 struct dc_state *context) 1560 { 1561 int i; 1562 struct dc_stream_status *stream_status = NULL; 1563 struct resource_pool *pool = dc->res_pool; 1564 1565 for (i = 0; i < context->stream_count; i++) 1566 if (context->streams[i] == stream) { 1567 stream_status = &context->stream_status[i]; 1568 break; 1569 } 1570 1571 if (stream_status == NULL) { 1572 dm_error("Existing stream not found; failed to remove plane.\n"); 1573 return false; 1574 } 1575 1576 /* release pipe for plane*/ 1577 for (i = pool->pipe_count - 1; i >= 0; i--) { 1578 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 1579 1580 if (pipe_ctx->plane_state == plane_state) { 1581 if (pipe_ctx->top_pipe) 1582 pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe; 1583 1584 /* Second condition is to avoid setting NULL to top pipe 1585 * of tail pipe making it look like head pipe in subsequent 1586 * deletes 1587 */ 1588 if (pipe_ctx->bottom_pipe && pipe_ctx->top_pipe) 1589 pipe_ctx->bottom_pipe->top_pipe = pipe_ctx->top_pipe; 1590 1591 /* 1592 * For head pipe detach surfaces from pipe for tail 1593 * pipe just zero it out 1594 */ 1595 if (!pipe_ctx->top_pipe) 1596 pipe_ctx->plane_state = NULL; 1597 else 1598 memset(pipe_ctx, 0, sizeof(*pipe_ctx)); 1599 } 1600 } 1601 1602 1603 for (i = 0; i < stream_status->plane_count; i++) { 1604 if (stream_status->plane_states[i] == plane_state) { 1605 1606 dc_plane_state_release(stream_status->plane_states[i]); 1607 break; 1608 } 1609 } 1610 1611 if (i == stream_status->plane_count) { 1612 dm_error("Existing plane_state not found; failed to detach it!\n"); 1613 return false; 1614 } 1615 1616 stream_status->plane_count--; 1617 1618 /* Start at the plane we've just released, and move all the planes one index forward to "trim" the array */ 1619 for (; i < stream_status->plane_count; i++) 1620 stream_status->plane_states[i] = stream_status->plane_states[i + 1]; 1621 1622 stream_status->plane_states[stream_status->plane_count] = NULL; 1623 1624 return true; 1625 } 1626 1627 bool dc_rem_all_planes_for_stream( 1628 const struct dc *dc, 1629 struct dc_stream_state *stream, 1630 struct dc_state *context) 1631 { 1632 int i, old_plane_count; 1633 struct dc_stream_status *stream_status = NULL; 1634 struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 }; 1635 1636 for (i = 0; i < context->stream_count; i++) 1637 if (context->streams[i] == stream) { 1638 stream_status = &context->stream_status[i]; 1639 break; 1640 } 1641 1642 if (stream_status == NULL) { 1643 dm_error("Existing stream %p not found!\n", stream); 1644 return false; 1645 } 1646 1647 old_plane_count = stream_status->plane_count; 1648 1649 for (i = 0; i < old_plane_count; i++) 1650 del_planes[i] = stream_status->plane_states[i]; 1651 1652 for (i = 0; i < old_plane_count; i++) 1653 if (!dc_remove_plane_from_context(dc, stream, del_planes[i], context)) 1654 return false; 1655 1656 return true; 1657 } 1658 1659 static bool add_all_planes_for_stream( 1660 const struct dc *dc, 1661 struct dc_stream_state *stream, 1662 const struct dc_validation_set set[], 1663 int set_count, 1664 struct dc_state *context) 1665 { 1666 int i, j; 1667 1668 for (i = 0; i < set_count; i++) 1669 if (set[i].stream == stream) 1670 break; 1671 1672 if (i == set_count) { 1673 dm_error("Stream %p not found in set!\n", stream); 1674 return false; 1675 } 1676 1677 for (j = 0; j < set[i].plane_count; j++) 1678 if (!dc_add_plane_to_context(dc, stream, set[i].plane_states[j], context)) 1679 return false; 1680 1681 return true; 1682 } 1683 1684 bool dc_add_all_planes_for_stream( 1685 const struct dc *dc, 1686 struct dc_stream_state *stream, 1687 struct dc_plane_state * const *plane_states, 1688 int plane_count, 1689 struct dc_state *context) 1690 { 1691 struct dc_validation_set set; 1692 int i; 1693 1694 set.stream = stream; 1695 set.plane_count = plane_count; 1696 1697 for (i = 0; i < plane_count; i++) 1698 set.plane_states[i] = plane_states[i]; 1699 1700 return add_all_planes_for_stream(dc, stream, &set, 1, context); 1701 } 1702 1703 static bool is_timing_changed(struct dc_stream_state *cur_stream, 1704 struct dc_stream_state *new_stream) 1705 { 1706 if (cur_stream == NULL) 1707 return true; 1708 1709 /* If sink pointer changed, it means this is a hotplug, we should do 1710 * full hw setting. 1711 */ 1712 if (cur_stream->sink != new_stream->sink) 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 } 2683 2684 void dc_resource_state_copy_construct( 2685 const struct dc_state *src_ctx, 2686 struct dc_state *dst_ctx) 2687 { 2688 int i, j; 2689 struct kref refcount = dst_ctx->refcount; 2690 2691 *dst_ctx = *src_ctx; 2692 2693 for (i = 0; i < MAX_PIPES; i++) { 2694 struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i]; 2695 2696 if (cur_pipe->top_pipe) 2697 cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx]; 2698 2699 if (cur_pipe->bottom_pipe) 2700 cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx]; 2701 2702 if (cur_pipe->next_odm_pipe) 2703 cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx]; 2704 2705 if (cur_pipe->prev_odm_pipe) 2706 cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx]; 2707 } 2708 2709 for (i = 0; i < dst_ctx->stream_count; i++) { 2710 dc_stream_retain(dst_ctx->streams[i]); 2711 for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++) 2712 dc_plane_state_retain( 2713 dst_ctx->stream_status[i].plane_states[j]); 2714 } 2715 2716 /* context refcount should not be overridden */ 2717 dst_ctx->refcount = refcount; 2718 2719 } 2720 2721 struct clock_source *dc_resource_find_first_free_pll( 2722 struct resource_context *res_ctx, 2723 const struct resource_pool *pool) 2724 { 2725 int i; 2726 2727 for (i = 0; i < pool->clk_src_count; ++i) { 2728 if (res_ctx->clock_source_ref_count[i] == 0) 2729 return pool->clock_sources[i]; 2730 } 2731 2732 return NULL; 2733 } 2734 2735 void resource_build_info_frame(struct pipe_ctx *pipe_ctx) 2736 { 2737 enum signal_type signal = SIGNAL_TYPE_NONE; 2738 struct encoder_info_frame *info = &pipe_ctx->stream_res.encoder_info_frame; 2739 2740 /* default all packets to invalid */ 2741 info->avi.valid = false; 2742 info->gamut.valid = false; 2743 info->vendor.valid = false; 2744 info->spd.valid = false; 2745 info->hdrsmd.valid = false; 2746 info->vsc.valid = false; 2747 2748 signal = pipe_ctx->stream->signal; 2749 2750 /* HDMi and DP have different info packets*/ 2751 if (dc_is_hdmi_signal(signal)) { 2752 set_avi_info_frame(&info->avi, pipe_ctx); 2753 2754 set_vendor_info_packet(&info->vendor, pipe_ctx->stream); 2755 2756 set_spd_info_packet(&info->spd, pipe_ctx->stream); 2757 2758 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2759 2760 } else if (dc_is_dp_signal(signal)) { 2761 set_vsc_info_packet(&info->vsc, pipe_ctx->stream); 2762 2763 set_spd_info_packet(&info->spd, pipe_ctx->stream); 2764 2765 set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream); 2766 } 2767 2768 patch_gamut_packet_checksum(&info->gamut); 2769 } 2770 2771 enum dc_status resource_map_clock_resources( 2772 const struct dc *dc, 2773 struct dc_state *context, 2774 struct dc_stream_state *stream) 2775 { 2776 /* acquire new resources */ 2777 const struct resource_pool *pool = dc->res_pool; 2778 struct pipe_ctx *pipe_ctx = resource_get_head_pipe_for_stream( 2779 &context->res_ctx, stream); 2780 2781 if (!pipe_ctx) 2782 return DC_ERROR_UNEXPECTED; 2783 2784 if (dc_is_dp_signal(pipe_ctx->stream->signal) 2785 || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL) 2786 pipe_ctx->clock_source = pool->dp_clock_source; 2787 else { 2788 pipe_ctx->clock_source = NULL; 2789 2790 if (!dc->config.disable_disp_pll_sharing) 2791 pipe_ctx->clock_source = resource_find_used_clk_src_for_sharing( 2792 &context->res_ctx, 2793 pipe_ctx); 2794 2795 if (pipe_ctx->clock_source == NULL) 2796 pipe_ctx->clock_source = 2797 dc_resource_find_first_free_pll( 2798 &context->res_ctx, 2799 pool); 2800 } 2801 2802 if (pipe_ctx->clock_source == NULL) 2803 return DC_NO_CLOCK_SOURCE_RESOURCE; 2804 2805 resource_reference_clock_source( 2806 &context->res_ctx, pool, 2807 pipe_ctx->clock_source); 2808 2809 return DC_OK; 2810 } 2811 2812 /* 2813 * Note: We need to disable output if clock sources change, 2814 * since bios does optimization and doesn't apply if changing 2815 * PHY when not already disabled. 2816 */ 2817 bool pipe_need_reprogram( 2818 struct pipe_ctx *pipe_ctx_old, 2819 struct pipe_ctx *pipe_ctx) 2820 { 2821 if (!pipe_ctx_old->stream) 2822 return false; 2823 2824 if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) 2825 return true; 2826 2827 if (pipe_ctx_old->stream->signal != pipe_ctx->stream->signal) 2828 return true; 2829 2830 if (pipe_ctx_old->stream_res.audio != pipe_ctx->stream_res.audio) 2831 return true; 2832 2833 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source 2834 && pipe_ctx_old->stream != pipe_ctx->stream) 2835 return true; 2836 2837 if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc) 2838 return true; 2839 2840 if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream)) 2841 return true; 2842 2843 if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off) 2844 return true; 2845 2846 if (false == pipe_ctx_old->stream->link->link_state_valid && 2847 false == pipe_ctx_old->stream->dpms_off) 2848 return true; 2849 2850 if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) 2851 return true; 2852 2853 /* DIG link encoder resource assignment for stream changed. */ 2854 if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc) 2855 return true; 2856 2857 return false; 2858 } 2859 2860 void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, 2861 struct bit_depth_reduction_params *fmt_bit_depth) 2862 { 2863 enum dc_dither_option option = stream->dither_option; 2864 enum dc_pixel_encoding pixel_encoding = 2865 stream->timing.pixel_encoding; 2866 2867 memset(fmt_bit_depth, 0, sizeof(*fmt_bit_depth)); 2868 2869 if (option == DITHER_OPTION_DEFAULT) { 2870 switch (stream->timing.display_color_depth) { 2871 case COLOR_DEPTH_666: 2872 option = DITHER_OPTION_SPATIAL6; 2873 break; 2874 case COLOR_DEPTH_888: 2875 option = DITHER_OPTION_SPATIAL8; 2876 break; 2877 case COLOR_DEPTH_101010: 2878 option = DITHER_OPTION_SPATIAL10; 2879 break; 2880 default: 2881 option = DITHER_OPTION_DISABLE; 2882 } 2883 } 2884 2885 if (option == DITHER_OPTION_DISABLE) 2886 return; 2887 2888 if (option == DITHER_OPTION_TRUN6) { 2889 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2890 fmt_bit_depth->flags.TRUNCATE_DEPTH = 0; 2891 } else if (option == DITHER_OPTION_TRUN8 || 2892 option == DITHER_OPTION_TRUN8_SPATIAL6 || 2893 option == DITHER_OPTION_TRUN8_FM6) { 2894 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2895 fmt_bit_depth->flags.TRUNCATE_DEPTH = 1; 2896 } else if (option == DITHER_OPTION_TRUN10 || 2897 option == DITHER_OPTION_TRUN10_SPATIAL6 || 2898 option == DITHER_OPTION_TRUN10_SPATIAL8 || 2899 option == DITHER_OPTION_TRUN10_FM8 || 2900 option == DITHER_OPTION_TRUN10_FM6 || 2901 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2902 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2903 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2904 } 2905 2906 /* special case - Formatter can only reduce by 4 bits at most. 2907 * When reducing from 12 to 6 bits, 2908 * HW recommends we use trunc with round mode 2909 * (if we did nothing, trunc to 10 bits would be used) 2910 * note that any 12->10 bit reduction is ignored prior to DCE8, 2911 * as the input was 10 bits. 2912 */ 2913 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2914 option == DITHER_OPTION_SPATIAL6 || 2915 option == DITHER_OPTION_FM6) { 2916 fmt_bit_depth->flags.TRUNCATE_ENABLED = 1; 2917 fmt_bit_depth->flags.TRUNCATE_DEPTH = 2; 2918 fmt_bit_depth->flags.TRUNCATE_MODE = 1; 2919 } 2920 2921 /* spatial dither 2922 * note that spatial modes 1-3 are never used 2923 */ 2924 if (option == DITHER_OPTION_SPATIAL6_FRAME_RANDOM || 2925 option == DITHER_OPTION_SPATIAL6 || 2926 option == DITHER_OPTION_TRUN10_SPATIAL6 || 2927 option == DITHER_OPTION_TRUN8_SPATIAL6) { 2928 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2929 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 0; 2930 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2931 fmt_bit_depth->flags.RGB_RANDOM = 2932 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2933 } else if (option == DITHER_OPTION_SPATIAL8_FRAME_RANDOM || 2934 option == DITHER_OPTION_SPATIAL8 || 2935 option == DITHER_OPTION_SPATIAL8_FM6 || 2936 option == DITHER_OPTION_TRUN10_SPATIAL8 || 2937 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2938 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2939 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 1; 2940 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2941 fmt_bit_depth->flags.RGB_RANDOM = 2942 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2943 } else if (option == DITHER_OPTION_SPATIAL10_FRAME_RANDOM || 2944 option == DITHER_OPTION_SPATIAL10 || 2945 option == DITHER_OPTION_SPATIAL10_FM8 || 2946 option == DITHER_OPTION_SPATIAL10_FM6) { 2947 fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED = 1; 2948 fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH = 2; 2949 fmt_bit_depth->flags.HIGHPASS_RANDOM = 1; 2950 fmt_bit_depth->flags.RGB_RANDOM = 2951 (pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 2952 } 2953 2954 if (option == DITHER_OPTION_SPATIAL6 || 2955 option == DITHER_OPTION_SPATIAL8 || 2956 option == DITHER_OPTION_SPATIAL10) { 2957 fmt_bit_depth->flags.FRAME_RANDOM = 0; 2958 } else { 2959 fmt_bit_depth->flags.FRAME_RANDOM = 1; 2960 } 2961 2962 ////////////////////// 2963 //// temporal dither 2964 ////////////////////// 2965 if (option == DITHER_OPTION_FM6 || 2966 option == DITHER_OPTION_SPATIAL8_FM6 || 2967 option == DITHER_OPTION_SPATIAL10_FM6 || 2968 option == DITHER_OPTION_TRUN10_FM6 || 2969 option == DITHER_OPTION_TRUN8_FM6 || 2970 option == DITHER_OPTION_TRUN10_SPATIAL8_FM6) { 2971 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2972 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 0; 2973 } else if (option == DITHER_OPTION_FM8 || 2974 option == DITHER_OPTION_SPATIAL10_FM8 || 2975 option == DITHER_OPTION_TRUN10_FM8) { 2976 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2977 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 1; 2978 } else if (option == DITHER_OPTION_FM10) { 2979 fmt_bit_depth->flags.FRAME_MODULATION_ENABLED = 1; 2980 fmt_bit_depth->flags.FRAME_MODULATION_DEPTH = 2; 2981 } 2982 2983 fmt_bit_depth->pixel_encoding = pixel_encoding; 2984 } 2985 2986 enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) 2987 { 2988 struct dc_link *link = stream->link; 2989 struct timing_generator *tg = dc->res_pool->timing_generators[0]; 2990 enum dc_status res = DC_OK; 2991 2992 calculate_phy_pix_clks(stream); 2993 2994 if (!tg->funcs->validate_timing(tg, &stream->timing)) 2995 res = DC_FAIL_CONTROLLER_VALIDATE; 2996 2997 if (res == DC_OK) { 2998 if (!link->link_enc->funcs->validate_output_with_stream( 2999 link->link_enc, stream)) 3000 res = DC_FAIL_ENC_VALIDATE; 3001 } 3002 3003 /* TODO: validate audio ASIC caps, encoder */ 3004 3005 if (res == DC_OK) 3006 res = dc_link_validate_mode_timing(stream, 3007 link, 3008 &stream->timing); 3009 3010 return res; 3011 } 3012 3013 enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state) 3014 { 3015 enum dc_status res = DC_OK; 3016 3017 /* TODO For now validates pixel format only */ 3018 if (dc->res_pool->funcs->validate_plane) 3019 return dc->res_pool->funcs->validate_plane(plane_state, &dc->caps); 3020 3021 return res; 3022 } 3023 3024 unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format) 3025 { 3026 switch (format) { 3027 case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS: 3028 return 8; 3029 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr: 3030 case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb: 3031 return 12; 3032 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555: 3033 case SURFACE_PIXEL_FORMAT_GRPH_RGB565: 3034 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr: 3035 case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb: 3036 return 16; 3037 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888: 3038 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888: 3039 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010: 3040 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010: 3041 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS: 3042 #if defined(CONFIG_DRM_AMD_DC_DCN) 3043 case SURFACE_PIXEL_FORMAT_GRPH_RGBE: 3044 case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA: 3045 #endif 3046 return 32; 3047 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: 3048 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: 3049 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: 3050 return 64; 3051 default: 3052 ASSERT_CRITICAL(false); 3053 return -1; 3054 } 3055 } 3056 static unsigned int get_max_audio_sample_rate(struct audio_mode *modes) 3057 { 3058 if (modes) { 3059 if (modes->sample_rates.rate.RATE_192) 3060 return 192000; 3061 if (modes->sample_rates.rate.RATE_176_4) 3062 return 176400; 3063 if (modes->sample_rates.rate.RATE_96) 3064 return 96000; 3065 if (modes->sample_rates.rate.RATE_88_2) 3066 return 88200; 3067 if (modes->sample_rates.rate.RATE_48) 3068 return 48000; 3069 if (modes->sample_rates.rate.RATE_44_1) 3070 return 44100; 3071 if (modes->sample_rates.rate.RATE_32) 3072 return 32000; 3073 } 3074 /*original logic when no audio info*/ 3075 return 441000; 3076 } 3077 3078 void get_audio_check(struct audio_info *aud_modes, 3079 struct audio_check *audio_chk) 3080 { 3081 unsigned int i; 3082 unsigned int max_sample_rate = 0; 3083 3084 if (aud_modes) { 3085 audio_chk->audio_packet_type = 0x2;/*audio sample packet AP = .25 for layout0, 1 for layout1*/ 3086 3087 audio_chk->max_audiosample_rate = 0; 3088 for (i = 0; i < aud_modes->mode_count; i++) { 3089 max_sample_rate = get_max_audio_sample_rate(&aud_modes->modes[i]); 3090 if (audio_chk->max_audiosample_rate < max_sample_rate) 3091 audio_chk->max_audiosample_rate = max_sample_rate; 3092 /*dts takes the same as type 2: AP = 0.25*/ 3093 } 3094 /*check which one take more bandwidth*/ 3095 if (audio_chk->max_audiosample_rate > 192000) 3096 audio_chk->audio_packet_type = 0x9;/*AP =1*/ 3097 audio_chk->acat = 0;/*not support*/ 3098 } 3099 } 3100 3101