1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2020 Intel Corporation 4 */ 5 6 #include <drm/drm_atomic_helper.h> 7 #include <drm/drm_blend.h> 8 #include <drm/drm_damage_helper.h> 9 #include <drm/drm_fourcc.h> 10 #include <drm/drm_print.h> 11 12 #include "pxp/intel_pxp.h" 13 #include "intel_bo.h" 14 #include "intel_color.h" 15 #include "intel_color_pipeline.h" 16 #include "intel_de.h" 17 #include "intel_display_irq.h" 18 #include "intel_display_regs.h" 19 #include "intel_display_types.h" 20 #include "intel_display_utils.h" 21 #include "intel_dpt.h" 22 #include "intel_fb.h" 23 #include "intel_fbc.h" 24 #include "intel_frontbuffer.h" 25 #include "intel_panic.h" 26 #include "intel_plane.h" 27 #include "intel_psr.h" 28 #include "intel_psr_regs.h" 29 #include "intel_step.h" 30 #include "skl_scaler.h" 31 #include "skl_universal_plane.h" 32 #include "skl_universal_plane_regs.h" 33 #include "skl_watermark.h" 34 35 static const u32 skl_plane_formats[] = { 36 DRM_FORMAT_C8, 37 DRM_FORMAT_RGB565, 38 DRM_FORMAT_XRGB8888, 39 DRM_FORMAT_XBGR8888, 40 DRM_FORMAT_ARGB8888, 41 DRM_FORMAT_ABGR8888, 42 DRM_FORMAT_XRGB2101010, 43 DRM_FORMAT_XBGR2101010, 44 DRM_FORMAT_XRGB16161616F, 45 DRM_FORMAT_XBGR16161616F, 46 DRM_FORMAT_YUYV, 47 DRM_FORMAT_YVYU, 48 DRM_FORMAT_UYVY, 49 DRM_FORMAT_VYUY, 50 DRM_FORMAT_XYUV8888, 51 }; 52 53 static const u32 skl_planar_formats[] = { 54 DRM_FORMAT_C8, 55 DRM_FORMAT_RGB565, 56 DRM_FORMAT_XRGB8888, 57 DRM_FORMAT_XBGR8888, 58 DRM_FORMAT_ARGB8888, 59 DRM_FORMAT_ABGR8888, 60 DRM_FORMAT_XRGB2101010, 61 DRM_FORMAT_XBGR2101010, 62 DRM_FORMAT_XRGB16161616F, 63 DRM_FORMAT_XBGR16161616F, 64 DRM_FORMAT_YUYV, 65 DRM_FORMAT_YVYU, 66 DRM_FORMAT_UYVY, 67 DRM_FORMAT_VYUY, 68 DRM_FORMAT_NV12, 69 DRM_FORMAT_XYUV8888, 70 }; 71 72 static const u32 glk_planar_formats[] = { 73 DRM_FORMAT_C8, 74 DRM_FORMAT_RGB565, 75 DRM_FORMAT_XRGB8888, 76 DRM_FORMAT_XBGR8888, 77 DRM_FORMAT_ARGB8888, 78 DRM_FORMAT_ABGR8888, 79 DRM_FORMAT_XRGB2101010, 80 DRM_FORMAT_XBGR2101010, 81 DRM_FORMAT_XRGB16161616F, 82 DRM_FORMAT_XBGR16161616F, 83 DRM_FORMAT_YUYV, 84 DRM_FORMAT_YVYU, 85 DRM_FORMAT_UYVY, 86 DRM_FORMAT_VYUY, 87 DRM_FORMAT_NV12, 88 DRM_FORMAT_XYUV8888, 89 DRM_FORMAT_P010, 90 DRM_FORMAT_P012, 91 DRM_FORMAT_P016, 92 }; 93 94 static const u32 icl_sdr_y_plane_formats[] = { 95 DRM_FORMAT_C8, 96 DRM_FORMAT_RGB565, 97 DRM_FORMAT_XRGB8888, 98 DRM_FORMAT_XBGR8888, 99 DRM_FORMAT_ARGB8888, 100 DRM_FORMAT_ABGR8888, 101 DRM_FORMAT_XRGB2101010, 102 DRM_FORMAT_XBGR2101010, 103 DRM_FORMAT_ARGB2101010, 104 DRM_FORMAT_ABGR2101010, 105 DRM_FORMAT_YUYV, 106 DRM_FORMAT_YVYU, 107 DRM_FORMAT_UYVY, 108 DRM_FORMAT_VYUY, 109 DRM_FORMAT_Y210, 110 DRM_FORMAT_Y212, 111 DRM_FORMAT_Y216, 112 DRM_FORMAT_XYUV8888, 113 DRM_FORMAT_XVYU2101010, 114 }; 115 116 static const u32 icl_sdr_uv_plane_formats[] = { 117 DRM_FORMAT_C8, 118 DRM_FORMAT_RGB565, 119 DRM_FORMAT_XRGB8888, 120 DRM_FORMAT_XBGR8888, 121 DRM_FORMAT_ARGB8888, 122 DRM_FORMAT_ABGR8888, 123 DRM_FORMAT_XRGB2101010, 124 DRM_FORMAT_XBGR2101010, 125 DRM_FORMAT_ARGB2101010, 126 DRM_FORMAT_ABGR2101010, 127 DRM_FORMAT_YUYV, 128 DRM_FORMAT_YVYU, 129 DRM_FORMAT_UYVY, 130 DRM_FORMAT_VYUY, 131 DRM_FORMAT_NV12, 132 DRM_FORMAT_P010, 133 DRM_FORMAT_P012, 134 DRM_FORMAT_P016, 135 DRM_FORMAT_Y210, 136 DRM_FORMAT_Y212, 137 DRM_FORMAT_Y216, 138 DRM_FORMAT_XYUV8888, 139 DRM_FORMAT_XVYU2101010, 140 }; 141 142 static const u32 icl_hdr_plane_formats[] = { 143 DRM_FORMAT_C8, 144 DRM_FORMAT_RGB565, 145 DRM_FORMAT_XRGB8888, 146 DRM_FORMAT_XBGR8888, 147 DRM_FORMAT_ARGB8888, 148 DRM_FORMAT_ABGR8888, 149 DRM_FORMAT_XRGB2101010, 150 DRM_FORMAT_XBGR2101010, 151 DRM_FORMAT_ARGB2101010, 152 DRM_FORMAT_ABGR2101010, 153 DRM_FORMAT_XRGB16161616F, 154 DRM_FORMAT_XBGR16161616F, 155 DRM_FORMAT_ARGB16161616F, 156 DRM_FORMAT_ABGR16161616F, 157 DRM_FORMAT_YUYV, 158 DRM_FORMAT_YVYU, 159 DRM_FORMAT_UYVY, 160 DRM_FORMAT_VYUY, 161 DRM_FORMAT_NV12, 162 DRM_FORMAT_P010, 163 DRM_FORMAT_P012, 164 DRM_FORMAT_P016, 165 DRM_FORMAT_Y210, 166 DRM_FORMAT_Y212, 167 DRM_FORMAT_Y216, 168 DRM_FORMAT_XYUV8888, 169 DRM_FORMAT_XVYU2101010, 170 DRM_FORMAT_XVYU12_16161616, 171 DRM_FORMAT_XVYU16161616, 172 }; 173 174 int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) 175 { 176 switch (format) { 177 case PLANE_CTL_FORMAT_RGB_565: 178 return DRM_FORMAT_RGB565; 179 case PLANE_CTL_FORMAT_NV12: 180 return DRM_FORMAT_NV12; 181 case PLANE_CTL_FORMAT_XYUV: 182 return DRM_FORMAT_XYUV8888; 183 case PLANE_CTL_FORMAT_P010: 184 return DRM_FORMAT_P010; 185 case PLANE_CTL_FORMAT_P012: 186 return DRM_FORMAT_P012; 187 case PLANE_CTL_FORMAT_P016: 188 return DRM_FORMAT_P016; 189 case PLANE_CTL_FORMAT_Y210: 190 return DRM_FORMAT_Y210; 191 case PLANE_CTL_FORMAT_Y212: 192 return DRM_FORMAT_Y212; 193 case PLANE_CTL_FORMAT_Y216: 194 return DRM_FORMAT_Y216; 195 case PLANE_CTL_FORMAT_Y410: 196 return DRM_FORMAT_XVYU2101010; 197 case PLANE_CTL_FORMAT_Y412: 198 return DRM_FORMAT_XVYU12_16161616; 199 case PLANE_CTL_FORMAT_Y416: 200 return DRM_FORMAT_XVYU16161616; 201 default: 202 case PLANE_CTL_FORMAT_XRGB_8888: 203 if (rgb_order) { 204 if (alpha) 205 return DRM_FORMAT_ABGR8888; 206 else 207 return DRM_FORMAT_XBGR8888; 208 } else { 209 if (alpha) 210 return DRM_FORMAT_ARGB8888; 211 else 212 return DRM_FORMAT_XRGB8888; 213 } 214 case PLANE_CTL_FORMAT_XRGB_2101010: 215 if (rgb_order) { 216 if (alpha) 217 return DRM_FORMAT_ABGR2101010; 218 else 219 return DRM_FORMAT_XBGR2101010; 220 } else { 221 if (alpha) 222 return DRM_FORMAT_ARGB2101010; 223 else 224 return DRM_FORMAT_XRGB2101010; 225 } 226 case PLANE_CTL_FORMAT_XRGB_16161616F: 227 if (rgb_order) { 228 if (alpha) 229 return DRM_FORMAT_ABGR16161616F; 230 else 231 return DRM_FORMAT_XBGR16161616F; 232 } else { 233 if (alpha) 234 return DRM_FORMAT_ARGB16161616F; 235 else 236 return DRM_FORMAT_XRGB16161616F; 237 } 238 } 239 } 240 241 static u8 icl_nv12_y_plane_mask(struct intel_display *display) 242 { 243 if (DISPLAY_VER(display) >= 13 || HAS_D12_PLANE_MINIMIZATION(display)) 244 return BIT(PLANE_4) | BIT(PLANE_5); 245 else 246 return BIT(PLANE_6) | BIT(PLANE_7); 247 } 248 249 bool icl_is_nv12_y_plane(struct intel_display *display, 250 enum plane_id plane_id) 251 { 252 return DISPLAY_VER(display) >= 11 && 253 icl_nv12_y_plane_mask(display) & BIT(plane_id); 254 } 255 256 u8 icl_hdr_plane_mask(void) 257 { 258 return BIT(PLANE_1) | BIT(PLANE_2) | BIT(PLANE_3); 259 } 260 261 bool icl_is_hdr_plane(struct intel_display *display, enum plane_id plane_id) 262 { 263 return DISPLAY_VER(display) >= 11 && 264 icl_hdr_plane_mask() & BIT(plane_id); 265 } 266 267 static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state, 268 const struct intel_plane_state *plane_state) 269 { 270 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state); 271 272 /* two pixels per clock */ 273 return DIV_ROUND_UP(pixel_rate, 2); 274 } 275 276 static void 277 glk_plane_ratio(const struct intel_plane_state *plane_state, 278 unsigned int *num, unsigned int *den) 279 { 280 const struct drm_framebuffer *fb = plane_state->hw.fb; 281 282 if (fb->format->cpp[0] == 8) { 283 *num = 10; 284 *den = 8; 285 } else { 286 *num = 1; 287 *den = 1; 288 } 289 } 290 291 static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state, 292 const struct intel_plane_state *plane_state) 293 { 294 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state); 295 unsigned int num, den; 296 297 glk_plane_ratio(plane_state, &num, &den); 298 299 /* two pixels per clock */ 300 return DIV_ROUND_UP(pixel_rate * num, 2 * den); 301 } 302 303 static void 304 skl_plane_ratio(const struct intel_plane_state *plane_state, 305 unsigned int *num, unsigned int *den) 306 { 307 const struct drm_framebuffer *fb = plane_state->hw.fb; 308 309 if (fb->format->cpp[0] == 8) { 310 *num = 9; 311 *den = 8; 312 } else { 313 *num = 1; 314 *den = 1; 315 } 316 } 317 318 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state, 319 const struct intel_plane_state *plane_state) 320 { 321 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state); 322 unsigned int num, den; 323 324 skl_plane_ratio(plane_state, &num, &den); 325 326 return DIV_ROUND_UP(pixel_rate * num, den); 327 } 328 329 static int skl_plane_max_width(const struct drm_framebuffer *fb, 330 int color_plane, 331 unsigned int rotation) 332 { 333 int cpp = fb->format->cpp[color_plane]; 334 335 switch (fb->modifier) { 336 case DRM_FORMAT_MOD_LINEAR: 337 case I915_FORMAT_MOD_X_TILED: 338 /* 339 * Validated limit is 4k, but has 5k should 340 * work apart from the following features: 341 * - Ytile (already limited to 4k) 342 * - FP16 (already limited to 4k) 343 * - render compression (already limited to 4k) 344 * - KVMR sprite and cursor (don't care) 345 * - horizontal panning (TODO verify this) 346 * - pipe and plane scaling (TODO verify this) 347 */ 348 if (cpp == 8) 349 return 4096; 350 else 351 return 5120; 352 case I915_FORMAT_MOD_Y_TILED_CCS: 353 case I915_FORMAT_MOD_Yf_TILED_CCS: 354 /* FIXME AUX plane? */ 355 case I915_FORMAT_MOD_Y_TILED: 356 case I915_FORMAT_MOD_Yf_TILED: 357 if (cpp == 8) 358 return 2048; 359 else 360 return 4096; 361 default: 362 MISSING_CASE(fb->modifier); 363 return 2048; 364 } 365 } 366 367 static int glk_plane_max_width(const struct drm_framebuffer *fb, 368 int color_plane, 369 unsigned int rotation) 370 { 371 int cpp = fb->format->cpp[color_plane]; 372 373 switch (fb->modifier) { 374 case DRM_FORMAT_MOD_LINEAR: 375 case I915_FORMAT_MOD_X_TILED: 376 if (cpp == 8) 377 return 4096; 378 else 379 return 5120; 380 case I915_FORMAT_MOD_Y_TILED_CCS: 381 case I915_FORMAT_MOD_Yf_TILED_CCS: 382 /* FIXME AUX plane? */ 383 case I915_FORMAT_MOD_Y_TILED: 384 case I915_FORMAT_MOD_Yf_TILED: 385 if (cpp == 8) 386 return 2048; 387 else 388 return 5120; 389 default: 390 MISSING_CASE(fb->modifier); 391 return 2048; 392 } 393 } 394 395 static int adl_plane_min_width(const struct drm_framebuffer *fb, 396 int color_plane, 397 unsigned int rotation) 398 { 399 return 16 / fb->format->cpp[color_plane]; 400 } 401 402 static int icl_plane_min_width(const struct drm_framebuffer *fb, 403 int color_plane, 404 unsigned int rotation) 405 { 406 /* Wa_14011264657, Wa_14011050563: gen11+ */ 407 return 16 / fb->format->cpp[color_plane] + 2; 408 } 409 410 static int xe3_plane_max_width(const struct drm_framebuffer *fb, 411 int color_plane, 412 unsigned int rotation) 413 { 414 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) 415 return 4096; 416 else 417 return 6144; 418 } 419 420 static int icl_hdr_plane_max_width(const struct drm_framebuffer *fb, 421 int color_plane, 422 unsigned int rotation) 423 { 424 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) 425 return 4096; 426 else 427 return 5120; 428 } 429 430 static int icl_sdr_plane_max_width(const struct drm_framebuffer *fb, 431 int color_plane, 432 unsigned int rotation) 433 { 434 return 5120; 435 } 436 437 static int skl_plane_max_height(const struct drm_framebuffer *fb, 438 int color_plane, 439 unsigned int rotation) 440 { 441 return 4096; 442 } 443 444 static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) 445 { 446 return pipe - PIPE_A + INTEL_FBC_A; 447 } 448 449 static bool skl_plane_has_fbc(struct intel_display *display, 450 enum intel_fbc_id fbc_id, enum plane_id plane_id) 451 { 452 if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) 453 return false; 454 455 if (DISPLAY_VER(display) >= 20) 456 return icl_is_hdr_plane(display, plane_id); 457 else 458 return plane_id == PLANE_1; 459 } 460 461 static int icl_plane_max_height(const struct drm_framebuffer *fb, 462 int color_plane, 463 unsigned int rotation) 464 { 465 return 4320; 466 } 467 468 static unsigned int 469 plane_max_stride(struct intel_plane *plane, 470 const struct drm_format_info *info, 471 u64 modifier, unsigned int rotation, 472 unsigned int max_pixels, 473 unsigned int max_bytes) 474 { 475 int cpp = info->cpp[0]; 476 477 if (drm_rotation_90_or_270(rotation)) 478 return min(max_pixels, max_bytes / cpp); 479 else 480 return min(max_pixels * cpp, max_bytes); 481 } 482 483 static unsigned int 484 adl_plane_max_stride(struct intel_plane *plane, 485 const struct drm_format_info *info, 486 u64 modifier, unsigned int rotation) 487 { 488 unsigned int max_pixels = 65536; /* PLANE_OFFSET limit */ 489 unsigned int max_bytes = 128 * 1024; 490 491 return plane_max_stride(plane, info, 492 modifier, rotation, 493 max_pixels, max_bytes); 494 } 495 496 static unsigned int 497 skl_plane_max_stride(struct intel_plane *plane, 498 const struct drm_format_info *info, 499 u64 modifier, unsigned int rotation) 500 { 501 unsigned int max_pixels = 8192; /* PLANE_OFFSET limit */ 502 unsigned int max_bytes = 32 * 1024; 503 504 return plane_max_stride(plane, info, 505 modifier, rotation, 506 max_pixels, max_bytes); 507 } 508 509 static bool tgl_plane_can_async_flip(u64 modifier) 510 { 511 switch (modifier) { 512 case DRM_FORMAT_MOD_LINEAR: 513 case I915_FORMAT_MOD_X_TILED: 514 case I915_FORMAT_MOD_Y_TILED: 515 case I915_FORMAT_MOD_4_TILED: 516 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: 517 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: 518 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: 519 case I915_FORMAT_MOD_4_TILED_BMG_CCS: 520 case I915_FORMAT_MOD_4_TILED_LNL_CCS: 521 return true; 522 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 523 case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: 524 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: 525 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: 526 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: 527 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: 528 return false; 529 default: 530 return false; 531 } 532 } 533 534 static bool icl_plane_can_async_flip(u64 modifier) 535 { 536 switch (modifier) { 537 case DRM_FORMAT_MOD_LINEAR: 538 /* 539 * FIXME: Async on Linear buffer is supported on ICL 540 * but with additional alignment and fbc restrictions 541 * need to be taken care of. 542 */ 543 return false; 544 case I915_FORMAT_MOD_X_TILED: 545 case I915_FORMAT_MOD_Y_TILED: 546 case I915_FORMAT_MOD_Yf_TILED: 547 case I915_FORMAT_MOD_Y_TILED_CCS: 548 case I915_FORMAT_MOD_Yf_TILED_CCS: 549 return true; 550 default: 551 return false; 552 } 553 } 554 555 static bool skl_plane_can_async_flip(u64 modifier) 556 { 557 switch (modifier) { 558 case DRM_FORMAT_MOD_LINEAR: 559 return false; 560 case I915_FORMAT_MOD_X_TILED: 561 case I915_FORMAT_MOD_Y_TILED: 562 case I915_FORMAT_MOD_Yf_TILED: 563 return true; 564 case I915_FORMAT_MOD_Y_TILED_CCS: 565 case I915_FORMAT_MOD_Yf_TILED_CCS: 566 /* 567 * Display WA #0731: skl 568 * WaDisableRCWithAsyncFlip: skl 569 * "When render decompression is enabled, hardware 570 * internally converts the Async flips to Sync flips." 571 * 572 * Display WA #1159: glk 573 * "Async flip with render compression may result in 574 * intermittent underrun corruption." 575 */ 576 return false; 577 default: 578 return false; 579 } 580 } 581 582 static u32 tgl_plane_min_alignment(struct intel_plane *plane, 583 const struct drm_framebuffer *fb, 584 int color_plane) 585 { 586 struct intel_display *display = to_intel_display(plane); 587 /* PLANE_SURF GGTT -> DPT alignment */ 588 int mult = intel_fb_uses_dpt(fb) ? 512 : 1; 589 590 /* AUX_DIST needs only 4K alignment */ 591 if (intel_fb_is_ccs_aux_plane(fb, color_plane)) 592 return mult * 4 * 1024; 593 594 /* 595 * FIXME ADL sees GGTT/DMAR faults with async 596 * flips unless we align to 16k at least. 597 * Figure out what's going on here... 598 */ 599 if (display->platform.alderlake_p && 600 intel_plane_can_async_flip(plane, fb->format->format, fb->modifier)) 601 return mult * 16 * 1024; 602 603 switch (fb->modifier) { 604 case DRM_FORMAT_MOD_LINEAR: 605 case I915_FORMAT_MOD_X_TILED: 606 case I915_FORMAT_MOD_Y_TILED: 607 case I915_FORMAT_MOD_4_TILED: 608 return mult * 4 * 1024; 609 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: 610 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: 611 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: 612 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 613 case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: 614 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: 615 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: 616 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: 617 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: 618 case I915_FORMAT_MOD_4_TILED_BMG_CCS: 619 case I915_FORMAT_MOD_4_TILED_LNL_CCS: 620 /* 621 * Align to at least 4x1 main surface 622 * tiles (16K) to match 64B of AUX. 623 */ 624 return max(mult * 4 * 1024, 16 * 1024); 625 default: 626 MISSING_CASE(fb->modifier); 627 return 0; 628 } 629 } 630 631 static u32 skl_plane_min_alignment(struct intel_plane *plane, 632 const struct drm_framebuffer *fb, 633 int color_plane) 634 { 635 /* 636 * AUX_DIST needs only 4K alignment, 637 * as does ICL UV PLANE_SURF. 638 */ 639 if (color_plane != 0) 640 return 4 * 1024; 641 642 /* 643 * VT-d needs at least 256k alignment, 644 * but that's already covered below. 645 */ 646 switch (fb->modifier) { 647 case DRM_FORMAT_MOD_LINEAR: 648 case I915_FORMAT_MOD_X_TILED: 649 return 256 * 1024; 650 case I915_FORMAT_MOD_Y_TILED_CCS: 651 case I915_FORMAT_MOD_Yf_TILED_CCS: 652 case I915_FORMAT_MOD_Y_TILED: 653 case I915_FORMAT_MOD_Yf_TILED: 654 return 1 * 1024 * 1024; 655 default: 656 MISSING_CASE(fb->modifier); 657 return 0; 658 } 659 } 660 661 /* Preoffset values for YUV to RGB Conversion */ 662 #define PREOFF_YUV_TO_RGB_HI 0x1800 663 #define PREOFF_YUV_TO_RGB_ME 0x0000 664 #define PREOFF_YUV_TO_RGB_LO 0x1800 665 666 #define ROFF(x) (((x) & 0xffff) << 16) 667 #define GOFF(x) (((x) & 0xffff) << 0) 668 #define BOFF(x) (((x) & 0xffff) << 16) 669 670 /* 671 * Programs the input color space conversion stage for ICL HDR planes. 672 * Note that it is assumed that this stage always happens after YUV 673 * range correction. Thus, the input to this stage is assumed to be 674 * in full-range YCbCr. 675 */ 676 static void 677 icl_program_input_csc(struct intel_dsb *dsb, 678 struct intel_plane *plane, 679 const struct intel_plane_state *plane_state) 680 { 681 struct intel_display *display = to_intel_display(plane); 682 enum pipe pipe = plane->pipe; 683 enum plane_id plane_id = plane->id; 684 685 static const u16 input_csc_matrix[][9] = { 686 /* 687 * BT.601 full range YCbCr -> full range RGB 688 * The matrix required is : 689 * [1.000, 0.000, 1.371, 690 * 1.000, -0.336, -0.698, 691 * 1.000, 1.732, 0.0000] 692 */ 693 [DRM_COLOR_YCBCR_BT601] = { 694 0x7AF8, 0x7800, 0x0, 695 0x8B28, 0x7800, 0x9AC0, 696 0x0, 0x7800, 0x7DD8, 697 }, 698 /* 699 * BT.709 full range YCbCr -> full range RGB 700 * The matrix required is : 701 * [1.000, 0.000, 1.574, 702 * 1.000, -0.187, -0.468, 703 * 1.000, 1.855, 0.0000] 704 */ 705 [DRM_COLOR_YCBCR_BT709] = { 706 0x7C98, 0x7800, 0x0, 707 0x9EF8, 0x7800, 0xAC00, 708 0x0, 0x7800, 0x7ED8, 709 }, 710 /* 711 * BT.2020 full range YCbCr -> full range RGB 712 * The matrix required is : 713 * [1.000, 0.000, 1.474, 714 * 1.000, -0.1645, -0.5713, 715 * 1.000, 1.8814, 0.0000] 716 */ 717 [DRM_COLOR_YCBCR_BT2020] = { 718 0x7BC8, 0x7800, 0x0, 719 0x8928, 0x7800, 0xAA88, 720 0x0, 0x7800, 0x7F10, 721 }, 722 }; 723 const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding]; 724 725 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), 726 ROFF(csc[0]) | GOFF(csc[1])); 727 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), 728 BOFF(csc[2])); 729 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), 730 ROFF(csc[3]) | GOFF(csc[4])); 731 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), 732 BOFF(csc[5])); 733 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), 734 ROFF(csc[6]) | GOFF(csc[7])); 735 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), 736 BOFF(csc[8])); 737 738 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0), 739 PREOFF_YUV_TO_RGB_HI); 740 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 741 PREOFF_YUV_TO_RGB_ME); 742 intel_de_write_dsb(display, dsb, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2), 743 PREOFF_YUV_TO_RGB_LO); 744 intel_de_write_dsb(display, dsb, 745 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0); 746 intel_de_write_dsb(display, dsb, 747 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0); 748 intel_de_write_dsb(display, dsb, 749 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0); 750 } 751 752 static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb, 753 int color_plane, unsigned int rotation) 754 { 755 /* 756 * The stride is either expressed as a multiple of 64 bytes chunks for 757 * linear buffers or in number of tiles for tiled buffers. 758 */ 759 if (is_surface_linear(fb, color_plane)) 760 return 64; 761 else if (drm_rotation_90_or_270(rotation)) 762 return intel_tile_height(fb, color_plane); 763 else 764 return intel_tile_width_bytes(fb, color_plane); 765 } 766 767 static u32 skl_plane_stride(const struct intel_plane_state *plane_state, 768 int color_plane) 769 { 770 const struct drm_framebuffer *fb = plane_state->hw.fb; 771 unsigned int rotation = plane_state->hw.rotation; 772 u32 stride = plane_state->view.color_plane[color_plane].scanout_stride; 773 774 if (color_plane >= fb->format->num_planes) 775 return 0; 776 777 return stride / skl_plane_stride_mult(fb, color_plane, rotation); 778 } 779 780 static u32 skl_plane_ddb_reg_val(const struct skl_ddb_entry *entry) 781 { 782 if (!entry->end) 783 return 0; 784 785 return PLANE_BUF_END(entry->end - 1) | 786 PLANE_BUF_START(entry->start); 787 } 788 789 static u32 xe3_plane_min_ddb_reg_val(const u16 *min_ddb, 790 const u16 *interim_ddb) 791 { 792 u32 val = 0; 793 794 if (*min_ddb) 795 val |= PLANE_MIN_DBUF_BLOCKS(*min_ddb); 796 797 if (*interim_ddb) 798 val |= PLANE_INTERIM_DBUF_BLOCKS(*interim_ddb); 799 800 val |= val ? PLANE_AUTO_MIN_DBUF_EN : 0; 801 802 return val; 803 } 804 805 static u32 skl_plane_wm_reg_val(const struct skl_wm_level *level) 806 { 807 u32 val = 0; 808 809 if (level->enable) 810 val |= PLANE_WM_EN; 811 if (level->ignore_lines) 812 val |= PLANE_WM_IGNORE_LINES; 813 if (level->auto_min_alloc_wm_enable) 814 val |= PLANE_WM_AUTO_MIN_ALLOC_EN; 815 816 val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); 817 val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); 818 819 return val; 820 } 821 822 static void skl_write_plane_wm(struct intel_dsb *dsb, 823 struct intel_plane *plane, 824 const struct intel_crtc_state *crtc_state) 825 { 826 struct intel_display *display = to_intel_display(plane); 827 enum plane_id plane_id = plane->id; 828 enum pipe pipe = plane->pipe; 829 const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; 830 const struct skl_ddb_entry *ddb = 831 &crtc_state->wm.skl.plane_ddb[plane_id]; 832 const struct skl_ddb_entry *ddb_y = 833 &crtc_state->wm.skl.plane_ddb_y[plane_id]; 834 const u16 *min_ddb = &crtc_state->wm.skl.plane_min_ddb[plane_id]; 835 const u16 *interim_ddb = 836 &crtc_state->wm.skl.plane_interim_ddb[plane_id]; 837 int level; 838 839 for (level = 0; level < display->wm.num_levels; level++) 840 intel_de_write_dsb(display, dsb, PLANE_WM(pipe, plane_id, level), 841 skl_plane_wm_reg_val(skl_plane_wm_level(pipe_wm, plane_id, level))); 842 843 intel_de_write_dsb(display, dsb, PLANE_WM_TRANS(pipe, plane_id), 844 skl_plane_wm_reg_val(skl_plane_trans_wm(pipe_wm, plane_id))); 845 846 if (HAS_HW_SAGV_WM(display)) { 847 const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; 848 849 intel_de_write_dsb(display, dsb, PLANE_WM_SAGV(pipe, plane_id), 850 skl_plane_wm_reg_val(&wm->sagv.wm0)); 851 intel_de_write_dsb(display, dsb, PLANE_WM_SAGV_TRANS(pipe, plane_id), 852 skl_plane_wm_reg_val(&wm->sagv.trans_wm)); 853 } 854 855 intel_de_write_dsb(display, dsb, PLANE_BUF_CFG(pipe, plane_id), 856 skl_plane_ddb_reg_val(ddb)); 857 858 if (DISPLAY_VER(display) < 11) 859 intel_de_write_dsb(display, dsb, PLANE_NV12_BUF_CFG(pipe, plane_id), 860 skl_plane_ddb_reg_val(ddb_y)); 861 862 if (DISPLAY_VER(display) >= 30) 863 intel_de_write_dsb(display, dsb, PLANE_MIN_BUF_CFG(pipe, plane_id), 864 xe3_plane_min_ddb_reg_val(min_ddb, interim_ddb)); 865 } 866 867 static void 868 skl_plane_disable_arm(struct intel_dsb *dsb, 869 struct intel_plane *plane, 870 const struct intel_crtc_state *crtc_state) 871 { 872 struct intel_display *display = to_intel_display(plane); 873 enum plane_id plane_id = plane->id; 874 enum pipe pipe = plane->pipe; 875 876 skl_write_plane_wm(dsb, plane, crtc_state); 877 878 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0); 879 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0); 880 } 881 882 static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb, 883 struct intel_plane *plane, 884 const struct intel_crtc_state *crtc_state) 885 { 886 struct intel_display *display = to_intel_display(plane); 887 enum pipe pipe = plane->pipe; 888 889 if (!crtc_state->enable_psr2_sel_fetch) 890 return; 891 892 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); 893 } 894 895 static void x3p_lpd_plane_update_pixel_normalizer(struct intel_dsb *dsb, 896 struct intel_plane *plane, 897 bool enable) 898 { 899 struct intel_display *display = to_intel_display(plane); 900 enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(plane->pipe); 901 u32 val; 902 903 /* Only HDR planes have pixel normalizer and don't matter if no FBC */ 904 if (!skl_plane_has_fbc(display, fbc_id, plane->id)) 905 return; 906 907 val = enable ? PLANE_PIXEL_NORMALIZE_NORM_FACTOR(PLANE_PIXEL_NORMALIZE_NORM_FACTOR_1_0) | 908 PLANE_PIXEL_NORMALIZE_ENABLE : 0; 909 910 intel_de_write_dsb(display, dsb, 911 PLANE_PIXEL_NORMALIZE(plane->pipe, plane->id), val); 912 } 913 914 static void 915 icl_plane_disable_arm(struct intel_dsb *dsb, 916 struct intel_plane *plane, 917 const struct intel_crtc_state *crtc_state) 918 { 919 struct intel_display *display = to_intel_display(plane); 920 enum plane_id plane_id = plane->id; 921 enum pipe pipe = plane->pipe; 922 923 if (icl_is_hdr_plane(display, plane_id)) 924 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id), 0); 925 926 skl_write_plane_wm(dsb, plane, crtc_state); 927 928 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); 929 930 if (DISPLAY_VER(display) >= 35) 931 x3p_lpd_plane_update_pixel_normalizer(dsb, plane, false); 932 933 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 0); 934 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 0); 935 } 936 937 static bool 938 skl_plane_get_hw_state(struct intel_plane *plane, 939 enum pipe *pipe) 940 { 941 struct intel_display *display = to_intel_display(plane); 942 enum intel_display_power_domain power_domain; 943 enum plane_id plane_id = plane->id; 944 intel_wakeref_t wakeref; 945 bool ret; 946 947 power_domain = POWER_DOMAIN_PIPE(plane->pipe); 948 wakeref = intel_display_power_get_if_enabled(display, power_domain); 949 if (!wakeref) 950 return false; 951 952 ret = intel_de_read(display, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE; 953 954 *pipe = plane->pipe; 955 956 intel_display_power_put(display, power_domain, wakeref); 957 958 return ret; 959 } 960 961 static u32 skl_plane_ctl_format(u32 pixel_format) 962 { 963 switch (pixel_format) { 964 case DRM_FORMAT_C8: 965 return PLANE_CTL_FORMAT_INDEXED; 966 case DRM_FORMAT_RGB565: 967 return PLANE_CTL_FORMAT_RGB_565; 968 case DRM_FORMAT_XBGR8888: 969 case DRM_FORMAT_ABGR8888: 970 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX; 971 case DRM_FORMAT_XRGB8888: 972 case DRM_FORMAT_ARGB8888: 973 return PLANE_CTL_FORMAT_XRGB_8888; 974 case DRM_FORMAT_XBGR2101010: 975 case DRM_FORMAT_ABGR2101010: 976 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX; 977 case DRM_FORMAT_XRGB2101010: 978 case DRM_FORMAT_ARGB2101010: 979 return PLANE_CTL_FORMAT_XRGB_2101010; 980 case DRM_FORMAT_XBGR16161616F: 981 case DRM_FORMAT_ABGR16161616F: 982 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX; 983 case DRM_FORMAT_XRGB16161616F: 984 case DRM_FORMAT_ARGB16161616F: 985 return PLANE_CTL_FORMAT_XRGB_16161616F; 986 case DRM_FORMAT_XYUV8888: 987 return PLANE_CTL_FORMAT_XYUV; 988 case DRM_FORMAT_YUYV: 989 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YUYV; 990 case DRM_FORMAT_YVYU: 991 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YVYU; 992 case DRM_FORMAT_UYVY: 993 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_UYVY; 994 case DRM_FORMAT_VYUY: 995 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_VYUY; 996 case DRM_FORMAT_NV12: 997 return PLANE_CTL_FORMAT_NV12; 998 case DRM_FORMAT_P010: 999 return PLANE_CTL_FORMAT_P010; 1000 case DRM_FORMAT_P012: 1001 return PLANE_CTL_FORMAT_P012; 1002 case DRM_FORMAT_P016: 1003 return PLANE_CTL_FORMAT_P016; 1004 case DRM_FORMAT_Y210: 1005 return PLANE_CTL_FORMAT_Y210; 1006 case DRM_FORMAT_Y212: 1007 return PLANE_CTL_FORMAT_Y212; 1008 case DRM_FORMAT_Y216: 1009 return PLANE_CTL_FORMAT_Y216; 1010 case DRM_FORMAT_XVYU2101010: 1011 return PLANE_CTL_FORMAT_Y410; 1012 case DRM_FORMAT_XVYU12_16161616: 1013 return PLANE_CTL_FORMAT_Y412; 1014 case DRM_FORMAT_XVYU16161616: 1015 return PLANE_CTL_FORMAT_Y416; 1016 default: 1017 MISSING_CASE(pixel_format); 1018 } 1019 1020 return 0; 1021 } 1022 1023 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state) 1024 { 1025 if (!plane_state->hw.fb->format->has_alpha) 1026 return PLANE_CTL_ALPHA_DISABLE; 1027 1028 switch (plane_state->hw.pixel_blend_mode) { 1029 case DRM_MODE_BLEND_PIXEL_NONE: 1030 return PLANE_CTL_ALPHA_DISABLE; 1031 case DRM_MODE_BLEND_PREMULTI: 1032 return PLANE_CTL_ALPHA_SW_PREMULTIPLY; 1033 case DRM_MODE_BLEND_COVERAGE: 1034 return PLANE_CTL_ALPHA_HW_PREMULTIPLY; 1035 default: 1036 MISSING_CASE(plane_state->hw.pixel_blend_mode); 1037 return PLANE_CTL_ALPHA_DISABLE; 1038 } 1039 } 1040 1041 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state) 1042 { 1043 if (!plane_state->hw.fb->format->has_alpha) 1044 return PLANE_COLOR_ALPHA_DISABLE; 1045 1046 switch (plane_state->hw.pixel_blend_mode) { 1047 case DRM_MODE_BLEND_PIXEL_NONE: 1048 return PLANE_COLOR_ALPHA_DISABLE; 1049 case DRM_MODE_BLEND_PREMULTI: 1050 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY; 1051 case DRM_MODE_BLEND_COVERAGE: 1052 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY; 1053 default: 1054 MISSING_CASE(plane_state->hw.pixel_blend_mode); 1055 return PLANE_COLOR_ALPHA_DISABLE; 1056 } 1057 } 1058 1059 static u32 skl_plane_ctl_tiling(u64 fb_modifier) 1060 { 1061 switch (fb_modifier) { 1062 case DRM_FORMAT_MOD_LINEAR: 1063 break; 1064 case I915_FORMAT_MOD_X_TILED: 1065 return PLANE_CTL_TILED_X; 1066 case I915_FORMAT_MOD_Y_TILED: 1067 return PLANE_CTL_TILED_Y; 1068 case I915_FORMAT_MOD_4_TILED: 1069 return PLANE_CTL_TILED_4; 1070 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS: 1071 return PLANE_CTL_TILED_4 | 1072 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | 1073 PLANE_CTL_CLEAR_COLOR_DISABLE; 1074 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS: 1075 return PLANE_CTL_TILED_4 | 1076 PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE | 1077 PLANE_CTL_CLEAR_COLOR_DISABLE; 1078 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC: 1079 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 1080 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: 1081 return PLANE_CTL_TILED_4 | 1082 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | 1083 PLANE_CTL_CLEAR_COLOR_DISABLE; 1084 case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC: 1085 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 1086 case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS: 1087 return PLANE_CTL_TILED_4 | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE; 1088 case I915_FORMAT_MOD_4_TILED_BMG_CCS: 1089 case I915_FORMAT_MOD_4_TILED_LNL_CCS: 1090 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 1091 case I915_FORMAT_MOD_Y_TILED_CCS: 1092 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: 1093 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 1094 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: 1095 return PLANE_CTL_TILED_Y | 1096 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | 1097 PLANE_CTL_CLEAR_COLOR_DISABLE; 1098 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 1099 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE; 1100 case I915_FORMAT_MOD_Yf_TILED: 1101 return PLANE_CTL_TILED_YF; 1102 case I915_FORMAT_MOD_Yf_TILED_CCS: 1103 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 1104 default: 1105 MISSING_CASE(fb_modifier); 1106 } 1107 1108 return 0; 1109 } 1110 1111 static u32 skl_plane_ctl_rotate(unsigned int rotate) 1112 { 1113 switch (rotate) { 1114 case DRM_MODE_ROTATE_0: 1115 break; 1116 /* 1117 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr 1118 * while i915 HW rotation is clockwise, that's why this swapping. 1119 */ 1120 case DRM_MODE_ROTATE_90: 1121 return PLANE_CTL_ROTATE_270; 1122 case DRM_MODE_ROTATE_180: 1123 return PLANE_CTL_ROTATE_180; 1124 case DRM_MODE_ROTATE_270: 1125 return PLANE_CTL_ROTATE_90; 1126 default: 1127 MISSING_CASE(rotate); 1128 } 1129 1130 return 0; 1131 } 1132 1133 static u32 icl_plane_ctl_flip(unsigned int reflect) 1134 { 1135 switch (reflect) { 1136 case 0: 1137 break; 1138 case DRM_MODE_REFLECT_X: 1139 return PLANE_CTL_FLIP_HORIZONTAL; 1140 case DRM_MODE_REFLECT_Y: 1141 default: 1142 MISSING_CASE(reflect); 1143 } 1144 1145 return 0; 1146 } 1147 1148 static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state) 1149 { 1150 const struct drm_framebuffer *fb = plane_state->hw.fb; 1151 1152 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { 1153 switch (fb->format->cpp[0]) { 1154 case 2: 1155 return PLANE_CTL_ARB_SLOTS(1); 1156 default: 1157 return PLANE_CTL_ARB_SLOTS(0); 1158 } 1159 } else { 1160 switch (fb->format->cpp[0]) { 1161 case 8: 1162 return PLANE_CTL_ARB_SLOTS(3); 1163 case 4: 1164 return PLANE_CTL_ARB_SLOTS(1); 1165 default: 1166 return PLANE_CTL_ARB_SLOTS(0); 1167 } 1168 } 1169 } 1170 1171 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) 1172 { 1173 struct intel_display *display = to_intel_display(crtc_state); 1174 u32 plane_ctl = 0; 1175 1176 if (DISPLAY_VER(display) >= 10) 1177 return plane_ctl; 1178 1179 if (crtc_state->gamma_enable) 1180 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE; 1181 1182 if (crtc_state->csc_enable) 1183 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE; 1184 1185 return plane_ctl; 1186 } 1187 1188 static u32 skl_plane_ctl(const struct intel_plane_state *plane_state) 1189 { 1190 struct intel_display *display = to_intel_display(plane_state); 1191 const struct drm_framebuffer *fb = plane_state->hw.fb; 1192 unsigned int rotation = plane_state->hw.rotation; 1193 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1194 u32 plane_ctl; 1195 1196 plane_ctl = PLANE_CTL_ENABLE; 1197 1198 if (DISPLAY_VER(display) < 10) { 1199 plane_ctl |= skl_plane_ctl_alpha(plane_state); 1200 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; 1201 1202 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) 1203 plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709; 1204 1205 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 1206 plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE; 1207 } 1208 1209 plane_ctl |= skl_plane_ctl_format(fb->format->format); 1210 plane_ctl |= skl_plane_ctl_tiling(fb->modifier); 1211 plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK); 1212 1213 if (DISPLAY_VER(display) >= 11) 1214 plane_ctl |= icl_plane_ctl_flip(rotation & 1215 DRM_MODE_REFLECT_MASK); 1216 1217 if (key->flags & I915_SET_COLORKEY_DESTINATION) 1218 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; 1219 else if (key->flags & I915_SET_COLORKEY_SOURCE) 1220 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; 1221 1222 /* Wa_22012358565:adl-p */ 1223 if (DISPLAY_VER(display) == 13) 1224 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state); 1225 1226 return plane_ctl; 1227 } 1228 1229 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state) 1230 { 1231 struct intel_display *display = to_intel_display(crtc_state); 1232 u32 plane_color_ctl = 0; 1233 1234 if (DISPLAY_VER(display) >= 11) 1235 return plane_color_ctl; 1236 1237 if (crtc_state->gamma_enable) 1238 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE; 1239 1240 if (crtc_state->csc_enable) 1241 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE; 1242 1243 return plane_color_ctl; 1244 } 1245 1246 static u32 glk_plane_color_ctl(const struct intel_plane_state *plane_state) 1247 { 1248 struct intel_display *display = to_intel_display(plane_state); 1249 const struct drm_framebuffer *fb = plane_state->hw.fb; 1250 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1251 u32 plane_color_ctl = 0; 1252 1253 plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; 1254 plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); 1255 1256 if (fb->format->is_yuv && !icl_is_hdr_plane(display, plane->id)) { 1257 switch (plane_state->hw.color_encoding) { 1258 case DRM_COLOR_YCBCR_BT709: 1259 plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; 1260 break; 1261 case DRM_COLOR_YCBCR_BT2020: 1262 plane_color_ctl |= 1263 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; 1264 break; 1265 default: 1266 plane_color_ctl |= 1267 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; 1268 } 1269 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 1270 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; 1271 } else if (fb->format->is_yuv) { 1272 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; 1273 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 1274 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; 1275 } 1276 1277 if (plane_state->force_black) 1278 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; 1279 1280 if (plane_state->hw.degamma_lut) 1281 plane_color_ctl |= PLANE_COLOR_PRE_CSC_GAMMA_ENABLE; 1282 1283 if (plane_state->hw.ctm) 1284 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; 1285 1286 if (plane_state->hw.gamma_lut) { 1287 plane_color_ctl &= ~PLANE_COLOR_PLANE_GAMMA_DISABLE; 1288 if (drm_color_lut32_size(plane_state->hw.gamma_lut) != 32) 1289 plane_color_ctl |= PLANE_COLOR_POST_CSC_GAMMA_MULTSEG_ENABLE; 1290 } 1291 1292 return plane_color_ctl; 1293 } 1294 1295 static u32 skl_surf_address(const struct intel_plane_state *plane_state, 1296 int color_plane) 1297 { 1298 struct intel_display *display = to_intel_display(plane_state); 1299 const struct drm_framebuffer *fb = plane_state->hw.fb; 1300 u32 offset = plane_state->view.color_plane[color_plane].offset; 1301 1302 if (intel_fb_uses_dpt(fb)) { 1303 drm_WARN_ON(display->drm, offset & 0x1fffff); 1304 return offset >> 9; 1305 } else { 1306 drm_WARN_ON(display->drm, offset & 0xfff); 1307 return offset; 1308 } 1309 } 1310 1311 static int icl_plane_color_plane(const struct intel_plane_state *plane_state) 1312 { 1313 if (plane_state->planar_linked_plane && !plane_state->is_y_plane) 1314 return 1; 1315 else 1316 return 0; 1317 } 1318 1319 static u32 skl_plane_surf_offset(const struct intel_plane_state *plane_state) 1320 { 1321 int color_plane = icl_plane_color_plane(plane_state); 1322 u32 plane_surf; 1323 1324 plane_surf = skl_surf_address(plane_state, color_plane); 1325 1326 if (plane_state->decrypt) 1327 plane_surf |= PLANE_SURF_DECRYPT; 1328 1329 return plane_surf; 1330 } 1331 1332 u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state, 1333 int color_plane) 1334 { 1335 struct intel_display *display = to_intel_display(plane_state); 1336 const struct drm_framebuffer *fb = plane_state->hw.fb; 1337 int aux_plane = skl_main_to_aux_plane(fb, color_plane); 1338 u32 aux_dist; 1339 1340 if (!aux_plane) 1341 return 0; 1342 1343 aux_dist = skl_surf_address(plane_state, aux_plane) - 1344 skl_surf_address(plane_state, color_plane); 1345 1346 if (DISPLAY_VER(display) < 12) 1347 aux_dist |= PLANE_AUX_STRIDE(skl_plane_stride(plane_state, aux_plane)); 1348 1349 return aux_dist; 1350 } 1351 1352 static u32 skl_plane_keyval(const struct intel_plane_state *plane_state) 1353 { 1354 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1355 1356 return key->min_value; 1357 } 1358 1359 static u32 skl_plane_keymax(const struct intel_plane_state *plane_state) 1360 { 1361 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1362 u8 alpha = plane_state->hw.alpha >> 8; 1363 1364 return (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); 1365 } 1366 1367 static u32 skl_plane_keymsk(const struct intel_plane_state *plane_state) 1368 { 1369 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1370 u8 alpha = plane_state->hw.alpha >> 8; 1371 u32 keymsk; 1372 1373 keymsk = key->channel_mask & 0x7ffffff; 1374 if (alpha < 0xff) 1375 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; 1376 1377 return keymsk; 1378 } 1379 1380 static void icl_plane_csc_load_black(struct intel_dsb *dsb, 1381 struct intel_plane *plane, 1382 const struct intel_crtc_state *crtc_state) 1383 { 1384 struct intel_display *display = to_intel_display(plane); 1385 enum plane_id plane_id = plane->id; 1386 enum pipe pipe = plane->pipe; 1387 1388 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 0), 0); 1389 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 1), 0); 1390 1391 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 2), 0); 1392 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 3), 0); 1393 1394 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 4), 0); 1395 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 5), 0); 1396 1397 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0); 1398 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0); 1399 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0); 1400 1401 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0); 1402 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0); 1403 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0); 1404 } 1405 1406 static void 1407 skl_plane_update_noarm(struct intel_dsb *dsb, 1408 struct intel_plane *plane, 1409 const struct intel_crtc_state *crtc_state, 1410 const struct intel_plane_state *plane_state) 1411 { 1412 struct intel_display *display = to_intel_display(plane); 1413 enum plane_id plane_id = plane->id; 1414 enum pipe pipe = plane->pipe; 1415 u32 stride = skl_plane_stride(plane_state, 0); 1416 int crtc_x = plane_state->uapi.dst.x1; 1417 int crtc_y = plane_state->uapi.dst.y1; 1418 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1419 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 1420 1421 /* The scaler will handle the output position */ 1422 if (plane_state->scaler_id >= 0) { 1423 crtc_x = 0; 1424 crtc_y = 0; 1425 } 1426 1427 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id), 1428 PLANE_STRIDE_(stride)); 1429 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id), 1430 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x)); 1431 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id), 1432 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); 1433 1434 skl_write_plane_wm(dsb, plane, crtc_state); 1435 } 1436 1437 static void 1438 skl_plane_update_arm(struct intel_dsb *dsb, 1439 struct intel_plane *plane, 1440 const struct intel_crtc_state *crtc_state, 1441 const struct intel_plane_state *plane_state) 1442 { 1443 struct intel_display *display = to_intel_display(plane); 1444 enum plane_id plane_id = plane->id; 1445 enum pipe pipe = plane->pipe; 1446 u32 x = plane_state->view.color_plane[0].x; 1447 u32 y = plane_state->view.color_plane[0].y; 1448 u32 plane_ctl, plane_color_ctl = 0; 1449 1450 plane_ctl = plane_state->ctl | 1451 skl_plane_ctl_crtc(crtc_state); 1452 1453 /* see intel_plane_atomic_calc_changes() */ 1454 if (plane->need_async_flip_toggle_wa && 1455 crtc_state->async_flip_planes & BIT(plane->id)) 1456 plane_ctl |= PLANE_CTL_ASYNC_FLIP; 1457 1458 if (DISPLAY_VER(display) >= 10) 1459 plane_color_ctl = plane_state->color_ctl | 1460 glk_plane_color_ctl_crtc(crtc_state); 1461 1462 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id), 1463 skl_plane_keyval(plane_state)); 1464 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id), 1465 skl_plane_keymsk(plane_state)); 1466 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id), 1467 skl_plane_keymax(plane_state)); 1468 1469 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id), 1470 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); 1471 1472 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id), 1473 skl_plane_aux_dist(plane_state, 0)); 1474 1475 intel_de_write_dsb(display, dsb, PLANE_AUX_OFFSET(pipe, plane_id), 1476 PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) | 1477 PLANE_OFFSET_X(plane_state->view.color_plane[1].x)); 1478 1479 if (DISPLAY_VER(display) >= 10) 1480 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id), 1481 plane_color_ctl); 1482 1483 /* 1484 * Enable the scaler before the plane so that we don't 1485 * get a catastrophic underrun even if the two operations 1486 * end up happening in two different frames. 1487 * 1488 * TODO: split into noarm+arm pair 1489 */ 1490 if (plane_state->scaler_id >= 0) 1491 skl_program_plane_scaler(dsb, plane, crtc_state, plane_state); 1492 1493 /* 1494 * The control register self-arms if the plane was previously 1495 * disabled. Try to make the plane enable atomic by writing 1496 * the control register just before the surface register. 1497 */ 1498 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 1499 plane_ctl); 1500 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 1501 plane_state->surf); 1502 } 1503 1504 static void icl_plane_update_sel_fetch_noarm(struct intel_dsb *dsb, 1505 struct intel_plane *plane, 1506 const struct intel_crtc_state *crtc_state, 1507 const struct intel_plane_state *plane_state, 1508 int color_plane) 1509 { 1510 struct intel_display *display = to_intel_display(plane); 1511 enum pipe pipe = plane->pipe; 1512 const struct drm_rect *clip; 1513 u32 val; 1514 int x, y; 1515 1516 if (!crtc_state->enable_psr2_sel_fetch) 1517 return; 1518 1519 clip = &plane_state->psr2_sel_fetch_area; 1520 1521 if (crtc_state->enable_psr2_su_region_et) 1522 y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1); 1523 else 1524 y = (clip->y1 + plane_state->uapi.dst.y1); 1525 val = y << 16; 1526 val |= plane_state->uapi.dst.x1; 1527 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_POS(pipe, plane->id), val); 1528 1529 x = plane_state->view.color_plane[color_plane].x; 1530 1531 /* 1532 * From Bspec: UV surface Start Y Position = half of Y plane Y 1533 * start position. 1534 */ 1535 if (!color_plane) 1536 y = plane_state->view.color_plane[color_plane].y + clip->y1; 1537 else 1538 y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2; 1539 1540 val = y << 16 | x; 1541 1542 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_OFFSET(pipe, plane->id), val); 1543 1544 /* Sizes are 0 based */ 1545 val = (drm_rect_height(clip) - 1) << 16; 1546 val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1; 1547 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val); 1548 } 1549 1550 static void 1551 icl_plane_update_noarm(struct intel_dsb *dsb, 1552 struct intel_plane *plane, 1553 const struct intel_crtc_state *crtc_state, 1554 const struct intel_plane_state *plane_state) 1555 { 1556 struct intel_display *display = to_intel_display(plane); 1557 enum plane_id plane_id = plane->id; 1558 enum pipe pipe = plane->pipe; 1559 int color_plane = icl_plane_color_plane(plane_state); 1560 u32 stride = skl_plane_stride(plane_state, color_plane); 1561 const struct drm_framebuffer *fb = plane_state->hw.fb; 1562 int crtc_x = plane_state->uapi.dst.x1; 1563 int crtc_y = plane_state->uapi.dst.y1; 1564 int x = plane_state->view.color_plane[color_plane].x; 1565 int y = plane_state->view.color_plane[color_plane].y; 1566 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1567 int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 1568 u32 plane_color_ctl; 1569 1570 plane_color_ctl = plane_state->color_ctl | 1571 glk_plane_color_ctl_crtc(crtc_state); 1572 1573 intel_color_plane_program_pipeline(dsb, plane_state); 1574 1575 /* The scaler will handle the output position */ 1576 if (plane_state->scaler_id >= 0) { 1577 crtc_x = 0; 1578 crtc_y = 0; 1579 } 1580 1581 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id), 1582 PLANE_STRIDE_(stride)); 1583 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id), 1584 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x)); 1585 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id), 1586 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); 1587 1588 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id), 1589 skl_plane_keyval(plane_state)); 1590 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id), 1591 skl_plane_keymsk(plane_state)); 1592 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id), 1593 skl_plane_keymax(plane_state)); 1594 1595 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id), 1596 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); 1597 1598 if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) { 1599 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 0), 1600 lower_32_bits(plane_state->ccval)); 1601 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 1), 1602 upper_32_bits(plane_state->ccval)); 1603 } 1604 1605 /* FLAT CCS doesn't need to program AUX_DIST */ 1606 if (HAS_AUX_CCS(display)) 1607 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id), 1608 skl_plane_aux_dist(plane_state, color_plane)); 1609 1610 if (icl_is_hdr_plane(display, plane_id)) 1611 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id), 1612 plane_state->cus_ctl); 1613 1614 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id), 1615 plane_color_ctl); 1616 1617 if (fb->format->is_yuv && icl_is_hdr_plane(display, plane_id)) 1618 icl_program_input_csc(dsb, plane, plane_state); 1619 1620 skl_write_plane_wm(dsb, plane, crtc_state); 1621 1622 /* 1623 * FIXME: pxp session invalidation can hit any time even at time of commit 1624 * or after the commit, display content will be garbage. 1625 */ 1626 if (plane_state->force_black) 1627 icl_plane_csc_load_black(dsb, plane, crtc_state); 1628 1629 icl_plane_update_sel_fetch_noarm(dsb, plane, crtc_state, plane_state, color_plane); 1630 } 1631 1632 static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb, 1633 struct intel_plane *plane, 1634 const struct intel_crtc_state *crtc_state, 1635 const struct intel_plane_state *plane_state) 1636 { 1637 struct intel_display *display = to_intel_display(plane); 1638 enum pipe pipe = plane->pipe; 1639 1640 if (!crtc_state->enable_psr2_sel_fetch) 1641 return; 1642 1643 if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) 1644 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 1645 SEL_FETCH_PLANE_CTL_ENABLE); 1646 else 1647 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); 1648 } 1649 1650 static void 1651 icl_plane_update_arm(struct intel_dsb *dsb, 1652 struct intel_plane *plane, 1653 const struct intel_crtc_state *crtc_state, 1654 const struct intel_plane_state *plane_state) 1655 { 1656 struct intel_display *display = to_intel_display(plane); 1657 enum plane_id plane_id = plane->id; 1658 enum pipe pipe = plane->pipe; 1659 u32 plane_ctl; 1660 1661 plane_ctl = plane_state->ctl | 1662 skl_plane_ctl_crtc(crtc_state); 1663 1664 /* 1665 * Enable the scaler before the plane so that we don't 1666 * get a catastrophic underrun even if the two operations 1667 * end up happening in two different frames. 1668 * 1669 * TODO: split into noarm+arm pair 1670 */ 1671 if (plane_state->scaler_id >= 0) 1672 skl_program_plane_scaler(dsb, plane, crtc_state, plane_state); 1673 1674 icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state); 1675 1676 intel_color_plane_commit_arm(dsb, plane_state); 1677 1678 /* 1679 * In order to have FBC for fp16 formats pixel normalizer block must be 1680 * active. Check if pixel normalizer block need to be enabled for FBC. 1681 * If needed, use normalization factor as 1.0 and enable the block. 1682 */ 1683 if (intel_fbc_is_enable_pixel_normalizer(plane_state)) 1684 x3p_lpd_plane_update_pixel_normalizer(dsb, plane, true); 1685 1686 /* 1687 * The control register self-arms if the plane was previously 1688 * disabled. Try to make the plane enable atomic by writing 1689 * the control register just before the surface register. 1690 */ 1691 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 1692 plane_ctl); 1693 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 1694 plane_state->surf); 1695 } 1696 1697 static void skl_plane_capture_error(struct intel_crtc *crtc, 1698 struct intel_plane *plane, 1699 struct intel_plane_error *error) 1700 { 1701 struct intel_display *display = to_intel_display(plane); 1702 1703 error->ctl = intel_de_read(display, PLANE_CTL(crtc->pipe, plane->id)); 1704 error->surf = intel_de_read(display, PLANE_SURF(crtc->pipe, plane->id)); 1705 error->surflive = intel_de_read(display, PLANE_SURFLIVE(crtc->pipe, plane->id)); 1706 } 1707 1708 static void 1709 skl_plane_async_flip(struct intel_dsb *dsb, 1710 struct intel_plane *plane, 1711 const struct intel_crtc_state *crtc_state, 1712 const struct intel_plane_state *plane_state, 1713 bool async_flip) 1714 { 1715 struct intel_display *display = to_intel_display(plane); 1716 enum plane_id plane_id = plane->id; 1717 enum pipe pipe = plane->pipe; 1718 u32 plane_ctl = plane_state->ctl; 1719 u32 plane_surf = plane_state->surf; 1720 1721 plane_ctl |= skl_plane_ctl_crtc(crtc_state); 1722 1723 if (async_flip) { 1724 if (DISPLAY_VER(display) >= 30) 1725 plane_surf |= PLANE_SURF_ASYNC_UPDATE; 1726 else 1727 plane_ctl |= PLANE_CTL_ASYNC_FLIP; 1728 } 1729 1730 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 1731 plane_ctl); 1732 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 1733 plane_surf); 1734 } 1735 1736 static bool intel_format_is_p01x(u32 format) 1737 { 1738 switch (format) { 1739 case DRM_FORMAT_P010: 1740 case DRM_FORMAT_P012: 1741 case DRM_FORMAT_P016: 1742 return true; 1743 default: 1744 return false; 1745 } 1746 } 1747 1748 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, 1749 const struct intel_plane_state *plane_state) 1750 { 1751 struct intel_display *display = to_intel_display(plane_state); 1752 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1753 const struct drm_framebuffer *fb = plane_state->hw.fb; 1754 unsigned int rotation = plane_state->hw.rotation; 1755 1756 if (!fb) 1757 return 0; 1758 1759 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) && 1760 intel_fb_is_ccs_modifier(fb->modifier)) { 1761 drm_dbg_kms(display->drm, 1762 "[PLANE:%d:%s] RC support only with 0/180 degree rotation (%x)\n", 1763 plane->base.base.id, plane->base.name, rotation); 1764 return -EINVAL; 1765 } 1766 1767 if (rotation & DRM_MODE_REFLECT_X && 1768 fb->modifier == DRM_FORMAT_MOD_LINEAR && 1769 DISPLAY_VER(display) < 35) { 1770 drm_dbg_kms(display->drm, 1771 "[PLANE:%d:%s] horizontal flip is not supported with linear surface formats\n", 1772 plane->base.base.id, plane->base.name); 1773 return -EINVAL; 1774 } 1775 1776 /* 1777 * Display20 onward tile4 hflip is not supported 1778 */ 1779 if (rotation & DRM_MODE_REFLECT_X && 1780 intel_fb_is_tile4_modifier(fb->modifier) && 1781 DISPLAY_VER(display) >= 20) { 1782 drm_dbg_kms(display->drm, 1783 "[PLANE:%d:%s] horizontal flip is not supported with tile4 surface formats\n", 1784 plane->base.base.id, plane->base.name); 1785 return -EINVAL; 1786 } 1787 1788 if (drm_rotation_90_or_270(rotation)) { 1789 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) { 1790 drm_dbg_kms(display->drm, 1791 "[PLANE:%d:%s] Y/Yf tiling required for 90/270!\n", 1792 plane->base.base.id, plane->base.name); 1793 return -EINVAL; 1794 } 1795 1796 /* 1797 * 90/270 is not allowed with RGB64 16:16:16:16 and 1798 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards. 1799 */ 1800 switch (fb->format->format) { 1801 case DRM_FORMAT_RGB565: 1802 if (DISPLAY_VER(display) >= 11) 1803 break; 1804 fallthrough; 1805 case DRM_FORMAT_C8: 1806 case DRM_FORMAT_XRGB16161616F: 1807 case DRM_FORMAT_XBGR16161616F: 1808 case DRM_FORMAT_ARGB16161616F: 1809 case DRM_FORMAT_ABGR16161616F: 1810 case DRM_FORMAT_Y210: 1811 case DRM_FORMAT_Y212: 1812 case DRM_FORMAT_Y216: 1813 case DRM_FORMAT_XVYU12_16161616: 1814 case DRM_FORMAT_XVYU16161616: 1815 drm_dbg_kms(display->drm, 1816 "[PLANE:%d:%s] unsupported pixel format %p4cc for 90/270!\n", 1817 plane->base.base.id, plane->base.name, &fb->format->format); 1818 return -EINVAL; 1819 default: 1820 break; 1821 } 1822 } 1823 1824 /* Y-tiling is not supported in IF-ID Interlace mode */ 1825 if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && 1826 fb->modifier != DRM_FORMAT_MOD_LINEAR && 1827 fb->modifier != I915_FORMAT_MOD_X_TILED) { 1828 drm_dbg_kms(display->drm, 1829 "[PLANE:%d:%s] Y/Yf tiling not supported in IF-ID mode\n", 1830 plane->base.base.id, plane->base.name); 1831 return -EINVAL; 1832 } 1833 1834 /* Wa_1606054188:tgl,adl-s */ 1835 if ((display->platform.alderlake_s || display->platform.tigerlake) && 1836 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE && 1837 intel_format_is_p01x(fb->format->format)) { 1838 drm_dbg_kms(display->drm, 1839 "[PLANE:%d:%s] source color keying not supported with P01x formats\n", 1840 plane->base.base.id, plane->base.name); 1841 return -EINVAL; 1842 } 1843 1844 return 0; 1845 } 1846 1847 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state, 1848 const struct intel_plane_state *plane_state) 1849 { 1850 struct intel_display *display = to_intel_display(plane_state); 1851 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1852 int crtc_x = plane_state->uapi.dst.x1; 1853 int crtc_w = drm_rect_width(&plane_state->uapi.dst); 1854 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); 1855 1856 /* 1857 * Display WA #1175: glk 1858 * Planes other than the cursor may cause FIFO underflow and display 1859 * corruption if starting less than 4 pixels from the right edge of 1860 * the screen. 1861 * Besides the above WA fix the similar problem, where planes other 1862 * than the cursor ending less than 4 pixels from the left edge of the 1863 * screen may cause FIFO underflow and display corruption. 1864 */ 1865 if (DISPLAY_VER(display) == 10 && 1866 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) { 1867 drm_dbg_kms(display->drm, 1868 "[PLANE:%d:%s] requested plane X %s position %d invalid (valid range %d-%d)\n", 1869 plane->base.base.id, plane->base.name, 1870 crtc_x + crtc_w < 4 ? "end" : "start", 1871 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x, 1872 4, pipe_src_w - 4); 1873 return -ERANGE; 1874 } 1875 1876 return 0; 1877 } 1878 1879 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state) 1880 { 1881 struct intel_display *display = to_intel_display(plane_state); 1882 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1883 const struct drm_framebuffer *fb = plane_state->hw.fb; 1884 unsigned int rotation = plane_state->hw.rotation; 1885 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1886 1887 /* Display WA #1106 */ 1888 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && 1889 src_w & 3 && 1890 (rotation == DRM_MODE_ROTATE_270 || 1891 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) { 1892 drm_dbg_kms(display->drm, 1893 "[PLANE:%d:%s] src width must be multiple of 4 for rotated planar YUV\n", 1894 plane->base.base.id, plane->base.name); 1895 return -EINVAL; 1896 } 1897 1898 return 0; 1899 } 1900 1901 static int skl_plane_max_scale(struct intel_display *display, 1902 const struct drm_framebuffer *fb) 1903 { 1904 /* 1905 * We don't yet know the final source width nor 1906 * whether we can use the HQ scaler mode. Assume 1907 * the best case. 1908 * FIXME need to properly check this later. 1909 */ 1910 if (DISPLAY_VER(display) >= 10 || 1911 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) 1912 return 0x30000 - 1; 1913 else 1914 return 0x20000 - 1; 1915 } 1916 1917 static int intel_plane_min_width(struct intel_plane *plane, 1918 const struct drm_framebuffer *fb, 1919 int color_plane, 1920 unsigned int rotation) 1921 { 1922 if (plane->min_width) 1923 return plane->min_width(fb, color_plane, rotation); 1924 else 1925 return 1; 1926 } 1927 1928 static int intel_plane_min_height(struct intel_plane *plane, 1929 const struct drm_framebuffer *fb, 1930 int color_plane, 1931 unsigned int rotation) 1932 { 1933 return 1; 1934 } 1935 1936 static int intel_plane_max_width(struct intel_plane *plane, 1937 const struct drm_framebuffer *fb, 1938 int color_plane, 1939 unsigned int rotation) 1940 { 1941 if (plane->max_width) 1942 return plane->max_width(fb, color_plane, rotation); 1943 else 1944 return INT_MAX; 1945 } 1946 1947 static int intel_plane_max_height(struct intel_plane *plane, 1948 const struct drm_framebuffer *fb, 1949 int color_plane, 1950 unsigned int rotation) 1951 { 1952 if (plane->max_height) 1953 return plane->max_height(fb, color_plane, rotation); 1954 else 1955 return INT_MAX; 1956 } 1957 1958 static bool 1959 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, 1960 int main_x, int main_y, u32 main_offset, 1961 int ccs_plane) 1962 { 1963 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1964 const struct drm_framebuffer *fb = plane_state->hw.fb; 1965 int aux_x = plane_state->view.color_plane[ccs_plane].x; 1966 int aux_y = plane_state->view.color_plane[ccs_plane].y; 1967 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 1968 unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane); 1969 int hsub; 1970 int vsub; 1971 1972 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); 1973 while (aux_offset >= main_offset && aux_y <= main_y) { 1974 int x, y; 1975 1976 if (aux_x == main_x && aux_y == main_y) 1977 break; 1978 1979 if (aux_offset == 0) 1980 break; 1981 1982 x = aux_x / hsub; 1983 y = aux_y / vsub; 1984 aux_offset = intel_plane_adjust_aligned_offset(&x, &y, 1985 plane_state, 1986 ccs_plane, 1987 aux_offset, 1988 aux_offset - alignment); 1989 aux_x = x * hsub + aux_x % hsub; 1990 aux_y = y * vsub + aux_y % vsub; 1991 } 1992 1993 if (aux_x != main_x || aux_y != main_y) 1994 return false; 1995 1996 plane_state->view.color_plane[ccs_plane].offset = aux_offset; 1997 plane_state->view.color_plane[ccs_plane].x = aux_x; 1998 plane_state->view.color_plane[ccs_plane].y = aux_y; 1999 2000 return true; 2001 } 2002 2003 2004 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state, 2005 int *x, int *y, u32 *offset) 2006 { 2007 struct intel_display *display = to_intel_display(plane_state); 2008 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2009 const struct drm_framebuffer *fb = plane_state->hw.fb; 2010 int aux_plane = skl_main_to_aux_plane(fb, 0); 2011 u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; 2012 unsigned int alignment = plane->min_alignment(plane, fb, 0); 2013 int w = drm_rect_width(&plane_state->uapi.src) >> 16; 2014 2015 intel_add_fb_offsets(x, y, plane_state, 0); 2016 *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0); 2017 if (drm_WARN_ON(display->drm, alignment && !is_power_of_2(alignment))) 2018 return -EINVAL; 2019 2020 /* 2021 * AUX surface offset is specified as the distance from the 2022 * main surface offset, and it must be non-negative. Make 2023 * sure that is what we will get. 2024 */ 2025 if (aux_plane && *offset > aux_offset) 2026 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0, 2027 *offset, 2028 aux_offset & ~(alignment - 1)); 2029 2030 /* 2031 * When using an X-tiled surface, the plane blows up 2032 * if the x offset + width exceed the stride. 2033 * 2034 * TODO: linear and Y-tiled seem fine, Yf untested, 2035 */ 2036 if (fb->modifier == I915_FORMAT_MOD_X_TILED) { 2037 int cpp = fb->format->cpp[0]; 2038 2039 while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) { 2040 if (*offset == 0) { 2041 drm_dbg_kms(display->drm, 2042 "[PLANE:%d:%s] unable to find suitable display surface offset due to X-tiling\n", 2043 plane->base.base.id, plane->base.name); 2044 return -EINVAL; 2045 } 2046 2047 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0, 2048 *offset, 2049 *offset - alignment); 2050 } 2051 } 2052 2053 return 0; 2054 } 2055 2056 static int skl_check_main_surface(struct intel_plane_state *plane_state) 2057 { 2058 struct intel_display *display = to_intel_display(plane_state); 2059 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2060 const struct drm_framebuffer *fb = plane_state->hw.fb; 2061 unsigned int rotation = plane_state->hw.rotation; 2062 int x = plane_state->uapi.src.x1 >> 16; 2063 int y = plane_state->uapi.src.y1 >> 16; 2064 int w = drm_rect_width(&plane_state->uapi.src) >> 16; 2065 int h = drm_rect_height(&plane_state->uapi.src) >> 16; 2066 int min_width = intel_plane_min_width(plane, fb, 0, rotation); 2067 int min_height = intel_plane_min_height(plane, fb, 0, rotation); 2068 int max_width = intel_plane_max_width(plane, fb, 0, rotation); 2069 int max_height = intel_plane_max_height(plane, fb, 0, rotation); 2070 unsigned int alignment = plane->min_alignment(plane, fb, 0); 2071 int aux_plane = skl_main_to_aux_plane(fb, 0); 2072 u32 offset; 2073 int ret; 2074 2075 if (w > max_width || w < min_width || h > max_height || h < min_height) { 2076 drm_dbg_kms(display->drm, 2077 "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx%d max: %dx%d)\n", 2078 plane->base.base.id, plane->base.name, 2079 w, h, min_width, min_height, max_width, max_height); 2080 return -EINVAL; 2081 } 2082 2083 ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset); 2084 if (ret) 2085 return ret; 2086 2087 /* 2088 * CCS AUX surface doesn't have its own x/y offsets, we must make sure 2089 * they match with the main surface x/y offsets. On DG2 2090 * there's no aux plane on fb so skip this checking. 2091 */ 2092 if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) { 2093 while (!skl_check_main_ccs_coordinates(plane_state, x, y, 2094 offset, aux_plane)) { 2095 if (offset == 0) 2096 break; 2097 2098 offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, 2099 offset, offset - alignment); 2100 } 2101 2102 if (x != plane_state->view.color_plane[aux_plane].x || 2103 y != plane_state->view.color_plane[aux_plane].y) { 2104 drm_dbg_kms(display->drm, 2105 "[PLANE:%d:%s] unable to find suitable display surface offset due to CCS\n", 2106 plane->base.base.id, plane->base.name); 2107 return -EINVAL; 2108 } 2109 } 2110 2111 if (DISPLAY_VER(display) >= 13) 2112 drm_WARN_ON(display->drm, x > 65535 || y > 65535); 2113 else 2114 drm_WARN_ON(display->drm, x > 8191 || y > 8191); 2115 2116 plane_state->view.color_plane[0].offset = offset; 2117 plane_state->view.color_plane[0].x = x; 2118 plane_state->view.color_plane[0].y = y; 2119 2120 /* 2121 * Put the final coordinates back so that the src 2122 * coordinate checks will see the right values. 2123 */ 2124 drm_rect_translate_to(&plane_state->uapi.src, 2125 x << 16, y << 16); 2126 2127 return 0; 2128 } 2129 2130 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) 2131 { 2132 struct intel_display *display = to_intel_display(plane_state); 2133 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2134 const struct drm_framebuffer *fb = plane_state->hw.fb; 2135 unsigned int rotation = plane_state->hw.rotation; 2136 int uv_plane = 1; 2137 int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ? 2138 skl_main_to_aux_plane(fb, uv_plane) : 0; 2139 int min_width = intel_plane_min_width(plane, fb, uv_plane, rotation); 2140 int min_height = intel_plane_min_height(plane, fb, uv_plane, rotation); 2141 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); 2142 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); 2143 int x = plane_state->uapi.src.x1 >> 17; 2144 int y = plane_state->uapi.src.y1 >> 17; 2145 int w = drm_rect_width(&plane_state->uapi.src) >> 17; 2146 int h = drm_rect_height(&plane_state->uapi.src) >> 17; 2147 u32 offset; 2148 2149 /* FIXME not quite sure how/if these apply to the chroma plane */ 2150 if (w > max_width || w < min_width || h > max_height || h < min_height) { 2151 drm_dbg_kms(display->drm, 2152 "[PLANE:%d:%s] requested CbCr source size %dx%d outside limits (min: %dx%d max: %dx%d)\n", 2153 plane->base.base.id, plane->base.name, 2154 w, h, min_width, min_height, max_width, max_height); 2155 return -EINVAL; 2156 } 2157 2158 intel_add_fb_offsets(&x, &y, plane_state, uv_plane); 2159 offset = intel_plane_compute_aligned_offset(&x, &y, 2160 plane_state, uv_plane); 2161 2162 if (ccs_plane) { 2163 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 2164 unsigned int alignment = plane->min_alignment(plane, fb, uv_plane); 2165 2166 if (offset > aux_offset) 2167 offset = intel_plane_adjust_aligned_offset(&x, &y, 2168 plane_state, 2169 uv_plane, 2170 offset, 2171 aux_offset & ~(alignment - 1)); 2172 2173 while (!skl_check_main_ccs_coordinates(plane_state, x, y, 2174 offset, ccs_plane)) { 2175 if (offset == 0) 2176 break; 2177 2178 offset = intel_plane_adjust_aligned_offset(&x, &y, 2179 plane_state, 2180 uv_plane, 2181 offset, offset - alignment); 2182 } 2183 2184 if (x != plane_state->view.color_plane[ccs_plane].x || 2185 y != plane_state->view.color_plane[ccs_plane].y) { 2186 drm_dbg_kms(display->drm, 2187 "[PLANE:%d:%s] unable to find suitable display surface offset due to CCS\n", 2188 plane->base.base.id, plane->base.name); 2189 return -EINVAL; 2190 } 2191 } 2192 2193 if (DISPLAY_VER(display) >= 13) 2194 drm_WARN_ON(display->drm, x > 65535 || y > 65535); 2195 else 2196 drm_WARN_ON(display->drm, x > 8191 || y > 8191); 2197 2198 plane_state->view.color_plane[uv_plane].offset = offset; 2199 plane_state->view.color_plane[uv_plane].x = x; 2200 plane_state->view.color_plane[uv_plane].y = y; 2201 2202 return 0; 2203 } 2204 2205 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) 2206 { 2207 const struct drm_framebuffer *fb = plane_state->hw.fb; 2208 int src_x = plane_state->uapi.src.x1 >> 16; 2209 int src_y = plane_state->uapi.src.y1 >> 16; 2210 u32 offset; 2211 int ccs_plane; 2212 2213 for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) { 2214 int main_hsub, main_vsub; 2215 int hsub, vsub; 2216 int x, y; 2217 2218 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane)) 2219 continue; 2220 2221 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, 2222 skl_ccs_to_main_plane(fb, ccs_plane)); 2223 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); 2224 2225 hsub *= main_hsub; 2226 vsub *= main_vsub; 2227 x = src_x / hsub; 2228 y = src_y / vsub; 2229 2230 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane); 2231 2232 offset = intel_plane_compute_aligned_offset(&x, &y, 2233 plane_state, 2234 ccs_plane); 2235 2236 plane_state->view.color_plane[ccs_plane].offset = offset; 2237 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub; 2238 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub; 2239 } 2240 2241 return 0; 2242 } 2243 2244 static int skl_check_plane_surface(struct intel_plane_state *plane_state) 2245 { 2246 const struct drm_framebuffer *fb = plane_state->hw.fb; 2247 int ret; 2248 2249 ret = intel_plane_compute_gtt(plane_state); 2250 if (ret) 2251 return ret; 2252 2253 if (!plane_state->uapi.visible) 2254 return 0; 2255 2256 /* 2257 * Handle the AUX surface first since the main surface setup depends on 2258 * it. 2259 */ 2260 if (intel_fb_is_ccs_modifier(fb->modifier)) { 2261 ret = skl_check_ccs_aux_surface(plane_state); 2262 if (ret) 2263 return ret; 2264 } 2265 2266 if (intel_format_info_is_yuv_semiplanar(fb->format, 2267 fb->modifier)) { 2268 ret = skl_check_nv12_aux_surface(plane_state); 2269 if (ret) 2270 return ret; 2271 } 2272 2273 ret = skl_check_main_surface(plane_state); 2274 if (ret) 2275 return ret; 2276 2277 return 0; 2278 } 2279 2280 static bool skl_fb_scalable(const struct drm_framebuffer *fb) 2281 { 2282 struct intel_display *display; 2283 2284 if (!fb) 2285 return false; 2286 2287 display = to_intel_display(fb->dev); 2288 2289 switch (fb->format->format) { 2290 case DRM_FORMAT_C8: 2291 return false; 2292 case DRM_FORMAT_XRGB16161616F: 2293 case DRM_FORMAT_ARGB16161616F: 2294 case DRM_FORMAT_XBGR16161616F: 2295 case DRM_FORMAT_ABGR16161616F: 2296 return DISPLAY_VER(display) >= 11; 2297 default: 2298 return true; 2299 } 2300 } 2301 2302 static void check_protection(struct intel_plane_state *plane_state) 2303 { 2304 struct intel_display *display = to_intel_display(plane_state); 2305 const struct drm_framebuffer *fb = plane_state->hw.fb; 2306 struct drm_gem_object *obj = intel_fb_bo(fb); 2307 2308 if (DISPLAY_VER(display) < 11) 2309 return; 2310 2311 plane_state->decrypt = intel_pxp_key_check(obj, false) == 0; 2312 plane_state->force_black = intel_bo_is_protected(obj) && 2313 !plane_state->decrypt; 2314 } 2315 2316 static void 2317 make_damage_viewport_relative(struct intel_plane_state *plane_state) 2318 { 2319 const struct drm_framebuffer *fb = plane_state->hw.fb; 2320 const struct drm_rect *src = &plane_state->uapi.src; 2321 unsigned int rotation = plane_state->hw.rotation; 2322 struct drm_rect *damage = &plane_state->damage; 2323 2324 if (!drm_rect_visible(damage)) 2325 return; 2326 2327 if (!fb || !plane_state->uapi.visible) { 2328 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0); 2329 return; 2330 } 2331 2332 if (drm_rotation_90_or_270(rotation)) { 2333 drm_rect_rotate(damage, fb->width, fb->height, 2334 DRM_MODE_ROTATE_270); 2335 drm_rect_translate(damage, -(src->y1 >> 16), -(src->x1 >> 16)); 2336 } else { 2337 drm_rect_translate(damage, -(src->x1 >> 16), -(src->y1 >> 16)); 2338 } 2339 } 2340 2341 static void clip_damage(struct intel_plane_state *plane_state) 2342 { 2343 struct drm_rect *damage = &plane_state->damage; 2344 struct drm_rect src; 2345 2346 if (!drm_rect_visible(damage)) 2347 return; 2348 2349 drm_rect_fp_to_int(&src, &plane_state->uapi.src); 2350 drm_rect_translate(damage, src.x1, src.y1); 2351 drm_rect_intersect(damage, &src); 2352 } 2353 2354 static int skl_plane_check(struct intel_crtc_state *crtc_state, 2355 struct intel_plane_state *plane_state) 2356 { 2357 struct intel_display *display = to_intel_display(plane_state); 2358 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2359 const struct drm_framebuffer *fb = plane_state->hw.fb; 2360 int min_scale = DRM_PLANE_NO_SCALING; 2361 int max_scale = DRM_PLANE_NO_SCALING; 2362 int ret; 2363 2364 ret = skl_plane_check_fb(crtc_state, plane_state); 2365 if (ret) 2366 return ret; 2367 2368 /* use scaler when colorkey is not required */ 2369 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) { 2370 min_scale = 1; 2371 max_scale = skl_plane_max_scale(display, fb); 2372 } 2373 2374 ret = intel_plane_check_clipping(plane_state, crtc_state, 2375 min_scale, max_scale, true); 2376 if (ret) 2377 return ret; 2378 2379 make_damage_viewport_relative(plane_state); 2380 2381 ret = skl_check_plane_surface(plane_state); 2382 if (ret) 2383 return ret; 2384 2385 if (!plane_state->uapi.visible) 2386 return 0; 2387 2388 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state); 2389 if (ret) 2390 return ret; 2391 2392 ret = intel_plane_check_src_coordinates(plane_state); 2393 if (ret) 2394 return ret; 2395 2396 clip_damage(plane_state); 2397 2398 ret = skl_plane_check_nv12_rotation(plane_state); 2399 if (ret) 2400 return ret; 2401 2402 check_protection(plane_state); 2403 2404 /* HW only has 8 bits pixel precision, disable plane if invisible */ 2405 if (!(plane_state->hw.alpha >> 8)) { 2406 plane_state->uapi.visible = false; 2407 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0); 2408 } 2409 2410 plane_state->ctl = skl_plane_ctl(plane_state); 2411 2412 if (DISPLAY_VER(display) >= 10) 2413 plane_state->color_ctl = glk_plane_color_ctl(plane_state); 2414 2415 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && 2416 icl_is_hdr_plane(display, plane->id)) 2417 /* Enable and use MPEG-2 chroma siting */ 2418 plane_state->cus_ctl = PLANE_CUS_ENABLE | 2419 PLANE_CUS_HPHASE_0 | 2420 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25; 2421 else 2422 plane_state->cus_ctl = 0; 2423 2424 return 0; 2425 } 2426 2427 void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state, 2428 struct intel_plane_state *y_plane_state) 2429 { 2430 struct intel_display *display = to_intel_display(uv_plane_state); 2431 struct intel_plane *uv_plane = to_intel_plane(uv_plane_state->uapi.plane); 2432 struct intel_plane *y_plane = to_intel_plane(y_plane_state->uapi.plane); 2433 2434 drm_WARN_ON(display->drm, icl_is_nv12_y_plane(display, uv_plane->id)); 2435 drm_WARN_ON(display->drm, !icl_is_nv12_y_plane(display, y_plane->id)); 2436 2437 y_plane_state->ctl |= PLANE_CTL_YUV420_Y_PLANE; 2438 2439 if (icl_is_hdr_plane(display, uv_plane->id)) { 2440 switch (y_plane->id) { 2441 case PLANE_7: 2442 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_7_ICL; 2443 break; 2444 case PLANE_6: 2445 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_6_ICL; 2446 break; 2447 case PLANE_5: 2448 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_5_RKL; 2449 break; 2450 case PLANE_4: 2451 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_4_RKL; 2452 break; 2453 default: 2454 MISSING_CASE(y_plane->id); 2455 } 2456 } 2457 } 2458 2459 static struct intel_fbc *skl_plane_fbc(struct intel_display *display, 2460 enum pipe pipe, enum plane_id plane_id) 2461 { 2462 enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe); 2463 2464 if (skl_plane_has_fbc(display, fbc_id, plane_id)) 2465 return display->fbc[fbc_id]; 2466 else 2467 return NULL; 2468 } 2469 2470 static bool skl_plane_has_planar(struct intel_display *display, 2471 enum pipe pipe, enum plane_id plane_id) 2472 { 2473 /* Display WA #0870: skl, bxt */ 2474 if (display->platform.skylake || display->platform.broxton) 2475 return false; 2476 2477 if (pipe == PIPE_C) 2478 return false; 2479 2480 return plane_id == PLANE_1 || plane_id == PLANE_2; 2481 } 2482 2483 static const u32 *skl_get_plane_formats(struct intel_display *display, 2484 enum pipe pipe, enum plane_id plane_id, 2485 int *num_formats) 2486 { 2487 if (skl_plane_has_planar(display, pipe, plane_id)) { 2488 *num_formats = ARRAY_SIZE(skl_planar_formats); 2489 return skl_planar_formats; 2490 } else { 2491 *num_formats = ARRAY_SIZE(skl_plane_formats); 2492 return skl_plane_formats; 2493 } 2494 } 2495 2496 static bool glk_plane_has_planar(struct intel_display *display, 2497 enum pipe pipe, enum plane_id plane_id) 2498 { 2499 return plane_id == PLANE_1 || plane_id == PLANE_2; 2500 } 2501 2502 static const u32 *glk_get_plane_formats(struct intel_display *display, 2503 enum pipe pipe, enum plane_id plane_id, 2504 int *num_formats) 2505 { 2506 if (glk_plane_has_planar(display, pipe, plane_id)) { 2507 *num_formats = ARRAY_SIZE(glk_planar_formats); 2508 return glk_planar_formats; 2509 } else { 2510 *num_formats = ARRAY_SIZE(skl_plane_formats); 2511 return skl_plane_formats; 2512 } 2513 } 2514 2515 static const u32 *icl_get_plane_formats(struct intel_display *display, 2516 enum pipe pipe, enum plane_id plane_id, 2517 int *num_formats) 2518 { 2519 if (icl_is_hdr_plane(display, plane_id)) { 2520 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats); 2521 return icl_hdr_plane_formats; 2522 } else if (icl_is_nv12_y_plane(display, plane_id)) { 2523 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats); 2524 return icl_sdr_y_plane_formats; 2525 } else { 2526 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats); 2527 return icl_sdr_uv_plane_formats; 2528 } 2529 } 2530 2531 static bool skl_plane_format_mod_supported(struct drm_plane *_plane, 2532 u32 format, u64 modifier) 2533 { 2534 struct intel_plane *plane = to_intel_plane(_plane); 2535 2536 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2537 return false; 2538 2539 switch (format) { 2540 case DRM_FORMAT_XRGB8888: 2541 case DRM_FORMAT_XBGR8888: 2542 case DRM_FORMAT_ARGB8888: 2543 case DRM_FORMAT_ABGR8888: 2544 if (intel_fb_is_ccs_modifier(modifier)) 2545 return true; 2546 fallthrough; 2547 case DRM_FORMAT_RGB565: 2548 case DRM_FORMAT_XRGB2101010: 2549 case DRM_FORMAT_XBGR2101010: 2550 case DRM_FORMAT_ARGB2101010: 2551 case DRM_FORMAT_ABGR2101010: 2552 case DRM_FORMAT_YUYV: 2553 case DRM_FORMAT_YVYU: 2554 case DRM_FORMAT_UYVY: 2555 case DRM_FORMAT_VYUY: 2556 case DRM_FORMAT_NV12: 2557 case DRM_FORMAT_XYUV8888: 2558 case DRM_FORMAT_P010: 2559 case DRM_FORMAT_P012: 2560 case DRM_FORMAT_P016: 2561 case DRM_FORMAT_XVYU2101010: 2562 if (modifier == I915_FORMAT_MOD_Yf_TILED) 2563 return true; 2564 fallthrough; 2565 case DRM_FORMAT_C8: 2566 case DRM_FORMAT_XBGR16161616F: 2567 case DRM_FORMAT_ABGR16161616F: 2568 case DRM_FORMAT_XRGB16161616F: 2569 case DRM_FORMAT_ARGB16161616F: 2570 case DRM_FORMAT_Y210: 2571 case DRM_FORMAT_Y212: 2572 case DRM_FORMAT_Y216: 2573 case DRM_FORMAT_XVYU12_16161616: 2574 case DRM_FORMAT_XVYU16161616: 2575 if (modifier == DRM_FORMAT_MOD_LINEAR || 2576 modifier == I915_FORMAT_MOD_X_TILED || 2577 modifier == I915_FORMAT_MOD_Y_TILED) 2578 return true; 2579 fallthrough; 2580 default: 2581 return false; 2582 } 2583 } 2584 2585 static bool icl_plane_format_mod_supported(struct drm_plane *_plane, 2586 u32 format, u64 modifier) 2587 { 2588 struct intel_plane *plane = to_intel_plane(_plane); 2589 2590 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2591 return false; 2592 2593 switch (format) { 2594 case DRM_FORMAT_XRGB8888: 2595 case DRM_FORMAT_XBGR8888: 2596 case DRM_FORMAT_ARGB8888: 2597 case DRM_FORMAT_ABGR8888: 2598 case DRM_FORMAT_XRGB2101010: 2599 case DRM_FORMAT_XBGR2101010: 2600 case DRM_FORMAT_ARGB2101010: 2601 case DRM_FORMAT_ABGR2101010: 2602 if (intel_fb_is_ccs_modifier(modifier)) 2603 return true; 2604 fallthrough; 2605 case DRM_FORMAT_RGB565: 2606 case DRM_FORMAT_YUYV: 2607 case DRM_FORMAT_YVYU: 2608 case DRM_FORMAT_UYVY: 2609 case DRM_FORMAT_VYUY: 2610 case DRM_FORMAT_NV12: 2611 case DRM_FORMAT_XYUV8888: 2612 case DRM_FORMAT_P010: 2613 case DRM_FORMAT_P012: 2614 case DRM_FORMAT_P016: 2615 case DRM_FORMAT_XVYU2101010: 2616 if (modifier == I915_FORMAT_MOD_Yf_TILED) 2617 return true; 2618 fallthrough; 2619 case DRM_FORMAT_C8: 2620 case DRM_FORMAT_XBGR16161616F: 2621 case DRM_FORMAT_ABGR16161616F: 2622 case DRM_FORMAT_XRGB16161616F: 2623 case DRM_FORMAT_ARGB16161616F: 2624 case DRM_FORMAT_Y210: 2625 case DRM_FORMAT_Y212: 2626 case DRM_FORMAT_Y216: 2627 case DRM_FORMAT_XVYU12_16161616: 2628 case DRM_FORMAT_XVYU16161616: 2629 if (modifier == DRM_FORMAT_MOD_LINEAR || 2630 modifier == I915_FORMAT_MOD_X_TILED || 2631 modifier == I915_FORMAT_MOD_Y_TILED) 2632 return true; 2633 fallthrough; 2634 default: 2635 return false; 2636 } 2637 } 2638 2639 static bool tgl_plane_format_mod_supported(struct drm_plane *_plane, 2640 u32 format, u64 modifier) 2641 { 2642 struct intel_plane *plane = to_intel_plane(_plane); 2643 2644 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2645 return false; 2646 2647 switch (format) { 2648 case DRM_FORMAT_XRGB8888: 2649 case DRM_FORMAT_XBGR8888: 2650 case DRM_FORMAT_ARGB8888: 2651 case DRM_FORMAT_ABGR8888: 2652 case DRM_FORMAT_XRGB2101010: 2653 case DRM_FORMAT_XBGR2101010: 2654 case DRM_FORMAT_ARGB2101010: 2655 case DRM_FORMAT_ABGR2101010: 2656 case DRM_FORMAT_XBGR16161616F: 2657 case DRM_FORMAT_ABGR16161616F: 2658 case DRM_FORMAT_XRGB16161616F: 2659 case DRM_FORMAT_ARGB16161616F: 2660 if (intel_fb_is_ccs_modifier(modifier)) 2661 return true; 2662 fallthrough; 2663 case DRM_FORMAT_YUYV: 2664 case DRM_FORMAT_YVYU: 2665 case DRM_FORMAT_UYVY: 2666 case DRM_FORMAT_VYUY: 2667 case DRM_FORMAT_NV12: 2668 case DRM_FORMAT_XYUV8888: 2669 case DRM_FORMAT_P010: 2670 case DRM_FORMAT_P012: 2671 case DRM_FORMAT_P016: 2672 if (intel_fb_is_mc_ccs_modifier(modifier)) 2673 return true; 2674 fallthrough; 2675 case DRM_FORMAT_RGB565: 2676 case DRM_FORMAT_XVYU2101010: 2677 case DRM_FORMAT_C8: 2678 case DRM_FORMAT_Y210: 2679 case DRM_FORMAT_Y212: 2680 case DRM_FORMAT_Y216: 2681 case DRM_FORMAT_XVYU12_16161616: 2682 case DRM_FORMAT_XVYU16161616: 2683 if (!intel_fb_is_ccs_modifier(modifier)) 2684 return true; 2685 fallthrough; 2686 default: 2687 return false; 2688 } 2689 } 2690 2691 static const struct drm_plane_funcs skl_plane_funcs = { 2692 .update_plane = drm_atomic_helper_update_plane, 2693 .disable_plane = drm_atomic_helper_disable_plane, 2694 .destroy = intel_plane_destroy, 2695 .atomic_duplicate_state = intel_plane_duplicate_state, 2696 .atomic_destroy_state = intel_plane_destroy_state, 2697 .format_mod_supported = skl_plane_format_mod_supported, 2698 .format_mod_supported_async = intel_plane_format_mod_supported_async, 2699 }; 2700 2701 static const struct drm_plane_funcs icl_plane_funcs = { 2702 .update_plane = drm_atomic_helper_update_plane, 2703 .disable_plane = drm_atomic_helper_disable_plane, 2704 .destroy = intel_plane_destroy, 2705 .atomic_duplicate_state = intel_plane_duplicate_state, 2706 .atomic_destroy_state = intel_plane_destroy_state, 2707 .format_mod_supported = icl_plane_format_mod_supported, 2708 .format_mod_supported_async = intel_plane_format_mod_supported_async, 2709 }; 2710 2711 static const struct drm_plane_funcs tgl_plane_funcs = { 2712 .update_plane = drm_atomic_helper_update_plane, 2713 .disable_plane = drm_atomic_helper_disable_plane, 2714 .destroy = intel_plane_destroy, 2715 .atomic_duplicate_state = intel_plane_duplicate_state, 2716 .atomic_destroy_state = intel_plane_destroy_state, 2717 .format_mod_supported = tgl_plane_format_mod_supported, 2718 .format_mod_supported_async = intel_plane_format_mod_supported_async, 2719 }; 2720 2721 static void 2722 skl_plane_enable_flip_done(struct intel_plane *plane) 2723 { 2724 struct intel_display *display = to_intel_display(plane); 2725 enum pipe pipe = plane->pipe; 2726 2727 spin_lock_irq(&display->irq.lock); 2728 bdw_enable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 2729 spin_unlock_irq(&display->irq.lock); 2730 } 2731 2732 static void 2733 skl_plane_disable_flip_done(struct intel_plane *plane) 2734 { 2735 struct intel_display *display = to_intel_display(plane); 2736 enum pipe pipe = plane->pipe; 2737 2738 spin_lock_irq(&display->irq.lock); 2739 bdw_disable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 2740 spin_unlock_irq(&display->irq.lock); 2741 } 2742 2743 static bool skl_plane_has_rc_ccs(struct intel_display *display, 2744 enum pipe pipe, enum plane_id plane_id) 2745 { 2746 if (pipe == PIPE_C) 2747 return false; 2748 2749 return plane_id == PLANE_1 || plane_id == PLANE_2; 2750 } 2751 2752 static u8 skl_plane_caps(struct intel_display *display, 2753 enum pipe pipe, enum plane_id plane_id) 2754 { 2755 u8 caps = INTEL_PLANE_CAP_TILING_X | 2756 INTEL_PLANE_CAP_TILING_Y | 2757 INTEL_PLANE_CAP_TILING_Yf; 2758 2759 if (skl_plane_has_rc_ccs(display, pipe, plane_id)) 2760 caps |= INTEL_PLANE_CAP_CCS_RC; 2761 2762 return caps; 2763 } 2764 2765 static bool glk_plane_has_rc_ccs(struct intel_display *display, 2766 enum pipe pipe) 2767 { 2768 return pipe != PIPE_C; 2769 } 2770 2771 static u8 glk_plane_caps(struct intel_display *display, 2772 enum pipe pipe, enum plane_id plane_id) 2773 { 2774 u8 caps = INTEL_PLANE_CAP_TILING_X | 2775 INTEL_PLANE_CAP_TILING_Y | 2776 INTEL_PLANE_CAP_TILING_Yf; 2777 2778 if (glk_plane_has_rc_ccs(display, pipe)) 2779 caps |= INTEL_PLANE_CAP_CCS_RC; 2780 2781 return caps; 2782 } 2783 2784 static u8 icl_plane_caps(struct intel_display *display, 2785 enum pipe pipe, enum plane_id plane_id) 2786 { 2787 return INTEL_PLANE_CAP_TILING_X | 2788 INTEL_PLANE_CAP_TILING_Y | 2789 INTEL_PLANE_CAP_TILING_Yf | 2790 INTEL_PLANE_CAP_CCS_RC; 2791 } 2792 2793 static bool tgl_plane_has_mc_ccs(struct intel_display *display, 2794 enum plane_id plane_id) 2795 { 2796 /* Wa_14010477008 */ 2797 if (display->platform.dg1 || display->platform.rocketlake || 2798 (display->platform.tigerlake && IS_DISPLAY_STEP(display, STEP_A0, STEP_D0))) 2799 return false; 2800 2801 return plane_id < PLANE_6; 2802 } 2803 2804 static u8 tgl_plane_caps(struct intel_display *display, 2805 enum pipe pipe, enum plane_id plane_id) 2806 { 2807 u8 caps = INTEL_PLANE_CAP_TILING_X | 2808 INTEL_PLANE_CAP_CCS_RC | 2809 INTEL_PLANE_CAP_CCS_RC_CC; 2810 2811 if (HAS_4TILE(display)) 2812 caps |= INTEL_PLANE_CAP_TILING_4; 2813 else 2814 caps |= INTEL_PLANE_CAP_TILING_Y; 2815 2816 if (tgl_plane_has_mc_ccs(display, plane_id)) 2817 caps |= INTEL_PLANE_CAP_CCS_MC; 2818 2819 if (DISPLAY_VER(display) >= 14 && display->platform.dgfx) 2820 caps |= INTEL_PLANE_CAP_NEED64K_PHYS; 2821 2822 return caps; 2823 } 2824 2825 static void skl_disable_tiling(struct intel_plane *plane) 2826 { 2827 struct intel_plane_state *state = to_intel_plane_state(plane->base.state); 2828 struct intel_display *display = to_intel_display(plane); 2829 const struct drm_framebuffer *fb = state->hw.fb; 2830 u32 plane_ctl; 2831 2832 plane_ctl = intel_de_read(display, PLANE_CTL(plane->pipe, plane->id)); 2833 2834 if (intel_fb_uses_dpt(fb)) { 2835 /* if DPT is enabled, keep tiling, but disable compression */ 2836 plane_ctl &= ~PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 2837 } else { 2838 /* if DPT is not supported, disable tiling, and update stride */ 2839 u32 stride = state->view.color_plane[0].scanout_stride / 64; 2840 2841 plane_ctl &= ~PLANE_CTL_TILED_MASK; 2842 intel_de_write_fw(display, PLANE_STRIDE(plane->pipe, plane->id), 2843 PLANE_STRIDE_(stride)); 2844 } 2845 intel_de_write_fw(display, PLANE_CTL(plane->pipe, plane->id), plane_ctl); 2846 2847 intel_de_write_fw(display, PLANE_SURF(plane->pipe, plane->id), 2848 state->surf); 2849 } 2850 2851 struct intel_plane * 2852 skl_universal_plane_create(struct intel_display *display, 2853 enum pipe pipe, enum plane_id plane_id) 2854 { 2855 const struct drm_plane_funcs *plane_funcs; 2856 struct intel_plane *plane; 2857 enum drm_plane_type plane_type; 2858 unsigned int supported_rotations; 2859 unsigned int supported_csc; 2860 const u64 *modifiers; 2861 const u32 *formats; 2862 int num_formats; 2863 int ret; 2864 u8 caps; 2865 2866 plane = intel_plane_alloc(); 2867 if (IS_ERR(plane)) 2868 return plane; 2869 2870 plane->pipe = pipe; 2871 plane->id = plane_id; 2872 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id); 2873 2874 intel_fbc_add_plane(skl_plane_fbc(display, pipe, plane_id), plane); 2875 2876 if (DISPLAY_VER(display) >= 30) { 2877 plane->min_width = adl_plane_min_width; 2878 plane->max_width = xe3_plane_max_width; 2879 plane->max_height = icl_plane_max_height; 2880 plane->min_cdclk = icl_plane_min_cdclk; 2881 } else if (DISPLAY_VER(display) >= 11) { 2882 if (DISPLAY_VER(display) >= 14 || display->platform.alderlake_p) 2883 plane->min_width = adl_plane_min_width; 2884 else 2885 plane->min_width = icl_plane_min_width; 2886 if (icl_is_hdr_plane(display, plane_id)) 2887 plane->max_width = icl_hdr_plane_max_width; 2888 else 2889 plane->max_width = icl_sdr_plane_max_width; 2890 plane->max_height = icl_plane_max_height; 2891 plane->min_cdclk = icl_plane_min_cdclk; 2892 } else if (DISPLAY_VER(display) >= 10) { 2893 plane->max_width = glk_plane_max_width; 2894 plane->max_height = skl_plane_max_height; 2895 plane->min_cdclk = glk_plane_min_cdclk; 2896 } else { 2897 plane->max_width = skl_plane_max_width; 2898 plane->max_height = skl_plane_max_height; 2899 plane->min_cdclk = skl_plane_min_cdclk; 2900 } 2901 plane->disable_tiling = skl_disable_tiling; 2902 2903 plane->surf_offset = skl_plane_surf_offset; 2904 2905 if (DISPLAY_VER(display) >= 13) 2906 plane->max_stride = adl_plane_max_stride; 2907 else 2908 plane->max_stride = skl_plane_max_stride; 2909 2910 if (DISPLAY_VER(display) >= 12) 2911 plane->min_alignment = tgl_plane_min_alignment; 2912 else 2913 plane->min_alignment = skl_plane_min_alignment; 2914 2915 if (intel_scanout_needs_vtd_wa(display)) 2916 plane->vtd_guard = DISPLAY_VER(display) >= 10 ? 168 : 136; 2917 2918 if (DISPLAY_VER(display) >= 11) { 2919 plane->update_noarm = icl_plane_update_noarm; 2920 plane->update_arm = icl_plane_update_arm; 2921 plane->disable_arm = icl_plane_disable_arm; 2922 } else { 2923 plane->update_noarm = skl_plane_update_noarm; 2924 plane->update_arm = skl_plane_update_arm; 2925 plane->disable_arm = skl_plane_disable_arm; 2926 } 2927 plane->capture_error = skl_plane_capture_error; 2928 plane->get_hw_state = skl_plane_get_hw_state; 2929 plane->check_plane = skl_plane_check; 2930 2931 if (HAS_ASYNC_FLIPS(display) && plane_id == PLANE_1) { 2932 plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(display, 9, 10); 2933 plane->async_flip = skl_plane_async_flip; 2934 plane->enable_flip_done = skl_plane_enable_flip_done; 2935 plane->disable_flip_done = skl_plane_disable_flip_done; 2936 2937 if (DISPLAY_VER(display) >= 12) 2938 plane->can_async_flip = tgl_plane_can_async_flip; 2939 else if (DISPLAY_VER(display) == 11) 2940 plane->can_async_flip = icl_plane_can_async_flip; 2941 else 2942 plane->can_async_flip = skl_plane_can_async_flip; 2943 } 2944 2945 if (DISPLAY_VER(display) >= 11) 2946 formats = icl_get_plane_formats(display, pipe, 2947 plane_id, &num_formats); 2948 else if (DISPLAY_VER(display) >= 10) 2949 formats = glk_get_plane_formats(display, pipe, 2950 plane_id, &num_formats); 2951 else 2952 formats = skl_get_plane_formats(display, pipe, 2953 plane_id, &num_formats); 2954 2955 if (DISPLAY_VER(display) >= 12) 2956 plane_funcs = &tgl_plane_funcs; 2957 else if (DISPLAY_VER(display) == 11) 2958 plane_funcs = &icl_plane_funcs; 2959 else 2960 plane_funcs = &skl_plane_funcs; 2961 2962 if (plane_id == PLANE_1) 2963 plane_type = DRM_PLANE_TYPE_PRIMARY; 2964 else 2965 plane_type = DRM_PLANE_TYPE_OVERLAY; 2966 2967 if (DISPLAY_VER(display) >= 12) 2968 caps = tgl_plane_caps(display, pipe, plane_id); 2969 else if (DISPLAY_VER(display) == 11) 2970 caps = icl_plane_caps(display, pipe, plane_id); 2971 else if (DISPLAY_VER(display) == 10) 2972 caps = glk_plane_caps(display, pipe, plane_id); 2973 else 2974 caps = skl_plane_caps(display, pipe, plane_id); 2975 2976 /* FIXME: xe has problems with AUX */ 2977 if (!IS_ENABLED(I915) && HAS_AUX_CCS(display)) 2978 caps &= ~(INTEL_PLANE_CAP_CCS_RC | 2979 INTEL_PLANE_CAP_CCS_RC_CC | 2980 INTEL_PLANE_CAP_CCS_MC); 2981 2982 modifiers = intel_fb_plane_get_modifiers(display, caps); 2983 2984 ret = drm_universal_plane_init(display->drm, &plane->base, 2985 0, plane_funcs, 2986 formats, num_formats, modifiers, 2987 plane_type, 2988 "plane %d%c", plane_id + 1, 2989 pipe_name(pipe)); 2990 2991 kfree(modifiers); 2992 2993 if (ret) 2994 goto fail; 2995 2996 if (DISPLAY_VER(display) >= 13) 2997 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; 2998 else 2999 supported_rotations = 3000 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | 3001 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; 3002 3003 if (DISPLAY_VER(display) >= 11) 3004 supported_rotations |= DRM_MODE_REFLECT_X; 3005 3006 drm_plane_create_rotation_property(&plane->base, 3007 DRM_MODE_ROTATE_0, 3008 supported_rotations); 3009 3010 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709); 3011 3012 if (DISPLAY_VER(display) >= 10) 3013 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020); 3014 3015 drm_plane_create_color_properties(&plane->base, 3016 supported_csc, 3017 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | 3018 BIT(DRM_COLOR_YCBCR_FULL_RANGE), 3019 DRM_COLOR_YCBCR_BT709, 3020 DRM_COLOR_YCBCR_LIMITED_RANGE); 3021 3022 if (DISPLAY_VER(display) >= 12) 3023 intel_color_pipeline_plane_init(&plane->base, pipe); 3024 3025 drm_plane_create_alpha_property(&plane->base); 3026 drm_plane_create_blend_mode_property(&plane->base, 3027 BIT(DRM_MODE_BLEND_PIXEL_NONE) | 3028 BIT(DRM_MODE_BLEND_PREMULTI) | 3029 BIT(DRM_MODE_BLEND_COVERAGE)); 3030 3031 drm_plane_create_zpos_immutable_property(&plane->base, plane_id); 3032 3033 if (DISPLAY_VER(display) >= 12) 3034 drm_plane_enable_fb_damage_clips(&plane->base); 3035 3036 if (DISPLAY_VER(display) >= 11) 3037 drm_plane_create_scaling_filter_property(&plane->base, 3038 BIT(DRM_SCALING_FILTER_DEFAULT) | 3039 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); 3040 3041 intel_plane_helper_add(plane); 3042 3043 return plane; 3044 3045 fail: 3046 intel_plane_free(plane); 3047 3048 return ERR_PTR(ret); 3049 } 3050 3051 void 3052 skl_get_initial_plane_config(struct intel_crtc *crtc, 3053 struct intel_initial_plane_config *plane_config) 3054 { 3055 struct intel_display *display = to_intel_display(crtc); 3056 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); 3057 struct intel_plane *plane = to_intel_plane(crtc->base.primary); 3058 enum plane_id plane_id = plane->id; 3059 enum pipe pipe; 3060 u32 val, base, offset, stride_mult, tiling, alpha; 3061 int fourcc, pixel_format; 3062 unsigned int aligned_height; 3063 struct drm_framebuffer *fb; 3064 struct intel_framebuffer *intel_fb; 3065 static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4); 3066 3067 if (!plane->get_hw_state(plane, &pipe)) 3068 return; 3069 3070 drm_WARN_ON(display->drm, pipe != crtc->pipe); 3071 3072 if (crtc_state->joiner_pipes) { 3073 drm_dbg_kms(display->drm, 3074 "[CRTC:%d:%s] Unsupported joiner configuration for initial FB\n", 3075 crtc->base.base.id, crtc->base.name); 3076 return; 3077 } 3078 3079 intel_fb = intel_framebuffer_alloc(); 3080 if (!intel_fb) { 3081 drm_dbg_kms(display->drm, "failed to alloc fb\n"); 3082 return; 3083 } 3084 3085 fb = &intel_fb->base; 3086 3087 fb->dev = display->drm; 3088 3089 val = intel_de_read(display, PLANE_CTL(pipe, plane_id)); 3090 3091 if (DISPLAY_VER(display) >= 11) 3092 pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL; 3093 else 3094 pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL; 3095 3096 if (DISPLAY_VER(display) >= 10) { 3097 u32 color_ctl; 3098 3099 color_ctl = intel_de_read(display, PLANE_COLOR_CTL(pipe, plane_id)); 3100 alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl); 3101 } else { 3102 alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val); 3103 } 3104 3105 fourcc = skl_format_to_fourcc(pixel_format, 3106 val & PLANE_CTL_ORDER_RGBX, alpha); 3107 3108 tiling = val & PLANE_CTL_TILED_MASK; 3109 switch (tiling) { 3110 case PLANE_CTL_TILED_LINEAR: 3111 fb->modifier = DRM_FORMAT_MOD_LINEAR; 3112 break; 3113 case PLANE_CTL_TILED_X: 3114 fb->modifier = I915_FORMAT_MOD_X_TILED; 3115 break; 3116 case PLANE_CTL_TILED_Y: 3117 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3118 if (DISPLAY_VER(display) >= 14) 3119 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS; 3120 else if (DISPLAY_VER(display) >= 12) 3121 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS; 3122 else 3123 fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS; 3124 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) 3125 if (DISPLAY_VER(display) >= 14) 3126 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS; 3127 else 3128 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS; 3129 else 3130 fb->modifier = I915_FORMAT_MOD_Y_TILED; 3131 break; 3132 case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */ 3133 if (HAS_4TILE(display)) { 3134 u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | 3135 PLANE_CTL_CLEAR_COLOR_DISABLE; 3136 3137 if ((val & rc_mask) == rc_mask) 3138 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS; 3139 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) 3140 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS; 3141 else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3142 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC; 3143 else 3144 fb->modifier = I915_FORMAT_MOD_4_TILED; 3145 } else { 3146 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3147 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; 3148 else 3149 fb->modifier = I915_FORMAT_MOD_Yf_TILED; 3150 } 3151 break; 3152 default: 3153 MISSING_CASE(tiling); 3154 goto error; 3155 } 3156 3157 fb->format = drm_get_format_info(display->drm, fourcc, fb->modifier); 3158 3159 if (!display->params.enable_dpt && 3160 intel_fb_modifier_uses_dpt(display, fb->modifier)) { 3161 drm_dbg_kms(display->drm, "DPT disabled, skipping initial FB\n"); 3162 goto error; 3163 } 3164 3165 /* 3166 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr 3167 * while i915 HW rotation is clockwise, that's why this swapping. 3168 */ 3169 switch (val & PLANE_CTL_ROTATE_MASK) { 3170 case PLANE_CTL_ROTATE_0: 3171 plane_config->rotation = DRM_MODE_ROTATE_0; 3172 break; 3173 case PLANE_CTL_ROTATE_90: 3174 plane_config->rotation = DRM_MODE_ROTATE_270; 3175 break; 3176 case PLANE_CTL_ROTATE_180: 3177 plane_config->rotation = DRM_MODE_ROTATE_180; 3178 break; 3179 case PLANE_CTL_ROTATE_270: 3180 plane_config->rotation = DRM_MODE_ROTATE_90; 3181 break; 3182 } 3183 3184 if (DISPLAY_VER(display) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL) 3185 plane_config->rotation |= DRM_MODE_REFLECT_X; 3186 3187 /* 90/270 degree rotation would require extra work */ 3188 if (drm_rotation_90_or_270(plane_config->rotation)) 3189 goto error; 3190 3191 base = intel_de_read(display, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK; 3192 plane_config->base = base; 3193 3194 offset = intel_de_read(display, PLANE_OFFSET(pipe, plane_id)); 3195 drm_WARN_ON(display->drm, offset != 0); 3196 3197 val = intel_de_read(display, PLANE_SIZE(pipe, plane_id)); 3198 fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1; 3199 fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1; 3200 3201 val = intel_de_read(display, PLANE_STRIDE(pipe, plane_id)); 3202 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0); 3203 3204 fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult; 3205 3206 aligned_height = intel_fb_align_height(fb, 0, fb->height); 3207 3208 plane_config->size = fb->pitches[0] * aligned_height; 3209 3210 drm_dbg_kms(display->drm, 3211 "[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 3212 crtc->base.base.id, crtc->base.name, 3213 plane->base.base.id, plane->base.name, 3214 fb->width, fb->height, fb->format->cpp[0] * 8, 3215 base, fb->pitches[0], plane_config->size); 3216 3217 plane_config->fb = intel_fb; 3218 return; 3219 3220 error: 3221 kfree(intel_fb); 3222 } 3223 3224 bool skl_fixup_initial_plane_config(struct intel_crtc *crtc, 3225 const struct intel_initial_plane_config *plane_config) 3226 { 3227 struct intel_display *display = to_intel_display(crtc); 3228 struct intel_plane *plane = to_intel_plane(crtc->base.primary); 3229 const struct intel_plane_state *plane_state = 3230 to_intel_plane_state(plane->base.state); 3231 enum plane_id plane_id = plane->id; 3232 enum pipe pipe = crtc->pipe; 3233 3234 if (!plane_state->uapi.visible) 3235 return false; 3236 3237 /* 3238 * We may have moved the surface to a different 3239 * part of ggtt, make the plane aware of that. 3240 */ 3241 if (plane_config->base == plane_state->surf) 3242 return false; 3243 3244 intel_de_write(display, PLANE_SURF(pipe, plane_id), plane_state->surf); 3245 3246 return true; 3247 } 3248