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