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