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