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