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