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