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