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 void 2273 make_damage_viewport_relative(struct intel_plane_state *plane_state) 2274 { 2275 const struct drm_framebuffer *fb = plane_state->hw.fb; 2276 const struct drm_rect *src = &plane_state->uapi.src; 2277 unsigned int rotation = plane_state->hw.rotation; 2278 struct drm_rect *damage = &plane_state->damage; 2279 2280 if (!drm_rect_visible(damage)) 2281 return; 2282 2283 if (!fb || !plane_state->uapi.visible) { 2284 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0); 2285 return; 2286 } 2287 2288 if (drm_rotation_90_or_270(rotation)) { 2289 drm_rect_rotate(damage, fb->width, fb->height, 2290 DRM_MODE_ROTATE_270); 2291 drm_rect_translate(damage, -(src->y1 >> 16), -(src->x1 >> 16)); 2292 } else { 2293 drm_rect_translate(damage, -(src->x1 >> 16), -(src->y1 >> 16)); 2294 } 2295 } 2296 2297 static void clip_damage(struct intel_plane_state *plane_state) 2298 { 2299 struct drm_rect *damage = &plane_state->damage; 2300 struct drm_rect src; 2301 2302 if (!drm_rect_visible(damage)) 2303 return; 2304 2305 drm_rect_fp_to_int(&src, &plane_state->uapi.src); 2306 drm_rect_translate(damage, src.x1, src.y1); 2307 drm_rect_intersect(damage, &src); 2308 } 2309 2310 static int skl_plane_check(struct intel_crtc_state *crtc_state, 2311 struct intel_plane_state *plane_state) 2312 { 2313 struct intel_display *display = to_intel_display(plane_state); 2314 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2315 const struct drm_framebuffer *fb = plane_state->hw.fb; 2316 int min_scale = DRM_PLANE_NO_SCALING; 2317 int max_scale = DRM_PLANE_NO_SCALING; 2318 int ret; 2319 2320 ret = skl_plane_check_fb(crtc_state, plane_state); 2321 if (ret) 2322 return ret; 2323 2324 /* use scaler when colorkey is not required */ 2325 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) { 2326 min_scale = 1; 2327 max_scale = skl_plane_max_scale(display, fb); 2328 } 2329 2330 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, 2331 min_scale, max_scale, true); 2332 if (ret) 2333 return ret; 2334 2335 make_damage_viewport_relative(plane_state); 2336 2337 ret = skl_check_plane_surface(plane_state); 2338 if (ret) 2339 return ret; 2340 2341 if (!plane_state->uapi.visible) 2342 return 0; 2343 2344 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state); 2345 if (ret) 2346 return ret; 2347 2348 ret = intel_plane_check_src_coordinates(plane_state); 2349 if (ret) 2350 return ret; 2351 2352 clip_damage(plane_state); 2353 2354 ret = skl_plane_check_nv12_rotation(plane_state); 2355 if (ret) 2356 return ret; 2357 2358 check_protection(plane_state); 2359 2360 /* HW only has 8 bits pixel precision, disable plane if invisible */ 2361 if (!(plane_state->hw.alpha >> 8)) { 2362 plane_state->uapi.visible = false; 2363 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0); 2364 } 2365 2366 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); 2367 2368 if (DISPLAY_VER(display) >= 10) 2369 plane_state->color_ctl = glk_plane_color_ctl(crtc_state, 2370 plane_state); 2371 2372 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && 2373 icl_is_hdr_plane(display, plane->id)) 2374 /* Enable and use MPEG-2 chroma siting */ 2375 plane_state->cus_ctl = PLANE_CUS_ENABLE | 2376 PLANE_CUS_HPHASE_0 | 2377 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25; 2378 else 2379 plane_state->cus_ctl = 0; 2380 2381 return 0; 2382 } 2383 2384 void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state, 2385 struct intel_plane_state *y_plane_state) 2386 { 2387 struct intel_display *display = to_intel_display(uv_plane_state); 2388 struct intel_plane *uv_plane = to_intel_plane(uv_plane_state->uapi.plane); 2389 struct intel_plane *y_plane = to_intel_plane(y_plane_state->uapi.plane); 2390 2391 drm_WARN_ON(display->drm, icl_is_nv12_y_plane(display, uv_plane->id)); 2392 drm_WARN_ON(display->drm, !icl_is_nv12_y_plane(display, y_plane->id)); 2393 2394 y_plane_state->ctl |= PLANE_CTL_YUV420_Y_PLANE; 2395 2396 if (icl_is_hdr_plane(display, uv_plane->id)) { 2397 switch (y_plane->id) { 2398 case PLANE_7: 2399 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_7_ICL; 2400 break; 2401 case PLANE_6: 2402 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_6_ICL; 2403 break; 2404 case PLANE_5: 2405 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_5_RKL; 2406 break; 2407 case PLANE_4: 2408 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_4_RKL; 2409 break; 2410 default: 2411 MISSING_CASE(y_plane->id); 2412 } 2413 } 2414 } 2415 2416 static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) 2417 { 2418 return pipe - PIPE_A + INTEL_FBC_A; 2419 } 2420 2421 static bool skl_plane_has_fbc(struct intel_display *display, 2422 enum intel_fbc_id fbc_id, enum plane_id plane_id) 2423 { 2424 if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) 2425 return false; 2426 2427 if (DISPLAY_VER(display) >= 20) 2428 return icl_is_hdr_plane(display, plane_id); 2429 else 2430 return plane_id == PLANE_1; 2431 } 2432 2433 static struct intel_fbc *skl_plane_fbc(struct intel_display *display, 2434 enum pipe pipe, enum plane_id plane_id) 2435 { 2436 enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe); 2437 2438 if (skl_plane_has_fbc(display, fbc_id, plane_id)) 2439 return display->fbc[fbc_id]; 2440 else 2441 return NULL; 2442 } 2443 2444 static bool skl_plane_has_planar(struct intel_display *display, 2445 enum pipe pipe, enum plane_id plane_id) 2446 { 2447 /* Display WA #0870: skl, bxt */ 2448 if (display->platform.skylake || display->platform.broxton) 2449 return false; 2450 2451 if (DISPLAY_VER(display) == 9 && pipe == PIPE_C) 2452 return false; 2453 2454 if (plane_id != PLANE_1 && plane_id != PLANE_2) 2455 return false; 2456 2457 return true; 2458 } 2459 2460 static const u32 *skl_get_plane_formats(struct intel_display *display, 2461 enum pipe pipe, enum plane_id plane_id, 2462 int *num_formats) 2463 { 2464 if (skl_plane_has_planar(display, pipe, plane_id)) { 2465 *num_formats = ARRAY_SIZE(skl_planar_formats); 2466 return skl_planar_formats; 2467 } else { 2468 *num_formats = ARRAY_SIZE(skl_plane_formats); 2469 return skl_plane_formats; 2470 } 2471 } 2472 2473 static const u32 *glk_get_plane_formats(struct intel_display *display, 2474 enum pipe pipe, enum plane_id plane_id, 2475 int *num_formats) 2476 { 2477 if (skl_plane_has_planar(display, pipe, plane_id)) { 2478 *num_formats = ARRAY_SIZE(glk_planar_formats); 2479 return glk_planar_formats; 2480 } else { 2481 *num_formats = ARRAY_SIZE(skl_plane_formats); 2482 return skl_plane_formats; 2483 } 2484 } 2485 2486 static const u32 *icl_get_plane_formats(struct intel_display *display, 2487 enum pipe pipe, enum plane_id plane_id, 2488 int *num_formats) 2489 { 2490 if (icl_is_hdr_plane(display, plane_id)) { 2491 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats); 2492 return icl_hdr_plane_formats; 2493 } else if (icl_is_nv12_y_plane(display, plane_id)) { 2494 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats); 2495 return icl_sdr_y_plane_formats; 2496 } else { 2497 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats); 2498 return icl_sdr_uv_plane_formats; 2499 } 2500 } 2501 2502 static bool skl_plane_format_mod_supported(struct drm_plane *_plane, 2503 u32 format, u64 modifier) 2504 { 2505 struct intel_plane *plane = to_intel_plane(_plane); 2506 2507 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2508 return false; 2509 2510 switch (format) { 2511 case DRM_FORMAT_XRGB8888: 2512 case DRM_FORMAT_XBGR8888: 2513 case DRM_FORMAT_ARGB8888: 2514 case DRM_FORMAT_ABGR8888: 2515 if (intel_fb_is_ccs_modifier(modifier)) 2516 return true; 2517 fallthrough; 2518 case DRM_FORMAT_RGB565: 2519 case DRM_FORMAT_XRGB2101010: 2520 case DRM_FORMAT_XBGR2101010: 2521 case DRM_FORMAT_ARGB2101010: 2522 case DRM_FORMAT_ABGR2101010: 2523 case DRM_FORMAT_YUYV: 2524 case DRM_FORMAT_YVYU: 2525 case DRM_FORMAT_UYVY: 2526 case DRM_FORMAT_VYUY: 2527 case DRM_FORMAT_NV12: 2528 case DRM_FORMAT_XYUV8888: 2529 case DRM_FORMAT_P010: 2530 case DRM_FORMAT_P012: 2531 case DRM_FORMAT_P016: 2532 case DRM_FORMAT_XVYU2101010: 2533 if (modifier == I915_FORMAT_MOD_Yf_TILED) 2534 return true; 2535 fallthrough; 2536 case DRM_FORMAT_C8: 2537 case DRM_FORMAT_XBGR16161616F: 2538 case DRM_FORMAT_ABGR16161616F: 2539 case DRM_FORMAT_XRGB16161616F: 2540 case DRM_FORMAT_ARGB16161616F: 2541 case DRM_FORMAT_Y210: 2542 case DRM_FORMAT_Y212: 2543 case DRM_FORMAT_Y216: 2544 case DRM_FORMAT_XVYU12_16161616: 2545 case DRM_FORMAT_XVYU16161616: 2546 if (modifier == DRM_FORMAT_MOD_LINEAR || 2547 modifier == I915_FORMAT_MOD_X_TILED || 2548 modifier == I915_FORMAT_MOD_Y_TILED) 2549 return true; 2550 fallthrough; 2551 default: 2552 return false; 2553 } 2554 } 2555 2556 static bool icl_plane_format_mod_supported(struct drm_plane *_plane, 2557 u32 format, u64 modifier) 2558 { 2559 struct intel_plane *plane = to_intel_plane(_plane); 2560 2561 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2562 return false; 2563 2564 switch (format) { 2565 case DRM_FORMAT_XRGB8888: 2566 case DRM_FORMAT_XBGR8888: 2567 case DRM_FORMAT_ARGB8888: 2568 case DRM_FORMAT_ABGR8888: 2569 case DRM_FORMAT_XRGB2101010: 2570 case DRM_FORMAT_XBGR2101010: 2571 case DRM_FORMAT_ARGB2101010: 2572 case DRM_FORMAT_ABGR2101010: 2573 if (intel_fb_is_ccs_modifier(modifier)) 2574 return true; 2575 fallthrough; 2576 case DRM_FORMAT_RGB565: 2577 case DRM_FORMAT_YUYV: 2578 case DRM_FORMAT_YVYU: 2579 case DRM_FORMAT_UYVY: 2580 case DRM_FORMAT_VYUY: 2581 case DRM_FORMAT_NV12: 2582 case DRM_FORMAT_XYUV8888: 2583 case DRM_FORMAT_P010: 2584 case DRM_FORMAT_P012: 2585 case DRM_FORMAT_P016: 2586 case DRM_FORMAT_XVYU2101010: 2587 if (modifier == I915_FORMAT_MOD_Yf_TILED) 2588 return true; 2589 fallthrough; 2590 case DRM_FORMAT_C8: 2591 case DRM_FORMAT_XBGR16161616F: 2592 case DRM_FORMAT_ABGR16161616F: 2593 case DRM_FORMAT_XRGB16161616F: 2594 case DRM_FORMAT_ARGB16161616F: 2595 case DRM_FORMAT_Y210: 2596 case DRM_FORMAT_Y212: 2597 case DRM_FORMAT_Y216: 2598 case DRM_FORMAT_XVYU12_16161616: 2599 case DRM_FORMAT_XVYU16161616: 2600 if (modifier == DRM_FORMAT_MOD_LINEAR || 2601 modifier == I915_FORMAT_MOD_X_TILED || 2602 modifier == I915_FORMAT_MOD_Y_TILED) 2603 return true; 2604 fallthrough; 2605 default: 2606 return false; 2607 } 2608 } 2609 2610 static bool tgl_plane_format_mod_supported(struct drm_plane *_plane, 2611 u32 format, u64 modifier) 2612 { 2613 struct intel_plane *plane = to_intel_plane(_plane); 2614 2615 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2616 return false; 2617 2618 switch (format) { 2619 case DRM_FORMAT_XRGB8888: 2620 case DRM_FORMAT_XBGR8888: 2621 case DRM_FORMAT_ARGB8888: 2622 case DRM_FORMAT_ABGR8888: 2623 case DRM_FORMAT_XRGB2101010: 2624 case DRM_FORMAT_XBGR2101010: 2625 case DRM_FORMAT_ARGB2101010: 2626 case DRM_FORMAT_ABGR2101010: 2627 case DRM_FORMAT_XBGR16161616F: 2628 case DRM_FORMAT_ABGR16161616F: 2629 case DRM_FORMAT_XRGB16161616F: 2630 case DRM_FORMAT_ARGB16161616F: 2631 if (intel_fb_is_ccs_modifier(modifier)) 2632 return true; 2633 fallthrough; 2634 case DRM_FORMAT_YUYV: 2635 case DRM_FORMAT_YVYU: 2636 case DRM_FORMAT_UYVY: 2637 case DRM_FORMAT_VYUY: 2638 case DRM_FORMAT_NV12: 2639 case DRM_FORMAT_XYUV8888: 2640 case DRM_FORMAT_P010: 2641 case DRM_FORMAT_P012: 2642 case DRM_FORMAT_P016: 2643 if (intel_fb_is_mc_ccs_modifier(modifier)) 2644 return true; 2645 fallthrough; 2646 case DRM_FORMAT_RGB565: 2647 case DRM_FORMAT_XVYU2101010: 2648 case DRM_FORMAT_C8: 2649 case DRM_FORMAT_Y210: 2650 case DRM_FORMAT_Y212: 2651 case DRM_FORMAT_Y216: 2652 case DRM_FORMAT_XVYU12_16161616: 2653 case DRM_FORMAT_XVYU16161616: 2654 if (!intel_fb_is_ccs_modifier(modifier)) 2655 return true; 2656 fallthrough; 2657 default: 2658 return false; 2659 } 2660 } 2661 2662 static const struct drm_plane_funcs skl_plane_funcs = { 2663 .update_plane = drm_atomic_helper_update_plane, 2664 .disable_plane = drm_atomic_helper_disable_plane, 2665 .destroy = intel_plane_destroy, 2666 .atomic_duplicate_state = intel_plane_duplicate_state, 2667 .atomic_destroy_state = intel_plane_destroy_state, 2668 .format_mod_supported = skl_plane_format_mod_supported, 2669 }; 2670 2671 static const struct drm_plane_funcs icl_plane_funcs = { 2672 .update_plane = drm_atomic_helper_update_plane, 2673 .disable_plane = drm_atomic_helper_disable_plane, 2674 .destroy = intel_plane_destroy, 2675 .atomic_duplicate_state = intel_plane_duplicate_state, 2676 .atomic_destroy_state = intel_plane_destroy_state, 2677 .format_mod_supported = icl_plane_format_mod_supported, 2678 }; 2679 2680 static const struct drm_plane_funcs tgl_plane_funcs = { 2681 .update_plane = drm_atomic_helper_update_plane, 2682 .disable_plane = drm_atomic_helper_disable_plane, 2683 .destroy = intel_plane_destroy, 2684 .atomic_duplicate_state = intel_plane_duplicate_state, 2685 .atomic_destroy_state = intel_plane_destroy_state, 2686 .format_mod_supported = tgl_plane_format_mod_supported, 2687 }; 2688 2689 static void 2690 skl_plane_enable_flip_done(struct intel_plane *plane) 2691 { 2692 struct drm_i915_private *i915 = to_i915(plane->base.dev); 2693 enum pipe pipe = plane->pipe; 2694 2695 spin_lock_irq(&i915->irq_lock); 2696 bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 2697 spin_unlock_irq(&i915->irq_lock); 2698 } 2699 2700 static void 2701 skl_plane_disable_flip_done(struct intel_plane *plane) 2702 { 2703 struct drm_i915_private *i915 = to_i915(plane->base.dev); 2704 enum pipe pipe = plane->pipe; 2705 2706 spin_lock_irq(&i915->irq_lock); 2707 bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 2708 spin_unlock_irq(&i915->irq_lock); 2709 } 2710 2711 static bool skl_plane_has_rc_ccs(struct intel_display *display, 2712 enum pipe pipe, enum plane_id plane_id) 2713 { 2714 return pipe != PIPE_C && 2715 (plane_id == PLANE_1 || plane_id == PLANE_2); 2716 } 2717 2718 static u8 skl_plane_caps(struct intel_display *display, 2719 enum pipe pipe, enum plane_id plane_id) 2720 { 2721 u8 caps = INTEL_PLANE_CAP_TILING_X | 2722 INTEL_PLANE_CAP_TILING_Y | 2723 INTEL_PLANE_CAP_TILING_Yf; 2724 2725 if (skl_plane_has_rc_ccs(display, pipe, plane_id)) 2726 caps |= INTEL_PLANE_CAP_CCS_RC; 2727 2728 return caps; 2729 } 2730 2731 static bool glk_plane_has_rc_ccs(struct intel_display *display, 2732 enum pipe pipe) 2733 { 2734 return pipe != PIPE_C; 2735 } 2736 2737 static u8 glk_plane_caps(struct intel_display *display, 2738 enum pipe pipe, enum plane_id plane_id) 2739 { 2740 u8 caps = INTEL_PLANE_CAP_TILING_X | 2741 INTEL_PLANE_CAP_TILING_Y | 2742 INTEL_PLANE_CAP_TILING_Yf; 2743 2744 if (glk_plane_has_rc_ccs(display, pipe)) 2745 caps |= INTEL_PLANE_CAP_CCS_RC; 2746 2747 return caps; 2748 } 2749 2750 static u8 icl_plane_caps(struct intel_display *display, 2751 enum pipe pipe, enum plane_id plane_id) 2752 { 2753 return INTEL_PLANE_CAP_TILING_X | 2754 INTEL_PLANE_CAP_TILING_Y | 2755 INTEL_PLANE_CAP_TILING_Yf | 2756 INTEL_PLANE_CAP_CCS_RC; 2757 } 2758 2759 static bool tgl_plane_has_mc_ccs(struct intel_display *display, 2760 enum plane_id plane_id) 2761 { 2762 /* Wa_14010477008 */ 2763 if (display->platform.dg1 || display->platform.rocketlake || 2764 (display->platform.tigerlake && IS_DISPLAY_STEP(display, STEP_A0, STEP_D0))) 2765 return false; 2766 2767 return plane_id < PLANE_6; 2768 } 2769 2770 static u8 tgl_plane_caps(struct intel_display *display, 2771 enum pipe pipe, enum plane_id plane_id) 2772 { 2773 u8 caps = INTEL_PLANE_CAP_TILING_X | 2774 INTEL_PLANE_CAP_CCS_RC | 2775 INTEL_PLANE_CAP_CCS_RC_CC; 2776 2777 if (HAS_4TILE(display)) 2778 caps |= INTEL_PLANE_CAP_TILING_4; 2779 else 2780 caps |= INTEL_PLANE_CAP_TILING_Y; 2781 2782 if (tgl_plane_has_mc_ccs(display, plane_id)) 2783 caps |= INTEL_PLANE_CAP_CCS_MC; 2784 2785 if (DISPLAY_VER(display) >= 14 && display->platform.dgfx) 2786 caps |= INTEL_PLANE_CAP_NEED64K_PHYS; 2787 2788 return caps; 2789 } 2790 2791 struct intel_plane * 2792 skl_universal_plane_create(struct intel_display *display, 2793 enum pipe pipe, enum plane_id plane_id) 2794 { 2795 const struct drm_plane_funcs *plane_funcs; 2796 struct intel_plane *plane; 2797 enum drm_plane_type plane_type; 2798 unsigned int supported_rotations; 2799 unsigned int supported_csc; 2800 const u64 *modifiers; 2801 const u32 *formats; 2802 int num_formats; 2803 int ret; 2804 u8 caps; 2805 2806 plane = intel_plane_alloc(); 2807 if (IS_ERR(plane)) 2808 return plane; 2809 2810 plane->pipe = pipe; 2811 plane->id = plane_id; 2812 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id); 2813 2814 intel_fbc_add_plane(skl_plane_fbc(display, pipe, plane_id), plane); 2815 2816 if (DISPLAY_VER(display) >= 30) { 2817 plane->max_width = xe3_plane_max_width; 2818 plane->max_height = icl_plane_max_height; 2819 plane->min_cdclk = icl_plane_min_cdclk; 2820 } else if (DISPLAY_VER(display) >= 11) { 2821 plane->min_width = icl_plane_min_width; 2822 if (icl_is_hdr_plane(display, plane_id)) 2823 plane->max_width = icl_hdr_plane_max_width; 2824 else 2825 plane->max_width = icl_sdr_plane_max_width; 2826 plane->max_height = icl_plane_max_height; 2827 plane->min_cdclk = icl_plane_min_cdclk; 2828 } else if (DISPLAY_VER(display) >= 10) { 2829 plane->max_width = glk_plane_max_width; 2830 plane->max_height = skl_plane_max_height; 2831 plane->min_cdclk = glk_plane_min_cdclk; 2832 } else { 2833 plane->max_width = skl_plane_max_width; 2834 plane->max_height = skl_plane_max_height; 2835 plane->min_cdclk = skl_plane_min_cdclk; 2836 } 2837 2838 if (DISPLAY_VER(display) >= 13) 2839 plane->max_stride = adl_plane_max_stride; 2840 else 2841 plane->max_stride = skl_plane_max_stride; 2842 2843 if (DISPLAY_VER(display) >= 12) 2844 plane->min_alignment = tgl_plane_min_alignment; 2845 else 2846 plane->min_alignment = skl_plane_min_alignment; 2847 2848 if (intel_scanout_needs_vtd_wa(display)) 2849 plane->vtd_guard = DISPLAY_VER(display) >= 10 ? 168 : 136; 2850 2851 if (DISPLAY_VER(display) >= 11) { 2852 plane->update_noarm = icl_plane_update_noarm; 2853 plane->update_arm = icl_plane_update_arm; 2854 plane->disable_arm = icl_plane_disable_arm; 2855 } else { 2856 plane->update_noarm = skl_plane_update_noarm; 2857 plane->update_arm = skl_plane_update_arm; 2858 plane->disable_arm = skl_plane_disable_arm; 2859 } 2860 plane->capture_error = skl_plane_capture_error; 2861 plane->get_hw_state = skl_plane_get_hw_state; 2862 plane->check_plane = skl_plane_check; 2863 2864 if (HAS_ASYNC_FLIPS(display) && plane_id == PLANE_1) { 2865 plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(display, 9, 10); 2866 plane->async_flip = skl_plane_async_flip; 2867 plane->enable_flip_done = skl_plane_enable_flip_done; 2868 plane->disable_flip_done = skl_plane_disable_flip_done; 2869 2870 if (DISPLAY_VER(display) >= 12) 2871 plane->can_async_flip = tgl_plane_can_async_flip; 2872 else if (DISPLAY_VER(display) == 11) 2873 plane->can_async_flip = icl_plane_can_async_flip; 2874 else 2875 plane->can_async_flip = skl_plane_can_async_flip; 2876 } 2877 2878 if (DISPLAY_VER(display) >= 11) 2879 formats = icl_get_plane_formats(display, pipe, 2880 plane_id, &num_formats); 2881 else if (DISPLAY_VER(display) >= 10) 2882 formats = glk_get_plane_formats(display, pipe, 2883 plane_id, &num_formats); 2884 else 2885 formats = skl_get_plane_formats(display, pipe, 2886 plane_id, &num_formats); 2887 2888 if (DISPLAY_VER(display) >= 12) 2889 plane_funcs = &tgl_plane_funcs; 2890 else if (DISPLAY_VER(display) == 11) 2891 plane_funcs = &icl_plane_funcs; 2892 else 2893 plane_funcs = &skl_plane_funcs; 2894 2895 if (plane_id == PLANE_1) 2896 plane_type = DRM_PLANE_TYPE_PRIMARY; 2897 else 2898 plane_type = DRM_PLANE_TYPE_OVERLAY; 2899 2900 if (DISPLAY_VER(display) >= 12) 2901 caps = tgl_plane_caps(display, pipe, plane_id); 2902 else if (DISPLAY_VER(display) == 11) 2903 caps = icl_plane_caps(display, pipe, plane_id); 2904 else if (DISPLAY_VER(display) == 10) 2905 caps = glk_plane_caps(display, pipe, plane_id); 2906 else 2907 caps = skl_plane_caps(display, pipe, plane_id); 2908 2909 /* FIXME: xe has problems with AUX */ 2910 if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(to_i915(display->drm))) 2911 caps &= ~(INTEL_PLANE_CAP_CCS_RC | 2912 INTEL_PLANE_CAP_CCS_RC_CC | 2913 INTEL_PLANE_CAP_CCS_MC); 2914 2915 modifiers = intel_fb_plane_get_modifiers(display, caps); 2916 2917 ret = drm_universal_plane_init(display->drm, &plane->base, 2918 0, plane_funcs, 2919 formats, num_formats, modifiers, 2920 plane_type, 2921 "plane %d%c", plane_id + 1, 2922 pipe_name(pipe)); 2923 2924 kfree(modifiers); 2925 2926 if (ret) 2927 goto fail; 2928 2929 if (DISPLAY_VER(display) >= 13) 2930 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; 2931 else 2932 supported_rotations = 2933 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | 2934 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; 2935 2936 if (DISPLAY_VER(display) >= 11) 2937 supported_rotations |= DRM_MODE_REFLECT_X; 2938 2939 drm_plane_create_rotation_property(&plane->base, 2940 DRM_MODE_ROTATE_0, 2941 supported_rotations); 2942 2943 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709); 2944 2945 if (DISPLAY_VER(display) >= 10) 2946 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020); 2947 2948 drm_plane_create_color_properties(&plane->base, 2949 supported_csc, 2950 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | 2951 BIT(DRM_COLOR_YCBCR_FULL_RANGE), 2952 DRM_COLOR_YCBCR_BT709, 2953 DRM_COLOR_YCBCR_LIMITED_RANGE); 2954 2955 drm_plane_create_alpha_property(&plane->base); 2956 drm_plane_create_blend_mode_property(&plane->base, 2957 BIT(DRM_MODE_BLEND_PIXEL_NONE) | 2958 BIT(DRM_MODE_BLEND_PREMULTI) | 2959 BIT(DRM_MODE_BLEND_COVERAGE)); 2960 2961 drm_plane_create_zpos_immutable_property(&plane->base, plane_id); 2962 2963 if (DISPLAY_VER(display) >= 12) 2964 drm_plane_enable_fb_damage_clips(&plane->base); 2965 2966 if (DISPLAY_VER(display) >= 11) 2967 drm_plane_create_scaling_filter_property(&plane->base, 2968 BIT(DRM_SCALING_FILTER_DEFAULT) | 2969 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); 2970 2971 intel_plane_helper_add(plane); 2972 2973 return plane; 2974 2975 fail: 2976 intel_plane_free(plane); 2977 2978 return ERR_PTR(ret); 2979 } 2980 2981 void 2982 skl_get_initial_plane_config(struct intel_crtc *crtc, 2983 struct intel_initial_plane_config *plane_config) 2984 { 2985 struct intel_display *display = to_intel_display(crtc); 2986 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); 2987 struct intel_plane *plane = to_intel_plane(crtc->base.primary); 2988 enum plane_id plane_id = plane->id; 2989 enum pipe pipe; 2990 u32 val, base, offset, stride_mult, tiling, alpha; 2991 int fourcc, pixel_format; 2992 unsigned int aligned_height; 2993 struct drm_framebuffer *fb; 2994 struct intel_framebuffer *intel_fb; 2995 static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4); 2996 2997 if (!plane->get_hw_state(plane, &pipe)) 2998 return; 2999 3000 drm_WARN_ON(display->drm, pipe != crtc->pipe); 3001 3002 if (crtc_state->joiner_pipes) { 3003 drm_dbg_kms(display->drm, 3004 "[CRTC:%d:%s] Unsupported joiner configuration for initial FB\n", 3005 crtc->base.base.id, crtc->base.name); 3006 return; 3007 } 3008 3009 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); 3010 if (!intel_fb) { 3011 drm_dbg_kms(display->drm, "failed to alloc fb\n"); 3012 return; 3013 } 3014 3015 fb = &intel_fb->base; 3016 3017 fb->dev = display->drm; 3018 3019 val = intel_de_read(display, PLANE_CTL(pipe, plane_id)); 3020 3021 if (DISPLAY_VER(display) >= 11) 3022 pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL; 3023 else 3024 pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL; 3025 3026 if (DISPLAY_VER(display) >= 10) { 3027 u32 color_ctl; 3028 3029 color_ctl = intel_de_read(display, PLANE_COLOR_CTL(pipe, plane_id)); 3030 alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl); 3031 } else { 3032 alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val); 3033 } 3034 3035 fourcc = skl_format_to_fourcc(pixel_format, 3036 val & PLANE_CTL_ORDER_RGBX, alpha); 3037 fb->format = drm_format_info(fourcc); 3038 3039 tiling = val & PLANE_CTL_TILED_MASK; 3040 switch (tiling) { 3041 case PLANE_CTL_TILED_LINEAR: 3042 fb->modifier = DRM_FORMAT_MOD_LINEAR; 3043 break; 3044 case PLANE_CTL_TILED_X: 3045 plane_config->tiling = I915_TILING_X; 3046 fb->modifier = I915_FORMAT_MOD_X_TILED; 3047 break; 3048 case PLANE_CTL_TILED_Y: 3049 plane_config->tiling = I915_TILING_Y; 3050 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3051 if (DISPLAY_VER(display) >= 14) 3052 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS; 3053 else if (DISPLAY_VER(display) >= 12) 3054 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS; 3055 else 3056 fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS; 3057 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) 3058 if (DISPLAY_VER(display) >= 14) 3059 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS; 3060 else 3061 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS; 3062 else 3063 fb->modifier = I915_FORMAT_MOD_Y_TILED; 3064 break; 3065 case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */ 3066 if (HAS_4TILE(display)) { 3067 u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | 3068 PLANE_CTL_CLEAR_COLOR_DISABLE; 3069 3070 if ((val & rc_mask) == rc_mask) 3071 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS; 3072 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) 3073 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS; 3074 else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3075 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC; 3076 else 3077 fb->modifier = I915_FORMAT_MOD_4_TILED; 3078 } else { 3079 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3080 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; 3081 else 3082 fb->modifier = I915_FORMAT_MOD_Yf_TILED; 3083 } 3084 break; 3085 default: 3086 MISSING_CASE(tiling); 3087 goto error; 3088 } 3089 3090 if (!display->params.enable_dpt && 3091 intel_fb_modifier_uses_dpt(display, fb->modifier)) { 3092 drm_dbg_kms(display->drm, "DPT disabled, skipping initial FB\n"); 3093 goto error; 3094 } 3095 3096 /* 3097 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr 3098 * while i915 HW rotation is clockwise, that's why this swapping. 3099 */ 3100 switch (val & PLANE_CTL_ROTATE_MASK) { 3101 case PLANE_CTL_ROTATE_0: 3102 plane_config->rotation = DRM_MODE_ROTATE_0; 3103 break; 3104 case PLANE_CTL_ROTATE_90: 3105 plane_config->rotation = DRM_MODE_ROTATE_270; 3106 break; 3107 case PLANE_CTL_ROTATE_180: 3108 plane_config->rotation = DRM_MODE_ROTATE_180; 3109 break; 3110 case PLANE_CTL_ROTATE_270: 3111 plane_config->rotation = DRM_MODE_ROTATE_90; 3112 break; 3113 } 3114 3115 if (DISPLAY_VER(display) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL) 3116 plane_config->rotation |= DRM_MODE_REFLECT_X; 3117 3118 /* 90/270 degree rotation would require extra work */ 3119 if (drm_rotation_90_or_270(plane_config->rotation)) 3120 goto error; 3121 3122 base = intel_de_read(display, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK; 3123 plane_config->base = base; 3124 3125 offset = intel_de_read(display, PLANE_OFFSET(pipe, plane_id)); 3126 drm_WARN_ON(display->drm, offset != 0); 3127 3128 val = intel_de_read(display, PLANE_SIZE(pipe, plane_id)); 3129 fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1; 3130 fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1; 3131 3132 val = intel_de_read(display, PLANE_STRIDE(pipe, plane_id)); 3133 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0); 3134 3135 fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult; 3136 3137 aligned_height = intel_fb_align_height(fb, 0, fb->height); 3138 3139 plane_config->size = fb->pitches[0] * aligned_height; 3140 3141 drm_dbg_kms(display->drm, 3142 "[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 3143 crtc->base.base.id, crtc->base.name, 3144 plane->base.base.id, plane->base.name, 3145 fb->width, fb->height, fb->format->cpp[0] * 8, 3146 base, fb->pitches[0], plane_config->size); 3147 3148 plane_config->fb = intel_fb; 3149 return; 3150 3151 error: 3152 kfree(intel_fb); 3153 } 3154 3155 bool skl_fixup_initial_plane_config(struct intel_crtc *crtc, 3156 const struct intel_initial_plane_config *plane_config) 3157 { 3158 struct intel_display *display = to_intel_display(crtc); 3159 struct intel_plane *plane = to_intel_plane(crtc->base.primary); 3160 const struct intel_plane_state *plane_state = 3161 to_intel_plane_state(plane->base.state); 3162 enum plane_id plane_id = plane->id; 3163 enum pipe pipe = crtc->pipe; 3164 u32 base; 3165 3166 if (!plane_state->uapi.visible) 3167 return false; 3168 3169 base = intel_plane_ggtt_offset(plane_state); 3170 3171 /* 3172 * We may have moved the surface to a different 3173 * part of ggtt, make the plane aware of that. 3174 */ 3175 if (plane_config->base == base) 3176 return false; 3177 3178 intel_de_write(display, PLANE_SURF(pipe, plane_id), base); 3179 3180 return true; 3181 } 3182