1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2020 Intel Corporation 4 */ 5 6 #include <drm/drm_atomic_helper.h> 7 #include <drm/drm_damage_helper.h> 8 #include <drm/drm_fourcc.h> 9 #include <drm/drm_plane_helper.h> 10 11 #include "i915_drv.h" 12 #include "intel_atomic_plane.h" 13 #include "intel_display_types.h" 14 #include "intel_fb.h" 15 #include "intel_pm.h" 16 #include "intel_psr.h" 17 #include "intel_sprite.h" 18 #include "skl_scaler.h" 19 #include "skl_universal_plane.h" 20 21 static const u32 skl_plane_formats[] = { 22 DRM_FORMAT_C8, 23 DRM_FORMAT_RGB565, 24 DRM_FORMAT_XRGB8888, 25 DRM_FORMAT_XBGR8888, 26 DRM_FORMAT_ARGB8888, 27 DRM_FORMAT_ABGR8888, 28 DRM_FORMAT_XRGB2101010, 29 DRM_FORMAT_XBGR2101010, 30 DRM_FORMAT_XRGB16161616F, 31 DRM_FORMAT_XBGR16161616F, 32 DRM_FORMAT_YUYV, 33 DRM_FORMAT_YVYU, 34 DRM_FORMAT_UYVY, 35 DRM_FORMAT_VYUY, 36 DRM_FORMAT_XYUV8888, 37 }; 38 39 static const u32 skl_planar_formats[] = { 40 DRM_FORMAT_C8, 41 DRM_FORMAT_RGB565, 42 DRM_FORMAT_XRGB8888, 43 DRM_FORMAT_XBGR8888, 44 DRM_FORMAT_ARGB8888, 45 DRM_FORMAT_ABGR8888, 46 DRM_FORMAT_XRGB2101010, 47 DRM_FORMAT_XBGR2101010, 48 DRM_FORMAT_XRGB16161616F, 49 DRM_FORMAT_XBGR16161616F, 50 DRM_FORMAT_YUYV, 51 DRM_FORMAT_YVYU, 52 DRM_FORMAT_UYVY, 53 DRM_FORMAT_VYUY, 54 DRM_FORMAT_NV12, 55 DRM_FORMAT_XYUV8888, 56 }; 57 58 static const u32 glk_planar_formats[] = { 59 DRM_FORMAT_C8, 60 DRM_FORMAT_RGB565, 61 DRM_FORMAT_XRGB8888, 62 DRM_FORMAT_XBGR8888, 63 DRM_FORMAT_ARGB8888, 64 DRM_FORMAT_ABGR8888, 65 DRM_FORMAT_XRGB2101010, 66 DRM_FORMAT_XBGR2101010, 67 DRM_FORMAT_XRGB16161616F, 68 DRM_FORMAT_XBGR16161616F, 69 DRM_FORMAT_YUYV, 70 DRM_FORMAT_YVYU, 71 DRM_FORMAT_UYVY, 72 DRM_FORMAT_VYUY, 73 DRM_FORMAT_NV12, 74 DRM_FORMAT_XYUV8888, 75 DRM_FORMAT_P010, 76 DRM_FORMAT_P012, 77 DRM_FORMAT_P016, 78 }; 79 80 static const u32 icl_sdr_y_plane_formats[] = { 81 DRM_FORMAT_C8, 82 DRM_FORMAT_RGB565, 83 DRM_FORMAT_XRGB8888, 84 DRM_FORMAT_XBGR8888, 85 DRM_FORMAT_ARGB8888, 86 DRM_FORMAT_ABGR8888, 87 DRM_FORMAT_XRGB2101010, 88 DRM_FORMAT_XBGR2101010, 89 DRM_FORMAT_ARGB2101010, 90 DRM_FORMAT_ABGR2101010, 91 DRM_FORMAT_YUYV, 92 DRM_FORMAT_YVYU, 93 DRM_FORMAT_UYVY, 94 DRM_FORMAT_VYUY, 95 DRM_FORMAT_Y210, 96 DRM_FORMAT_Y212, 97 DRM_FORMAT_Y216, 98 DRM_FORMAT_XYUV8888, 99 DRM_FORMAT_XVYU2101010, 100 DRM_FORMAT_XVYU12_16161616, 101 DRM_FORMAT_XVYU16161616, 102 }; 103 104 static const u32 icl_sdr_uv_plane_formats[] = { 105 DRM_FORMAT_C8, 106 DRM_FORMAT_RGB565, 107 DRM_FORMAT_XRGB8888, 108 DRM_FORMAT_XBGR8888, 109 DRM_FORMAT_ARGB8888, 110 DRM_FORMAT_ABGR8888, 111 DRM_FORMAT_XRGB2101010, 112 DRM_FORMAT_XBGR2101010, 113 DRM_FORMAT_ARGB2101010, 114 DRM_FORMAT_ABGR2101010, 115 DRM_FORMAT_YUYV, 116 DRM_FORMAT_YVYU, 117 DRM_FORMAT_UYVY, 118 DRM_FORMAT_VYUY, 119 DRM_FORMAT_NV12, 120 DRM_FORMAT_P010, 121 DRM_FORMAT_P012, 122 DRM_FORMAT_P016, 123 DRM_FORMAT_Y210, 124 DRM_FORMAT_Y212, 125 DRM_FORMAT_Y216, 126 DRM_FORMAT_XYUV8888, 127 DRM_FORMAT_XVYU2101010, 128 DRM_FORMAT_XVYU12_16161616, 129 DRM_FORMAT_XVYU16161616, 130 }; 131 132 static const u32 icl_hdr_plane_formats[] = { 133 DRM_FORMAT_C8, 134 DRM_FORMAT_RGB565, 135 DRM_FORMAT_XRGB8888, 136 DRM_FORMAT_XBGR8888, 137 DRM_FORMAT_ARGB8888, 138 DRM_FORMAT_ABGR8888, 139 DRM_FORMAT_XRGB2101010, 140 DRM_FORMAT_XBGR2101010, 141 DRM_FORMAT_ARGB2101010, 142 DRM_FORMAT_ABGR2101010, 143 DRM_FORMAT_XRGB16161616F, 144 DRM_FORMAT_XBGR16161616F, 145 DRM_FORMAT_ARGB16161616F, 146 DRM_FORMAT_ABGR16161616F, 147 DRM_FORMAT_YUYV, 148 DRM_FORMAT_YVYU, 149 DRM_FORMAT_UYVY, 150 DRM_FORMAT_VYUY, 151 DRM_FORMAT_NV12, 152 DRM_FORMAT_P010, 153 DRM_FORMAT_P012, 154 DRM_FORMAT_P016, 155 DRM_FORMAT_Y210, 156 DRM_FORMAT_Y212, 157 DRM_FORMAT_Y216, 158 DRM_FORMAT_XYUV8888, 159 DRM_FORMAT_XVYU2101010, 160 DRM_FORMAT_XVYU12_16161616, 161 DRM_FORMAT_XVYU16161616, 162 }; 163 164 static const u64 skl_plane_format_modifiers_noccs[] = { 165 I915_FORMAT_MOD_Yf_TILED, 166 I915_FORMAT_MOD_Y_TILED, 167 I915_FORMAT_MOD_X_TILED, 168 DRM_FORMAT_MOD_LINEAR, 169 DRM_FORMAT_MOD_INVALID 170 }; 171 172 static const u64 skl_plane_format_modifiers_ccs[] = { 173 I915_FORMAT_MOD_Yf_TILED_CCS, 174 I915_FORMAT_MOD_Y_TILED_CCS, 175 I915_FORMAT_MOD_Yf_TILED, 176 I915_FORMAT_MOD_Y_TILED, 177 I915_FORMAT_MOD_X_TILED, 178 DRM_FORMAT_MOD_LINEAR, 179 DRM_FORMAT_MOD_INVALID 180 }; 181 182 static const u64 gen12_plane_format_modifiers_mc_ccs[] = { 183 I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, 184 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, 185 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, 186 I915_FORMAT_MOD_Y_TILED, 187 I915_FORMAT_MOD_X_TILED, 188 DRM_FORMAT_MOD_LINEAR, 189 DRM_FORMAT_MOD_INVALID 190 }; 191 192 static const u64 gen12_plane_format_modifiers_rc_ccs[] = { 193 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, 194 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC, 195 I915_FORMAT_MOD_Y_TILED, 196 I915_FORMAT_MOD_X_TILED, 197 DRM_FORMAT_MOD_LINEAR, 198 DRM_FORMAT_MOD_INVALID 199 }; 200 201 int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) 202 { 203 switch (format) { 204 case PLANE_CTL_FORMAT_RGB_565: 205 return DRM_FORMAT_RGB565; 206 case PLANE_CTL_FORMAT_NV12: 207 return DRM_FORMAT_NV12; 208 case PLANE_CTL_FORMAT_XYUV: 209 return DRM_FORMAT_XYUV8888; 210 case PLANE_CTL_FORMAT_P010: 211 return DRM_FORMAT_P010; 212 case PLANE_CTL_FORMAT_P012: 213 return DRM_FORMAT_P012; 214 case PLANE_CTL_FORMAT_P016: 215 return DRM_FORMAT_P016; 216 case PLANE_CTL_FORMAT_Y210: 217 return DRM_FORMAT_Y210; 218 case PLANE_CTL_FORMAT_Y212: 219 return DRM_FORMAT_Y212; 220 case PLANE_CTL_FORMAT_Y216: 221 return DRM_FORMAT_Y216; 222 case PLANE_CTL_FORMAT_Y410: 223 return DRM_FORMAT_XVYU2101010; 224 case PLANE_CTL_FORMAT_Y412: 225 return DRM_FORMAT_XVYU12_16161616; 226 case PLANE_CTL_FORMAT_Y416: 227 return DRM_FORMAT_XVYU16161616; 228 default: 229 case PLANE_CTL_FORMAT_XRGB_8888: 230 if (rgb_order) { 231 if (alpha) 232 return DRM_FORMAT_ABGR8888; 233 else 234 return DRM_FORMAT_XBGR8888; 235 } else { 236 if (alpha) 237 return DRM_FORMAT_ARGB8888; 238 else 239 return DRM_FORMAT_XRGB8888; 240 } 241 case PLANE_CTL_FORMAT_XRGB_2101010: 242 if (rgb_order) { 243 if (alpha) 244 return DRM_FORMAT_ABGR2101010; 245 else 246 return DRM_FORMAT_XBGR2101010; 247 } else { 248 if (alpha) 249 return DRM_FORMAT_ARGB2101010; 250 else 251 return DRM_FORMAT_XRGB2101010; 252 } 253 case PLANE_CTL_FORMAT_XRGB_16161616F: 254 if (rgb_order) { 255 if (alpha) 256 return DRM_FORMAT_ABGR16161616F; 257 else 258 return DRM_FORMAT_XBGR16161616F; 259 } else { 260 if (alpha) 261 return DRM_FORMAT_ARGB16161616F; 262 else 263 return DRM_FORMAT_XRGB16161616F; 264 } 265 } 266 } 267 268 static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915) 269 { 270 if (HAS_D12_PLANE_MINIMIZATION(i915)) 271 return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3); 272 else 273 return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5); 274 } 275 276 bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv, 277 enum plane_id plane_id) 278 { 279 return DISPLAY_VER(dev_priv) >= 11 && 280 icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id); 281 } 282 283 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id) 284 { 285 return DISPLAY_VER(dev_priv) >= 11 && 286 icl_hdr_plane_mask() & BIT(plane_id); 287 } 288 289 static void 290 skl_plane_ratio(const struct intel_crtc_state *crtc_state, 291 const struct intel_plane_state *plane_state, 292 unsigned int *num, unsigned int *den) 293 { 294 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); 295 const struct drm_framebuffer *fb = plane_state->hw.fb; 296 297 if (fb->format->cpp[0] == 8) { 298 if (DISPLAY_VER(dev_priv) >= 10) { 299 *num = 10; 300 *den = 8; 301 } else { 302 *num = 9; 303 *den = 8; 304 } 305 } else { 306 *num = 1; 307 *den = 1; 308 } 309 } 310 311 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state, 312 const struct intel_plane_state *plane_state) 313 { 314 struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); 315 unsigned int num, den; 316 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state); 317 318 skl_plane_ratio(crtc_state, plane_state, &num, &den); 319 320 /* two pixels per clock on glk+ */ 321 if (DISPLAY_VER(dev_priv) >= 10) 322 den *= 2; 323 324 return DIV_ROUND_UP(pixel_rate * num, den); 325 } 326 327 static int skl_plane_max_width(const struct drm_framebuffer *fb, 328 int color_plane, 329 unsigned int rotation) 330 { 331 int cpp = fb->format->cpp[color_plane]; 332 333 switch (fb->modifier) { 334 case DRM_FORMAT_MOD_LINEAR: 335 case I915_FORMAT_MOD_X_TILED: 336 /* 337 * Validated limit is 4k, but has 5k should 338 * work apart from the following features: 339 * - Ytile (already limited to 4k) 340 * - FP16 (already limited to 4k) 341 * - render compression (already limited to 4k) 342 * - KVMR sprite and cursor (don't care) 343 * - horizontal panning (TODO verify this) 344 * - pipe and plane scaling (TODO verify this) 345 */ 346 if (cpp == 8) 347 return 4096; 348 else 349 return 5120; 350 case I915_FORMAT_MOD_Y_TILED_CCS: 351 case I915_FORMAT_MOD_Yf_TILED_CCS: 352 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 353 /* FIXME AUX plane? */ 354 case I915_FORMAT_MOD_Y_TILED: 355 case I915_FORMAT_MOD_Yf_TILED: 356 if (cpp == 8) 357 return 2048; 358 else 359 return 4096; 360 default: 361 MISSING_CASE(fb->modifier); 362 return 2048; 363 } 364 } 365 366 static int glk_plane_max_width(const struct drm_framebuffer *fb, 367 int color_plane, 368 unsigned int rotation) 369 { 370 int cpp = fb->format->cpp[color_plane]; 371 372 switch (fb->modifier) { 373 case DRM_FORMAT_MOD_LINEAR: 374 case I915_FORMAT_MOD_X_TILED: 375 if (cpp == 8) 376 return 4096; 377 else 378 return 5120; 379 case I915_FORMAT_MOD_Y_TILED_CCS: 380 case I915_FORMAT_MOD_Yf_TILED_CCS: 381 /* FIXME AUX plane? */ 382 case I915_FORMAT_MOD_Y_TILED: 383 case I915_FORMAT_MOD_Yf_TILED: 384 if (cpp == 8) 385 return 2048; 386 else 387 return 5120; 388 default: 389 MISSING_CASE(fb->modifier); 390 return 2048; 391 } 392 } 393 394 static int icl_plane_min_width(const struct drm_framebuffer *fb, 395 int color_plane, 396 unsigned int rotation) 397 { 398 /* Wa_14011264657, Wa_14011050563: gen11+ */ 399 switch (fb->format->format) { 400 case DRM_FORMAT_C8: 401 return 18; 402 case DRM_FORMAT_RGB565: 403 return 10; 404 case DRM_FORMAT_XRGB8888: 405 case DRM_FORMAT_XBGR8888: 406 case DRM_FORMAT_ARGB8888: 407 case DRM_FORMAT_ABGR8888: 408 case DRM_FORMAT_XRGB2101010: 409 case DRM_FORMAT_XBGR2101010: 410 case DRM_FORMAT_ARGB2101010: 411 case DRM_FORMAT_ABGR2101010: 412 case DRM_FORMAT_XVYU2101010: 413 case DRM_FORMAT_Y212: 414 case DRM_FORMAT_Y216: 415 return 6; 416 case DRM_FORMAT_NV12: 417 return 20; 418 case DRM_FORMAT_P010: 419 case DRM_FORMAT_P012: 420 case DRM_FORMAT_P016: 421 return 12; 422 case DRM_FORMAT_XRGB16161616F: 423 case DRM_FORMAT_XBGR16161616F: 424 case DRM_FORMAT_ARGB16161616F: 425 case DRM_FORMAT_ABGR16161616F: 426 case DRM_FORMAT_XVYU12_16161616: 427 case DRM_FORMAT_XVYU16161616: 428 return 4; 429 default: 430 return 1; 431 } 432 } 433 434 static int icl_plane_max_width(const struct drm_framebuffer *fb, 435 int color_plane, 436 unsigned int rotation) 437 { 438 return 5120; 439 } 440 441 static int skl_plane_max_height(const struct drm_framebuffer *fb, 442 int color_plane, 443 unsigned int rotation) 444 { 445 return 4096; 446 } 447 448 static int icl_plane_max_height(const struct drm_framebuffer *fb, 449 int color_plane, 450 unsigned int rotation) 451 { 452 return 4320; 453 } 454 455 static unsigned int 456 skl_plane_max_stride(struct intel_plane *plane, 457 u32 pixel_format, u64 modifier, 458 unsigned int rotation) 459 { 460 const struct drm_format_info *info = drm_format_info(pixel_format); 461 int cpp = info->cpp[0]; 462 463 /* 464 * "The stride in bytes must not exceed the 465 * of the size of 8K pixels and 32K bytes." 466 */ 467 if (drm_rotation_90_or_270(rotation)) 468 return min(8192, 32768 / cpp); 469 else 470 return min(8192 * cpp, 32768); 471 } 472 473 474 /* Preoffset values for YUV to RGB Conversion */ 475 #define PREOFF_YUV_TO_RGB_HI 0x1800 476 #define PREOFF_YUV_TO_RGB_ME 0x0000 477 #define PREOFF_YUV_TO_RGB_LO 0x1800 478 479 #define ROFF(x) (((x) & 0xffff) << 16) 480 #define GOFF(x) (((x) & 0xffff) << 0) 481 #define BOFF(x) (((x) & 0xffff) << 16) 482 483 /* 484 * Programs the input color space conversion stage for ICL HDR planes. 485 * Note that it is assumed that this stage always happens after YUV 486 * range correction. Thus, the input to this stage is assumed to be 487 * in full-range YCbCr. 488 */ 489 static void 490 icl_program_input_csc(struct intel_plane *plane, 491 const struct intel_crtc_state *crtc_state, 492 const struct intel_plane_state *plane_state) 493 { 494 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 495 enum pipe pipe = plane->pipe; 496 enum plane_id plane_id = plane->id; 497 498 static const u16 input_csc_matrix[][9] = { 499 /* 500 * BT.601 full range YCbCr -> full range RGB 501 * The matrix required is : 502 * [1.000, 0.000, 1.371, 503 * 1.000, -0.336, -0.698, 504 * 1.000, 1.732, 0.0000] 505 */ 506 [DRM_COLOR_YCBCR_BT601] = { 507 0x7AF8, 0x7800, 0x0, 508 0x8B28, 0x7800, 0x9AC0, 509 0x0, 0x7800, 0x7DD8, 510 }, 511 /* 512 * BT.709 full range YCbCr -> full range RGB 513 * The matrix required is : 514 * [1.000, 0.000, 1.574, 515 * 1.000, -0.187, -0.468, 516 * 1.000, 1.855, 0.0000] 517 */ 518 [DRM_COLOR_YCBCR_BT709] = { 519 0x7C98, 0x7800, 0x0, 520 0x9EF8, 0x7800, 0xAC00, 521 0x0, 0x7800, 0x7ED8, 522 }, 523 /* 524 * BT.2020 full range YCbCr -> full range RGB 525 * The matrix required is : 526 * [1.000, 0.000, 1.474, 527 * 1.000, -0.1645, -0.5713, 528 * 1.000, 1.8814, 0.0000] 529 */ 530 [DRM_COLOR_YCBCR_BT2020] = { 531 0x7BC8, 0x7800, 0x0, 532 0x8928, 0x7800, 0xAA88, 533 0x0, 0x7800, 0x7F10, 534 }, 535 }; 536 const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding]; 537 538 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), 539 ROFF(csc[0]) | GOFF(csc[1])); 540 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), 541 BOFF(csc[2])); 542 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), 543 ROFF(csc[3]) | GOFF(csc[4])); 544 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), 545 BOFF(csc[5])); 546 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), 547 ROFF(csc[6]) | GOFF(csc[7])); 548 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), 549 BOFF(csc[8])); 550 551 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0), 552 PREOFF_YUV_TO_RGB_HI); 553 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 554 PREOFF_YUV_TO_RGB_ME); 555 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2), 556 PREOFF_YUV_TO_RGB_LO); 557 intel_de_write_fw(dev_priv, 558 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0); 559 intel_de_write_fw(dev_priv, 560 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0); 561 intel_de_write_fw(dev_priv, 562 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0); 563 } 564 565 static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb, 566 int color_plane, unsigned int rotation) 567 { 568 /* 569 * The stride is either expressed as a multiple of 64 bytes chunks for 570 * linear buffers or in number of tiles for tiled buffers. 571 */ 572 if (is_surface_linear(fb, color_plane)) 573 return 64; 574 else if (drm_rotation_90_or_270(rotation)) 575 return intel_tile_height(fb, color_plane); 576 else 577 return intel_tile_width_bytes(fb, color_plane); 578 } 579 580 static u32 skl_plane_stride(const struct intel_plane_state *plane_state, 581 int color_plane) 582 { 583 const struct drm_framebuffer *fb = plane_state->hw.fb; 584 unsigned int rotation = plane_state->hw.rotation; 585 u32 stride = plane_state->view.color_plane[color_plane].stride; 586 587 if (color_plane >= fb->format->num_planes) 588 return 0; 589 590 return stride / skl_plane_stride_mult(fb, color_plane, rotation); 591 } 592 593 static void 594 skl_disable_plane(struct intel_plane *plane, 595 const struct intel_crtc_state *crtc_state) 596 { 597 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 598 enum plane_id plane_id = plane->id; 599 enum pipe pipe = plane->pipe; 600 unsigned long irqflags; 601 602 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 603 604 if (icl_is_hdr_plane(dev_priv, plane_id)) 605 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0); 606 607 skl_write_plane_wm(plane, crtc_state); 608 609 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0); 610 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0); 611 612 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 613 } 614 615 static bool 616 skl_plane_get_hw_state(struct intel_plane *plane, 617 enum pipe *pipe) 618 { 619 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 620 enum intel_display_power_domain power_domain; 621 enum plane_id plane_id = plane->id; 622 intel_wakeref_t wakeref; 623 bool ret; 624 625 power_domain = POWER_DOMAIN_PIPE(plane->pipe); 626 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain); 627 if (!wakeref) 628 return false; 629 630 ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE; 631 632 *pipe = plane->pipe; 633 634 intel_display_power_put(dev_priv, power_domain, wakeref); 635 636 return ret; 637 } 638 639 static u32 skl_plane_ctl_format(u32 pixel_format) 640 { 641 switch (pixel_format) { 642 case DRM_FORMAT_C8: 643 return PLANE_CTL_FORMAT_INDEXED; 644 case DRM_FORMAT_RGB565: 645 return PLANE_CTL_FORMAT_RGB_565; 646 case DRM_FORMAT_XBGR8888: 647 case DRM_FORMAT_ABGR8888: 648 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX; 649 case DRM_FORMAT_XRGB8888: 650 case DRM_FORMAT_ARGB8888: 651 return PLANE_CTL_FORMAT_XRGB_8888; 652 case DRM_FORMAT_XBGR2101010: 653 case DRM_FORMAT_ABGR2101010: 654 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX; 655 case DRM_FORMAT_XRGB2101010: 656 case DRM_FORMAT_ARGB2101010: 657 return PLANE_CTL_FORMAT_XRGB_2101010; 658 case DRM_FORMAT_XBGR16161616F: 659 case DRM_FORMAT_ABGR16161616F: 660 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX; 661 case DRM_FORMAT_XRGB16161616F: 662 case DRM_FORMAT_ARGB16161616F: 663 return PLANE_CTL_FORMAT_XRGB_16161616F; 664 case DRM_FORMAT_XYUV8888: 665 return PLANE_CTL_FORMAT_XYUV; 666 case DRM_FORMAT_YUYV: 667 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV; 668 case DRM_FORMAT_YVYU: 669 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU; 670 case DRM_FORMAT_UYVY: 671 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY; 672 case DRM_FORMAT_VYUY: 673 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY; 674 case DRM_FORMAT_NV12: 675 return PLANE_CTL_FORMAT_NV12; 676 case DRM_FORMAT_P010: 677 return PLANE_CTL_FORMAT_P010; 678 case DRM_FORMAT_P012: 679 return PLANE_CTL_FORMAT_P012; 680 case DRM_FORMAT_P016: 681 return PLANE_CTL_FORMAT_P016; 682 case DRM_FORMAT_Y210: 683 return PLANE_CTL_FORMAT_Y210; 684 case DRM_FORMAT_Y212: 685 return PLANE_CTL_FORMAT_Y212; 686 case DRM_FORMAT_Y216: 687 return PLANE_CTL_FORMAT_Y216; 688 case DRM_FORMAT_XVYU2101010: 689 return PLANE_CTL_FORMAT_Y410; 690 case DRM_FORMAT_XVYU12_16161616: 691 return PLANE_CTL_FORMAT_Y412; 692 case DRM_FORMAT_XVYU16161616: 693 return PLANE_CTL_FORMAT_Y416; 694 default: 695 MISSING_CASE(pixel_format); 696 } 697 698 return 0; 699 } 700 701 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state) 702 { 703 if (!plane_state->hw.fb->format->has_alpha) 704 return PLANE_CTL_ALPHA_DISABLE; 705 706 switch (plane_state->hw.pixel_blend_mode) { 707 case DRM_MODE_BLEND_PIXEL_NONE: 708 return PLANE_CTL_ALPHA_DISABLE; 709 case DRM_MODE_BLEND_PREMULTI: 710 return PLANE_CTL_ALPHA_SW_PREMULTIPLY; 711 case DRM_MODE_BLEND_COVERAGE: 712 return PLANE_CTL_ALPHA_HW_PREMULTIPLY; 713 default: 714 MISSING_CASE(plane_state->hw.pixel_blend_mode); 715 return PLANE_CTL_ALPHA_DISABLE; 716 } 717 } 718 719 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state) 720 { 721 if (!plane_state->hw.fb->format->has_alpha) 722 return PLANE_COLOR_ALPHA_DISABLE; 723 724 switch (plane_state->hw.pixel_blend_mode) { 725 case DRM_MODE_BLEND_PIXEL_NONE: 726 return PLANE_COLOR_ALPHA_DISABLE; 727 case DRM_MODE_BLEND_PREMULTI: 728 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY; 729 case DRM_MODE_BLEND_COVERAGE: 730 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY; 731 default: 732 MISSING_CASE(plane_state->hw.pixel_blend_mode); 733 return PLANE_COLOR_ALPHA_DISABLE; 734 } 735 } 736 737 static u32 skl_plane_ctl_tiling(u64 fb_modifier) 738 { 739 switch (fb_modifier) { 740 case DRM_FORMAT_MOD_LINEAR: 741 break; 742 case I915_FORMAT_MOD_X_TILED: 743 return PLANE_CTL_TILED_X; 744 case I915_FORMAT_MOD_Y_TILED: 745 return PLANE_CTL_TILED_Y; 746 case I915_FORMAT_MOD_Y_TILED_CCS: 747 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: 748 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 749 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: 750 return PLANE_CTL_TILED_Y | 751 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE | 752 PLANE_CTL_CLEAR_COLOR_DISABLE; 753 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 754 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE; 755 case I915_FORMAT_MOD_Yf_TILED: 756 return PLANE_CTL_TILED_YF; 757 case I915_FORMAT_MOD_Yf_TILED_CCS: 758 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; 759 default: 760 MISSING_CASE(fb_modifier); 761 } 762 763 return 0; 764 } 765 766 static u32 skl_plane_ctl_rotate(unsigned int rotate) 767 { 768 switch (rotate) { 769 case DRM_MODE_ROTATE_0: 770 break; 771 /* 772 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr 773 * while i915 HW rotation is clockwise, thats why this swapping. 774 */ 775 case DRM_MODE_ROTATE_90: 776 return PLANE_CTL_ROTATE_270; 777 case DRM_MODE_ROTATE_180: 778 return PLANE_CTL_ROTATE_180; 779 case DRM_MODE_ROTATE_270: 780 return PLANE_CTL_ROTATE_90; 781 default: 782 MISSING_CASE(rotate); 783 } 784 785 return 0; 786 } 787 788 static u32 cnl_plane_ctl_flip(unsigned int reflect) 789 { 790 switch (reflect) { 791 case 0: 792 break; 793 case DRM_MODE_REFLECT_X: 794 return PLANE_CTL_FLIP_HORIZONTAL; 795 case DRM_MODE_REFLECT_Y: 796 default: 797 MISSING_CASE(reflect); 798 } 799 800 return 0; 801 } 802 803 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) 804 { 805 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 806 u32 plane_ctl = 0; 807 808 if (DISPLAY_VER(dev_priv) >= 10) 809 return plane_ctl; 810 811 if (crtc_state->gamma_enable) 812 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE; 813 814 if (crtc_state->csc_enable) 815 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE; 816 817 return plane_ctl; 818 } 819 820 static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, 821 const struct intel_plane_state *plane_state) 822 { 823 struct drm_i915_private *dev_priv = 824 to_i915(plane_state->uapi.plane->dev); 825 const struct drm_framebuffer *fb = plane_state->hw.fb; 826 unsigned int rotation = plane_state->hw.rotation; 827 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 828 u32 plane_ctl; 829 830 plane_ctl = PLANE_CTL_ENABLE; 831 832 if (DISPLAY_VER(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) { 833 plane_ctl |= skl_plane_ctl_alpha(plane_state); 834 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE; 835 836 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709) 837 plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709; 838 839 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 840 plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE; 841 } 842 843 plane_ctl |= skl_plane_ctl_format(fb->format->format); 844 plane_ctl |= skl_plane_ctl_tiling(fb->modifier); 845 plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK); 846 847 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) 848 plane_ctl |= cnl_plane_ctl_flip(rotation & 849 DRM_MODE_REFLECT_MASK); 850 851 if (key->flags & I915_SET_COLORKEY_DESTINATION) 852 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; 853 else if (key->flags & I915_SET_COLORKEY_SOURCE) 854 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; 855 856 return plane_ctl; 857 } 858 859 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state) 860 { 861 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 862 u32 plane_color_ctl = 0; 863 864 if (DISPLAY_VER(dev_priv) >= 11) 865 return plane_color_ctl; 866 867 if (crtc_state->gamma_enable) 868 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE; 869 870 if (crtc_state->csc_enable) 871 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE; 872 873 return plane_color_ctl; 874 } 875 876 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, 877 const struct intel_plane_state *plane_state) 878 { 879 struct drm_i915_private *dev_priv = 880 to_i915(plane_state->uapi.plane->dev); 881 const struct drm_framebuffer *fb = plane_state->hw.fb; 882 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 883 u32 plane_color_ctl = 0; 884 885 plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; 886 plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); 887 888 if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) { 889 switch (plane_state->hw.color_encoding) { 890 case DRM_COLOR_YCBCR_BT709: 891 plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; 892 break; 893 case DRM_COLOR_YCBCR_BT2020: 894 plane_color_ctl |= 895 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; 896 break; 897 default: 898 plane_color_ctl |= 899 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; 900 } 901 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 902 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; 903 } else if (fb->format->is_yuv) { 904 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; 905 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) 906 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; 907 } 908 909 return plane_color_ctl; 910 } 911 912 static void 913 skl_program_plane(struct intel_plane *plane, 914 const struct intel_crtc_state *crtc_state, 915 const struct intel_plane_state *plane_state, 916 int color_plane) 917 { 918 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 919 enum plane_id plane_id = plane->id; 920 enum pipe pipe = plane->pipe; 921 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; 922 u32 surf_addr = plane_state->view.color_plane[color_plane].offset; 923 u32 stride = skl_plane_stride(plane_state, color_plane); 924 const struct drm_framebuffer *fb = plane_state->hw.fb; 925 int aux_plane = skl_main_to_aux_plane(fb, color_plane); 926 int crtc_x = plane_state->uapi.dst.x1; 927 int crtc_y = plane_state->uapi.dst.y1; 928 u32 x = plane_state->view.color_plane[color_plane].x; 929 u32 y = plane_state->view.color_plane[color_plane].y; 930 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 931 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; 932 u8 alpha = plane_state->hw.alpha >> 8; 933 u32 plane_color_ctl = 0, aux_dist = 0; 934 unsigned long irqflags; 935 u32 keymsk, keymax; 936 u32 plane_ctl = plane_state->ctl; 937 938 plane_ctl |= skl_plane_ctl_crtc(crtc_state); 939 940 if (DISPLAY_VER(dev_priv) >= 10) 941 plane_color_ctl = plane_state->color_ctl | 942 glk_plane_color_ctl_crtc(crtc_state); 943 944 /* Sizes are 0 based */ 945 src_w--; 946 src_h--; 947 948 keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); 949 950 keymsk = key->channel_mask & 0x7ffffff; 951 if (alpha < 0xff) 952 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; 953 954 /* The scaler will handle the output position */ 955 if (plane_state->scaler_id >= 0) { 956 crtc_x = 0; 957 crtc_y = 0; 958 } 959 960 if (aux_plane) { 961 aux_dist = plane_state->view.color_plane[aux_plane].offset - surf_addr; 962 963 if (DISPLAY_VER(dev_priv) < 12) 964 aux_dist |= skl_plane_stride(plane_state, aux_plane); 965 } 966 967 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 968 969 intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), stride); 970 intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), 971 (crtc_y << 16) | crtc_x); 972 intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id), 973 (src_h << 16) | src_w); 974 975 intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), aux_dist); 976 977 if (icl_is_hdr_plane(dev_priv, plane_id)) 978 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 979 plane_state->cus_ctl); 980 981 if (DISPLAY_VER(dev_priv) >= 10) 982 intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), 983 plane_color_ctl); 984 985 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id)) 986 icl_program_input_csc(plane, crtc_state, plane_state); 987 988 if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC) 989 intel_uncore_write64_fw(&dev_priv->uncore, 990 PLANE_CC_VAL(pipe, plane_id), plane_state->ccval); 991 992 skl_write_plane_wm(plane, crtc_state); 993 994 intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), 995 key->min_value); 996 intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), keymsk); 997 intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), keymax); 998 999 intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id), 1000 (y << 16) | x); 1001 1002 if (DISPLAY_VER(dev_priv) < 11) 1003 intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id), 1004 (plane_state->view.color_plane[1].y << 16) | 1005 plane_state->view.color_plane[1].x); 1006 1007 if (!drm_atomic_crtc_needs_modeset(&crtc_state->uapi)) 1008 intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); 1009 1010 /* 1011 * The control register self-arms if the plane was previously 1012 * disabled. Try to make the plane enable atomic by writing 1013 * the control register just before the surface register. 1014 */ 1015 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); 1016 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 1017 intel_plane_ggtt_offset(plane_state) + surf_addr); 1018 1019 if (plane_state->scaler_id >= 0) 1020 skl_program_plane_scaler(plane, crtc_state, plane_state); 1021 1022 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 1023 } 1024 1025 static void 1026 skl_plane_async_flip(struct intel_plane *plane, 1027 const struct intel_crtc_state *crtc_state, 1028 const struct intel_plane_state *plane_state, 1029 bool async_flip) 1030 { 1031 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1032 unsigned long irqflags; 1033 enum plane_id plane_id = plane->id; 1034 enum pipe pipe = plane->pipe; 1035 u32 surf_addr = plane_state->view.color_plane[0].offset; 1036 u32 plane_ctl = plane_state->ctl; 1037 1038 plane_ctl |= skl_plane_ctl_crtc(crtc_state); 1039 1040 if (async_flip) 1041 plane_ctl |= PLANE_CTL_ASYNC_FLIP; 1042 1043 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); 1044 1045 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); 1046 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 1047 intel_plane_ggtt_offset(plane_state) + surf_addr); 1048 1049 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 1050 } 1051 1052 static void 1053 skl_update_plane(struct intel_plane *plane, 1054 const struct intel_crtc_state *crtc_state, 1055 const struct intel_plane_state *plane_state) 1056 { 1057 int color_plane = 0; 1058 1059 if (plane_state->planar_linked_plane && !plane_state->planar_slave) 1060 /* Program the UV plane on planar master */ 1061 color_plane = 1; 1062 1063 skl_program_plane(plane, crtc_state, plane_state, color_plane); 1064 } 1065 1066 static bool intel_format_is_p01x(u32 format) 1067 { 1068 switch (format) { 1069 case DRM_FORMAT_P010: 1070 case DRM_FORMAT_P012: 1071 case DRM_FORMAT_P016: 1072 return true; 1073 default: 1074 return false; 1075 } 1076 } 1077 1078 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, 1079 const struct intel_plane_state *plane_state) 1080 { 1081 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1082 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1083 const struct drm_framebuffer *fb = plane_state->hw.fb; 1084 unsigned int rotation = plane_state->hw.rotation; 1085 struct drm_format_name_buf format_name; 1086 1087 if (!fb) 1088 return 0; 1089 1090 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) && 1091 is_ccs_modifier(fb->modifier)) { 1092 drm_dbg_kms(&dev_priv->drm, 1093 "RC support only with 0/180 degree rotation (%x)\n", 1094 rotation); 1095 return -EINVAL; 1096 } 1097 1098 if (rotation & DRM_MODE_REFLECT_X && 1099 fb->modifier == DRM_FORMAT_MOD_LINEAR) { 1100 drm_dbg_kms(&dev_priv->drm, 1101 "horizontal flip is not supported with linear surface formats\n"); 1102 return -EINVAL; 1103 } 1104 1105 if (drm_rotation_90_or_270(rotation)) { 1106 if (fb->modifier != I915_FORMAT_MOD_Y_TILED && 1107 fb->modifier != I915_FORMAT_MOD_Yf_TILED) { 1108 drm_dbg_kms(&dev_priv->drm, 1109 "Y/Yf tiling required for 90/270!\n"); 1110 return -EINVAL; 1111 } 1112 1113 /* 1114 * 90/270 is not allowed with RGB64 16:16:16:16 and 1115 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards. 1116 */ 1117 switch (fb->format->format) { 1118 case DRM_FORMAT_RGB565: 1119 if (DISPLAY_VER(dev_priv) >= 11) 1120 break; 1121 fallthrough; 1122 case DRM_FORMAT_C8: 1123 case DRM_FORMAT_XRGB16161616F: 1124 case DRM_FORMAT_XBGR16161616F: 1125 case DRM_FORMAT_ARGB16161616F: 1126 case DRM_FORMAT_ABGR16161616F: 1127 case DRM_FORMAT_Y210: 1128 case DRM_FORMAT_Y212: 1129 case DRM_FORMAT_Y216: 1130 case DRM_FORMAT_XVYU12_16161616: 1131 case DRM_FORMAT_XVYU16161616: 1132 drm_dbg_kms(&dev_priv->drm, 1133 "Unsupported pixel format %s for 90/270!\n", 1134 drm_get_format_name(fb->format->format, 1135 &format_name)); 1136 return -EINVAL; 1137 default: 1138 break; 1139 } 1140 } 1141 1142 /* Y-tiling is not supported in IF-ID Interlace mode */ 1143 if (crtc_state->hw.enable && 1144 crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && 1145 (fb->modifier == I915_FORMAT_MOD_Y_TILED || 1146 fb->modifier == I915_FORMAT_MOD_Yf_TILED || 1147 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || 1148 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS || 1149 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || 1150 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || 1151 fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC)) { 1152 drm_dbg_kms(&dev_priv->drm, 1153 "Y/Yf tiling not supported in IF-ID mode\n"); 1154 return -EINVAL; 1155 } 1156 1157 /* Wa_1606054188:tgl,adl-s */ 1158 if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) && 1159 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE && 1160 intel_format_is_p01x(fb->format->format)) { 1161 drm_dbg_kms(&dev_priv->drm, 1162 "Source color keying not supported with P01x formats\n"); 1163 return -EINVAL; 1164 } 1165 1166 return 0; 1167 } 1168 1169 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state, 1170 const struct intel_plane_state *plane_state) 1171 { 1172 struct drm_i915_private *dev_priv = 1173 to_i915(plane_state->uapi.plane->dev); 1174 int crtc_x = plane_state->uapi.dst.x1; 1175 int crtc_w = drm_rect_width(&plane_state->uapi.dst); 1176 int pipe_src_w = crtc_state->pipe_src_w; 1177 1178 /* 1179 * Display WA #1175: cnl,glk 1180 * Planes other than the cursor may cause FIFO underflow and display 1181 * corruption if starting less than 4 pixels from the right edge of 1182 * the screen. 1183 * Besides the above WA fix the similar problem, where planes other 1184 * than the cursor ending less than 4 pixels from the left edge of the 1185 * screen may cause FIFO underflow and display corruption. 1186 */ 1187 if (IS_DISPLAY_VER(dev_priv, 10) && 1188 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) { 1189 drm_dbg_kms(&dev_priv->drm, 1190 "requested plane X %s position %d invalid (valid range %d-%d)\n", 1191 crtc_x + crtc_w < 4 ? "end" : "start", 1192 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x, 1193 4, pipe_src_w - 4); 1194 return -ERANGE; 1195 } 1196 1197 return 0; 1198 } 1199 1200 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state) 1201 { 1202 const struct drm_framebuffer *fb = plane_state->hw.fb; 1203 unsigned int rotation = plane_state->hw.rotation; 1204 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; 1205 1206 /* Display WA #1106 */ 1207 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && 1208 src_w & 3 && 1209 (rotation == DRM_MODE_ROTATE_270 || 1210 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) { 1211 DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n"); 1212 return -EINVAL; 1213 } 1214 1215 return 0; 1216 } 1217 1218 static int skl_plane_max_scale(struct drm_i915_private *dev_priv, 1219 const struct drm_framebuffer *fb) 1220 { 1221 /* 1222 * We don't yet know the final source width nor 1223 * whether we can use the HQ scaler mode. Assume 1224 * the best case. 1225 * FIXME need to properly check this later. 1226 */ 1227 if (DISPLAY_VER(dev_priv) >= 10 || 1228 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) 1229 return 0x30000 - 1; 1230 else 1231 return 0x20000 - 1; 1232 } 1233 1234 static int intel_plane_min_width(struct intel_plane *plane, 1235 const struct drm_framebuffer *fb, 1236 int color_plane, 1237 unsigned int rotation) 1238 { 1239 if (plane->min_width) 1240 return plane->min_width(fb, color_plane, rotation); 1241 else 1242 return 1; 1243 } 1244 1245 static int intel_plane_max_width(struct intel_plane *plane, 1246 const struct drm_framebuffer *fb, 1247 int color_plane, 1248 unsigned int rotation) 1249 { 1250 if (plane->max_width) 1251 return plane->max_width(fb, color_plane, rotation); 1252 else 1253 return INT_MAX; 1254 } 1255 1256 static int intel_plane_max_height(struct intel_plane *plane, 1257 const struct drm_framebuffer *fb, 1258 int color_plane, 1259 unsigned int rotation) 1260 { 1261 if (plane->max_height) 1262 return plane->max_height(fb, color_plane, rotation); 1263 else 1264 return INT_MAX; 1265 } 1266 1267 static bool 1268 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, 1269 int main_x, int main_y, u32 main_offset, 1270 int ccs_plane) 1271 { 1272 const struct drm_framebuffer *fb = plane_state->hw.fb; 1273 int aux_x = plane_state->view.color_plane[ccs_plane].x; 1274 int aux_y = plane_state->view.color_plane[ccs_plane].y; 1275 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 1276 u32 alignment = intel_surf_alignment(fb, ccs_plane); 1277 int hsub; 1278 int vsub; 1279 1280 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); 1281 while (aux_offset >= main_offset && aux_y <= main_y) { 1282 int x, y; 1283 1284 if (aux_x == main_x && aux_y == main_y) 1285 break; 1286 1287 if (aux_offset == 0) 1288 break; 1289 1290 x = aux_x / hsub; 1291 y = aux_y / vsub; 1292 aux_offset = intel_plane_adjust_aligned_offset(&x, &y, 1293 plane_state, 1294 ccs_plane, 1295 aux_offset, 1296 aux_offset - 1297 alignment); 1298 aux_x = x * hsub + aux_x % hsub; 1299 aux_y = y * vsub + aux_y % vsub; 1300 } 1301 1302 if (aux_x != main_x || aux_y != main_y) 1303 return false; 1304 1305 plane_state->view.color_plane[ccs_plane].offset = aux_offset; 1306 plane_state->view.color_plane[ccs_plane].x = aux_x; 1307 plane_state->view.color_plane[ccs_plane].y = aux_y; 1308 1309 return true; 1310 } 1311 1312 1313 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state, 1314 int *x, int *y, u32 *offset) 1315 { 1316 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1317 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1318 const struct drm_framebuffer *fb = plane_state->hw.fb; 1319 const int aux_plane = skl_main_to_aux_plane(fb, 0); 1320 const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset; 1321 const u32 alignment = intel_surf_alignment(fb, 0); 1322 const int w = drm_rect_width(&plane_state->uapi.src) >> 16; 1323 1324 intel_add_fb_offsets(x, y, plane_state, 0); 1325 *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0); 1326 if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment))) 1327 return -EINVAL; 1328 1329 /* 1330 * AUX surface offset is specified as the distance from the 1331 * main surface offset, and it must be non-negative. Make 1332 * sure that is what we will get. 1333 */ 1334 if (aux_plane && *offset > aux_offset) 1335 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0, 1336 *offset, 1337 aux_offset & ~(alignment - 1)); 1338 1339 /* 1340 * When using an X-tiled surface, the plane blows up 1341 * if the x offset + width exceed the stride. 1342 * 1343 * TODO: linear and Y-tiled seem fine, Yf untested, 1344 */ 1345 if (fb->modifier == I915_FORMAT_MOD_X_TILED) { 1346 int cpp = fb->format->cpp[0]; 1347 1348 while ((*x + w) * cpp > plane_state->view.color_plane[0].stride) { 1349 if (*offset == 0) { 1350 drm_dbg_kms(&dev_priv->drm, 1351 "Unable to find suitable display surface offset due to X-tiling\n"); 1352 return -EINVAL; 1353 } 1354 1355 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0, 1356 *offset, 1357 *offset - alignment); 1358 } 1359 } 1360 1361 return 0; 1362 } 1363 1364 static int skl_check_main_surface(struct intel_plane_state *plane_state) 1365 { 1366 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1367 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1368 const struct drm_framebuffer *fb = plane_state->hw.fb; 1369 const unsigned int rotation = plane_state->hw.rotation; 1370 int x = plane_state->uapi.src.x1 >> 16; 1371 int y = plane_state->uapi.src.y1 >> 16; 1372 const int w = drm_rect_width(&plane_state->uapi.src) >> 16; 1373 const int h = drm_rect_height(&plane_state->uapi.src) >> 16; 1374 const int min_width = intel_plane_min_width(plane, fb, 0, rotation); 1375 const int max_width = intel_plane_max_width(plane, fb, 0, rotation); 1376 const int max_height = intel_plane_max_height(plane, fb, 0, rotation); 1377 const int aux_plane = skl_main_to_aux_plane(fb, 0); 1378 const u32 alignment = intel_surf_alignment(fb, 0); 1379 u32 offset; 1380 int ret; 1381 1382 if (w > max_width || w < min_width || h > max_height) { 1383 drm_dbg_kms(&dev_priv->drm, 1384 "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", 1385 w, h, min_width, max_width, max_height); 1386 return -EINVAL; 1387 } 1388 1389 ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset); 1390 if (ret) 1391 return ret; 1392 1393 /* 1394 * CCS AUX surface doesn't have its own x/y offsets, we must make sure 1395 * they match with the main surface x/y offsets. 1396 */ 1397 if (is_ccs_modifier(fb->modifier)) { 1398 while (!skl_check_main_ccs_coordinates(plane_state, x, y, 1399 offset, aux_plane)) { 1400 if (offset == 0) 1401 break; 1402 1403 offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, 1404 offset, offset - alignment); 1405 } 1406 1407 if (x != plane_state->view.color_plane[aux_plane].x || 1408 y != plane_state->view.color_plane[aux_plane].y) { 1409 drm_dbg_kms(&dev_priv->drm, 1410 "Unable to find suitable display surface offset due to CCS\n"); 1411 return -EINVAL; 1412 } 1413 } 1414 1415 drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191); 1416 1417 plane_state->view.color_plane[0].offset = offset; 1418 plane_state->view.color_plane[0].x = x; 1419 plane_state->view.color_plane[0].y = y; 1420 1421 /* 1422 * Put the final coordinates back so that the src 1423 * coordinate checks will see the right values. 1424 */ 1425 drm_rect_translate_to(&plane_state->uapi.src, 1426 x << 16, y << 16); 1427 1428 return 0; 1429 } 1430 1431 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) 1432 { 1433 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1434 struct drm_i915_private *i915 = to_i915(plane->base.dev); 1435 const struct drm_framebuffer *fb = plane_state->hw.fb; 1436 unsigned int rotation = plane_state->hw.rotation; 1437 int uv_plane = 1; 1438 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); 1439 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); 1440 int x = plane_state->uapi.src.x1 >> 17; 1441 int y = plane_state->uapi.src.y1 >> 17; 1442 int w = drm_rect_width(&plane_state->uapi.src) >> 17; 1443 int h = drm_rect_height(&plane_state->uapi.src) >> 17; 1444 u32 offset; 1445 1446 /* FIXME not quite sure how/if these apply to the chroma plane */ 1447 if (w > max_width || h > max_height) { 1448 drm_dbg_kms(&i915->drm, 1449 "CbCr source size %dx%d too big (limit %dx%d)\n", 1450 w, h, max_width, max_height); 1451 return -EINVAL; 1452 } 1453 1454 intel_add_fb_offsets(&x, &y, plane_state, uv_plane); 1455 offset = intel_plane_compute_aligned_offset(&x, &y, 1456 plane_state, uv_plane); 1457 1458 if (is_ccs_modifier(fb->modifier)) { 1459 int ccs_plane = main_to_ccs_plane(fb, uv_plane); 1460 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset; 1461 u32 alignment = intel_surf_alignment(fb, uv_plane); 1462 1463 if (offset > aux_offset) 1464 offset = intel_plane_adjust_aligned_offset(&x, &y, 1465 plane_state, 1466 uv_plane, 1467 offset, 1468 aux_offset & ~(alignment - 1)); 1469 1470 while (!skl_check_main_ccs_coordinates(plane_state, x, y, 1471 offset, ccs_plane)) { 1472 if (offset == 0) 1473 break; 1474 1475 offset = intel_plane_adjust_aligned_offset(&x, &y, 1476 plane_state, 1477 uv_plane, 1478 offset, offset - alignment); 1479 } 1480 1481 if (x != plane_state->view.color_plane[ccs_plane].x || 1482 y != plane_state->view.color_plane[ccs_plane].y) { 1483 drm_dbg_kms(&i915->drm, 1484 "Unable to find suitable display surface offset due to CCS\n"); 1485 return -EINVAL; 1486 } 1487 } 1488 1489 drm_WARN_ON(&i915->drm, x > 8191 || y > 8191); 1490 1491 plane_state->view.color_plane[uv_plane].offset = offset; 1492 plane_state->view.color_plane[uv_plane].x = x; 1493 plane_state->view.color_plane[uv_plane].y = y; 1494 1495 return 0; 1496 } 1497 1498 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) 1499 { 1500 const struct drm_framebuffer *fb = plane_state->hw.fb; 1501 int src_x = plane_state->uapi.src.x1 >> 16; 1502 int src_y = plane_state->uapi.src.y1 >> 16; 1503 u32 offset; 1504 int ccs_plane; 1505 1506 for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) { 1507 int main_hsub, main_vsub; 1508 int hsub, vsub; 1509 int x, y; 1510 1511 if (!is_ccs_plane(fb, ccs_plane) || 1512 is_gen12_ccs_cc_plane(fb, ccs_plane)) 1513 continue; 1514 1515 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, 1516 skl_ccs_to_main_plane(fb, ccs_plane)); 1517 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane); 1518 1519 hsub *= main_hsub; 1520 vsub *= main_vsub; 1521 x = src_x / hsub; 1522 y = src_y / vsub; 1523 1524 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane); 1525 1526 offset = intel_plane_compute_aligned_offset(&x, &y, 1527 plane_state, 1528 ccs_plane); 1529 1530 plane_state->view.color_plane[ccs_plane].offset = offset; 1531 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub; 1532 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub; 1533 } 1534 1535 return 0; 1536 } 1537 1538 static int skl_check_plane_surface(struct intel_plane_state *plane_state) 1539 { 1540 const struct drm_framebuffer *fb = plane_state->hw.fb; 1541 int ret; 1542 1543 ret = intel_plane_compute_gtt(plane_state); 1544 if (ret) 1545 return ret; 1546 1547 if (!plane_state->uapi.visible) 1548 return 0; 1549 1550 /* 1551 * Handle the AUX surface first since the main surface setup depends on 1552 * it. 1553 */ 1554 if (is_ccs_modifier(fb->modifier)) { 1555 ret = skl_check_ccs_aux_surface(plane_state); 1556 if (ret) 1557 return ret; 1558 } 1559 1560 if (intel_format_info_is_yuv_semiplanar(fb->format, 1561 fb->modifier)) { 1562 ret = skl_check_nv12_aux_surface(plane_state); 1563 if (ret) 1564 return ret; 1565 } 1566 1567 ret = skl_check_main_surface(plane_state); 1568 if (ret) 1569 return ret; 1570 1571 return 0; 1572 } 1573 1574 static bool skl_fb_scalable(const struct drm_framebuffer *fb) 1575 { 1576 if (!fb) 1577 return false; 1578 1579 switch (fb->format->format) { 1580 case DRM_FORMAT_C8: 1581 return false; 1582 case DRM_FORMAT_XRGB16161616F: 1583 case DRM_FORMAT_ARGB16161616F: 1584 case DRM_FORMAT_XBGR16161616F: 1585 case DRM_FORMAT_ABGR16161616F: 1586 return DISPLAY_VER(to_i915(fb->dev)) >= 11; 1587 default: 1588 return true; 1589 } 1590 } 1591 1592 static int skl_plane_check(struct intel_crtc_state *crtc_state, 1593 struct intel_plane_state *plane_state) 1594 { 1595 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 1596 struct drm_i915_private *dev_priv = to_i915(plane->base.dev); 1597 const struct drm_framebuffer *fb = plane_state->hw.fb; 1598 int min_scale = DRM_PLANE_HELPER_NO_SCALING; 1599 int max_scale = DRM_PLANE_HELPER_NO_SCALING; 1600 int ret; 1601 1602 ret = skl_plane_check_fb(crtc_state, plane_state); 1603 if (ret) 1604 return ret; 1605 1606 /* use scaler when colorkey is not required */ 1607 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) { 1608 min_scale = 1; 1609 max_scale = skl_plane_max_scale(dev_priv, fb); 1610 } 1611 1612 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, 1613 min_scale, max_scale, true); 1614 if (ret) 1615 return ret; 1616 1617 ret = skl_check_plane_surface(plane_state); 1618 if (ret) 1619 return ret; 1620 1621 if (!plane_state->uapi.visible) 1622 return 0; 1623 1624 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state); 1625 if (ret) 1626 return ret; 1627 1628 ret = intel_plane_check_src_coordinates(plane_state); 1629 if (ret) 1630 return ret; 1631 1632 ret = skl_plane_check_nv12_rotation(plane_state); 1633 if (ret) 1634 return ret; 1635 1636 /* HW only has 8 bits pixel precision, disable plane if invisible */ 1637 if (!(plane_state->hw.alpha >> 8)) 1638 plane_state->uapi.visible = false; 1639 1640 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); 1641 1642 if (DISPLAY_VER(dev_priv) >= 10) 1643 plane_state->color_ctl = glk_plane_color_ctl(crtc_state, 1644 plane_state); 1645 1646 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && 1647 icl_is_hdr_plane(dev_priv, plane->id)) 1648 /* Enable and use MPEG-2 chroma siting */ 1649 plane_state->cus_ctl = PLANE_CUS_ENABLE | 1650 PLANE_CUS_HPHASE_0 | 1651 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25; 1652 else 1653 plane_state->cus_ctl = 0; 1654 1655 return 0; 1656 } 1657 1658 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv, 1659 enum pipe pipe, enum plane_id plane_id) 1660 { 1661 if (!HAS_FBC(dev_priv)) 1662 return false; 1663 1664 return pipe == PIPE_A && plane_id == PLANE_PRIMARY; 1665 } 1666 1667 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv, 1668 enum pipe pipe, enum plane_id plane_id) 1669 { 1670 /* Display WA #0870: skl, bxt */ 1671 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) 1672 return false; 1673 1674 if (IS_DISPLAY_VER(dev_priv, 9) && pipe == PIPE_C) 1675 return false; 1676 1677 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0) 1678 return false; 1679 1680 return true; 1681 } 1682 1683 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv, 1684 enum pipe pipe, enum plane_id plane_id, 1685 int *num_formats) 1686 { 1687 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) { 1688 *num_formats = ARRAY_SIZE(skl_planar_formats); 1689 return skl_planar_formats; 1690 } else { 1691 *num_formats = ARRAY_SIZE(skl_plane_formats); 1692 return skl_plane_formats; 1693 } 1694 } 1695 1696 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv, 1697 enum pipe pipe, enum plane_id plane_id, 1698 int *num_formats) 1699 { 1700 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) { 1701 *num_formats = ARRAY_SIZE(glk_planar_formats); 1702 return glk_planar_formats; 1703 } else { 1704 *num_formats = ARRAY_SIZE(skl_plane_formats); 1705 return skl_plane_formats; 1706 } 1707 } 1708 1709 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv, 1710 enum pipe pipe, enum plane_id plane_id, 1711 int *num_formats) 1712 { 1713 if (icl_is_hdr_plane(dev_priv, plane_id)) { 1714 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats); 1715 return icl_hdr_plane_formats; 1716 } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) { 1717 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats); 1718 return icl_sdr_y_plane_formats; 1719 } else { 1720 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats); 1721 return icl_sdr_uv_plane_formats; 1722 } 1723 } 1724 1725 static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, 1726 enum pipe pipe, enum plane_id plane_id) 1727 { 1728 if (plane_id == PLANE_CURSOR) 1729 return false; 1730 1731 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) 1732 return true; 1733 1734 if (IS_GEMINILAKE(dev_priv)) 1735 return pipe != PIPE_C; 1736 1737 return pipe != PIPE_C && 1738 (plane_id == PLANE_PRIMARY || 1739 plane_id == PLANE_SPRITE0); 1740 } 1741 1742 static bool skl_plane_format_mod_supported(struct drm_plane *_plane, 1743 u32 format, u64 modifier) 1744 { 1745 struct intel_plane *plane = to_intel_plane(_plane); 1746 1747 switch (modifier) { 1748 case DRM_FORMAT_MOD_LINEAR: 1749 case I915_FORMAT_MOD_X_TILED: 1750 case I915_FORMAT_MOD_Y_TILED: 1751 case I915_FORMAT_MOD_Yf_TILED: 1752 break; 1753 case I915_FORMAT_MOD_Y_TILED_CCS: 1754 case I915_FORMAT_MOD_Yf_TILED_CCS: 1755 if (!plane->has_ccs) 1756 return false; 1757 break; 1758 default: 1759 return false; 1760 } 1761 1762 switch (format) { 1763 case DRM_FORMAT_XRGB8888: 1764 case DRM_FORMAT_XBGR8888: 1765 case DRM_FORMAT_ARGB8888: 1766 case DRM_FORMAT_ABGR8888: 1767 if (is_ccs_modifier(modifier)) 1768 return true; 1769 fallthrough; 1770 case DRM_FORMAT_RGB565: 1771 case DRM_FORMAT_XRGB2101010: 1772 case DRM_FORMAT_XBGR2101010: 1773 case DRM_FORMAT_ARGB2101010: 1774 case DRM_FORMAT_ABGR2101010: 1775 case DRM_FORMAT_YUYV: 1776 case DRM_FORMAT_YVYU: 1777 case DRM_FORMAT_UYVY: 1778 case DRM_FORMAT_VYUY: 1779 case DRM_FORMAT_NV12: 1780 case DRM_FORMAT_XYUV8888: 1781 case DRM_FORMAT_P010: 1782 case DRM_FORMAT_P012: 1783 case DRM_FORMAT_P016: 1784 case DRM_FORMAT_XVYU2101010: 1785 if (modifier == I915_FORMAT_MOD_Yf_TILED) 1786 return true; 1787 fallthrough; 1788 case DRM_FORMAT_C8: 1789 case DRM_FORMAT_XBGR16161616F: 1790 case DRM_FORMAT_ABGR16161616F: 1791 case DRM_FORMAT_XRGB16161616F: 1792 case DRM_FORMAT_ARGB16161616F: 1793 case DRM_FORMAT_Y210: 1794 case DRM_FORMAT_Y212: 1795 case DRM_FORMAT_Y216: 1796 case DRM_FORMAT_XVYU12_16161616: 1797 case DRM_FORMAT_XVYU16161616: 1798 if (modifier == DRM_FORMAT_MOD_LINEAR || 1799 modifier == I915_FORMAT_MOD_X_TILED || 1800 modifier == I915_FORMAT_MOD_Y_TILED) 1801 return true; 1802 fallthrough; 1803 default: 1804 return false; 1805 } 1806 } 1807 1808 static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv, 1809 enum plane_id plane_id) 1810 { 1811 /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */ 1812 if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv) || 1813 IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0)) 1814 return false; 1815 1816 return plane_id < PLANE_SPRITE4; 1817 } 1818 1819 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, 1820 u32 format, u64 modifier) 1821 { 1822 struct drm_i915_private *dev_priv = to_i915(_plane->dev); 1823 struct intel_plane *plane = to_intel_plane(_plane); 1824 1825 switch (modifier) { 1826 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: 1827 if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id)) 1828 return false; 1829 fallthrough; 1830 case DRM_FORMAT_MOD_LINEAR: 1831 case I915_FORMAT_MOD_X_TILED: 1832 case I915_FORMAT_MOD_Y_TILED: 1833 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: 1834 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: 1835 break; 1836 default: 1837 return false; 1838 } 1839 1840 switch (format) { 1841 case DRM_FORMAT_XRGB8888: 1842 case DRM_FORMAT_XBGR8888: 1843 case DRM_FORMAT_ARGB8888: 1844 case DRM_FORMAT_ABGR8888: 1845 if (is_ccs_modifier(modifier)) 1846 return true; 1847 fallthrough; 1848 case DRM_FORMAT_YUYV: 1849 case DRM_FORMAT_YVYU: 1850 case DRM_FORMAT_UYVY: 1851 case DRM_FORMAT_VYUY: 1852 case DRM_FORMAT_NV12: 1853 case DRM_FORMAT_XYUV8888: 1854 case DRM_FORMAT_P010: 1855 case DRM_FORMAT_P012: 1856 case DRM_FORMAT_P016: 1857 if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS) 1858 return true; 1859 fallthrough; 1860 case DRM_FORMAT_RGB565: 1861 case DRM_FORMAT_XRGB2101010: 1862 case DRM_FORMAT_XBGR2101010: 1863 case DRM_FORMAT_ARGB2101010: 1864 case DRM_FORMAT_ABGR2101010: 1865 case DRM_FORMAT_XVYU2101010: 1866 case DRM_FORMAT_C8: 1867 case DRM_FORMAT_XBGR16161616F: 1868 case DRM_FORMAT_ABGR16161616F: 1869 case DRM_FORMAT_XRGB16161616F: 1870 case DRM_FORMAT_ARGB16161616F: 1871 case DRM_FORMAT_Y210: 1872 case DRM_FORMAT_Y212: 1873 case DRM_FORMAT_Y216: 1874 case DRM_FORMAT_XVYU12_16161616: 1875 case DRM_FORMAT_XVYU16161616: 1876 if (modifier == DRM_FORMAT_MOD_LINEAR || 1877 modifier == I915_FORMAT_MOD_X_TILED || 1878 modifier == I915_FORMAT_MOD_Y_TILED) 1879 return true; 1880 fallthrough; 1881 default: 1882 return false; 1883 } 1884 } 1885 1886 static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv, 1887 enum plane_id plane_id) 1888 { 1889 if (gen12_plane_supports_mc_ccs(dev_priv, plane_id)) 1890 return gen12_plane_format_modifiers_mc_ccs; 1891 else 1892 return gen12_plane_format_modifiers_rc_ccs; 1893 } 1894 1895 static const struct drm_plane_funcs skl_plane_funcs = { 1896 .update_plane = drm_atomic_helper_update_plane, 1897 .disable_plane = drm_atomic_helper_disable_plane, 1898 .destroy = intel_plane_destroy, 1899 .atomic_duplicate_state = intel_plane_duplicate_state, 1900 .atomic_destroy_state = intel_plane_destroy_state, 1901 .format_mod_supported = skl_plane_format_mod_supported, 1902 }; 1903 1904 static const struct drm_plane_funcs gen12_plane_funcs = { 1905 .update_plane = drm_atomic_helper_update_plane, 1906 .disable_plane = drm_atomic_helper_disable_plane, 1907 .destroy = intel_plane_destroy, 1908 .atomic_duplicate_state = intel_plane_duplicate_state, 1909 .atomic_destroy_state = intel_plane_destroy_state, 1910 .format_mod_supported = gen12_plane_format_mod_supported, 1911 }; 1912 1913 static void 1914 skl_plane_enable_flip_done(struct intel_plane *plane) 1915 { 1916 struct drm_i915_private *i915 = to_i915(plane->base.dev); 1917 enum pipe pipe = plane->pipe; 1918 1919 spin_lock_irq(&i915->irq_lock); 1920 bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 1921 spin_unlock_irq(&i915->irq_lock); 1922 } 1923 1924 static void 1925 skl_plane_disable_flip_done(struct intel_plane *plane) 1926 { 1927 struct drm_i915_private *i915 = to_i915(plane->base.dev); 1928 enum pipe pipe = plane->pipe; 1929 1930 spin_lock_irq(&i915->irq_lock); 1931 bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id)); 1932 spin_unlock_irq(&i915->irq_lock); 1933 } 1934 1935 struct intel_plane * 1936 skl_universal_plane_create(struct drm_i915_private *dev_priv, 1937 enum pipe pipe, enum plane_id plane_id) 1938 { 1939 const struct drm_plane_funcs *plane_funcs; 1940 struct intel_plane *plane; 1941 enum drm_plane_type plane_type; 1942 unsigned int supported_rotations; 1943 unsigned int supported_csc; 1944 const u64 *modifiers; 1945 const u32 *formats; 1946 int num_formats; 1947 int ret; 1948 1949 plane = intel_plane_alloc(); 1950 if (IS_ERR(plane)) 1951 return plane; 1952 1953 plane->pipe = pipe; 1954 plane->id = plane_id; 1955 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id); 1956 1957 plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id); 1958 if (plane->has_fbc) { 1959 struct intel_fbc *fbc = &dev_priv->fbc; 1960 1961 fbc->possible_framebuffer_bits |= plane->frontbuffer_bit; 1962 } 1963 1964 if (DISPLAY_VER(dev_priv) >= 11) { 1965 plane->min_width = icl_plane_min_width; 1966 plane->max_width = icl_plane_max_width; 1967 plane->max_height = icl_plane_max_height; 1968 } else if (DISPLAY_VER(dev_priv) >= 10) { 1969 plane->max_width = glk_plane_max_width; 1970 plane->max_height = skl_plane_max_height; 1971 } else { 1972 plane->max_width = skl_plane_max_width; 1973 plane->max_height = skl_plane_max_height; 1974 } 1975 1976 plane->max_stride = skl_plane_max_stride; 1977 plane->update_plane = skl_update_plane; 1978 plane->disable_plane = skl_disable_plane; 1979 plane->get_hw_state = skl_plane_get_hw_state; 1980 plane->check_plane = skl_plane_check; 1981 plane->min_cdclk = skl_plane_min_cdclk; 1982 1983 if (plane_id == PLANE_PRIMARY) { 1984 plane->need_async_flip_disable_wa = IS_DISPLAY_RANGE(dev_priv, 1985 9, 10); 1986 plane->async_flip = skl_plane_async_flip; 1987 plane->enable_flip_done = skl_plane_enable_flip_done; 1988 plane->disable_flip_done = skl_plane_disable_flip_done; 1989 } 1990 1991 if (DISPLAY_VER(dev_priv) >= 11) 1992 formats = icl_get_plane_formats(dev_priv, pipe, 1993 plane_id, &num_formats); 1994 else if (DISPLAY_VER(dev_priv) >= 10) 1995 formats = glk_get_plane_formats(dev_priv, pipe, 1996 plane_id, &num_formats); 1997 else 1998 formats = skl_get_plane_formats(dev_priv, pipe, 1999 plane_id, &num_formats); 2000 2001 plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id); 2002 if (DISPLAY_VER(dev_priv) >= 12) { 2003 modifiers = gen12_get_plane_modifiers(dev_priv, plane_id); 2004 plane_funcs = &gen12_plane_funcs; 2005 } else { 2006 if (plane->has_ccs) 2007 modifiers = skl_plane_format_modifiers_ccs; 2008 else 2009 modifiers = skl_plane_format_modifiers_noccs; 2010 plane_funcs = &skl_plane_funcs; 2011 } 2012 2013 if (plane_id == PLANE_PRIMARY) 2014 plane_type = DRM_PLANE_TYPE_PRIMARY; 2015 else 2016 plane_type = DRM_PLANE_TYPE_OVERLAY; 2017 2018 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base, 2019 0, plane_funcs, 2020 formats, num_formats, modifiers, 2021 plane_type, 2022 "plane %d%c", plane_id + 1, 2023 pipe_name(pipe)); 2024 if (ret) 2025 goto fail; 2026 2027 supported_rotations = 2028 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | 2029 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270; 2030 2031 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) 2032 supported_rotations |= DRM_MODE_REFLECT_X; 2033 2034 drm_plane_create_rotation_property(&plane->base, 2035 DRM_MODE_ROTATE_0, 2036 supported_rotations); 2037 2038 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709); 2039 2040 if (DISPLAY_VER(dev_priv) >= 10) 2041 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020); 2042 2043 drm_plane_create_color_properties(&plane->base, 2044 supported_csc, 2045 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | 2046 BIT(DRM_COLOR_YCBCR_FULL_RANGE), 2047 DRM_COLOR_YCBCR_BT709, 2048 DRM_COLOR_YCBCR_LIMITED_RANGE); 2049 2050 drm_plane_create_alpha_property(&plane->base); 2051 drm_plane_create_blend_mode_property(&plane->base, 2052 BIT(DRM_MODE_BLEND_PIXEL_NONE) | 2053 BIT(DRM_MODE_BLEND_PREMULTI) | 2054 BIT(DRM_MODE_BLEND_COVERAGE)); 2055 2056 drm_plane_create_zpos_immutable_property(&plane->base, plane_id); 2057 2058 if (DISPLAY_VER(dev_priv) >= 12) 2059 drm_plane_enable_fb_damage_clips(&plane->base); 2060 2061 if (DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) 2062 drm_plane_create_scaling_filter_property(&plane->base, 2063 BIT(DRM_SCALING_FILTER_DEFAULT) | 2064 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR)); 2065 2066 drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs); 2067 2068 return plane; 2069 2070 fail: 2071 intel_plane_free(plane); 2072 2073 return ERR_PTR(ret); 2074 } 2075 2076 void 2077 skl_get_initial_plane_config(struct intel_crtc *crtc, 2078 struct intel_initial_plane_config *plane_config) 2079 { 2080 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); 2081 struct drm_device *dev = crtc->base.dev; 2082 struct drm_i915_private *dev_priv = to_i915(dev); 2083 struct intel_plane *plane = to_intel_plane(crtc->base.primary); 2084 enum plane_id plane_id = plane->id; 2085 enum pipe pipe; 2086 u32 val, base, offset, stride_mult, tiling, alpha; 2087 int fourcc, pixel_format; 2088 unsigned int aligned_height; 2089 struct drm_framebuffer *fb; 2090 struct intel_framebuffer *intel_fb; 2091 2092 if (!plane->get_hw_state(plane, &pipe)) 2093 return; 2094 2095 drm_WARN_ON(dev, pipe != crtc->pipe); 2096 2097 if (crtc_state->bigjoiner) { 2098 drm_dbg_kms(&dev_priv->drm, 2099 "Unsupported bigjoiner configuration for initial FB\n"); 2100 return; 2101 } 2102 2103 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); 2104 if (!intel_fb) { 2105 drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n"); 2106 return; 2107 } 2108 2109 fb = &intel_fb->base; 2110 2111 fb->dev = dev; 2112 2113 val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id)); 2114 2115 if (DISPLAY_VER(dev_priv) >= 11) 2116 pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK; 2117 else 2118 pixel_format = val & PLANE_CTL_FORMAT_MASK; 2119 2120 if (DISPLAY_VER(dev_priv) >= 10) { 2121 alpha = intel_de_read(dev_priv, 2122 PLANE_COLOR_CTL(pipe, plane_id)); 2123 alpha &= PLANE_COLOR_ALPHA_MASK; 2124 } else { 2125 alpha = val & PLANE_CTL_ALPHA_MASK; 2126 } 2127 2128 fourcc = skl_format_to_fourcc(pixel_format, 2129 val & PLANE_CTL_ORDER_RGBX, alpha); 2130 fb->format = drm_format_info(fourcc); 2131 2132 tiling = val & PLANE_CTL_TILED_MASK; 2133 switch (tiling) { 2134 case PLANE_CTL_TILED_LINEAR: 2135 fb->modifier = DRM_FORMAT_MOD_LINEAR; 2136 break; 2137 case PLANE_CTL_TILED_X: 2138 plane_config->tiling = I915_TILING_X; 2139 fb->modifier = I915_FORMAT_MOD_X_TILED; 2140 break; 2141 case PLANE_CTL_TILED_Y: 2142 plane_config->tiling = I915_TILING_Y; 2143 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 2144 fb->modifier = DISPLAY_VER(dev_priv) >= 12 ? 2145 I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS : 2146 I915_FORMAT_MOD_Y_TILED_CCS; 2147 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE) 2148 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS; 2149 else 2150 fb->modifier = I915_FORMAT_MOD_Y_TILED; 2151 break; 2152 case PLANE_CTL_TILED_YF: 2153 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) 2154 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; 2155 else 2156 fb->modifier = I915_FORMAT_MOD_Yf_TILED; 2157 break; 2158 default: 2159 MISSING_CASE(tiling); 2160 goto error; 2161 } 2162 2163 /* 2164 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr 2165 * while i915 HW rotation is clockwise, thats why this swapping. 2166 */ 2167 switch (val & PLANE_CTL_ROTATE_MASK) { 2168 case PLANE_CTL_ROTATE_0: 2169 plane_config->rotation = DRM_MODE_ROTATE_0; 2170 break; 2171 case PLANE_CTL_ROTATE_90: 2172 plane_config->rotation = DRM_MODE_ROTATE_270; 2173 break; 2174 case PLANE_CTL_ROTATE_180: 2175 plane_config->rotation = DRM_MODE_ROTATE_180; 2176 break; 2177 case PLANE_CTL_ROTATE_270: 2178 plane_config->rotation = DRM_MODE_ROTATE_90; 2179 break; 2180 } 2181 2182 if ((DISPLAY_VER(dev_priv) >= 11 || IS_CANNONLAKE(dev_priv)) && val & PLANE_CTL_FLIP_HORIZONTAL) 2183 plane_config->rotation |= DRM_MODE_REFLECT_X; 2184 2185 /* 90/270 degree rotation would require extra work */ 2186 if (drm_rotation_90_or_270(plane_config->rotation)) 2187 goto error; 2188 2189 base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000; 2190 plane_config->base = base; 2191 2192 offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id)); 2193 2194 val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id)); 2195 fb->height = ((val >> 16) & 0xffff) + 1; 2196 fb->width = ((val >> 0) & 0xffff) + 1; 2197 2198 val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id)); 2199 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0); 2200 fb->pitches[0] = (val & 0x3ff) * stride_mult; 2201 2202 aligned_height = intel_fb_align_height(fb, 0, fb->height); 2203 2204 plane_config->size = fb->pitches[0] * aligned_height; 2205 2206 drm_dbg_kms(&dev_priv->drm, 2207 "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 2208 crtc->base.name, plane->base.name, fb->width, fb->height, 2209 fb->format->cpp[0] * 8, base, fb->pitches[0], 2210 plane_config->size); 2211 2212 plane_config->fb = intel_fb; 2213 return; 2214 2215 error: 2216 kfree(intel_fb); 2217 } 2218 2219