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