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