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