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