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