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