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