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