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 13 #include "i915_drv.h" 14 #include "intel_atomic_plane.h" 15 #include "intel_bo.h" 16 #include "intel_de.h" 17 #include "intel_display_irq.h" 18 #include "intel_display_regs.h" 19 #include "intel_display_types.h" 20 #include "intel_dpt.h" 21 #include "intel_fb.h" 22 #include "intel_fbc.h" 23 #include "intel_frontbuffer.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_crtc_state *crtc_state, 1171 const struct intel_plane_state *plane_state) 1172 { 1173 struct intel_display *display = to_intel_display(plane_state); 1174 const struct drm_framebuffer *fb = plane_state->hw.fb; 1175 unsigned int rotation = plane_state->hw.rotation; 1176 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1177 u32 plane_ctl; 1178 1179 plane_ctl = PLANE_CTL_ENABLE; 1180 1181 if (DISPLAY_VER(display) < 10) { 1182 plane_ctl |= skl_plane_ctl_alpha(plane_state); 1183 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; 1184 1185 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) 1186 plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709; 1187 1188 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 1189 plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE; 1190 } 1191 1192 plane_ctl |= skl_plane_ctl_format(fb->format->format); 1193 plane_ctl |= skl_plane_ctl_tiling(fb->modifier); 1194 plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK); 1195 1196 if (DISPLAY_VER(display) >= 11) 1197 plane_ctl |= icl_plane_ctl_flip(rotation & 1198 DRM_MODE_REFLECT_MASK); 1199 1200 if (key->flags & I915_SET_COLORKEY_DESTINATION) 1201 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; 1202 else if (key->flags & I915_SET_COLORKEY_SOURCE) 1203 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; 1204 1205 /* Wa_22012358565:adl-p */ 1206 if (DISPLAY_VER(display) == 13) 1207 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state); 1208 1209 return plane_ctl; 1210 } 1211 1212 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state) 1213 { 1214 struct intel_display *display = to_intel_display(crtc_state); 1215 u32 plane_color_ctl = 0; 1216 1217 if (DISPLAY_VER(display) >= 11) 1218 return plane_color_ctl; 1219 1220 if (crtc_state->gamma_enable) 1221 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE; 1222 1223 if (crtc_state->csc_enable) 1224 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE; 1225 1226 return plane_color_ctl; 1227 } 1228 1229 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, 1230 const struct intel_plane_state *plane_state) 1231 { 1232 struct intel_display *display = to_intel_display(plane_state); 1233 const struct drm_framebuffer *fb = plane_state->hw.fb; 1234 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1235 u32 plane_color_ctl = 0; 1236 1237 plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; 1238 plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); 1239 1240 if (fb->format->is_yuv && !icl_is_hdr_plane(display, plane->id)) { 1241 switch (plane_state->hw.color_encoding) { 1242 case DRM_COLOR_YCBCR_BT709: 1243 plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; 1244 break; 1245 case DRM_COLOR_YCBCR_BT2020: 1246 plane_color_ctl |= 1247 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; 1248 break; 1249 default: 1250 plane_color_ctl |= 1251 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; 1252 } 1253 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 1254 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; 1255 } else if (fb->format->is_yuv) { 1256 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; 1257 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 1258 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; 1259 } 1260 1261 if (plane_state->force_black) 1262 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; 1263 1264 return plane_color_ctl; 1265 } 1266 1267 static u32 skl_surf_address(const struct intel_plane_state *plane_state, 1268 int color_plane) 1269 { 1270 struct intel_display *display = to_intel_display(plane_state); 1271 const struct drm_framebuffer *fb = plane_state->hw.fb; 1272 u32 offset = plane_state->view.color_plane[color_plane].offset; 1273 1274 if (intel_fb_uses_dpt(fb)) { 1275 /* 1276 * The DPT object contains only one vma, so the VMA's offset 1277 * within the DPT is always 0. 1278 */ 1279 drm_WARN_ON(display->drm, plane_state->dpt_vma && 1280 intel_dpt_offset(plane_state->dpt_vma)); 1281 drm_WARN_ON(display->drm, offset & 0x1fffff); 1282 return offset >> 9; 1283 } else { 1284 drm_WARN_ON(display->drm, offset & 0xfff); 1285 return offset; 1286 } 1287 } 1288 1289 static u32 skl_plane_surf(const struct intel_plane_state *plane_state, 1290 int color_plane) 1291 { 1292 u32 plane_surf; 1293 1294 plane_surf = intel_plane_ggtt_offset(plane_state) + 1295 skl_surf_address(plane_state, color_plane); 1296 1297 if (plane_state->decrypt) 1298 plane_surf |= PLANE_SURF_DECRYPT; 1299 1300 return plane_surf; 1301 } 1302 1303 u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state, 1304 int color_plane) 1305 { 1306 struct intel_display *display = to_intel_display(plane_state); 1307 const struct drm_framebuffer *fb = plane_state->hw.fb; 1308 int aux_plane = skl_main_to_aux_plane(fb, color_plane); 1309 u32 aux_dist; 1310 1311 if (!aux_plane) 1312 return 0; 1313 1314 aux_dist = skl_surf_address(plane_state, aux_plane) - 1315 skl_surf_address(plane_state, color_plane); 1316 1317 if (DISPLAY_VER(display) < 12) 1318 aux_dist |= PLANE_AUX_STRIDE(skl_plane_stride(plane_state, aux_plane)); 1319 1320 return aux_dist; 1321 } 1322 1323 static u32 skl_plane_keyval(const struct intel_plane_state *plane_state) 1324 { 1325 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1326 1327 return key->min_value; 1328 } 1329 1330 static u32 skl_plane_keymax(const struct intel_plane_state *plane_state) 1331 { 1332 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1333 u8 alpha = plane_state->hw.alpha >> 8; 1334 1335 return (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); 1336 } 1337 1338 static u32 skl_plane_keymsk(const struct intel_plane_state *plane_state) 1339 { 1340 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 1341 u8 alpha = plane_state->hw.alpha >> 8; 1342 u32 keymsk; 1343 1344 keymsk = key->channel_mask & 0x7ffffff; 1345 if (alpha < 0xff) 1346 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; 1347 1348 return keymsk; 1349 } 1350 1351 static void icl_plane_csc_load_black(struct intel_dsb *dsb, 1352 struct intel_plane *plane, 1353 const struct intel_crtc_state *crtc_state) 1354 { 1355 struct intel_display *display = to_intel_display(plane); 1356 enum plane_id plane_id = plane->id; 1357 enum pipe pipe = plane->pipe; 1358 1359 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 0), 0); 1360 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 1), 0); 1361 1362 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 2), 0); 1363 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 3), 0); 1364 1365 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 4), 0); 1366 intel_de_write_dsb(display, dsb, PLANE_CSC_COEFF(pipe, plane_id, 5), 0); 1367 1368 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0); 1369 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0); 1370 intel_de_write_dsb(display, dsb, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0); 1371 1372 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0); 1373 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0); 1374 intel_de_write_dsb(display, dsb, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0); 1375 } 1376 1377 static int icl_plane_color_plane(const struct intel_plane_state *plane_state) 1378 { 1379 if (plane_state->planar_linked_plane && !plane_state->is_y_plane) 1380 return 1; 1381 else 1382 return 0; 1383 } 1384 1385 static void 1386 skl_plane_update_noarm(struct intel_dsb *dsb, 1387 struct intel_plane *plane, 1388 const struct intel_crtc_state *crtc_state, 1389 const struct intel_plane_state *plane_state) 1390 { 1391 struct intel_display *display = to_intel_display(plane); 1392 enum plane_id plane_id = plane->id; 1393 enum pipe pipe = plane->pipe; 1394 u32 stride = skl_plane_stride(plane_state, 0); 1395 int crtc_x = plane_state->uapi.dst.x1; 1396 int crtc_y = plane_state->uapi.dst.y1; 1397 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1398 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 1399 1400 /* The scaler will handle the output position */ 1401 if (plane_state->scaler_id >= 0) { 1402 crtc_x = 0; 1403 crtc_y = 0; 1404 } 1405 1406 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id), 1407 PLANE_STRIDE_(stride)); 1408 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id), 1409 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x)); 1410 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id), 1411 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); 1412 1413 skl_write_plane_wm(dsb, plane, crtc_state); 1414 } 1415 1416 static void 1417 skl_plane_update_arm(struct intel_dsb *dsb, 1418 struct intel_plane *plane, 1419 const struct intel_crtc_state *crtc_state, 1420 const struct intel_plane_state *plane_state) 1421 { 1422 struct intel_display *display = to_intel_display(plane); 1423 enum plane_id plane_id = plane->id; 1424 enum pipe pipe = plane->pipe; 1425 u32 x = plane_state->view.color_plane[0].x; 1426 u32 y = plane_state->view.color_plane[0].y; 1427 u32 plane_ctl, plane_color_ctl = 0; 1428 1429 plane_ctl = plane_state->ctl | 1430 skl_plane_ctl_crtc(crtc_state); 1431 1432 /* see intel_plane_atomic_calc_changes() */ 1433 if (plane->need_async_flip_toggle_wa && 1434 crtc_state->async_flip_planes & BIT(plane->id)) 1435 plane_ctl |= PLANE_CTL_ASYNC_FLIP; 1436 1437 if (DISPLAY_VER(display) >= 10) 1438 plane_color_ctl = plane_state->color_ctl | 1439 glk_plane_color_ctl_crtc(crtc_state); 1440 1441 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id), 1442 skl_plane_keyval(plane_state)); 1443 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id), 1444 skl_plane_keymsk(plane_state)); 1445 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id), 1446 skl_plane_keymax(plane_state)); 1447 1448 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id), 1449 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); 1450 1451 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id), 1452 skl_plane_aux_dist(plane_state, 0)); 1453 1454 intel_de_write_dsb(display, dsb, PLANE_AUX_OFFSET(pipe, plane_id), 1455 PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) | 1456 PLANE_OFFSET_X(plane_state->view.color_plane[1].x)); 1457 1458 if (DISPLAY_VER(display) >= 10) 1459 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id), 1460 plane_color_ctl); 1461 1462 /* 1463 * Enable the scaler before the plane so that we don't 1464 * get a catastrophic underrun even if the two operations 1465 * end up happening in two different frames. 1466 * 1467 * TODO: split into noarm+arm pair 1468 */ 1469 if (plane_state->scaler_id >= 0) 1470 skl_program_plane_scaler(dsb, plane, crtc_state, plane_state); 1471 1472 /* 1473 * The control register self-arms if the plane was previously 1474 * disabled. Try to make the plane enable atomic by writing 1475 * the control register just before the surface register. 1476 */ 1477 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 1478 plane_ctl); 1479 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 1480 skl_plane_surf(plane_state, 0)); 1481 } 1482 1483 static void icl_plane_update_sel_fetch_noarm(struct intel_dsb *dsb, 1484 struct intel_plane *plane, 1485 const struct intel_crtc_state *crtc_state, 1486 const struct intel_plane_state *plane_state, 1487 int color_plane) 1488 { 1489 struct intel_display *display = to_intel_display(plane); 1490 enum pipe pipe = plane->pipe; 1491 const struct drm_rect *clip; 1492 u32 val; 1493 int x, y; 1494 1495 if (!crtc_state->enable_psr2_sel_fetch) 1496 return; 1497 1498 clip = &plane_state->psr2_sel_fetch_area; 1499 1500 if (crtc_state->enable_psr2_su_region_et) 1501 y = max(0, plane_state->uapi.dst.y1 - crtc_state->psr2_su_area.y1); 1502 else 1503 y = (clip->y1 + plane_state->uapi.dst.y1); 1504 val = y << 16; 1505 val |= plane_state->uapi.dst.x1; 1506 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_POS(pipe, plane->id), val); 1507 1508 x = plane_state->view.color_plane[color_plane].x; 1509 1510 /* 1511 * From Bspec: UV surface Start Y Position = half of Y plane Y 1512 * start position. 1513 */ 1514 if (!color_plane) 1515 y = plane_state->view.color_plane[color_plane].y + clip->y1; 1516 else 1517 y = plane_state->view.color_plane[color_plane].y + clip->y1 / 2; 1518 1519 val = y << 16 | x; 1520 1521 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_OFFSET(pipe, plane->id), val); 1522 1523 /* Sizes are 0 based */ 1524 val = (drm_rect_height(clip) - 1) << 16; 1525 val |= (drm_rect_width(&plane_state->uapi.src) >> 16) - 1; 1526 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_SIZE(pipe, plane->id), val); 1527 } 1528 1529 static void 1530 icl_plane_update_noarm(struct intel_dsb *dsb, 1531 struct intel_plane *plane, 1532 const struct intel_crtc_state *crtc_state, 1533 const struct intel_plane_state *plane_state) 1534 { 1535 struct intel_display *display = to_intel_display(plane); 1536 enum plane_id plane_id = plane->id; 1537 enum pipe pipe = plane->pipe; 1538 int color_plane = icl_plane_color_plane(plane_state); 1539 u32 stride = skl_plane_stride(plane_state, color_plane); 1540 const struct drm_framebuffer *fb = plane_state->hw.fb; 1541 int crtc_x = plane_state->uapi.dst.x1; 1542 int crtc_y = plane_state->uapi.dst.y1; 1543 int x = plane_state->view.color_plane[color_plane].x; 1544 int y = plane_state->view.color_plane[color_plane].y; 1545 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1546 int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 1547 u32 plane_color_ctl; 1548 1549 plane_color_ctl = plane_state->color_ctl | 1550 glk_plane_color_ctl_crtc(crtc_state); 1551 1552 /* The scaler will handle the output position */ 1553 if (plane_state->scaler_id >= 0) { 1554 crtc_x = 0; 1555 crtc_y = 0; 1556 } 1557 1558 intel_de_write_dsb(display, dsb, PLANE_STRIDE(pipe, plane_id), 1559 PLANE_STRIDE_(stride)); 1560 intel_de_write_dsb(display, dsb, PLANE_POS(pipe, plane_id), 1561 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x)); 1562 intel_de_write_dsb(display, dsb, PLANE_SIZE(pipe, plane_id), 1563 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); 1564 1565 intel_de_write_dsb(display, dsb, PLANE_KEYVAL(pipe, plane_id), 1566 skl_plane_keyval(plane_state)); 1567 intel_de_write_dsb(display, dsb, PLANE_KEYMSK(pipe, plane_id), 1568 skl_plane_keymsk(plane_state)); 1569 intel_de_write_dsb(display, dsb, PLANE_KEYMAX(pipe, plane_id), 1570 skl_plane_keymax(plane_state)); 1571 1572 intel_de_write_dsb(display, dsb, PLANE_OFFSET(pipe, plane_id), 1573 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); 1574 1575 if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) { 1576 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 0), 1577 lower_32_bits(plane_state->ccval)); 1578 intel_de_write_dsb(display, dsb, PLANE_CC_VAL(pipe, plane_id, 1), 1579 upper_32_bits(plane_state->ccval)); 1580 } 1581 1582 /* FLAT CCS doesn't need to program AUX_DIST */ 1583 if (!HAS_FLAT_CCS(to_i915(display->drm)) && DISPLAY_VER(display) < 20) 1584 intel_de_write_dsb(display, dsb, PLANE_AUX_DIST(pipe, plane_id), 1585 skl_plane_aux_dist(plane_state, color_plane)); 1586 1587 if (icl_is_hdr_plane(display, plane_id)) 1588 intel_de_write_dsb(display, dsb, PLANE_CUS_CTL(pipe, plane_id), 1589 plane_state->cus_ctl); 1590 1591 intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id), 1592 plane_color_ctl); 1593 1594 if (fb->format->is_yuv && icl_is_hdr_plane(display, plane_id)) 1595 icl_program_input_csc(dsb, plane, plane_state); 1596 1597 skl_write_plane_wm(dsb, plane, crtc_state); 1598 1599 /* 1600 * FIXME: pxp session invalidation can hit any time even at time of commit 1601 * or after the commit, display content will be garbage. 1602 */ 1603 if (plane_state->force_black) 1604 icl_plane_csc_load_black(dsb, plane, crtc_state); 1605 1606 icl_plane_update_sel_fetch_noarm(dsb, plane, crtc_state, plane_state, color_plane); 1607 } 1608 1609 static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb, 1610 struct intel_plane *plane, 1611 const struct intel_crtc_state *crtc_state, 1612 const struct intel_plane_state *plane_state) 1613 { 1614 struct intel_display *display = to_intel_display(plane); 1615 enum pipe pipe = plane->pipe; 1616 1617 if (!crtc_state->enable_psr2_sel_fetch) 1618 return; 1619 1620 if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) 1621 intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 1622 SEL_FETCH_PLANE_CTL_ENABLE); 1623 else 1624 icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); 1625 } 1626 1627 static void 1628 icl_plane_update_arm(struct intel_dsb *dsb, 1629 struct intel_plane *plane, 1630 const struct intel_crtc_state *crtc_state, 1631 const struct intel_plane_state *plane_state) 1632 { 1633 struct intel_display *display = to_intel_display(plane); 1634 enum plane_id plane_id = plane->id; 1635 enum pipe pipe = plane->pipe; 1636 int color_plane = icl_plane_color_plane(plane_state); 1637 u32 plane_ctl; 1638 1639 plane_ctl = plane_state->ctl | 1640 skl_plane_ctl_crtc(crtc_state); 1641 1642 /* 1643 * Enable the scaler before the plane so that we don't 1644 * get a catastrophic underrun even if the two operations 1645 * end up happening in two different frames. 1646 * 1647 * TODO: split into noarm+arm pair 1648 */ 1649 if (plane_state->scaler_id >= 0) 1650 skl_program_plane_scaler(dsb, plane, crtc_state, plane_state); 1651 1652 icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state); 1653 1654 /* 1655 * The control register self-arms if the plane was previously 1656 * disabled. Try to make the plane enable atomic by writing 1657 * the control register just before the surface register. 1658 */ 1659 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 1660 plane_ctl); 1661 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 1662 skl_plane_surf(plane_state, color_plane)); 1663 } 1664 1665 static void skl_plane_capture_error(struct intel_crtc *crtc, 1666 struct intel_plane *plane, 1667 struct intel_plane_error *error) 1668 { 1669 struct intel_display *display = to_intel_display(plane); 1670 1671 error->ctl = intel_de_read(display, PLANE_CTL(crtc->pipe, plane->id)); 1672 error->surf = intel_de_read(display, PLANE_SURF(crtc->pipe, plane->id)); 1673 error->surflive = intel_de_read(display, PLANE_SURFLIVE(crtc->pipe, plane->id)); 1674 } 1675 1676 static void 1677 skl_plane_async_flip(struct intel_dsb *dsb, 1678 struct intel_plane *plane, 1679 const struct intel_crtc_state *crtc_state, 1680 const struct intel_plane_state *plane_state, 1681 bool async_flip) 1682 { 1683 struct intel_display *display = to_intel_display(plane); 1684 enum plane_id plane_id = plane->id; 1685 enum pipe pipe = plane->pipe; 1686 u32 plane_ctl = plane_state->ctl, plane_surf; 1687 1688 plane_ctl |= skl_plane_ctl_crtc(crtc_state); 1689 plane_surf = skl_plane_surf(plane_state, 0); 1690 1691 if (async_flip) { 1692 if (DISPLAY_VER(display) >= 30) 1693 plane_surf |= PLANE_SURF_ASYNC_UPDATE; 1694 else 1695 plane_ctl |= PLANE_CTL_ASYNC_FLIP; 1696 } 1697 1698 intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id), 1699 plane_ctl); 1700 intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id), 1701 plane_surf); 1702 } 1703 1704 static bool intel_format_is_p01x(u32 format) 1705 { 1706 switch (format) { 1707 case DRM_FORMAT_P010: 1708 case DRM_FORMAT_P012: 1709 case DRM_FORMAT_P016: 1710 return true; 1711 default: 1712 return false; 1713 } 1714 } 1715 1716 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, 1717 const struct intel_plane_state *plane_state) 1718 { 1719 struct intel_display *display = to_intel_display(plane_state); 1720 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1721 const struct drm_framebuffer *fb = plane_state->hw.fb; 1722 unsigned int rotation = plane_state->hw.rotation; 1723 1724 if (!fb) 1725 return 0; 1726 1727 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) && 1728 intel_fb_is_ccs_modifier(fb->modifier)) { 1729 drm_dbg_kms(display->drm, 1730 "[PLANE:%d:%s] RC support only with 0/180 degree rotation (%x)\n", 1731 plane->base.base.id, plane->base.name, rotation); 1732 return -EINVAL; 1733 } 1734 1735 if (rotation & DRM_MODE_REFLECT_X && 1736 fb->modifier == DRM_FORMAT_MOD_LINEAR) { 1737 drm_dbg_kms(display->drm, 1738 "[PLANE:%d:%s] horizontal flip is not supported with linear surface formats\n", 1739 plane->base.base.id, plane->base.name); 1740 return -EINVAL; 1741 } 1742 1743 /* 1744 * Display20 onward tile4 hflip is not supported 1745 */ 1746 if (rotation & DRM_MODE_REFLECT_X && 1747 intel_fb_is_tile4_modifier(fb->modifier) && 1748 DISPLAY_VER(display) >= 20) { 1749 drm_dbg_kms(display->drm, 1750 "[PLANE:%d:%s] horizontal flip is not supported with tile4 surface formats\n", 1751 plane->base.base.id, plane->base.name); 1752 return -EINVAL; 1753 } 1754 1755 if (drm_rotation_90_or_270(rotation)) { 1756 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) { 1757 drm_dbg_kms(display->drm, 1758 "[PLANE:%d:%s] Y/Yf tiling required for 90/270!\n", 1759 plane->base.base.id, plane->base.name); 1760 return -EINVAL; 1761 } 1762 1763 /* 1764 * 90/270 is not allowed with RGB64 16:16:16:16 and 1765 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards. 1766 */ 1767 switch (fb->format->format) { 1768 case DRM_FORMAT_RGB565: 1769 if (DISPLAY_VER(display) >= 11) 1770 break; 1771 fallthrough; 1772 case DRM_FORMAT_C8: 1773 case DRM_FORMAT_XRGB16161616F: 1774 case DRM_FORMAT_XBGR16161616F: 1775 case DRM_FORMAT_ARGB16161616F: 1776 case DRM_FORMAT_ABGR16161616F: 1777 case DRM_FORMAT_Y210: 1778 case DRM_FORMAT_Y212: 1779 case DRM_FORMAT_Y216: 1780 case DRM_FORMAT_XVYU12_16161616: 1781 case DRM_FORMAT_XVYU16161616: 1782 drm_dbg_kms(display->drm, 1783 "[PLANE:%d:%s] unsupported pixel format %p4cc for 90/270!\n", 1784 plane->base.base.id, plane->base.name, &fb->format->format); 1785 return -EINVAL; 1786 default: 1787 break; 1788 } 1789 } 1790 1791 /* Y-tiling is not supported in IF-ID Interlace mode */ 1792 if (crtc_state->hw.enable && 1793 crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && 1794 fb->modifier != DRM_FORMAT_MOD_LINEAR && 1795 fb->modifier != I915_FORMAT_MOD_X_TILED) { 1796 drm_dbg_kms(display->drm, 1797 "[PLANE:%d:%s] Y/Yf tiling not supported in IF-ID mode\n", 1798 plane->base.base.id, plane->base.name); 1799 return -EINVAL; 1800 } 1801 1802 /* Wa_1606054188:tgl,adl-s */ 1803 if ((display->platform.alderlake_s || display->platform.tigerlake) && 1804 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE && 1805 intel_format_is_p01x(fb->format->format)) { 1806 drm_dbg_kms(display->drm, 1807 "[PLANE:%d:%s] source color keying not supported with P01x formats\n", 1808 plane->base.base.id, plane->base.name); 1809 return -EINVAL; 1810 } 1811 1812 return 0; 1813 } 1814 1815 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state, 1816 const struct intel_plane_state *plane_state) 1817 { 1818 struct intel_display *display = to_intel_display(plane_state); 1819 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1820 int crtc_x = plane_state->uapi.dst.x1; 1821 int crtc_w = drm_rect_width(&plane_state->uapi.dst); 1822 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); 1823 1824 /* 1825 * Display WA #1175: glk 1826 * Planes other than the cursor may cause FIFO underflow and display 1827 * corruption if starting less than 4 pixels from the right edge of 1828 * the screen. 1829 * Besides the above WA fix the similar problem, where planes other 1830 * than the cursor ending less than 4 pixels from the left edge of the 1831 * screen may cause FIFO underflow and display corruption. 1832 */ 1833 if (DISPLAY_VER(display) == 10 && 1834 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) { 1835 drm_dbg_kms(display->drm, 1836 "[PLANE:%d:%s] requested plane X %s position %d invalid (valid range %d-%d)\n", 1837 plane->base.base.id, plane->base.name, 1838 crtc_x + crtc_w < 4 ? "end" : "start", 1839 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x, 1840 4, pipe_src_w - 4); 1841 return -ERANGE; 1842 } 1843 1844 return 0; 1845 } 1846 1847 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state) 1848 { 1849 struct intel_display *display = to_intel_display(plane_state); 1850 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1851 const struct drm_framebuffer *fb = plane_state->hw.fb; 1852 unsigned int rotation = plane_state->hw.rotation; 1853 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1854 1855 /* Display WA #1106 */ 1856 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && 1857 src_w & 3 && 1858 (rotation == DRM_MODE_ROTATE_270 || 1859 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) { 1860 drm_dbg_kms(display->drm, 1861 "[PLANE:%d:%s] src width must be multiple of 4 for rotated planar YUV\n", 1862 plane->base.base.id, plane->base.name); 1863 return -EINVAL; 1864 } 1865 1866 return 0; 1867 } 1868 1869 static int skl_plane_max_scale(struct intel_display *display, 1870 const struct drm_framebuffer *fb) 1871 { 1872 /* 1873 * We don't yet know the final source width nor 1874 * whether we can use the HQ scaler mode. Assume 1875 * the best case. 1876 * FIXME need to properly check this later. 1877 */ 1878 if (DISPLAY_VER(display) >= 10 || 1879 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) 1880 return 0x30000 - 1; 1881 else 1882 return 0x20000 - 1; 1883 } 1884 1885 static int intel_plane_min_width(struct intel_plane *plane, 1886 const struct drm_framebuffer *fb, 1887 int color_plane, 1888 unsigned int rotation) 1889 { 1890 if (plane->min_width) 1891 return plane->min_width(fb, color_plane, rotation); 1892 else 1893 return 1; 1894 } 1895 1896 static int intel_plane_max_width(struct intel_plane *plane, 1897 const struct drm_framebuffer *fb, 1898 int color_plane, 1899 unsigned int rotation) 1900 { 1901 if (plane->max_width) 1902 return plane->max_width(fb, color_plane, rotation); 1903 else 1904 return INT_MAX; 1905 } 1906 1907 static int intel_plane_max_height(struct intel_plane *plane, 1908 const struct drm_framebuffer *fb, 1909 int color_plane, 1910 unsigned int rotation) 1911 { 1912 if (plane->max_height) 1913 return plane->max_height(fb, color_plane, rotation); 1914 else 1915 return INT_MAX; 1916 } 1917 1918 static bool 1919 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, 1920 int main_x, int main_y, u32 main_offset, 1921 int ccs_plane) 1922 { 1923 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1924 const struct drm_framebuffer *fb = plane_state->hw.fb; 1925 int aux_x = plane_state->view.color_plane[ccs_plane].x; 1926 int aux_y = plane_state->view.color_plane[ccs_plane].y; 1927 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 1928 unsigned int alignment = plane->min_alignment(plane, fb, ccs_plane); 1929 int hsub; 1930 int vsub; 1931 1932 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); 1933 while (aux_offset >= main_offset && aux_y <= main_y) { 1934 int x, y; 1935 1936 if (aux_x == main_x && aux_y == main_y) 1937 break; 1938 1939 if (aux_offset == 0) 1940 break; 1941 1942 x = aux_x / hsub; 1943 y = aux_y / vsub; 1944 aux_offset = intel_plane_adjust_aligned_offset(&x, &y, 1945 plane_state, 1946 ccs_plane, 1947 aux_offset, 1948 aux_offset - alignment); 1949 aux_x = x * hsub + aux_x % hsub; 1950 aux_y = y * vsub + aux_y % vsub; 1951 } 1952 1953 if (aux_x != main_x || aux_y != main_y) 1954 return false; 1955 1956 plane_state->view.color_plane[ccs_plane].offset = aux_offset; 1957 plane_state->view.color_plane[ccs_plane].x = aux_x; 1958 plane_state->view.color_plane[ccs_plane].y = aux_y; 1959 1960 return true; 1961 } 1962 1963 1964 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state, 1965 int *x, int *y, u32 *offset) 1966 { 1967 struct intel_display *display = to_intel_display(plane_state); 1968 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1969 const struct drm_framebuffer *fb = plane_state->hw.fb; 1970 int aux_plane = skl_main_to_aux_plane(fb, 0); 1971 u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; 1972 unsigned int alignment = plane->min_alignment(plane, fb, 0); 1973 int w = drm_rect_width(&plane_state->uapi.src) >> 16; 1974 1975 intel_add_fb_offsets(x, y, plane_state, 0); 1976 *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0); 1977 if (drm_WARN_ON(display->drm, alignment && !is_power_of_2(alignment))) 1978 return -EINVAL; 1979 1980 /* 1981 * AUX surface offset is specified as the distance from the 1982 * main surface offset, and it must be non-negative. Make 1983 * sure that is what we will get. 1984 */ 1985 if (aux_plane && *offset > aux_offset) 1986 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0, 1987 *offset, 1988 aux_offset & ~(alignment - 1)); 1989 1990 /* 1991 * When using an X-tiled surface, the plane blows up 1992 * if the x offset + width exceed the stride. 1993 * 1994 * TODO: linear and Y-tiled seem fine, Yf untested, 1995 */ 1996 if (fb->modifier == I915_FORMAT_MOD_X_TILED) { 1997 int cpp = fb->format->cpp[0]; 1998 1999 while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) { 2000 if (*offset == 0) { 2001 drm_dbg_kms(display->drm, 2002 "[PLANE:%d:%s] unable to find suitable display surface offset due to X-tiling\n", 2003 plane->base.base.id, plane->base.name); 2004 return -EINVAL; 2005 } 2006 2007 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0, 2008 *offset, 2009 *offset - alignment); 2010 } 2011 } 2012 2013 return 0; 2014 } 2015 2016 static int skl_check_main_surface(struct intel_plane_state *plane_state) 2017 { 2018 struct intel_display *display = to_intel_display(plane_state); 2019 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2020 const struct drm_framebuffer *fb = plane_state->hw.fb; 2021 unsigned int rotation = plane_state->hw.rotation; 2022 int x = plane_state->uapi.src.x1 >> 16; 2023 int y = plane_state->uapi.src.y1 >> 16; 2024 int w = drm_rect_width(&plane_state->uapi.src) >> 16; 2025 int h = drm_rect_height(&plane_state->uapi.src) >> 16; 2026 int min_width = intel_plane_min_width(plane, fb, 0, rotation); 2027 int max_width = intel_plane_max_width(plane, fb, 0, rotation); 2028 int max_height = intel_plane_max_height(plane, fb, 0, rotation); 2029 unsigned int alignment = plane->min_alignment(plane, fb, 0); 2030 int aux_plane = skl_main_to_aux_plane(fb, 0); 2031 u32 offset; 2032 int ret; 2033 2034 if (w > max_width || w < min_width || h > max_height || h < 1) { 2035 drm_dbg_kms(display->drm, 2036 "[PLANE:%d:%s] requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", 2037 plane->base.base.id, plane->base.name, 2038 w, h, min_width, max_width, max_height); 2039 return -EINVAL; 2040 } 2041 2042 ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset); 2043 if (ret) 2044 return ret; 2045 2046 /* 2047 * CCS AUX surface doesn't have its own x/y offsets, we must make sure 2048 * they match with the main surface x/y offsets. On DG2 2049 * there's no aux plane on fb so skip this checking. 2050 */ 2051 if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) { 2052 while (!skl_check_main_ccs_coordinates(plane_state, x, y, 2053 offset, aux_plane)) { 2054 if (offset == 0) 2055 break; 2056 2057 offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, 2058 offset, offset - alignment); 2059 } 2060 2061 if (x != plane_state->view.color_plane[aux_plane].x || 2062 y != plane_state->view.color_plane[aux_plane].y) { 2063 drm_dbg_kms(display->drm, 2064 "[PLANE:%d:%s] unable to find suitable display surface offset due to CCS\n", 2065 plane->base.base.id, plane->base.name); 2066 return -EINVAL; 2067 } 2068 } 2069 2070 if (DISPLAY_VER(display) >= 13) 2071 drm_WARN_ON(display->drm, x > 65535 || y > 65535); 2072 else 2073 drm_WARN_ON(display->drm, x > 8191 || y > 8191); 2074 2075 plane_state->view.color_plane[0].offset = offset; 2076 plane_state->view.color_plane[0].x = x; 2077 plane_state->view.color_plane[0].y = y; 2078 2079 /* 2080 * Put the final coordinates back so that the src 2081 * coordinate checks will see the right values. 2082 */ 2083 drm_rect_translate_to(&plane_state->uapi.src, 2084 x << 16, y << 16); 2085 2086 return 0; 2087 } 2088 2089 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) 2090 { 2091 struct intel_display *display = to_intel_display(plane_state); 2092 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2093 const struct drm_framebuffer *fb = plane_state->hw.fb; 2094 unsigned int rotation = plane_state->hw.rotation; 2095 int uv_plane = 1; 2096 int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ? 2097 skl_main_to_aux_plane(fb, uv_plane) : 0; 2098 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); 2099 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); 2100 int x = plane_state->uapi.src.x1 >> 17; 2101 int y = plane_state->uapi.src.y1 >> 17; 2102 int w = drm_rect_width(&plane_state->uapi.src) >> 17; 2103 int h = drm_rect_height(&plane_state->uapi.src) >> 17; 2104 u32 offset; 2105 2106 /* FIXME not quite sure how/if these apply to the chroma plane */ 2107 if (w > max_width || h > max_height) { 2108 drm_dbg_kms(display->drm, 2109 "[PLANE:%d:%s] CbCr source size %dx%d too big (limit %dx%d)\n", 2110 plane->base.base.id, plane->base.name, 2111 w, h, max_width, max_height); 2112 return -EINVAL; 2113 } 2114 2115 intel_add_fb_offsets(&x, &y, plane_state, uv_plane); 2116 offset = intel_plane_compute_aligned_offset(&x, &y, 2117 plane_state, uv_plane); 2118 2119 if (ccs_plane) { 2120 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 2121 unsigned int alignment = plane->min_alignment(plane, fb, uv_plane); 2122 2123 if (offset > aux_offset) 2124 offset = intel_plane_adjust_aligned_offset(&x, &y, 2125 plane_state, 2126 uv_plane, 2127 offset, 2128 aux_offset & ~(alignment - 1)); 2129 2130 while (!skl_check_main_ccs_coordinates(plane_state, x, y, 2131 offset, ccs_plane)) { 2132 if (offset == 0) 2133 break; 2134 2135 offset = intel_plane_adjust_aligned_offset(&x, &y, 2136 plane_state, 2137 uv_plane, 2138 offset, offset - alignment); 2139 } 2140 2141 if (x != plane_state->view.color_plane[ccs_plane].x || 2142 y != plane_state->view.color_plane[ccs_plane].y) { 2143 drm_dbg_kms(display->drm, 2144 "[PLANE:%d:%s] unable to find suitable display surface offset due to CCS\n", 2145 plane->base.base.id, plane->base.name); 2146 return -EINVAL; 2147 } 2148 } 2149 2150 if (DISPLAY_VER(display) >= 13) 2151 drm_WARN_ON(display->drm, x > 65535 || y > 65535); 2152 else 2153 drm_WARN_ON(display->drm, x > 8191 || y > 8191); 2154 2155 plane_state->view.color_plane[uv_plane].offset = offset; 2156 plane_state->view.color_plane[uv_plane].x = x; 2157 plane_state->view.color_plane[uv_plane].y = y; 2158 2159 return 0; 2160 } 2161 2162 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) 2163 { 2164 const struct drm_framebuffer *fb = plane_state->hw.fb; 2165 int src_x = plane_state->uapi.src.x1 >> 16; 2166 int src_y = plane_state->uapi.src.y1 >> 16; 2167 u32 offset; 2168 int ccs_plane; 2169 2170 for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) { 2171 int main_hsub, main_vsub; 2172 int hsub, vsub; 2173 int x, y; 2174 2175 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane)) 2176 continue; 2177 2178 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, 2179 skl_ccs_to_main_plane(fb, ccs_plane)); 2180 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); 2181 2182 hsub *= main_hsub; 2183 vsub *= main_vsub; 2184 x = src_x / hsub; 2185 y = src_y / vsub; 2186 2187 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane); 2188 2189 offset = intel_plane_compute_aligned_offset(&x, &y, 2190 plane_state, 2191 ccs_plane); 2192 2193 plane_state->view.color_plane[ccs_plane].offset = offset; 2194 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub; 2195 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub; 2196 } 2197 2198 return 0; 2199 } 2200 2201 static int skl_check_plane_surface(struct intel_plane_state *plane_state) 2202 { 2203 const struct drm_framebuffer *fb = plane_state->hw.fb; 2204 int ret; 2205 2206 ret = intel_plane_compute_gtt(plane_state); 2207 if (ret) 2208 return ret; 2209 2210 if (!plane_state->uapi.visible) 2211 return 0; 2212 2213 /* 2214 * Handle the AUX surface first since the main surface setup depends on 2215 * it. 2216 */ 2217 if (intel_fb_is_ccs_modifier(fb->modifier)) { 2218 ret = skl_check_ccs_aux_surface(plane_state); 2219 if (ret) 2220 return ret; 2221 } 2222 2223 if (intel_format_info_is_yuv_semiplanar(fb->format, 2224 fb->modifier)) { 2225 ret = skl_check_nv12_aux_surface(plane_state); 2226 if (ret) 2227 return ret; 2228 } 2229 2230 ret = skl_check_main_surface(plane_state); 2231 if (ret) 2232 return ret; 2233 2234 return 0; 2235 } 2236 2237 static bool skl_fb_scalable(const struct drm_framebuffer *fb) 2238 { 2239 struct intel_display *display; 2240 2241 if (!fb) 2242 return false; 2243 2244 display = to_intel_display(fb->dev); 2245 2246 switch (fb->format->format) { 2247 case DRM_FORMAT_C8: 2248 return false; 2249 case DRM_FORMAT_XRGB16161616F: 2250 case DRM_FORMAT_ARGB16161616F: 2251 case DRM_FORMAT_XBGR16161616F: 2252 case DRM_FORMAT_ABGR16161616F: 2253 return DISPLAY_VER(display) >= 11; 2254 default: 2255 return true; 2256 } 2257 } 2258 2259 static void check_protection(struct intel_plane_state *plane_state) 2260 { 2261 struct intel_display *display = to_intel_display(plane_state); 2262 const struct drm_framebuffer *fb = plane_state->hw.fb; 2263 struct drm_gem_object *obj = intel_fb_bo(fb); 2264 2265 if (DISPLAY_VER(display) < 11) 2266 return; 2267 2268 plane_state->decrypt = intel_pxp_key_check(obj, false) == 0; 2269 plane_state->force_black = intel_bo_is_protected(obj) && 2270 !plane_state->decrypt; 2271 } 2272 2273 static void 2274 make_damage_viewport_relative(struct intel_plane_state *plane_state) 2275 { 2276 const struct drm_framebuffer *fb = plane_state->hw.fb; 2277 const struct drm_rect *src = &plane_state->uapi.src; 2278 unsigned int rotation = plane_state->hw.rotation; 2279 struct drm_rect *damage = &plane_state->damage; 2280 2281 if (!drm_rect_visible(damage)) 2282 return; 2283 2284 if (!fb || !plane_state->uapi.visible) { 2285 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0); 2286 return; 2287 } 2288 2289 if (drm_rotation_90_or_270(rotation)) { 2290 drm_rect_rotate(damage, fb->width, fb->height, 2291 DRM_MODE_ROTATE_270); 2292 drm_rect_translate(damage, -(src->y1 >> 16), -(src->x1 >> 16)); 2293 } else { 2294 drm_rect_translate(damage, -(src->x1 >> 16), -(src->y1 >> 16)); 2295 } 2296 } 2297 2298 static void clip_damage(struct intel_plane_state *plane_state) 2299 { 2300 struct drm_rect *damage = &plane_state->damage; 2301 struct drm_rect src; 2302 2303 if (!drm_rect_visible(damage)) 2304 return; 2305 2306 drm_rect_fp_to_int(&src, &plane_state->uapi.src); 2307 drm_rect_translate(damage, src.x1, src.y1); 2308 drm_rect_intersect(damage, &src); 2309 } 2310 2311 static int skl_plane_check(struct intel_crtc_state *crtc_state, 2312 struct intel_plane_state *plane_state) 2313 { 2314 struct intel_display *display = to_intel_display(plane_state); 2315 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 2316 const struct drm_framebuffer *fb = plane_state->hw.fb; 2317 int min_scale = DRM_PLANE_NO_SCALING; 2318 int max_scale = DRM_PLANE_NO_SCALING; 2319 int ret; 2320 2321 ret = skl_plane_check_fb(crtc_state, plane_state); 2322 if (ret) 2323 return ret; 2324 2325 /* use scaler when colorkey is not required */ 2326 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) { 2327 min_scale = 1; 2328 max_scale = skl_plane_max_scale(display, fb); 2329 } 2330 2331 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, 2332 min_scale, max_scale, true); 2333 if (ret) 2334 return ret; 2335 2336 make_damage_viewport_relative(plane_state); 2337 2338 ret = skl_check_plane_surface(plane_state); 2339 if (ret) 2340 return ret; 2341 2342 if (!plane_state->uapi.visible) 2343 return 0; 2344 2345 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state); 2346 if (ret) 2347 return ret; 2348 2349 ret = intel_plane_check_src_coordinates(plane_state); 2350 if (ret) 2351 return ret; 2352 2353 clip_damage(plane_state); 2354 2355 ret = skl_plane_check_nv12_rotation(plane_state); 2356 if (ret) 2357 return ret; 2358 2359 check_protection(plane_state); 2360 2361 /* HW only has 8 bits pixel precision, disable plane if invisible */ 2362 if (!(plane_state->hw.alpha >> 8)) { 2363 plane_state->uapi.visible = false; 2364 plane_state->damage = DRM_RECT_INIT(0, 0, 0, 0); 2365 } 2366 2367 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); 2368 2369 if (DISPLAY_VER(display) >= 10) 2370 plane_state->color_ctl = glk_plane_color_ctl(crtc_state, 2371 plane_state); 2372 2373 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && 2374 icl_is_hdr_plane(display, plane->id)) 2375 /* Enable and use MPEG-2 chroma siting */ 2376 plane_state->cus_ctl = PLANE_CUS_ENABLE | 2377 PLANE_CUS_HPHASE_0 | 2378 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25; 2379 else 2380 plane_state->cus_ctl = 0; 2381 2382 return 0; 2383 } 2384 2385 void icl_link_nv12_planes(struct intel_plane_state *uv_plane_state, 2386 struct intel_plane_state *y_plane_state) 2387 { 2388 struct intel_display *display = to_intel_display(uv_plane_state); 2389 struct intel_plane *uv_plane = to_intel_plane(uv_plane_state->uapi.plane); 2390 struct intel_plane *y_plane = to_intel_plane(y_plane_state->uapi.plane); 2391 2392 drm_WARN_ON(display->drm, icl_is_nv12_y_plane(display, uv_plane->id)); 2393 drm_WARN_ON(display->drm, !icl_is_nv12_y_plane(display, y_plane->id)); 2394 2395 y_plane_state->ctl |= PLANE_CTL_YUV420_Y_PLANE; 2396 2397 if (icl_is_hdr_plane(display, uv_plane->id)) { 2398 switch (y_plane->id) { 2399 case PLANE_7: 2400 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_7_ICL; 2401 break; 2402 case PLANE_6: 2403 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_6_ICL; 2404 break; 2405 case PLANE_5: 2406 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_5_RKL; 2407 break; 2408 case PLANE_4: 2409 uv_plane_state->cus_ctl |= PLANE_CUS_Y_PLANE_4_RKL; 2410 break; 2411 default: 2412 MISSING_CASE(y_plane->id); 2413 } 2414 } 2415 } 2416 2417 static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe) 2418 { 2419 return pipe - PIPE_A + INTEL_FBC_A; 2420 } 2421 2422 static bool skl_plane_has_fbc(struct intel_display *display, 2423 enum intel_fbc_id fbc_id, enum plane_id plane_id) 2424 { 2425 if ((DISPLAY_RUNTIME_INFO(display)->fbc_mask & BIT(fbc_id)) == 0) 2426 return false; 2427 2428 if (DISPLAY_VER(display) >= 20) 2429 return icl_is_hdr_plane(display, plane_id); 2430 else 2431 return plane_id == PLANE_1; 2432 } 2433 2434 static struct intel_fbc *skl_plane_fbc(struct intel_display *display, 2435 enum pipe pipe, enum plane_id plane_id) 2436 { 2437 enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe); 2438 2439 if (skl_plane_has_fbc(display, fbc_id, plane_id)) 2440 return display->fbc[fbc_id]; 2441 else 2442 return NULL; 2443 } 2444 2445 static bool skl_plane_has_planar(struct intel_display *display, 2446 enum pipe pipe, enum plane_id plane_id) 2447 { 2448 /* Display WA #0870: skl, bxt */ 2449 if (display->platform.skylake || display->platform.broxton) 2450 return false; 2451 2452 if (DISPLAY_VER(display) == 9 && pipe == PIPE_C) 2453 return false; 2454 2455 if (plane_id != PLANE_1 && plane_id != PLANE_2) 2456 return false; 2457 2458 return true; 2459 } 2460 2461 static const u32 *skl_get_plane_formats(struct intel_display *display, 2462 enum pipe pipe, enum plane_id plane_id, 2463 int *num_formats) 2464 { 2465 if (skl_plane_has_planar(display, pipe, plane_id)) { 2466 *num_formats = ARRAY_SIZE(skl_planar_formats); 2467 return skl_planar_formats; 2468 } else { 2469 *num_formats = ARRAY_SIZE(skl_plane_formats); 2470 return skl_plane_formats; 2471 } 2472 } 2473 2474 static const u32 *glk_get_plane_formats(struct intel_display *display, 2475 enum pipe pipe, enum plane_id plane_id, 2476 int *num_formats) 2477 { 2478 if (skl_plane_has_planar(display, pipe, plane_id)) { 2479 *num_formats = ARRAY_SIZE(glk_planar_formats); 2480 return glk_planar_formats; 2481 } else { 2482 *num_formats = ARRAY_SIZE(skl_plane_formats); 2483 return skl_plane_formats; 2484 } 2485 } 2486 2487 static const u32 *icl_get_plane_formats(struct intel_display *display, 2488 enum pipe pipe, enum plane_id plane_id, 2489 int *num_formats) 2490 { 2491 if (icl_is_hdr_plane(display, plane_id)) { 2492 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats); 2493 return icl_hdr_plane_formats; 2494 } else if (icl_is_nv12_y_plane(display, plane_id)) { 2495 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats); 2496 return icl_sdr_y_plane_formats; 2497 } else { 2498 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats); 2499 return icl_sdr_uv_plane_formats; 2500 } 2501 } 2502 2503 static bool skl_plane_format_mod_supported(struct drm_plane *_plane, 2504 u32 format, u64 modifier) 2505 { 2506 struct intel_plane *plane = to_intel_plane(_plane); 2507 2508 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2509 return false; 2510 2511 switch (format) { 2512 case DRM_FORMAT_XRGB8888: 2513 case DRM_FORMAT_XBGR8888: 2514 case DRM_FORMAT_ARGB8888: 2515 case DRM_FORMAT_ABGR8888: 2516 if (intel_fb_is_ccs_modifier(modifier)) 2517 return true; 2518 fallthrough; 2519 case DRM_FORMAT_RGB565: 2520 case DRM_FORMAT_XRGB2101010: 2521 case DRM_FORMAT_XBGR2101010: 2522 case DRM_FORMAT_ARGB2101010: 2523 case DRM_FORMAT_ABGR2101010: 2524 case DRM_FORMAT_YUYV: 2525 case DRM_FORMAT_YVYU: 2526 case DRM_FORMAT_UYVY: 2527 case DRM_FORMAT_VYUY: 2528 case DRM_FORMAT_NV12: 2529 case DRM_FORMAT_XYUV8888: 2530 case DRM_FORMAT_P010: 2531 case DRM_FORMAT_P012: 2532 case DRM_FORMAT_P016: 2533 case DRM_FORMAT_XVYU2101010: 2534 if (modifier == I915_FORMAT_MOD_Yf_TILED) 2535 return true; 2536 fallthrough; 2537 case DRM_FORMAT_C8: 2538 case DRM_FORMAT_XBGR16161616F: 2539 case DRM_FORMAT_ABGR16161616F: 2540 case DRM_FORMAT_XRGB16161616F: 2541 case DRM_FORMAT_ARGB16161616F: 2542 case DRM_FORMAT_Y210: 2543 case DRM_FORMAT_Y212: 2544 case DRM_FORMAT_Y216: 2545 case DRM_FORMAT_XVYU12_16161616: 2546 case DRM_FORMAT_XVYU16161616: 2547 if (modifier == DRM_FORMAT_MOD_LINEAR || 2548 modifier == I915_FORMAT_MOD_X_TILED || 2549 modifier == I915_FORMAT_MOD_Y_TILED) 2550 return true; 2551 fallthrough; 2552 default: 2553 return false; 2554 } 2555 } 2556 2557 static bool icl_plane_format_mod_supported(struct drm_plane *_plane, 2558 u32 format, u64 modifier) 2559 { 2560 struct intel_plane *plane = to_intel_plane(_plane); 2561 2562 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2563 return false; 2564 2565 switch (format) { 2566 case DRM_FORMAT_XRGB8888: 2567 case DRM_FORMAT_XBGR8888: 2568 case DRM_FORMAT_ARGB8888: 2569 case DRM_FORMAT_ABGR8888: 2570 case DRM_FORMAT_XRGB2101010: 2571 case DRM_FORMAT_XBGR2101010: 2572 case DRM_FORMAT_ARGB2101010: 2573 case DRM_FORMAT_ABGR2101010: 2574 if (intel_fb_is_ccs_modifier(modifier)) 2575 return true; 2576 fallthrough; 2577 case DRM_FORMAT_RGB565: 2578 case DRM_FORMAT_YUYV: 2579 case DRM_FORMAT_YVYU: 2580 case DRM_FORMAT_UYVY: 2581 case DRM_FORMAT_VYUY: 2582 case DRM_FORMAT_NV12: 2583 case DRM_FORMAT_XYUV8888: 2584 case DRM_FORMAT_P010: 2585 case DRM_FORMAT_P012: 2586 case DRM_FORMAT_P016: 2587 case DRM_FORMAT_XVYU2101010: 2588 if (modifier == I915_FORMAT_MOD_Yf_TILED) 2589 return true; 2590 fallthrough; 2591 case DRM_FORMAT_C8: 2592 case DRM_FORMAT_XBGR16161616F: 2593 case DRM_FORMAT_ABGR16161616F: 2594 case DRM_FORMAT_XRGB16161616F: 2595 case DRM_FORMAT_ARGB16161616F: 2596 case DRM_FORMAT_Y210: 2597 case DRM_FORMAT_Y212: 2598 case DRM_FORMAT_Y216: 2599 case DRM_FORMAT_XVYU12_16161616: 2600 case DRM_FORMAT_XVYU16161616: 2601 if (modifier == DRM_FORMAT_MOD_LINEAR || 2602 modifier == I915_FORMAT_MOD_X_TILED || 2603 modifier == I915_FORMAT_MOD_Y_TILED) 2604 return true; 2605 fallthrough; 2606 default: 2607 return false; 2608 } 2609 } 2610 2611 static bool tgl_plane_format_mod_supported(struct drm_plane *_plane, 2612 u32 format, u64 modifier) 2613 { 2614 struct intel_plane *plane = to_intel_plane(_plane); 2615 2616 if (!intel_fb_plane_supports_modifier(plane, modifier)) 2617 return false; 2618 2619 switch (format) { 2620 case DRM_FORMAT_XRGB8888: 2621 case DRM_FORMAT_XBGR8888: 2622 case DRM_FORMAT_ARGB8888: 2623 case DRM_FORMAT_ABGR8888: 2624 case DRM_FORMAT_XRGB2101010: 2625 case DRM_FORMAT_XBGR2101010: 2626 case DRM_FORMAT_ARGB2101010: 2627 case DRM_FORMAT_ABGR2101010: 2628 case DRM_FORMAT_XBGR16161616F: 2629 case DRM_FORMAT_ABGR16161616F: 2630 case DRM_FORMAT_XRGB16161616F: 2631 case DRM_FORMAT_ARGB16161616F: 2632 if (intel_fb_is_ccs_modifier(modifier)) 2633 return true; 2634 fallthrough; 2635 case DRM_FORMAT_YUYV: 2636 case DRM_FORMAT_YVYU: 2637 case DRM_FORMAT_UYVY: 2638 case DRM_FORMAT_VYUY: 2639 case DRM_FORMAT_NV12: 2640 case DRM_FORMAT_XYUV8888: 2641 case DRM_FORMAT_P010: 2642 case DRM_FORMAT_P012: 2643 case DRM_FORMAT_P016: 2644 if (intel_fb_is_mc_ccs_modifier(modifier)) 2645 return true; 2646 fallthrough; 2647 case DRM_FORMAT_RGB565: 2648 case DRM_FORMAT_XVYU2101010: 2649 case DRM_FORMAT_C8: 2650 case DRM_FORMAT_Y210: 2651 case DRM_FORMAT_Y212: 2652 case DRM_FORMAT_Y216: 2653 case DRM_FORMAT_XVYU12_16161616: 2654 case DRM_FORMAT_XVYU16161616: 2655 if (!intel_fb_is_ccs_modifier(modifier)) 2656 return true; 2657 fallthrough; 2658 default: 2659 return false; 2660 } 2661 } 2662 2663 static const struct drm_plane_funcs skl_plane_funcs = { 2664 .update_plane = drm_atomic_helper_update_plane, 2665 .disable_plane = drm_atomic_helper_disable_plane, 2666 .destroy = intel_plane_destroy, 2667 .atomic_duplicate_state = intel_plane_duplicate_state, 2668 .atomic_destroy_state = intel_plane_destroy_state, 2669 .format_mod_supported = skl_plane_format_mod_supported, 2670 .format_mod_supported_async = intel_plane_format_mod_supported_async, 2671 }; 2672 2673 static const struct drm_plane_funcs icl_plane_funcs = { 2674 .update_plane = drm_atomic_helper_update_plane, 2675 .disable_plane = drm_atomic_helper_disable_plane, 2676 .destroy = intel_plane_destroy, 2677 .atomic_duplicate_state = intel_plane_duplicate_state, 2678 .atomic_destroy_state = intel_plane_destroy_state, 2679 .format_mod_supported = icl_plane_format_mod_supported, 2680 .format_mod_supported_async = intel_plane_format_mod_supported_async, 2681 }; 2682 2683 static const struct drm_plane_funcs tgl_plane_funcs = { 2684 .update_plane = drm_atomic_helper_update_plane, 2685 .disable_plane = drm_atomic_helper_disable_plane, 2686 .destroy = intel_plane_destroy, 2687 .atomic_duplicate_state = intel_plane_duplicate_state, 2688 .atomic_destroy_state = intel_plane_destroy_state, 2689 .format_mod_supported = tgl_plane_format_mod_supported, 2690 .format_mod_supported_async = intel_plane_format_mod_supported_async, 2691 }; 2692 2693 static void 2694 skl_plane_enable_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_enable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 2701 spin_unlock_irq(&display->irq.lock); 2702 } 2703 2704 static void 2705 skl_plane_disable_flip_done(struct intel_plane *plane) 2706 { 2707 struct intel_display *display = to_intel_display(plane); 2708 enum pipe pipe = plane->pipe; 2709 2710 spin_lock_irq(&display->irq.lock); 2711 bdw_disable_pipe_irq(display, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 2712 spin_unlock_irq(&display->irq.lock); 2713 } 2714 2715 static bool skl_plane_has_rc_ccs(struct intel_display *display, 2716 enum pipe pipe, enum plane_id plane_id) 2717 { 2718 return pipe != PIPE_C && 2719 (plane_id == PLANE_1 || plane_id == PLANE_2); 2720 } 2721 2722 static u8 skl_plane_caps(struct intel_display *display, 2723 enum pipe pipe, enum plane_id plane_id) 2724 { 2725 u8 caps = INTEL_PLANE_CAP_TILING_X | 2726 INTEL_PLANE_CAP_TILING_Y | 2727 INTEL_PLANE_CAP_TILING_Yf; 2728 2729 if (skl_plane_has_rc_ccs(display, pipe, plane_id)) 2730 caps |= INTEL_PLANE_CAP_CCS_RC; 2731 2732 return caps; 2733 } 2734 2735 static bool glk_plane_has_rc_ccs(struct intel_display *display, 2736 enum pipe pipe) 2737 { 2738 return pipe != PIPE_C; 2739 } 2740 2741 static u8 glk_plane_caps(struct intel_display *display, 2742 enum pipe pipe, enum plane_id plane_id) 2743 { 2744 u8 caps = INTEL_PLANE_CAP_TILING_X | 2745 INTEL_PLANE_CAP_TILING_Y | 2746 INTEL_PLANE_CAP_TILING_Yf; 2747 2748 if (glk_plane_has_rc_ccs(display, pipe)) 2749 caps |= INTEL_PLANE_CAP_CCS_RC; 2750 2751 return caps; 2752 } 2753 2754 static u8 icl_plane_caps(struct intel_display *display, 2755 enum pipe pipe, enum plane_id plane_id) 2756 { 2757 return INTEL_PLANE_CAP_TILING_X | 2758 INTEL_PLANE_CAP_TILING_Y | 2759 INTEL_PLANE_CAP_TILING_Yf | 2760 INTEL_PLANE_CAP_CCS_RC; 2761 } 2762 2763 static bool tgl_plane_has_mc_ccs(struct intel_display *display, 2764 enum plane_id plane_id) 2765 { 2766 /* Wa_14010477008 */ 2767 if (display->platform.dg1 || display->platform.rocketlake || 2768 (display->platform.tigerlake && IS_DISPLAY_STEP(display, STEP_A0, STEP_D0))) 2769 return false; 2770 2771 return plane_id < PLANE_6; 2772 } 2773 2774 static u8 tgl_plane_caps(struct intel_display *display, 2775 enum pipe pipe, enum plane_id plane_id) 2776 { 2777 u8 caps = INTEL_PLANE_CAP_TILING_X | 2778 INTEL_PLANE_CAP_CCS_RC | 2779 INTEL_PLANE_CAP_CCS_RC_CC; 2780 2781 if (HAS_4TILE(display)) 2782 caps |= INTEL_PLANE_CAP_TILING_4; 2783 else 2784 caps |= INTEL_PLANE_CAP_TILING_Y; 2785 2786 if (tgl_plane_has_mc_ccs(display, plane_id)) 2787 caps |= INTEL_PLANE_CAP_CCS_MC; 2788 2789 if (DISPLAY_VER(display) >= 14 && display->platform.dgfx) 2790 caps |= INTEL_PLANE_CAP_NEED64K_PHYS; 2791 2792 return caps; 2793 } 2794 2795 struct intel_plane * 2796 skl_universal_plane_create(struct intel_display *display, 2797 enum pipe pipe, enum plane_id plane_id) 2798 { 2799 const struct drm_plane_funcs *plane_funcs; 2800 struct intel_plane *plane; 2801 enum drm_plane_type plane_type; 2802 unsigned int supported_rotations; 2803 unsigned int supported_csc; 2804 const u64 *modifiers; 2805 const u32 *formats; 2806 int num_formats; 2807 int ret; 2808 u8 caps; 2809 2810 plane = intel_plane_alloc(); 2811 if (IS_ERR(plane)) 2812 return plane; 2813 2814 plane->pipe = pipe; 2815 plane->id = plane_id; 2816 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id); 2817 2818 intel_fbc_add_plane(skl_plane_fbc(display, pipe, plane_id), plane); 2819 2820 if (DISPLAY_VER(display) >= 30) { 2821 plane->max_width = xe3_plane_max_width; 2822 plane->max_height = icl_plane_max_height; 2823 plane->min_cdclk = icl_plane_min_cdclk; 2824 } else if (DISPLAY_VER(display) >= 11) { 2825 plane->min_width = icl_plane_min_width; 2826 if (icl_is_hdr_plane(display, plane_id)) 2827 plane->max_width = icl_hdr_plane_max_width; 2828 else 2829 plane->max_width = icl_sdr_plane_max_width; 2830 plane->max_height = icl_plane_max_height; 2831 plane->min_cdclk = icl_plane_min_cdclk; 2832 } else if (DISPLAY_VER(display) >= 10) { 2833 plane->max_width = glk_plane_max_width; 2834 plane->max_height = skl_plane_max_height; 2835 plane->min_cdclk = glk_plane_min_cdclk; 2836 } else { 2837 plane->max_width = skl_plane_max_width; 2838 plane->max_height = skl_plane_max_height; 2839 plane->min_cdclk = skl_plane_min_cdclk; 2840 } 2841 2842 if (DISPLAY_VER(display) >= 13) 2843 plane->max_stride = adl_plane_max_stride; 2844 else 2845 plane->max_stride = skl_plane_max_stride; 2846 2847 if (DISPLAY_VER(display) >= 12) 2848 plane->min_alignment = tgl_plane_min_alignment; 2849 else 2850 plane->min_alignment = skl_plane_min_alignment; 2851 2852 if (intel_scanout_needs_vtd_wa(display)) 2853 plane->vtd_guard = DISPLAY_VER(display) >= 10 ? 168 : 136; 2854 2855 if (DISPLAY_VER(display) >= 11) { 2856 plane->update_noarm = icl_plane_update_noarm; 2857 plane->update_arm = icl_plane_update_arm; 2858 plane->disable_arm = icl_plane_disable_arm; 2859 } else { 2860 plane->update_noarm = skl_plane_update_noarm; 2861 plane->update_arm = skl_plane_update_arm; 2862 plane->disable_arm = skl_plane_disable_arm; 2863 } 2864 plane->capture_error = skl_plane_capture_error; 2865 plane->get_hw_state = skl_plane_get_hw_state; 2866 plane->check_plane = skl_plane_check; 2867 2868 if (HAS_ASYNC_FLIPS(display) && plane_id == PLANE_1) { 2869 plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(display, 9, 10); 2870 plane->async_flip = skl_plane_async_flip; 2871 plane->enable_flip_done = skl_plane_enable_flip_done; 2872 plane->disable_flip_done = skl_plane_disable_flip_done; 2873 2874 if (DISPLAY_VER(display) >= 12) 2875 plane->can_async_flip = tgl_plane_can_async_flip; 2876 else if (DISPLAY_VER(display) == 11) 2877 plane->can_async_flip = icl_plane_can_async_flip; 2878 else 2879 plane->can_async_flip = skl_plane_can_async_flip; 2880 } 2881 2882 if (DISPLAY_VER(display) >= 11) 2883 formats = icl_get_plane_formats(display, pipe, 2884 plane_id, &num_formats); 2885 else if (DISPLAY_VER(display) >= 10) 2886 formats = glk_get_plane_formats(display, pipe, 2887 plane_id, &num_formats); 2888 else 2889 formats = skl_get_plane_formats(display, pipe, 2890 plane_id, &num_formats); 2891 2892 if (DISPLAY_VER(display) >= 12) 2893 plane_funcs = &tgl_plane_funcs; 2894 else if (DISPLAY_VER(display) == 11) 2895 plane_funcs = &icl_plane_funcs; 2896 else 2897 plane_funcs = &skl_plane_funcs; 2898 2899 if (plane_id == PLANE_1) 2900 plane_type = DRM_PLANE_TYPE_PRIMARY; 2901 else 2902 plane_type = DRM_PLANE_TYPE_OVERLAY; 2903 2904 if (DISPLAY_VER(display) >= 12) 2905 caps = tgl_plane_caps(display, pipe, plane_id); 2906 else if (DISPLAY_VER(display) == 11) 2907 caps = icl_plane_caps(display, pipe, plane_id); 2908 else if (DISPLAY_VER(display) == 10) 2909 caps = glk_plane_caps(display, pipe, plane_id); 2910 else 2911 caps = skl_plane_caps(display, pipe, plane_id); 2912 2913 /* FIXME: xe has problems with AUX */ 2914 if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(to_i915(display->drm))) 2915 caps &= ~(INTEL_PLANE_CAP_CCS_RC | 2916 INTEL_PLANE_CAP_CCS_RC_CC | 2917 INTEL_PLANE_CAP_CCS_MC); 2918 2919 modifiers = intel_fb_plane_get_modifiers(display, caps); 2920 2921 ret = drm_universal_plane_init(display->drm, &plane->base, 2922 0, plane_funcs, 2923 formats, num_formats, modifiers, 2924 plane_type, 2925 "plane %d%c", plane_id + 1, 2926 pipe_name(pipe)); 2927 2928 kfree(modifiers); 2929 2930 if (ret) 2931 goto fail; 2932 2933 if (DISPLAY_VER(display) >= 13) 2934 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180; 2935 else 2936 supported_rotations = 2937 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | 2938 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; 2939 2940 if (DISPLAY_VER(display) >= 11) 2941 supported_rotations |= DRM_MODE_REFLECT_X; 2942 2943 drm_plane_create_rotation_property(&plane->base, 2944 DRM_MODE_ROTATE_0, 2945 supported_rotations); 2946 2947 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709); 2948 2949 if (DISPLAY_VER(display) >= 10) 2950 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020); 2951 2952 drm_plane_create_color_properties(&plane->base, 2953 supported_csc, 2954 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | 2955 BIT(DRM_COLOR_YCBCR_FULL_RANGE), 2956 DRM_COLOR_YCBCR_BT709, 2957 DRM_COLOR_YCBCR_LIMITED_RANGE); 2958 2959 drm_plane_create_alpha_property(&plane->base); 2960 drm_plane_create_blend_mode_property(&plane->base, 2961 BIT(DRM_MODE_BLEND_PIXEL_NONE) | 2962 BIT(DRM_MODE_BLEND_PREMULTI) | 2963 BIT(DRM_MODE_BLEND_COVERAGE)); 2964 2965 drm_plane_create_zpos_immutable_property(&plane->base, plane_id); 2966 2967 if (DISPLAY_VER(display) >= 12) 2968 drm_plane_enable_fb_damage_clips(&plane->base); 2969 2970 if (DISPLAY_VER(display) >= 11) 2971 drm_plane_create_scaling_filter_property(&plane->base, 2972 BIT(DRM_SCALING_FILTER_DEFAULT) | 2973 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); 2974 2975 intel_plane_helper_add(plane); 2976 2977 return plane; 2978 2979 fail: 2980 intel_plane_free(plane); 2981 2982 return ERR_PTR(ret); 2983 } 2984 2985 void 2986 skl_get_initial_plane_config(struct intel_crtc *crtc, 2987 struct intel_initial_plane_config *plane_config) 2988 { 2989 struct intel_display *display = to_intel_display(crtc); 2990 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); 2991 struct intel_plane *plane = to_intel_plane(crtc->base.primary); 2992 enum plane_id plane_id = plane->id; 2993 enum pipe pipe; 2994 u32 val, base, offset, stride_mult, tiling, alpha; 2995 int fourcc, pixel_format; 2996 unsigned int aligned_height; 2997 struct drm_framebuffer *fb; 2998 struct intel_framebuffer *intel_fb; 2999 static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4); 3000 3001 if (!plane->get_hw_state(plane, &pipe)) 3002 return; 3003 3004 drm_WARN_ON(display->drm, pipe != crtc->pipe); 3005 3006 if (crtc_state->joiner_pipes) { 3007 drm_dbg_kms(display->drm, 3008 "[CRTC:%d:%s] Unsupported joiner configuration for initial FB\n", 3009 crtc->base.base.id, crtc->base.name); 3010 return; 3011 } 3012 3013 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); 3014 if (!intel_fb) { 3015 drm_dbg_kms(display->drm, "failed to alloc fb\n"); 3016 return; 3017 } 3018 3019 fb = &intel_fb->base; 3020 3021 fb->dev = display->drm; 3022 3023 val = intel_de_read(display, PLANE_CTL(pipe, plane_id)); 3024 3025 if (DISPLAY_VER(display) >= 11) 3026 pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL; 3027 else 3028 pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL; 3029 3030 if (DISPLAY_VER(display) >= 10) { 3031 u32 color_ctl; 3032 3033 color_ctl = intel_de_read(display, PLANE_COLOR_CTL(pipe, plane_id)); 3034 alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl); 3035 } else { 3036 alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val); 3037 } 3038 3039 fourcc = skl_format_to_fourcc(pixel_format, 3040 val & PLANE_CTL_ORDER_RGBX, alpha); 3041 fb->format = drm_format_info(fourcc); 3042 3043 tiling = val & PLANE_CTL_TILED_MASK; 3044 switch (tiling) { 3045 case PLANE_CTL_TILED_LINEAR: 3046 fb->modifier = DRM_FORMAT_MOD_LINEAR; 3047 break; 3048 case PLANE_CTL_TILED_X: 3049 plane_config->tiling = I915_TILING_X; 3050 fb->modifier = I915_FORMAT_MOD_X_TILED; 3051 break; 3052 case PLANE_CTL_TILED_Y: 3053 plane_config->tiling = I915_TILING_Y; 3054 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3055 if (DISPLAY_VER(display) >= 14) 3056 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_RC_CCS; 3057 else if (DISPLAY_VER(display) >= 12) 3058 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS; 3059 else 3060 fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS; 3061 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) 3062 if (DISPLAY_VER(display) >= 14) 3063 fb->modifier = I915_FORMAT_MOD_4_TILED_MTL_MC_CCS; 3064 else 3065 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS; 3066 else 3067 fb->modifier = I915_FORMAT_MOD_Y_TILED; 3068 break; 3069 case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */ 3070 if (HAS_4TILE(display)) { 3071 u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | 3072 PLANE_CTL_CLEAR_COLOR_DISABLE; 3073 3074 if ((val & rc_mask) == rc_mask) 3075 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS; 3076 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) 3077 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS; 3078 else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3079 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC; 3080 else 3081 fb->modifier = I915_FORMAT_MOD_4_TILED; 3082 } else { 3083 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 3084 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; 3085 else 3086 fb->modifier = I915_FORMAT_MOD_Yf_TILED; 3087 } 3088 break; 3089 default: 3090 MISSING_CASE(tiling); 3091 goto error; 3092 } 3093 3094 if (!display->params.enable_dpt && 3095 intel_fb_modifier_uses_dpt(display, fb->modifier)) { 3096 drm_dbg_kms(display->drm, "DPT disabled, skipping initial FB\n"); 3097 goto error; 3098 } 3099 3100 /* 3101 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr 3102 * while i915 HW rotation is clockwise, that's why this swapping. 3103 */ 3104 switch (val & PLANE_CTL_ROTATE_MASK) { 3105 case PLANE_CTL_ROTATE_0: 3106 plane_config->rotation = DRM_MODE_ROTATE_0; 3107 break; 3108 case PLANE_CTL_ROTATE_90: 3109 plane_config->rotation = DRM_MODE_ROTATE_270; 3110 break; 3111 case PLANE_CTL_ROTATE_180: 3112 plane_config->rotation = DRM_MODE_ROTATE_180; 3113 break; 3114 case PLANE_CTL_ROTATE_270: 3115 plane_config->rotation = DRM_MODE_ROTATE_90; 3116 break; 3117 } 3118 3119 if (DISPLAY_VER(display) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL) 3120 plane_config->rotation |= DRM_MODE_REFLECT_X; 3121 3122 /* 90/270 degree rotation would require extra work */ 3123 if (drm_rotation_90_or_270(plane_config->rotation)) 3124 goto error; 3125 3126 base = intel_de_read(display, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK; 3127 plane_config->base = base; 3128 3129 offset = intel_de_read(display, PLANE_OFFSET(pipe, plane_id)); 3130 drm_WARN_ON(display->drm, offset != 0); 3131 3132 val = intel_de_read(display, PLANE_SIZE(pipe, plane_id)); 3133 fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1; 3134 fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1; 3135 3136 val = intel_de_read(display, PLANE_STRIDE(pipe, plane_id)); 3137 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0); 3138 3139 fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult; 3140 3141 aligned_height = intel_fb_align_height(fb, 0, fb->height); 3142 3143 plane_config->size = fb->pitches[0] * aligned_height; 3144 3145 drm_dbg_kms(display->drm, 3146 "[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 3147 crtc->base.base.id, crtc->base.name, 3148 plane->base.base.id, plane->base.name, 3149 fb->width, fb->height, fb->format->cpp[0] * 8, 3150 base, fb->pitches[0], plane_config->size); 3151 3152 plane_config->fb = intel_fb; 3153 return; 3154 3155 error: 3156 kfree(intel_fb); 3157 } 3158 3159 bool skl_fixup_initial_plane_config(struct intel_crtc *crtc, 3160 const struct intel_initial_plane_config *plane_config) 3161 { 3162 struct intel_display *display = to_intel_display(crtc); 3163 struct intel_plane *plane = to_intel_plane(crtc->base.primary); 3164 const struct intel_plane_state *plane_state = 3165 to_intel_plane_state(plane->base.state); 3166 enum plane_id plane_id = plane->id; 3167 enum pipe pipe = crtc->pipe; 3168 u32 base; 3169 3170 if (!plane_state->uapi.visible) 3171 return false; 3172 3173 base = intel_plane_ggtt_offset(plane_state); 3174 3175 /* 3176 * We may have moved the surface to a different 3177 * part of ggtt, make the plane aware of that. 3178 */ 3179 if (plane_config->base == base) 3180 return false; 3181 3182 intel_de_write(display, PLANE_SURF(pipe, plane_id), base); 3183 3184 return true; 3185 } 3186