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