0001
0002
0003
0004
0005
0006 #include <drm/drm_atomic_helper.h>
0007 #include <drm/drm_blend.h>
0008 #include <drm/drm_damage_helper.h>
0009 #include <drm/drm_fourcc.h>
0010 #include <drm/drm_plane_helper.h>
0011
0012 #include "i915_drv.h"
0013 #include "intel_atomic_plane.h"
0014 #include "intel_de.h"
0015 #include "intel_display_types.h"
0016 #include "intel_fb.h"
0017 #include "intel_fbc.h"
0018 #include "intel_pm.h"
0019 #include "intel_psr.h"
0020 #include "intel_sprite.h"
0021 #include "skl_scaler.h"
0022 #include "skl_universal_plane.h"
0023 #include "pxp/intel_pxp.h"
0024
0025 static const u32 skl_plane_formats[] = {
0026 DRM_FORMAT_C8,
0027 DRM_FORMAT_RGB565,
0028 DRM_FORMAT_XRGB8888,
0029 DRM_FORMAT_XBGR8888,
0030 DRM_FORMAT_ARGB8888,
0031 DRM_FORMAT_ABGR8888,
0032 DRM_FORMAT_XRGB2101010,
0033 DRM_FORMAT_XBGR2101010,
0034 DRM_FORMAT_XRGB16161616F,
0035 DRM_FORMAT_XBGR16161616F,
0036 DRM_FORMAT_YUYV,
0037 DRM_FORMAT_YVYU,
0038 DRM_FORMAT_UYVY,
0039 DRM_FORMAT_VYUY,
0040 DRM_FORMAT_XYUV8888,
0041 };
0042
0043 static const u32 skl_planar_formats[] = {
0044 DRM_FORMAT_C8,
0045 DRM_FORMAT_RGB565,
0046 DRM_FORMAT_XRGB8888,
0047 DRM_FORMAT_XBGR8888,
0048 DRM_FORMAT_ARGB8888,
0049 DRM_FORMAT_ABGR8888,
0050 DRM_FORMAT_XRGB2101010,
0051 DRM_FORMAT_XBGR2101010,
0052 DRM_FORMAT_XRGB16161616F,
0053 DRM_FORMAT_XBGR16161616F,
0054 DRM_FORMAT_YUYV,
0055 DRM_FORMAT_YVYU,
0056 DRM_FORMAT_UYVY,
0057 DRM_FORMAT_VYUY,
0058 DRM_FORMAT_NV12,
0059 DRM_FORMAT_XYUV8888,
0060 };
0061
0062 static const u32 glk_planar_formats[] = {
0063 DRM_FORMAT_C8,
0064 DRM_FORMAT_RGB565,
0065 DRM_FORMAT_XRGB8888,
0066 DRM_FORMAT_XBGR8888,
0067 DRM_FORMAT_ARGB8888,
0068 DRM_FORMAT_ABGR8888,
0069 DRM_FORMAT_XRGB2101010,
0070 DRM_FORMAT_XBGR2101010,
0071 DRM_FORMAT_XRGB16161616F,
0072 DRM_FORMAT_XBGR16161616F,
0073 DRM_FORMAT_YUYV,
0074 DRM_FORMAT_YVYU,
0075 DRM_FORMAT_UYVY,
0076 DRM_FORMAT_VYUY,
0077 DRM_FORMAT_NV12,
0078 DRM_FORMAT_XYUV8888,
0079 DRM_FORMAT_P010,
0080 DRM_FORMAT_P012,
0081 DRM_FORMAT_P016,
0082 };
0083
0084 static const u32 icl_sdr_y_plane_formats[] = {
0085 DRM_FORMAT_C8,
0086 DRM_FORMAT_RGB565,
0087 DRM_FORMAT_XRGB8888,
0088 DRM_FORMAT_XBGR8888,
0089 DRM_FORMAT_ARGB8888,
0090 DRM_FORMAT_ABGR8888,
0091 DRM_FORMAT_XRGB2101010,
0092 DRM_FORMAT_XBGR2101010,
0093 DRM_FORMAT_ARGB2101010,
0094 DRM_FORMAT_ABGR2101010,
0095 DRM_FORMAT_YUYV,
0096 DRM_FORMAT_YVYU,
0097 DRM_FORMAT_UYVY,
0098 DRM_FORMAT_VYUY,
0099 DRM_FORMAT_Y210,
0100 DRM_FORMAT_Y212,
0101 DRM_FORMAT_Y216,
0102 DRM_FORMAT_XYUV8888,
0103 DRM_FORMAT_XVYU2101010,
0104 DRM_FORMAT_XVYU12_16161616,
0105 DRM_FORMAT_XVYU16161616,
0106 };
0107
0108 static const u32 icl_sdr_uv_plane_formats[] = {
0109 DRM_FORMAT_C8,
0110 DRM_FORMAT_RGB565,
0111 DRM_FORMAT_XRGB8888,
0112 DRM_FORMAT_XBGR8888,
0113 DRM_FORMAT_ARGB8888,
0114 DRM_FORMAT_ABGR8888,
0115 DRM_FORMAT_XRGB2101010,
0116 DRM_FORMAT_XBGR2101010,
0117 DRM_FORMAT_ARGB2101010,
0118 DRM_FORMAT_ABGR2101010,
0119 DRM_FORMAT_YUYV,
0120 DRM_FORMAT_YVYU,
0121 DRM_FORMAT_UYVY,
0122 DRM_FORMAT_VYUY,
0123 DRM_FORMAT_NV12,
0124 DRM_FORMAT_P010,
0125 DRM_FORMAT_P012,
0126 DRM_FORMAT_P016,
0127 DRM_FORMAT_Y210,
0128 DRM_FORMAT_Y212,
0129 DRM_FORMAT_Y216,
0130 DRM_FORMAT_XYUV8888,
0131 DRM_FORMAT_XVYU2101010,
0132 DRM_FORMAT_XVYU12_16161616,
0133 DRM_FORMAT_XVYU16161616,
0134 };
0135
0136 static const u32 icl_hdr_plane_formats[] = {
0137 DRM_FORMAT_C8,
0138 DRM_FORMAT_RGB565,
0139 DRM_FORMAT_XRGB8888,
0140 DRM_FORMAT_XBGR8888,
0141 DRM_FORMAT_ARGB8888,
0142 DRM_FORMAT_ABGR8888,
0143 DRM_FORMAT_XRGB2101010,
0144 DRM_FORMAT_XBGR2101010,
0145 DRM_FORMAT_ARGB2101010,
0146 DRM_FORMAT_ABGR2101010,
0147 DRM_FORMAT_XRGB16161616F,
0148 DRM_FORMAT_XBGR16161616F,
0149 DRM_FORMAT_ARGB16161616F,
0150 DRM_FORMAT_ABGR16161616F,
0151 DRM_FORMAT_YUYV,
0152 DRM_FORMAT_YVYU,
0153 DRM_FORMAT_UYVY,
0154 DRM_FORMAT_VYUY,
0155 DRM_FORMAT_NV12,
0156 DRM_FORMAT_P010,
0157 DRM_FORMAT_P012,
0158 DRM_FORMAT_P016,
0159 DRM_FORMAT_Y210,
0160 DRM_FORMAT_Y212,
0161 DRM_FORMAT_Y216,
0162 DRM_FORMAT_XYUV8888,
0163 DRM_FORMAT_XVYU2101010,
0164 DRM_FORMAT_XVYU12_16161616,
0165 DRM_FORMAT_XVYU16161616,
0166 };
0167
0168 int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
0169 {
0170 switch (format) {
0171 case PLANE_CTL_FORMAT_RGB_565:
0172 return DRM_FORMAT_RGB565;
0173 case PLANE_CTL_FORMAT_NV12:
0174 return DRM_FORMAT_NV12;
0175 case PLANE_CTL_FORMAT_XYUV:
0176 return DRM_FORMAT_XYUV8888;
0177 case PLANE_CTL_FORMAT_P010:
0178 return DRM_FORMAT_P010;
0179 case PLANE_CTL_FORMAT_P012:
0180 return DRM_FORMAT_P012;
0181 case PLANE_CTL_FORMAT_P016:
0182 return DRM_FORMAT_P016;
0183 case PLANE_CTL_FORMAT_Y210:
0184 return DRM_FORMAT_Y210;
0185 case PLANE_CTL_FORMAT_Y212:
0186 return DRM_FORMAT_Y212;
0187 case PLANE_CTL_FORMAT_Y216:
0188 return DRM_FORMAT_Y216;
0189 case PLANE_CTL_FORMAT_Y410:
0190 return DRM_FORMAT_XVYU2101010;
0191 case PLANE_CTL_FORMAT_Y412:
0192 return DRM_FORMAT_XVYU12_16161616;
0193 case PLANE_CTL_FORMAT_Y416:
0194 return DRM_FORMAT_XVYU16161616;
0195 default:
0196 case PLANE_CTL_FORMAT_XRGB_8888:
0197 if (rgb_order) {
0198 if (alpha)
0199 return DRM_FORMAT_ABGR8888;
0200 else
0201 return DRM_FORMAT_XBGR8888;
0202 } else {
0203 if (alpha)
0204 return DRM_FORMAT_ARGB8888;
0205 else
0206 return DRM_FORMAT_XRGB8888;
0207 }
0208 case PLANE_CTL_FORMAT_XRGB_2101010:
0209 if (rgb_order) {
0210 if (alpha)
0211 return DRM_FORMAT_ABGR2101010;
0212 else
0213 return DRM_FORMAT_XBGR2101010;
0214 } else {
0215 if (alpha)
0216 return DRM_FORMAT_ARGB2101010;
0217 else
0218 return DRM_FORMAT_XRGB2101010;
0219 }
0220 case PLANE_CTL_FORMAT_XRGB_16161616F:
0221 if (rgb_order) {
0222 if (alpha)
0223 return DRM_FORMAT_ABGR16161616F;
0224 else
0225 return DRM_FORMAT_XBGR16161616F;
0226 } else {
0227 if (alpha)
0228 return DRM_FORMAT_ARGB16161616F;
0229 else
0230 return DRM_FORMAT_XRGB16161616F;
0231 }
0232 }
0233 }
0234
0235 static u8 icl_nv12_y_plane_mask(struct drm_i915_private *i915)
0236 {
0237 if (DISPLAY_VER(i915) >= 13 || HAS_D12_PLANE_MINIMIZATION(i915))
0238 return BIT(PLANE_SPRITE2) | BIT(PLANE_SPRITE3);
0239 else
0240 return BIT(PLANE_SPRITE4) | BIT(PLANE_SPRITE5);
0241 }
0242
0243 bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
0244 enum plane_id plane_id)
0245 {
0246 return DISPLAY_VER(dev_priv) >= 11 &&
0247 icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
0248 }
0249
0250 bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
0251 {
0252 return DISPLAY_VER(dev_priv) >= 11 &&
0253 icl_hdr_plane_mask() & BIT(plane_id);
0254 }
0255
0256 static int icl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0257 const struct intel_plane_state *plane_state)
0258 {
0259 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
0260
0261
0262 return DIV_ROUND_UP(pixel_rate, 2);
0263 }
0264
0265 static void
0266 glk_plane_ratio(const struct intel_plane_state *plane_state,
0267 unsigned int *num, unsigned int *den)
0268 {
0269 const struct drm_framebuffer *fb = plane_state->hw.fb;
0270
0271 if (fb->format->cpp[0] == 8) {
0272 *num = 10;
0273 *den = 8;
0274 } else {
0275 *num = 1;
0276 *den = 1;
0277 }
0278 }
0279
0280 static int glk_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0281 const struct intel_plane_state *plane_state)
0282 {
0283 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
0284 unsigned int num, den;
0285
0286 glk_plane_ratio(plane_state, &num, &den);
0287
0288
0289 return DIV_ROUND_UP(pixel_rate * num, 2 * den);
0290 }
0291
0292 static void
0293 skl_plane_ratio(const struct intel_plane_state *plane_state,
0294 unsigned int *num, unsigned int *den)
0295 {
0296 const struct drm_framebuffer *fb = plane_state->hw.fb;
0297
0298 if (fb->format->cpp[0] == 8) {
0299 *num = 9;
0300 *den = 8;
0301 } else {
0302 *num = 1;
0303 *den = 1;
0304 }
0305 }
0306
0307 static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0308 const struct intel_plane_state *plane_state)
0309 {
0310 unsigned int pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state);
0311 unsigned int num, den;
0312
0313 skl_plane_ratio(plane_state, &num, &den);
0314
0315 return DIV_ROUND_UP(pixel_rate * num, den);
0316 }
0317
0318 static int skl_plane_max_width(const struct drm_framebuffer *fb,
0319 int color_plane,
0320 unsigned int rotation)
0321 {
0322 int cpp = fb->format->cpp[color_plane];
0323
0324 switch (fb->modifier) {
0325 case DRM_FORMAT_MOD_LINEAR:
0326 case I915_FORMAT_MOD_X_TILED:
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337 if (cpp == 8)
0338 return 4096;
0339 else
0340 return 5120;
0341 case I915_FORMAT_MOD_Y_TILED_CCS:
0342 case I915_FORMAT_MOD_Yf_TILED_CCS:
0343 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
0344
0345 case I915_FORMAT_MOD_Y_TILED:
0346 case I915_FORMAT_MOD_Yf_TILED:
0347 if (cpp == 8)
0348 return 2048;
0349 else
0350 return 4096;
0351 default:
0352 MISSING_CASE(fb->modifier);
0353 return 2048;
0354 }
0355 }
0356
0357 static int glk_plane_max_width(const struct drm_framebuffer *fb,
0358 int color_plane,
0359 unsigned int rotation)
0360 {
0361 int cpp = fb->format->cpp[color_plane];
0362
0363 switch (fb->modifier) {
0364 case DRM_FORMAT_MOD_LINEAR:
0365 case I915_FORMAT_MOD_X_TILED:
0366 if (cpp == 8)
0367 return 4096;
0368 else
0369 return 5120;
0370 case I915_FORMAT_MOD_Y_TILED_CCS:
0371 case I915_FORMAT_MOD_Yf_TILED_CCS:
0372
0373 case I915_FORMAT_MOD_Y_TILED:
0374 case I915_FORMAT_MOD_Yf_TILED:
0375 if (cpp == 8)
0376 return 2048;
0377 else
0378 return 5120;
0379 default:
0380 MISSING_CASE(fb->modifier);
0381 return 2048;
0382 }
0383 }
0384
0385 static int icl_plane_min_width(const struct drm_framebuffer *fb,
0386 int color_plane,
0387 unsigned int rotation)
0388 {
0389
0390 switch (fb->format->format) {
0391 case DRM_FORMAT_C8:
0392 return 18;
0393 case DRM_FORMAT_RGB565:
0394 return 10;
0395 case DRM_FORMAT_XRGB8888:
0396 case DRM_FORMAT_XBGR8888:
0397 case DRM_FORMAT_ARGB8888:
0398 case DRM_FORMAT_ABGR8888:
0399 case DRM_FORMAT_XRGB2101010:
0400 case DRM_FORMAT_XBGR2101010:
0401 case DRM_FORMAT_ARGB2101010:
0402 case DRM_FORMAT_ABGR2101010:
0403 case DRM_FORMAT_XVYU2101010:
0404 case DRM_FORMAT_Y212:
0405 case DRM_FORMAT_Y216:
0406 return 6;
0407 case DRM_FORMAT_NV12:
0408 return 20;
0409 case DRM_FORMAT_P010:
0410 case DRM_FORMAT_P012:
0411 case DRM_FORMAT_P016:
0412 return 12;
0413 case DRM_FORMAT_XRGB16161616F:
0414 case DRM_FORMAT_XBGR16161616F:
0415 case DRM_FORMAT_ARGB16161616F:
0416 case DRM_FORMAT_ABGR16161616F:
0417 case DRM_FORMAT_XVYU12_16161616:
0418 case DRM_FORMAT_XVYU16161616:
0419 return 4;
0420 default:
0421 return 1;
0422 }
0423 }
0424
0425 static int icl_hdr_plane_max_width(const struct drm_framebuffer *fb,
0426 int color_plane,
0427 unsigned int rotation)
0428 {
0429 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
0430 return 4096;
0431 else
0432 return 5120;
0433 }
0434
0435 static int icl_sdr_plane_max_width(const struct drm_framebuffer *fb,
0436 int color_plane,
0437 unsigned int rotation)
0438 {
0439 return 5120;
0440 }
0441
0442 static int skl_plane_max_height(const struct drm_framebuffer *fb,
0443 int color_plane,
0444 unsigned int rotation)
0445 {
0446 return 4096;
0447 }
0448
0449 static int icl_plane_max_height(const struct drm_framebuffer *fb,
0450 int color_plane,
0451 unsigned int rotation)
0452 {
0453 return 4320;
0454 }
0455
0456 static unsigned int
0457 skl_plane_max_stride(struct intel_plane *plane,
0458 u32 pixel_format, u64 modifier,
0459 unsigned int rotation)
0460 {
0461 struct drm_i915_private *i915 = to_i915(plane->base.dev);
0462 const struct drm_format_info *info = drm_format_info(pixel_format);
0463 int cpp = info->cpp[0];
0464 int max_horizontal_pixels = 8192;
0465 int max_stride_bytes;
0466
0467 if (DISPLAY_VER(i915) >= 13) {
0468
0469
0470
0471
0472
0473 max_stride_bytes = 131072;
0474 if (cpp == 8)
0475 max_horizontal_pixels = 16384;
0476 else
0477 max_horizontal_pixels = 65536;
0478 } else {
0479
0480
0481
0482
0483 max_stride_bytes = 32768;
0484 }
0485
0486 if (drm_rotation_90_or_270(rotation))
0487 return min(max_horizontal_pixels, max_stride_bytes / cpp);
0488 else
0489 return min(max_horizontal_pixels * cpp, max_stride_bytes);
0490 }
0491
0492
0493
0494 #define PREOFF_YUV_TO_RGB_HI 0x1800
0495 #define PREOFF_YUV_TO_RGB_ME 0x0000
0496 #define PREOFF_YUV_TO_RGB_LO 0x1800
0497
0498 #define ROFF(x) (((x) & 0xffff) << 16)
0499 #define GOFF(x) (((x) & 0xffff) << 0)
0500 #define BOFF(x) (((x) & 0xffff) << 16)
0501
0502
0503
0504
0505
0506
0507
0508 static void
0509 icl_program_input_csc(struct intel_plane *plane,
0510 const struct intel_crtc_state *crtc_state,
0511 const struct intel_plane_state *plane_state)
0512 {
0513 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0514 enum pipe pipe = plane->pipe;
0515 enum plane_id plane_id = plane->id;
0516
0517 static const u16 input_csc_matrix[][9] = {
0518
0519
0520
0521
0522
0523
0524
0525 [DRM_COLOR_YCBCR_BT601] = {
0526 0x7AF8, 0x7800, 0x0,
0527 0x8B28, 0x7800, 0x9AC0,
0528 0x0, 0x7800, 0x7DD8,
0529 },
0530
0531
0532
0533
0534
0535
0536
0537 [DRM_COLOR_YCBCR_BT709] = {
0538 0x7C98, 0x7800, 0x0,
0539 0x9EF8, 0x7800, 0xAC00,
0540 0x0, 0x7800, 0x7ED8,
0541 },
0542
0543
0544
0545
0546
0547
0548
0549 [DRM_COLOR_YCBCR_BT2020] = {
0550 0x7BC8, 0x7800, 0x0,
0551 0x8928, 0x7800, 0xAA88,
0552 0x0, 0x7800, 0x7F10,
0553 },
0554 };
0555 const u16 *csc = input_csc_matrix[plane_state->hw.color_encoding];
0556
0557 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0),
0558 ROFF(csc[0]) | GOFF(csc[1]));
0559 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1),
0560 BOFF(csc[2]));
0561 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2),
0562 ROFF(csc[3]) | GOFF(csc[4]));
0563 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3),
0564 BOFF(csc[5]));
0565 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4),
0566 ROFF(csc[6]) | GOFF(csc[7]));
0567 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5),
0568 BOFF(csc[8]));
0569
0570 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
0571 PREOFF_YUV_TO_RGB_HI);
0572 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
0573 PREOFF_YUV_TO_RGB_ME);
0574 intel_de_write_fw(dev_priv, PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
0575 PREOFF_YUV_TO_RGB_LO);
0576 intel_de_write_fw(dev_priv,
0577 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
0578 intel_de_write_fw(dev_priv,
0579 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
0580 intel_de_write_fw(dev_priv,
0581 PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
0582 }
0583
0584 static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
0585 int color_plane, unsigned int rotation)
0586 {
0587
0588
0589
0590
0591 if (is_surface_linear(fb, color_plane))
0592 return 64;
0593 else if (drm_rotation_90_or_270(rotation))
0594 return intel_tile_height(fb, color_plane);
0595 else
0596 return intel_tile_width_bytes(fb, color_plane);
0597 }
0598
0599 static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
0600 int color_plane)
0601 {
0602 const struct drm_framebuffer *fb = plane_state->hw.fb;
0603 unsigned int rotation = plane_state->hw.rotation;
0604 u32 stride = plane_state->view.color_plane[color_plane].scanout_stride;
0605
0606 if (color_plane >= fb->format->num_planes)
0607 return 0;
0608
0609 return stride / skl_plane_stride_mult(fb, color_plane, rotation);
0610 }
0611
0612 static void
0613 skl_plane_disable_arm(struct intel_plane *plane,
0614 const struct intel_crtc_state *crtc_state)
0615 {
0616 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0617 enum plane_id plane_id = plane->id;
0618 enum pipe pipe = plane->pipe;
0619
0620 skl_write_plane_wm(plane, crtc_state);
0621
0622 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
0623 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
0624 }
0625
0626 static void
0627 icl_plane_disable_arm(struct intel_plane *plane,
0628 const struct intel_crtc_state *crtc_state)
0629 {
0630 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0631 enum plane_id plane_id = plane->id;
0632 enum pipe pipe = plane->pipe;
0633
0634 if (icl_is_hdr_plane(dev_priv, plane_id))
0635 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0);
0636
0637 skl_write_plane_wm(plane, crtc_state);
0638
0639 intel_psr2_disable_plane_sel_fetch(plane, crtc_state);
0640 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0);
0641 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0);
0642 }
0643
0644 static bool
0645 skl_plane_get_hw_state(struct intel_plane *plane,
0646 enum pipe *pipe)
0647 {
0648 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0649 enum intel_display_power_domain power_domain;
0650 enum plane_id plane_id = plane->id;
0651 intel_wakeref_t wakeref;
0652 bool ret;
0653
0654 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
0655 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0656 if (!wakeref)
0657 return false;
0658
0659 ret = intel_de_read(dev_priv, PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
0660
0661 *pipe = plane->pipe;
0662
0663 intel_display_power_put(dev_priv, power_domain, wakeref);
0664
0665 return ret;
0666 }
0667
0668 static u32 skl_plane_ctl_format(u32 pixel_format)
0669 {
0670 switch (pixel_format) {
0671 case DRM_FORMAT_C8:
0672 return PLANE_CTL_FORMAT_INDEXED;
0673 case DRM_FORMAT_RGB565:
0674 return PLANE_CTL_FORMAT_RGB_565;
0675 case DRM_FORMAT_XBGR8888:
0676 case DRM_FORMAT_ABGR8888:
0677 return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
0678 case DRM_FORMAT_XRGB8888:
0679 case DRM_FORMAT_ARGB8888:
0680 return PLANE_CTL_FORMAT_XRGB_8888;
0681 case DRM_FORMAT_XBGR2101010:
0682 case DRM_FORMAT_ABGR2101010:
0683 return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
0684 case DRM_FORMAT_XRGB2101010:
0685 case DRM_FORMAT_ARGB2101010:
0686 return PLANE_CTL_FORMAT_XRGB_2101010;
0687 case DRM_FORMAT_XBGR16161616F:
0688 case DRM_FORMAT_ABGR16161616F:
0689 return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
0690 case DRM_FORMAT_XRGB16161616F:
0691 case DRM_FORMAT_ARGB16161616F:
0692 return PLANE_CTL_FORMAT_XRGB_16161616F;
0693 case DRM_FORMAT_XYUV8888:
0694 return PLANE_CTL_FORMAT_XYUV;
0695 case DRM_FORMAT_YUYV:
0696 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YUYV;
0697 case DRM_FORMAT_YVYU:
0698 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_YVYU;
0699 case DRM_FORMAT_UYVY:
0700 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_UYVY;
0701 case DRM_FORMAT_VYUY:
0702 return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_ORDER_VYUY;
0703 case DRM_FORMAT_NV12:
0704 return PLANE_CTL_FORMAT_NV12;
0705 case DRM_FORMAT_P010:
0706 return PLANE_CTL_FORMAT_P010;
0707 case DRM_FORMAT_P012:
0708 return PLANE_CTL_FORMAT_P012;
0709 case DRM_FORMAT_P016:
0710 return PLANE_CTL_FORMAT_P016;
0711 case DRM_FORMAT_Y210:
0712 return PLANE_CTL_FORMAT_Y210;
0713 case DRM_FORMAT_Y212:
0714 return PLANE_CTL_FORMAT_Y212;
0715 case DRM_FORMAT_Y216:
0716 return PLANE_CTL_FORMAT_Y216;
0717 case DRM_FORMAT_XVYU2101010:
0718 return PLANE_CTL_FORMAT_Y410;
0719 case DRM_FORMAT_XVYU12_16161616:
0720 return PLANE_CTL_FORMAT_Y412;
0721 case DRM_FORMAT_XVYU16161616:
0722 return PLANE_CTL_FORMAT_Y416;
0723 default:
0724 MISSING_CASE(pixel_format);
0725 }
0726
0727 return 0;
0728 }
0729
0730 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
0731 {
0732 if (!plane_state->hw.fb->format->has_alpha)
0733 return PLANE_CTL_ALPHA_DISABLE;
0734
0735 switch (plane_state->hw.pixel_blend_mode) {
0736 case DRM_MODE_BLEND_PIXEL_NONE:
0737 return PLANE_CTL_ALPHA_DISABLE;
0738 case DRM_MODE_BLEND_PREMULTI:
0739 return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
0740 case DRM_MODE_BLEND_COVERAGE:
0741 return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
0742 default:
0743 MISSING_CASE(plane_state->hw.pixel_blend_mode);
0744 return PLANE_CTL_ALPHA_DISABLE;
0745 }
0746 }
0747
0748 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
0749 {
0750 if (!plane_state->hw.fb->format->has_alpha)
0751 return PLANE_COLOR_ALPHA_DISABLE;
0752
0753 switch (plane_state->hw.pixel_blend_mode) {
0754 case DRM_MODE_BLEND_PIXEL_NONE:
0755 return PLANE_COLOR_ALPHA_DISABLE;
0756 case DRM_MODE_BLEND_PREMULTI:
0757 return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
0758 case DRM_MODE_BLEND_COVERAGE:
0759 return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
0760 default:
0761 MISSING_CASE(plane_state->hw.pixel_blend_mode);
0762 return PLANE_COLOR_ALPHA_DISABLE;
0763 }
0764 }
0765
0766 static u32 skl_plane_ctl_tiling(u64 fb_modifier)
0767 {
0768 switch (fb_modifier) {
0769 case DRM_FORMAT_MOD_LINEAR:
0770 break;
0771 case I915_FORMAT_MOD_X_TILED:
0772 return PLANE_CTL_TILED_X;
0773 case I915_FORMAT_MOD_Y_TILED:
0774 return PLANE_CTL_TILED_Y;
0775 case I915_FORMAT_MOD_4_TILED:
0776 return PLANE_CTL_TILED_4;
0777 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
0778 return PLANE_CTL_TILED_4 |
0779 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
0780 PLANE_CTL_CLEAR_COLOR_DISABLE;
0781 case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
0782 return PLANE_CTL_TILED_4 |
0783 PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE |
0784 PLANE_CTL_CLEAR_COLOR_DISABLE;
0785 case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
0786 return PLANE_CTL_TILED_4 | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
0787 case I915_FORMAT_MOD_Y_TILED_CCS:
0788 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
0789 return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
0790 case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
0791 return PLANE_CTL_TILED_Y |
0792 PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
0793 PLANE_CTL_CLEAR_COLOR_DISABLE;
0794 case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
0795 return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
0796 case I915_FORMAT_MOD_Yf_TILED:
0797 return PLANE_CTL_TILED_YF;
0798 case I915_FORMAT_MOD_Yf_TILED_CCS:
0799 return PLANE_CTL_TILED_YF | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
0800 default:
0801 MISSING_CASE(fb_modifier);
0802 }
0803
0804 return 0;
0805 }
0806
0807 static u32 skl_plane_ctl_rotate(unsigned int rotate)
0808 {
0809 switch (rotate) {
0810 case DRM_MODE_ROTATE_0:
0811 break;
0812
0813
0814
0815
0816 case DRM_MODE_ROTATE_90:
0817 return PLANE_CTL_ROTATE_270;
0818 case DRM_MODE_ROTATE_180:
0819 return PLANE_CTL_ROTATE_180;
0820 case DRM_MODE_ROTATE_270:
0821 return PLANE_CTL_ROTATE_90;
0822 default:
0823 MISSING_CASE(rotate);
0824 }
0825
0826 return 0;
0827 }
0828
0829 static u32 icl_plane_ctl_flip(unsigned int reflect)
0830 {
0831 switch (reflect) {
0832 case 0:
0833 break;
0834 case DRM_MODE_REFLECT_X:
0835 return PLANE_CTL_FLIP_HORIZONTAL;
0836 case DRM_MODE_REFLECT_Y:
0837 default:
0838 MISSING_CASE(reflect);
0839 }
0840
0841 return 0;
0842 }
0843
0844 static u32 adlp_plane_ctl_arb_slots(const struct intel_plane_state *plane_state)
0845 {
0846 const struct drm_framebuffer *fb = plane_state->hw.fb;
0847
0848 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) {
0849 switch (fb->format->cpp[0]) {
0850 case 2:
0851 return PLANE_CTL_ARB_SLOTS(1);
0852 default:
0853 return PLANE_CTL_ARB_SLOTS(0);
0854 }
0855 } else {
0856 switch (fb->format->cpp[0]) {
0857 case 8:
0858 return PLANE_CTL_ARB_SLOTS(3);
0859 case 4:
0860 return PLANE_CTL_ARB_SLOTS(1);
0861 default:
0862 return PLANE_CTL_ARB_SLOTS(0);
0863 }
0864 }
0865 }
0866
0867 static u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
0868 {
0869 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
0870 u32 plane_ctl = 0;
0871
0872 if (DISPLAY_VER(dev_priv) >= 10)
0873 return plane_ctl;
0874
0875 if (crtc_state->gamma_enable)
0876 plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
0877
0878 if (crtc_state->csc_enable)
0879 plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
0880
0881 return plane_ctl;
0882 }
0883
0884 static u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
0885 const struct intel_plane_state *plane_state)
0886 {
0887 struct drm_i915_private *dev_priv =
0888 to_i915(plane_state->uapi.plane->dev);
0889 const struct drm_framebuffer *fb = plane_state->hw.fb;
0890 unsigned int rotation = plane_state->hw.rotation;
0891 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0892 u32 plane_ctl;
0893
0894 plane_ctl = PLANE_CTL_ENABLE;
0895
0896 if (DISPLAY_VER(dev_priv) < 10) {
0897 plane_ctl |= skl_plane_ctl_alpha(plane_state);
0898 plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
0899
0900 if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
0901 plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
0902
0903 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
0904 plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
0905 }
0906
0907 plane_ctl |= skl_plane_ctl_format(fb->format->format);
0908 plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
0909 plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
0910
0911 if (DISPLAY_VER(dev_priv) >= 11)
0912 plane_ctl |= icl_plane_ctl_flip(rotation &
0913 DRM_MODE_REFLECT_MASK);
0914
0915 if (key->flags & I915_SET_COLORKEY_DESTINATION)
0916 plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
0917 else if (key->flags & I915_SET_COLORKEY_SOURCE)
0918 plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
0919
0920
0921 if (DISPLAY_VER(dev_priv) == 13)
0922 plane_ctl |= adlp_plane_ctl_arb_slots(plane_state);
0923
0924 return plane_ctl;
0925 }
0926
0927 static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
0928 {
0929 struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
0930 u32 plane_color_ctl = 0;
0931
0932 if (DISPLAY_VER(dev_priv) >= 11)
0933 return plane_color_ctl;
0934
0935 if (crtc_state->gamma_enable)
0936 plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
0937
0938 if (crtc_state->csc_enable)
0939 plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
0940
0941 return plane_color_ctl;
0942 }
0943
0944 static u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
0945 const struct intel_plane_state *plane_state)
0946 {
0947 struct drm_i915_private *dev_priv =
0948 to_i915(plane_state->uapi.plane->dev);
0949 const struct drm_framebuffer *fb = plane_state->hw.fb;
0950 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0951 u32 plane_color_ctl = 0;
0952
0953 plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
0954 plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
0955
0956 if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
0957 switch (plane_state->hw.color_encoding) {
0958 case DRM_COLOR_YCBCR_BT709:
0959 plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
0960 break;
0961 case DRM_COLOR_YCBCR_BT2020:
0962 plane_color_ctl |=
0963 PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020;
0964 break;
0965 default:
0966 plane_color_ctl |=
0967 PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601;
0968 }
0969 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
0970 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
0971 } else if (fb->format->is_yuv) {
0972 plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
0973 if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
0974 plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
0975 }
0976
0977 if (plane_state->force_black)
0978 plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE;
0979
0980 return plane_color_ctl;
0981 }
0982
0983 static u32 skl_surf_address(const struct intel_plane_state *plane_state,
0984 int color_plane)
0985 {
0986 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
0987 const struct drm_framebuffer *fb = plane_state->hw.fb;
0988 u32 offset = plane_state->view.color_plane[color_plane].offset;
0989
0990 if (intel_fb_uses_dpt(fb)) {
0991
0992
0993
0994
0995 drm_WARN_ON(&i915->drm, plane_state->dpt_vma->node.start);
0996 drm_WARN_ON(&i915->drm, offset & 0x1fffff);
0997 return offset >> 9;
0998 } else {
0999 drm_WARN_ON(&i915->drm, offset & 0xfff);
1000 return offset;
1001 }
1002 }
1003
1004 static u32 skl_plane_surf(const struct intel_plane_state *plane_state,
1005 int color_plane)
1006 {
1007 u32 plane_surf;
1008
1009 plane_surf = intel_plane_ggtt_offset(plane_state) +
1010 skl_surf_address(plane_state, color_plane);
1011
1012 if (plane_state->decrypt)
1013 plane_surf |= PLANE_SURF_DECRYPT;
1014
1015 return plane_surf;
1016 }
1017
1018 static u32 skl_plane_aux_dist(const struct intel_plane_state *plane_state,
1019 int color_plane)
1020 {
1021 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1022 const struct drm_framebuffer *fb = plane_state->hw.fb;
1023 int aux_plane = skl_main_to_aux_plane(fb, color_plane);
1024 u32 aux_dist;
1025
1026 if (!aux_plane)
1027 return 0;
1028
1029 aux_dist = skl_surf_address(plane_state, aux_plane) -
1030 skl_surf_address(plane_state, color_plane);
1031
1032 if (DISPLAY_VER(i915) < 12)
1033 aux_dist |= PLANE_AUX_STRIDE(skl_plane_stride(plane_state, aux_plane));
1034
1035 return aux_dist;
1036 }
1037
1038 static u32 skl_plane_keyval(const struct intel_plane_state *plane_state)
1039 {
1040 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1041
1042 return key->min_value;
1043 }
1044
1045 static u32 skl_plane_keymax(const struct intel_plane_state *plane_state)
1046 {
1047 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1048 u8 alpha = plane_state->hw.alpha >> 8;
1049
1050 return (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
1051 }
1052
1053 static u32 skl_plane_keymsk(const struct intel_plane_state *plane_state)
1054 {
1055 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1056 u8 alpha = plane_state->hw.alpha >> 8;
1057 u32 keymsk;
1058
1059 keymsk = key->channel_mask & 0x7ffffff;
1060 if (alpha < 0xff)
1061 keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
1062
1063 return keymsk;
1064 }
1065
1066 static void icl_plane_csc_load_black(struct intel_plane *plane)
1067 {
1068 struct drm_i915_private *i915 = to_i915(plane->base.dev);
1069 enum plane_id plane_id = plane->id;
1070 enum pipe pipe = plane->pipe;
1071
1072 intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 0), 0);
1073 intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 1), 0);
1074
1075 intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 2), 0);
1076 intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 3), 0);
1077
1078 intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 4), 0);
1079 intel_de_write_fw(i915, PLANE_CSC_COEFF(pipe, plane_id, 5), 0);
1080
1081 intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 0), 0);
1082 intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 1), 0);
1083 intel_de_write_fw(i915, PLANE_CSC_PREOFF(pipe, plane_id, 2), 0);
1084
1085 intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 0), 0);
1086 intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 1), 0);
1087 intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0);
1088 }
1089
1090 static int icl_plane_color_plane(const struct intel_plane_state *plane_state)
1091 {
1092
1093 if (plane_state->planar_linked_plane && !plane_state->planar_slave)
1094 return 1;
1095 else
1096 return 0;
1097 }
1098
1099 static void
1100 skl_plane_update_noarm(struct intel_plane *plane,
1101 const struct intel_crtc_state *crtc_state,
1102 const struct intel_plane_state *plane_state)
1103 {
1104 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1105 enum plane_id plane_id = plane->id;
1106 enum pipe pipe = plane->pipe;
1107 u32 stride = skl_plane_stride(plane_state, 0);
1108 int crtc_x = plane_state->uapi.dst.x1;
1109 int crtc_y = plane_state->uapi.dst.y1;
1110 u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1111 u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1112
1113
1114 if (plane_state->scaler_id >= 0) {
1115 crtc_x = 0;
1116 crtc_y = 0;
1117 }
1118
1119 intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
1120 PLANE_STRIDE_(stride));
1121 intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
1122 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1123 intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
1124 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1125
1126 skl_write_plane_wm(plane, crtc_state);
1127 }
1128
1129 static void
1130 skl_plane_update_arm(struct intel_plane *plane,
1131 const struct intel_crtc_state *crtc_state,
1132 const struct intel_plane_state *plane_state)
1133 {
1134 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1135 enum plane_id plane_id = plane->id;
1136 enum pipe pipe = plane->pipe;
1137 u32 x = plane_state->view.color_plane[0].x;
1138 u32 y = plane_state->view.color_plane[0].y;
1139 u32 plane_ctl, plane_color_ctl = 0;
1140
1141 plane_ctl = plane_state->ctl |
1142 skl_plane_ctl_crtc(crtc_state);
1143
1144 if (DISPLAY_VER(dev_priv) >= 10)
1145 plane_color_ctl = plane_state->color_ctl |
1146 glk_plane_color_ctl_crtc(crtc_state);
1147
1148 intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
1149 intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
1150 intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
1151
1152 intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1153 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1154
1155 intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
1156 skl_plane_aux_dist(plane_state, 0));
1157
1158 intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id),
1159 PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) |
1160 PLANE_OFFSET_X(plane_state->view.color_plane[1].x));
1161
1162 if (DISPLAY_VER(dev_priv) >= 10)
1163 intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
1164
1165
1166
1167
1168
1169
1170
1171
1172 if (plane_state->scaler_id >= 0)
1173 skl_program_plane_scaler(plane, crtc_state, plane_state);
1174
1175
1176
1177
1178
1179
1180 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1181 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1182 skl_plane_surf(plane_state, 0));
1183 }
1184
1185 static void
1186 icl_plane_update_noarm(struct intel_plane *plane,
1187 const struct intel_crtc_state *crtc_state,
1188 const struct intel_plane_state *plane_state)
1189 {
1190 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1191 enum plane_id plane_id = plane->id;
1192 enum pipe pipe = plane->pipe;
1193 int color_plane = icl_plane_color_plane(plane_state);
1194 u32 stride = skl_plane_stride(plane_state, color_plane);
1195 const struct drm_framebuffer *fb = plane_state->hw.fb;
1196 int crtc_x = plane_state->uapi.dst.x1;
1197 int crtc_y = plane_state->uapi.dst.y1;
1198 int x = plane_state->view.color_plane[color_plane].x;
1199 int y = plane_state->view.color_plane[color_plane].y;
1200 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1201 int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1202 u32 plane_color_ctl;
1203
1204 plane_color_ctl = plane_state->color_ctl |
1205 glk_plane_color_ctl_crtc(crtc_state);
1206
1207
1208 if (plane_state->scaler_id >= 0) {
1209 crtc_x = 0;
1210 crtc_y = 0;
1211 }
1212
1213 intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id),
1214 PLANE_STRIDE_(stride));
1215 intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id),
1216 PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x));
1217 intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id),
1218 PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1));
1219
1220 intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state));
1221 intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state));
1222 intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state));
1223
1224 intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id),
1225 PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x));
1226
1227 if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) {
1228 intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0),
1229 lower_32_bits(plane_state->ccval));
1230 intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 1),
1231 upper_32_bits(plane_state->ccval));
1232 }
1233
1234
1235 if (!HAS_FLAT_CCS(dev_priv))
1236 intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id),
1237 skl_plane_aux_dist(plane_state, color_plane));
1238
1239 if (icl_is_hdr_plane(dev_priv, plane_id))
1240 intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id),
1241 plane_state->cus_ctl);
1242
1243 intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
1244
1245 if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
1246 icl_program_input_csc(plane, crtc_state, plane_state);
1247
1248 skl_write_plane_wm(plane, crtc_state);
1249
1250
1251
1252
1253
1254 if (plane_state->force_black)
1255 icl_plane_csc_load_black(plane);
1256
1257 intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane);
1258 }
1259
1260 static void
1261 icl_plane_update_arm(struct intel_plane *plane,
1262 const struct intel_crtc_state *crtc_state,
1263 const struct intel_plane_state *plane_state)
1264 {
1265 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1266 enum plane_id plane_id = plane->id;
1267 enum pipe pipe = plane->pipe;
1268 int color_plane = icl_plane_color_plane(plane_state);
1269 u32 plane_ctl;
1270
1271 plane_ctl = plane_state->ctl |
1272 skl_plane_ctl_crtc(crtc_state);
1273
1274
1275
1276
1277
1278
1279
1280
1281 if (plane_state->scaler_id >= 0)
1282 skl_program_plane_scaler(plane, crtc_state, plane_state);
1283
1284
1285
1286
1287
1288
1289 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1290 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1291 skl_plane_surf(plane_state, color_plane));
1292 }
1293
1294 static void
1295 skl_plane_async_flip(struct intel_plane *plane,
1296 const struct intel_crtc_state *crtc_state,
1297 const struct intel_plane_state *plane_state,
1298 bool async_flip)
1299 {
1300 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1301 enum plane_id plane_id = plane->id;
1302 enum pipe pipe = plane->pipe;
1303 u32 plane_ctl = plane_state->ctl;
1304
1305 plane_ctl |= skl_plane_ctl_crtc(crtc_state);
1306
1307 if (async_flip)
1308 plane_ctl |= PLANE_CTL_ASYNC_FLIP;
1309
1310 intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
1311 intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id),
1312 skl_plane_surf(plane_state, 0));
1313 }
1314
1315 static bool intel_format_is_p01x(u32 format)
1316 {
1317 switch (format) {
1318 case DRM_FORMAT_P010:
1319 case DRM_FORMAT_P012:
1320 case DRM_FORMAT_P016:
1321 return true;
1322 default:
1323 return false;
1324 }
1325 }
1326
1327 static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1328 const struct intel_plane_state *plane_state)
1329 {
1330 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1331 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1332 const struct drm_framebuffer *fb = plane_state->hw.fb;
1333 unsigned int rotation = plane_state->hw.rotation;
1334
1335 if (!fb)
1336 return 0;
1337
1338 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1339 intel_fb_is_ccs_modifier(fb->modifier)) {
1340 drm_dbg_kms(&dev_priv->drm,
1341 "RC support only with 0/180 degree rotation (%x)\n",
1342 rotation);
1343 return -EINVAL;
1344 }
1345
1346 if (rotation & DRM_MODE_REFLECT_X &&
1347 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1348 drm_dbg_kms(&dev_priv->drm,
1349 "horizontal flip is not supported with linear surface formats\n");
1350 return -EINVAL;
1351 }
1352
1353 if (drm_rotation_90_or_270(rotation)) {
1354 if (!intel_fb_supports_90_270_rotation(to_intel_framebuffer(fb))) {
1355 drm_dbg_kms(&dev_priv->drm,
1356 "Y/Yf tiling required for 90/270!\n");
1357 return -EINVAL;
1358 }
1359
1360
1361
1362
1363
1364 switch (fb->format->format) {
1365 case DRM_FORMAT_RGB565:
1366 if (DISPLAY_VER(dev_priv) >= 11)
1367 break;
1368 fallthrough;
1369 case DRM_FORMAT_C8:
1370 case DRM_FORMAT_XRGB16161616F:
1371 case DRM_FORMAT_XBGR16161616F:
1372 case DRM_FORMAT_ARGB16161616F:
1373 case DRM_FORMAT_ABGR16161616F:
1374 case DRM_FORMAT_Y210:
1375 case DRM_FORMAT_Y212:
1376 case DRM_FORMAT_Y216:
1377 case DRM_FORMAT_XVYU12_16161616:
1378 case DRM_FORMAT_XVYU16161616:
1379 drm_dbg_kms(&dev_priv->drm,
1380 "Unsupported pixel format %p4cc for 90/270!\n",
1381 &fb->format->format);
1382 return -EINVAL;
1383 default:
1384 break;
1385 }
1386 }
1387
1388
1389 if (crtc_state->hw.enable &&
1390 crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1391 fb->modifier != DRM_FORMAT_MOD_LINEAR &&
1392 fb->modifier != I915_FORMAT_MOD_X_TILED) {
1393 drm_dbg_kms(&dev_priv->drm,
1394 "Y/Yf tiling not supported in IF-ID mode\n");
1395 return -EINVAL;
1396 }
1397
1398
1399 if ((IS_ALDERLAKE_S(dev_priv) || IS_TIGERLAKE(dev_priv)) &&
1400 plane_state->ckey.flags & I915_SET_COLORKEY_SOURCE &&
1401 intel_format_is_p01x(fb->format->format)) {
1402 drm_dbg_kms(&dev_priv->drm,
1403 "Source color keying not supported with P01x formats\n");
1404 return -EINVAL;
1405 }
1406
1407 return 0;
1408 }
1409
1410 static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
1411 const struct intel_plane_state *plane_state)
1412 {
1413 struct drm_i915_private *dev_priv =
1414 to_i915(plane_state->uapi.plane->dev);
1415 int crtc_x = plane_state->uapi.dst.x1;
1416 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
1417 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src);
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428 if (DISPLAY_VER(dev_priv) == 10 &&
1429 (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
1430 drm_dbg_kms(&dev_priv->drm,
1431 "requested plane X %s position %d invalid (valid range %d-%d)\n",
1432 crtc_x + crtc_w < 4 ? "end" : "start",
1433 crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
1434 4, pipe_src_w - 4);
1435 return -ERANGE;
1436 }
1437
1438 return 0;
1439 }
1440
1441 static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
1442 {
1443 struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1444 const struct drm_framebuffer *fb = plane_state->hw.fb;
1445 unsigned int rotation = plane_state->hw.rotation;
1446 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1447
1448
1449 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1450 src_w & 3 &&
1451 (rotation == DRM_MODE_ROTATE_270 ||
1452 rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
1453 drm_dbg_kms(&i915->drm, "src width must be multiple of 4 for rotated planar YUV\n");
1454 return -EINVAL;
1455 }
1456
1457 return 0;
1458 }
1459
1460 static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
1461 const struct drm_framebuffer *fb)
1462 {
1463
1464
1465
1466
1467
1468
1469 if (DISPLAY_VER(dev_priv) >= 10 ||
1470 !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
1471 return 0x30000 - 1;
1472 else
1473 return 0x20000 - 1;
1474 }
1475
1476 static int intel_plane_min_width(struct intel_plane *plane,
1477 const struct drm_framebuffer *fb,
1478 int color_plane,
1479 unsigned int rotation)
1480 {
1481 if (plane->min_width)
1482 return plane->min_width(fb, color_plane, rotation);
1483 else
1484 return 1;
1485 }
1486
1487 static int intel_plane_max_width(struct intel_plane *plane,
1488 const struct drm_framebuffer *fb,
1489 int color_plane,
1490 unsigned int rotation)
1491 {
1492 if (plane->max_width)
1493 return plane->max_width(fb, color_plane, rotation);
1494 else
1495 return INT_MAX;
1496 }
1497
1498 static int intel_plane_max_height(struct intel_plane *plane,
1499 const struct drm_framebuffer *fb,
1500 int color_plane,
1501 unsigned int rotation)
1502 {
1503 if (plane->max_height)
1504 return plane->max_height(fb, color_plane, rotation);
1505 else
1506 return INT_MAX;
1507 }
1508
1509 static bool
1510 skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
1511 int main_x, int main_y, u32 main_offset,
1512 int ccs_plane)
1513 {
1514 const struct drm_framebuffer *fb = plane_state->hw.fb;
1515 int aux_x = plane_state->view.color_plane[ccs_plane].x;
1516 int aux_y = plane_state->view.color_plane[ccs_plane].y;
1517 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1518 u32 alignment = intel_surf_alignment(fb, ccs_plane);
1519 int hsub;
1520 int vsub;
1521
1522 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1523 while (aux_offset >= main_offset && aux_y <= main_y) {
1524 int x, y;
1525
1526 if (aux_x == main_x && aux_y == main_y)
1527 break;
1528
1529 if (aux_offset == 0)
1530 break;
1531
1532 x = aux_x / hsub;
1533 y = aux_y / vsub;
1534 aux_offset = intel_plane_adjust_aligned_offset(&x, &y,
1535 plane_state,
1536 ccs_plane,
1537 aux_offset,
1538 aux_offset -
1539 alignment);
1540 aux_x = x * hsub + aux_x % hsub;
1541 aux_y = y * vsub + aux_y % vsub;
1542 }
1543
1544 if (aux_x != main_x || aux_y != main_y)
1545 return false;
1546
1547 plane_state->view.color_plane[ccs_plane].offset = aux_offset;
1548 plane_state->view.color_plane[ccs_plane].x = aux_x;
1549 plane_state->view.color_plane[ccs_plane].y = aux_y;
1550
1551 return true;
1552 }
1553
1554
1555 int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
1556 int *x, int *y, u32 *offset)
1557 {
1558 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1559 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1560 const struct drm_framebuffer *fb = plane_state->hw.fb;
1561 const int aux_plane = skl_main_to_aux_plane(fb, 0);
1562 const u32 aux_offset = plane_state->view.color_plane[aux_plane].offset;
1563 const u32 alignment = intel_surf_alignment(fb, 0);
1564 const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1565
1566 intel_add_fb_offsets(x, y, plane_state, 0);
1567 *offset = intel_plane_compute_aligned_offset(x, y, plane_state, 0);
1568 if (drm_WARN_ON(&dev_priv->drm, alignment && !is_power_of_2(alignment)))
1569 return -EINVAL;
1570
1571
1572
1573
1574
1575
1576 if (aux_plane && *offset > aux_offset)
1577 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1578 *offset,
1579 aux_offset & ~(alignment - 1));
1580
1581
1582
1583
1584
1585
1586
1587 if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
1588 int cpp = fb->format->cpp[0];
1589
1590 while ((*x + w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
1591 if (*offset == 0) {
1592 drm_dbg_kms(&dev_priv->drm,
1593 "Unable to find suitable display surface offset due to X-tiling\n");
1594 return -EINVAL;
1595 }
1596
1597 *offset = intel_plane_adjust_aligned_offset(x, y, plane_state, 0,
1598 *offset,
1599 *offset - alignment);
1600 }
1601 }
1602
1603 return 0;
1604 }
1605
1606 static int skl_check_main_surface(struct intel_plane_state *plane_state)
1607 {
1608 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1609 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1610 const struct drm_framebuffer *fb = plane_state->hw.fb;
1611 const unsigned int rotation = plane_state->hw.rotation;
1612 int x = plane_state->uapi.src.x1 >> 16;
1613 int y = plane_state->uapi.src.y1 >> 16;
1614 const int w = drm_rect_width(&plane_state->uapi.src) >> 16;
1615 const int h = drm_rect_height(&plane_state->uapi.src) >> 16;
1616 const int min_width = intel_plane_min_width(plane, fb, 0, rotation);
1617 const int max_width = intel_plane_max_width(plane, fb, 0, rotation);
1618 const int max_height = intel_plane_max_height(plane, fb, 0, rotation);
1619 const int aux_plane = skl_main_to_aux_plane(fb, 0);
1620 const u32 alignment = intel_surf_alignment(fb, 0);
1621 u32 offset;
1622 int ret;
1623
1624 if (w > max_width || w < min_width || h > max_height) {
1625 drm_dbg_kms(&dev_priv->drm,
1626 "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
1627 w, h, min_width, max_width, max_height);
1628 return -EINVAL;
1629 }
1630
1631 ret = skl_calc_main_surface_offset(plane_state, &x, &y, &offset);
1632 if (ret)
1633 return ret;
1634
1635
1636
1637
1638
1639
1640 if (intel_fb_is_ccs_modifier(fb->modifier) && aux_plane) {
1641 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1642 offset, aux_plane)) {
1643 if (offset == 0)
1644 break;
1645
1646 offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
1647 offset, offset - alignment);
1648 }
1649
1650 if (x != plane_state->view.color_plane[aux_plane].x ||
1651 y != plane_state->view.color_plane[aux_plane].y) {
1652 drm_dbg_kms(&dev_priv->drm,
1653 "Unable to find suitable display surface offset due to CCS\n");
1654 return -EINVAL;
1655 }
1656 }
1657
1658 if (DISPLAY_VER(dev_priv) >= 13)
1659 drm_WARN_ON(&dev_priv->drm, x > 65535 || y > 65535);
1660 else
1661 drm_WARN_ON(&dev_priv->drm, x > 8191 || y > 8191);
1662
1663 plane_state->view.color_plane[0].offset = offset;
1664 plane_state->view.color_plane[0].x = x;
1665 plane_state->view.color_plane[0].y = y;
1666
1667
1668
1669
1670
1671 drm_rect_translate_to(&plane_state->uapi.src,
1672 x << 16, y << 16);
1673
1674 return 0;
1675 }
1676
1677 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
1678 {
1679 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1680 struct drm_i915_private *i915 = to_i915(plane->base.dev);
1681 const struct drm_framebuffer *fb = plane_state->hw.fb;
1682 unsigned int rotation = plane_state->hw.rotation;
1683 int uv_plane = 1;
1684 int ccs_plane = intel_fb_is_ccs_modifier(fb->modifier) ?
1685 skl_main_to_aux_plane(fb, uv_plane) : 0;
1686 int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation);
1687 int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation);
1688 int x = plane_state->uapi.src.x1 >> 17;
1689 int y = plane_state->uapi.src.y1 >> 17;
1690 int w = drm_rect_width(&plane_state->uapi.src) >> 17;
1691 int h = drm_rect_height(&plane_state->uapi.src) >> 17;
1692 u32 offset;
1693
1694
1695 if (w > max_width || h > max_height) {
1696 drm_dbg_kms(&i915->drm,
1697 "CbCr source size %dx%d too big (limit %dx%d)\n",
1698 w, h, max_width, max_height);
1699 return -EINVAL;
1700 }
1701
1702 intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
1703 offset = intel_plane_compute_aligned_offset(&x, &y,
1704 plane_state, uv_plane);
1705
1706 if (ccs_plane) {
1707 u32 aux_offset = plane_state->view.color_plane[ccs_plane].offset;
1708 u32 alignment = intel_surf_alignment(fb, uv_plane);
1709
1710 if (offset > aux_offset)
1711 offset = intel_plane_adjust_aligned_offset(&x, &y,
1712 plane_state,
1713 uv_plane,
1714 offset,
1715 aux_offset & ~(alignment - 1));
1716
1717 while (!skl_check_main_ccs_coordinates(plane_state, x, y,
1718 offset, ccs_plane)) {
1719 if (offset == 0)
1720 break;
1721
1722 offset = intel_plane_adjust_aligned_offset(&x, &y,
1723 plane_state,
1724 uv_plane,
1725 offset, offset - alignment);
1726 }
1727
1728 if (x != plane_state->view.color_plane[ccs_plane].x ||
1729 y != plane_state->view.color_plane[ccs_plane].y) {
1730 drm_dbg_kms(&i915->drm,
1731 "Unable to find suitable display surface offset due to CCS\n");
1732 return -EINVAL;
1733 }
1734 }
1735
1736 if (DISPLAY_VER(i915) >= 13)
1737 drm_WARN_ON(&i915->drm, x > 65535 || y > 65535);
1738 else
1739 drm_WARN_ON(&i915->drm, x > 8191 || y > 8191);
1740
1741 plane_state->view.color_plane[uv_plane].offset = offset;
1742 plane_state->view.color_plane[uv_plane].x = x;
1743 plane_state->view.color_plane[uv_plane].y = y;
1744
1745 return 0;
1746 }
1747
1748 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
1749 {
1750 const struct drm_framebuffer *fb = plane_state->hw.fb;
1751 int src_x = plane_state->uapi.src.x1 >> 16;
1752 int src_y = plane_state->uapi.src.y1 >> 16;
1753 u32 offset;
1754 int ccs_plane;
1755
1756 for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
1757 int main_hsub, main_vsub;
1758 int hsub, vsub;
1759 int x, y;
1760
1761 if (!intel_fb_is_ccs_aux_plane(fb, ccs_plane))
1762 continue;
1763
1764 intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
1765 skl_ccs_to_main_plane(fb, ccs_plane));
1766 intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);
1767
1768 hsub *= main_hsub;
1769 vsub *= main_vsub;
1770 x = src_x / hsub;
1771 y = src_y / vsub;
1772
1773 intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);
1774
1775 offset = intel_plane_compute_aligned_offset(&x, &y,
1776 plane_state,
1777 ccs_plane);
1778
1779 plane_state->view.color_plane[ccs_plane].offset = offset;
1780 plane_state->view.color_plane[ccs_plane].x = (x * hsub + src_x % hsub) / main_hsub;
1781 plane_state->view.color_plane[ccs_plane].y = (y * vsub + src_y % vsub) / main_vsub;
1782 }
1783
1784 return 0;
1785 }
1786
1787 static int skl_check_plane_surface(struct intel_plane_state *plane_state)
1788 {
1789 const struct drm_framebuffer *fb = plane_state->hw.fb;
1790 int ret;
1791
1792 ret = intel_plane_compute_gtt(plane_state);
1793 if (ret)
1794 return ret;
1795
1796 if (!plane_state->uapi.visible)
1797 return 0;
1798
1799
1800
1801
1802
1803 if (intel_fb_is_ccs_modifier(fb->modifier)) {
1804 ret = skl_check_ccs_aux_surface(plane_state);
1805 if (ret)
1806 return ret;
1807 }
1808
1809 if (intel_format_info_is_yuv_semiplanar(fb->format,
1810 fb->modifier)) {
1811 ret = skl_check_nv12_aux_surface(plane_state);
1812 if (ret)
1813 return ret;
1814 }
1815
1816 ret = skl_check_main_surface(plane_state);
1817 if (ret)
1818 return ret;
1819
1820 return 0;
1821 }
1822
1823 static bool skl_fb_scalable(const struct drm_framebuffer *fb)
1824 {
1825 if (!fb)
1826 return false;
1827
1828 switch (fb->format->format) {
1829 case DRM_FORMAT_C8:
1830 return false;
1831 case DRM_FORMAT_XRGB16161616F:
1832 case DRM_FORMAT_ARGB16161616F:
1833 case DRM_FORMAT_XBGR16161616F:
1834 case DRM_FORMAT_ABGR16161616F:
1835 return DISPLAY_VER(to_i915(fb->dev)) >= 11;
1836 default:
1837 return true;
1838 }
1839 }
1840
1841 static bool bo_has_valid_encryption(struct drm_i915_gem_object *obj)
1842 {
1843 struct drm_i915_private *i915 = to_i915(obj->base.dev);
1844
1845 return intel_pxp_key_check(&to_gt(i915)->pxp, obj, false) == 0;
1846 }
1847
1848 static bool pxp_is_borked(struct drm_i915_gem_object *obj)
1849 {
1850 return i915_gem_object_is_protected(obj) && !bo_has_valid_encryption(obj);
1851 }
1852
1853 static int skl_plane_check(struct intel_crtc_state *crtc_state,
1854 struct intel_plane_state *plane_state)
1855 {
1856 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1857 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1858 const struct drm_framebuffer *fb = plane_state->hw.fb;
1859 int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1860 int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1861 int ret;
1862
1863 ret = skl_plane_check_fb(crtc_state, plane_state);
1864 if (ret)
1865 return ret;
1866
1867
1868 if (!plane_state->ckey.flags && skl_fb_scalable(fb)) {
1869 min_scale = 1;
1870 max_scale = skl_plane_max_scale(dev_priv, fb);
1871 }
1872
1873 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1874 min_scale, max_scale, true);
1875 if (ret)
1876 return ret;
1877
1878 ret = skl_check_plane_surface(plane_state);
1879 if (ret)
1880 return ret;
1881
1882 if (!plane_state->uapi.visible)
1883 return 0;
1884
1885 ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
1886 if (ret)
1887 return ret;
1888
1889 ret = intel_plane_check_src_coordinates(plane_state);
1890 if (ret)
1891 return ret;
1892
1893 ret = skl_plane_check_nv12_rotation(plane_state);
1894 if (ret)
1895 return ret;
1896
1897 if (DISPLAY_VER(dev_priv) >= 11) {
1898 plane_state->decrypt = bo_has_valid_encryption(intel_fb_obj(fb));
1899 plane_state->force_black = pxp_is_borked(intel_fb_obj(fb));
1900 }
1901
1902
1903 if (!(plane_state->hw.alpha >> 8))
1904 plane_state->uapi.visible = false;
1905
1906 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1907
1908 if (DISPLAY_VER(dev_priv) >= 10)
1909 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1910 plane_state);
1911
1912 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
1913 icl_is_hdr_plane(dev_priv, plane->id))
1914
1915 plane_state->cus_ctl = PLANE_CUS_ENABLE |
1916 PLANE_CUS_HPHASE_0 |
1917 PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
1918 else
1919 plane_state->cus_ctl = 0;
1920
1921 return 0;
1922 }
1923
1924 static enum intel_fbc_id skl_fbc_id_for_pipe(enum pipe pipe)
1925 {
1926 return pipe - PIPE_A + INTEL_FBC_A;
1927 }
1928
1929 static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
1930 enum intel_fbc_id fbc_id, enum plane_id plane_id)
1931 {
1932 if ((INTEL_INFO(dev_priv)->display.fbc_mask & BIT(fbc_id)) == 0)
1933 return false;
1934
1935 return plane_id == PLANE_PRIMARY;
1936 }
1937
1938 static struct intel_fbc *skl_plane_fbc(struct drm_i915_private *dev_priv,
1939 enum pipe pipe, enum plane_id plane_id)
1940 {
1941 enum intel_fbc_id fbc_id = skl_fbc_id_for_pipe(pipe);
1942
1943 if (skl_plane_has_fbc(dev_priv, fbc_id, plane_id))
1944 return dev_priv->fbc[fbc_id];
1945 else
1946 return NULL;
1947 }
1948
1949 static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
1950 enum pipe pipe, enum plane_id plane_id)
1951 {
1952
1953 if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
1954 return false;
1955
1956 if (DISPLAY_VER(dev_priv) == 9 && pipe == PIPE_C)
1957 return false;
1958
1959 if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
1960 return false;
1961
1962 return true;
1963 }
1964
1965 static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
1966 enum pipe pipe, enum plane_id plane_id,
1967 int *num_formats)
1968 {
1969 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1970 *num_formats = ARRAY_SIZE(skl_planar_formats);
1971 return skl_planar_formats;
1972 } else {
1973 *num_formats = ARRAY_SIZE(skl_plane_formats);
1974 return skl_plane_formats;
1975 }
1976 }
1977
1978 static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
1979 enum pipe pipe, enum plane_id plane_id,
1980 int *num_formats)
1981 {
1982 if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
1983 *num_formats = ARRAY_SIZE(glk_planar_formats);
1984 return glk_planar_formats;
1985 } else {
1986 *num_formats = ARRAY_SIZE(skl_plane_formats);
1987 return skl_plane_formats;
1988 }
1989 }
1990
1991 static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
1992 enum pipe pipe, enum plane_id plane_id,
1993 int *num_formats)
1994 {
1995 if (icl_is_hdr_plane(dev_priv, plane_id)) {
1996 *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
1997 return icl_hdr_plane_formats;
1998 } else if (icl_is_nv12_y_plane(dev_priv, plane_id)) {
1999 *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2000 return icl_sdr_y_plane_formats;
2001 } else {
2002 *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2003 return icl_sdr_uv_plane_formats;
2004 }
2005 }
2006
2007 static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2008 u32 format, u64 modifier)
2009 {
2010 struct intel_plane *plane = to_intel_plane(_plane);
2011
2012 if (!intel_fb_plane_supports_modifier(plane, modifier))
2013 return false;
2014
2015 switch (format) {
2016 case DRM_FORMAT_XRGB8888:
2017 case DRM_FORMAT_XBGR8888:
2018 case DRM_FORMAT_ARGB8888:
2019 case DRM_FORMAT_ABGR8888:
2020 if (intel_fb_is_ccs_modifier(modifier))
2021 return true;
2022 fallthrough;
2023 case DRM_FORMAT_RGB565:
2024 case DRM_FORMAT_XRGB2101010:
2025 case DRM_FORMAT_XBGR2101010:
2026 case DRM_FORMAT_ARGB2101010:
2027 case DRM_FORMAT_ABGR2101010:
2028 case DRM_FORMAT_YUYV:
2029 case DRM_FORMAT_YVYU:
2030 case DRM_FORMAT_UYVY:
2031 case DRM_FORMAT_VYUY:
2032 case DRM_FORMAT_NV12:
2033 case DRM_FORMAT_XYUV8888:
2034 case DRM_FORMAT_P010:
2035 case DRM_FORMAT_P012:
2036 case DRM_FORMAT_P016:
2037 case DRM_FORMAT_XVYU2101010:
2038 if (modifier == I915_FORMAT_MOD_Yf_TILED)
2039 return true;
2040 fallthrough;
2041 case DRM_FORMAT_C8:
2042 case DRM_FORMAT_XBGR16161616F:
2043 case DRM_FORMAT_ABGR16161616F:
2044 case DRM_FORMAT_XRGB16161616F:
2045 case DRM_FORMAT_ARGB16161616F:
2046 case DRM_FORMAT_Y210:
2047 case DRM_FORMAT_Y212:
2048 case DRM_FORMAT_Y216:
2049 case DRM_FORMAT_XVYU12_16161616:
2050 case DRM_FORMAT_XVYU16161616:
2051 if (modifier == DRM_FORMAT_MOD_LINEAR ||
2052 modifier == I915_FORMAT_MOD_X_TILED ||
2053 modifier == I915_FORMAT_MOD_Y_TILED)
2054 return true;
2055 fallthrough;
2056 default:
2057 return false;
2058 }
2059 }
2060
2061 static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
2062 u32 format, u64 modifier)
2063 {
2064 struct intel_plane *plane = to_intel_plane(_plane);
2065
2066 if (!intel_fb_plane_supports_modifier(plane, modifier))
2067 return false;
2068
2069 switch (format) {
2070 case DRM_FORMAT_XRGB8888:
2071 case DRM_FORMAT_XBGR8888:
2072 case DRM_FORMAT_ARGB8888:
2073 case DRM_FORMAT_ABGR8888:
2074 if (intel_fb_is_ccs_modifier(modifier))
2075 return true;
2076 fallthrough;
2077 case DRM_FORMAT_YUYV:
2078 case DRM_FORMAT_YVYU:
2079 case DRM_FORMAT_UYVY:
2080 case DRM_FORMAT_VYUY:
2081 case DRM_FORMAT_NV12:
2082 case DRM_FORMAT_XYUV8888:
2083 case DRM_FORMAT_P010:
2084 case DRM_FORMAT_P012:
2085 case DRM_FORMAT_P016:
2086 if (intel_fb_is_mc_ccs_modifier(modifier))
2087 return true;
2088 fallthrough;
2089 case DRM_FORMAT_RGB565:
2090 case DRM_FORMAT_XRGB2101010:
2091 case DRM_FORMAT_XBGR2101010:
2092 case DRM_FORMAT_ARGB2101010:
2093 case DRM_FORMAT_ABGR2101010:
2094 case DRM_FORMAT_XVYU2101010:
2095 case DRM_FORMAT_C8:
2096 case DRM_FORMAT_XBGR16161616F:
2097 case DRM_FORMAT_ABGR16161616F:
2098 case DRM_FORMAT_XRGB16161616F:
2099 case DRM_FORMAT_ARGB16161616F:
2100 case DRM_FORMAT_Y210:
2101 case DRM_FORMAT_Y212:
2102 case DRM_FORMAT_Y216:
2103 case DRM_FORMAT_XVYU12_16161616:
2104 case DRM_FORMAT_XVYU16161616:
2105 if (!intel_fb_is_ccs_modifier(modifier))
2106 return true;
2107 fallthrough;
2108 default:
2109 return false;
2110 }
2111 }
2112
2113 static const struct drm_plane_funcs skl_plane_funcs = {
2114 .update_plane = drm_atomic_helper_update_plane,
2115 .disable_plane = drm_atomic_helper_disable_plane,
2116 .destroy = intel_plane_destroy,
2117 .atomic_duplicate_state = intel_plane_duplicate_state,
2118 .atomic_destroy_state = intel_plane_destroy_state,
2119 .format_mod_supported = skl_plane_format_mod_supported,
2120 };
2121
2122 static const struct drm_plane_funcs gen12_plane_funcs = {
2123 .update_plane = drm_atomic_helper_update_plane,
2124 .disable_plane = drm_atomic_helper_disable_plane,
2125 .destroy = intel_plane_destroy,
2126 .atomic_duplicate_state = intel_plane_duplicate_state,
2127 .atomic_destroy_state = intel_plane_destroy_state,
2128 .format_mod_supported = gen12_plane_format_mod_supported,
2129 };
2130
2131 static void
2132 skl_plane_enable_flip_done(struct intel_plane *plane)
2133 {
2134 struct drm_i915_private *i915 = to_i915(plane->base.dev);
2135 enum pipe pipe = plane->pipe;
2136
2137 spin_lock_irq(&i915->irq_lock);
2138 bdw_enable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2139 spin_unlock_irq(&i915->irq_lock);
2140 }
2141
2142 static void
2143 skl_plane_disable_flip_done(struct intel_plane *plane)
2144 {
2145 struct drm_i915_private *i915 = to_i915(plane->base.dev);
2146 enum pipe pipe = plane->pipe;
2147
2148 spin_lock_irq(&i915->irq_lock);
2149 bdw_disable_pipe_irq(i915, pipe, GEN9_PIPE_PLANE_FLIP_DONE(plane->id));
2150 spin_unlock_irq(&i915->irq_lock);
2151 }
2152
2153 static bool skl_plane_has_rc_ccs(struct drm_i915_private *i915,
2154 enum pipe pipe, enum plane_id plane_id)
2155 {
2156
2157 if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2158 return false;
2159
2160 if (DISPLAY_VER(i915) >= 11)
2161 return true;
2162
2163 if (IS_GEMINILAKE(i915))
2164 return pipe != PIPE_C;
2165
2166 return pipe != PIPE_C &&
2167 (plane_id == PLANE_PRIMARY ||
2168 plane_id == PLANE_SPRITE0);
2169 }
2170
2171 static bool gen12_plane_has_mc_ccs(struct drm_i915_private *i915,
2172 enum plane_id plane_id)
2173 {
2174 if (DISPLAY_VER(i915) < 12)
2175 return false;
2176
2177
2178 if (IS_DG1(i915) || IS_ROCKETLAKE(i915) ||
2179 IS_TGL_DISPLAY_STEP(i915, STEP_A0, STEP_D0))
2180 return false;
2181
2182
2183 if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2184 return false;
2185
2186
2187 if (IS_DG2_DISPLAY_STEP(i915, STEP_A0, STEP_C0))
2188 return false;
2189
2190 return plane_id < PLANE_SPRITE4;
2191 }
2192
2193 static u8 skl_get_plane_caps(struct drm_i915_private *i915,
2194 enum pipe pipe, enum plane_id plane_id)
2195 {
2196 u8 caps = INTEL_PLANE_CAP_TILING_X;
2197
2198 if (DISPLAY_VER(i915) < 13 || IS_ALDERLAKE_P(i915))
2199 caps |= INTEL_PLANE_CAP_TILING_Y;
2200 if (DISPLAY_VER(i915) < 12)
2201 caps |= INTEL_PLANE_CAP_TILING_Yf;
2202 if (HAS_4TILE(i915))
2203 caps |= INTEL_PLANE_CAP_TILING_4;
2204
2205 if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
2206 caps |= INTEL_PLANE_CAP_CCS_RC;
2207 if (DISPLAY_VER(i915) >= 12)
2208 caps |= INTEL_PLANE_CAP_CCS_RC_CC;
2209 }
2210
2211 if (gen12_plane_has_mc_ccs(i915, plane_id))
2212 caps |= INTEL_PLANE_CAP_CCS_MC;
2213
2214 return caps;
2215 }
2216
2217 struct intel_plane *
2218 skl_universal_plane_create(struct drm_i915_private *dev_priv,
2219 enum pipe pipe, enum plane_id plane_id)
2220 {
2221 const struct drm_plane_funcs *plane_funcs;
2222 struct intel_plane *plane;
2223 enum drm_plane_type plane_type;
2224 unsigned int supported_rotations;
2225 unsigned int supported_csc;
2226 const u64 *modifiers;
2227 const u32 *formats;
2228 int num_formats;
2229 int ret;
2230
2231 plane = intel_plane_alloc();
2232 if (IS_ERR(plane))
2233 return plane;
2234
2235 plane->pipe = pipe;
2236 plane->id = plane_id;
2237 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2238
2239 intel_fbc_add_plane(skl_plane_fbc(dev_priv, pipe, plane_id), plane);
2240
2241 if (DISPLAY_VER(dev_priv) >= 11) {
2242 plane->min_width = icl_plane_min_width;
2243 if (icl_is_hdr_plane(dev_priv, plane_id))
2244 plane->max_width = icl_hdr_plane_max_width;
2245 else
2246 plane->max_width = icl_sdr_plane_max_width;
2247 plane->max_height = icl_plane_max_height;
2248 plane->min_cdclk = icl_plane_min_cdclk;
2249 } else if (DISPLAY_VER(dev_priv) >= 10) {
2250 plane->max_width = glk_plane_max_width;
2251 plane->max_height = skl_plane_max_height;
2252 plane->min_cdclk = glk_plane_min_cdclk;
2253 } else {
2254 plane->max_width = skl_plane_max_width;
2255 plane->max_height = skl_plane_max_height;
2256 plane->min_cdclk = skl_plane_min_cdclk;
2257 }
2258
2259 plane->max_stride = skl_plane_max_stride;
2260 if (DISPLAY_VER(dev_priv) >= 11) {
2261 plane->update_noarm = icl_plane_update_noarm;
2262 plane->update_arm = icl_plane_update_arm;
2263 plane->disable_arm = icl_plane_disable_arm;
2264 } else {
2265 plane->update_noarm = skl_plane_update_noarm;
2266 plane->update_arm = skl_plane_update_arm;
2267 plane->disable_arm = skl_plane_disable_arm;
2268 }
2269 plane->get_hw_state = skl_plane_get_hw_state;
2270 plane->check_plane = skl_plane_check;
2271
2272 if (plane_id == PLANE_PRIMARY) {
2273 plane->need_async_flip_disable_wa = IS_DISPLAY_VER(dev_priv,
2274 9, 10);
2275 plane->async_flip = skl_plane_async_flip;
2276 plane->enable_flip_done = skl_plane_enable_flip_done;
2277 plane->disable_flip_done = skl_plane_disable_flip_done;
2278 }
2279
2280 if (DISPLAY_VER(dev_priv) >= 11)
2281 formats = icl_get_plane_formats(dev_priv, pipe,
2282 plane_id, &num_formats);
2283 else if (DISPLAY_VER(dev_priv) >= 10)
2284 formats = glk_get_plane_formats(dev_priv, pipe,
2285 plane_id, &num_formats);
2286 else
2287 formats = skl_get_plane_formats(dev_priv, pipe,
2288 plane_id, &num_formats);
2289
2290 if (DISPLAY_VER(dev_priv) >= 12)
2291 plane_funcs = &gen12_plane_funcs;
2292 else
2293 plane_funcs = &skl_plane_funcs;
2294
2295 if (plane_id == PLANE_PRIMARY)
2296 plane_type = DRM_PLANE_TYPE_PRIMARY;
2297 else
2298 plane_type = DRM_PLANE_TYPE_OVERLAY;
2299
2300 modifiers = intel_fb_plane_get_modifiers(dev_priv,
2301 skl_get_plane_caps(dev_priv, pipe, plane_id));
2302
2303 ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
2304 0, plane_funcs,
2305 formats, num_formats, modifiers,
2306 plane_type,
2307 "plane %d%c", plane_id + 1,
2308 pipe_name(pipe));
2309
2310 kfree(modifiers);
2311
2312 if (ret)
2313 goto fail;
2314
2315 if (DISPLAY_VER(dev_priv) >= 13)
2316 supported_rotations = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
2317 else
2318 supported_rotations =
2319 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
2320 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
2321
2322 if (DISPLAY_VER(dev_priv) >= 11)
2323 supported_rotations |= DRM_MODE_REFLECT_X;
2324
2325 drm_plane_create_rotation_property(&plane->base,
2326 DRM_MODE_ROTATE_0,
2327 supported_rotations);
2328
2329 supported_csc = BIT(DRM_COLOR_YCBCR_BT601) | BIT(DRM_COLOR_YCBCR_BT709);
2330
2331 if (DISPLAY_VER(dev_priv) >= 10)
2332 supported_csc |= BIT(DRM_COLOR_YCBCR_BT2020);
2333
2334 drm_plane_create_color_properties(&plane->base,
2335 supported_csc,
2336 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
2337 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
2338 DRM_COLOR_YCBCR_BT709,
2339 DRM_COLOR_YCBCR_LIMITED_RANGE);
2340
2341 drm_plane_create_alpha_property(&plane->base);
2342 drm_plane_create_blend_mode_property(&plane->base,
2343 BIT(DRM_MODE_BLEND_PIXEL_NONE) |
2344 BIT(DRM_MODE_BLEND_PREMULTI) |
2345 BIT(DRM_MODE_BLEND_COVERAGE));
2346
2347 drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
2348
2349 if (DISPLAY_VER(dev_priv) >= 12)
2350 drm_plane_enable_fb_damage_clips(&plane->base);
2351
2352 if (DISPLAY_VER(dev_priv) >= 11)
2353 drm_plane_create_scaling_filter_property(&plane->base,
2354 BIT(DRM_SCALING_FILTER_DEFAULT) |
2355 BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
2356
2357 intel_plane_helper_add(plane);
2358
2359 return plane;
2360
2361 fail:
2362 intel_plane_free(plane);
2363
2364 return ERR_PTR(ret);
2365 }
2366
2367 void
2368 skl_get_initial_plane_config(struct intel_crtc *crtc,
2369 struct intel_initial_plane_config *plane_config)
2370 {
2371 struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
2372 struct drm_device *dev = crtc->base.dev;
2373 struct drm_i915_private *dev_priv = to_i915(dev);
2374 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
2375 enum plane_id plane_id = plane->id;
2376 enum pipe pipe;
2377 u32 val, base, offset, stride_mult, tiling, alpha;
2378 int fourcc, pixel_format;
2379 unsigned int aligned_height;
2380 struct drm_framebuffer *fb;
2381 struct intel_framebuffer *intel_fb;
2382 static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
2383
2384 if (!plane->get_hw_state(plane, &pipe))
2385 return;
2386
2387 drm_WARN_ON(dev, pipe != crtc->pipe);
2388
2389 if (crtc_state->bigjoiner_pipes) {
2390 drm_dbg_kms(&dev_priv->drm,
2391 "Unsupported bigjoiner configuration for initial FB\n");
2392 return;
2393 }
2394
2395 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
2396 if (!intel_fb) {
2397 drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
2398 return;
2399 }
2400
2401 fb = &intel_fb->base;
2402
2403 fb->dev = dev;
2404
2405 val = intel_de_read(dev_priv, PLANE_CTL(pipe, plane_id));
2406
2407 if (DISPLAY_VER(dev_priv) >= 11)
2408 pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL;
2409 else
2410 pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL;
2411
2412 if (DISPLAY_VER(dev_priv) >= 10) {
2413 u32 color_ctl;
2414
2415 color_ctl = intel_de_read(dev_priv, PLANE_COLOR_CTL(pipe, plane_id));
2416 alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl);
2417 } else {
2418 alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val);
2419 }
2420
2421 fourcc = skl_format_to_fourcc(pixel_format,
2422 val & PLANE_CTL_ORDER_RGBX, alpha);
2423 fb->format = drm_format_info(fourcc);
2424
2425 tiling = val & PLANE_CTL_TILED_MASK;
2426 switch (tiling) {
2427 case PLANE_CTL_TILED_LINEAR:
2428 fb->modifier = DRM_FORMAT_MOD_LINEAR;
2429 break;
2430 case PLANE_CTL_TILED_X:
2431 plane_config->tiling = I915_TILING_X;
2432 fb->modifier = I915_FORMAT_MOD_X_TILED;
2433 break;
2434 case PLANE_CTL_TILED_Y:
2435 plane_config->tiling = I915_TILING_Y;
2436 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2437 if (DISPLAY_VER(dev_priv) >= 12)
2438 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
2439 else
2440 fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
2441 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2442 fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
2443 else
2444 fb->modifier = I915_FORMAT_MOD_Y_TILED;
2445 break;
2446 case PLANE_CTL_TILED_YF:
2447 if (HAS_4TILE(dev_priv)) {
2448 u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
2449 PLANE_CTL_CLEAR_COLOR_DISABLE;
2450
2451 if ((val & rc_mask) == rc_mask)
2452 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
2453 else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
2454 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
2455 else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2456 fb->modifier = I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
2457 else
2458 fb->modifier = I915_FORMAT_MOD_4_TILED;
2459 } else {
2460 if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
2461 fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
2462 else
2463 fb->modifier = I915_FORMAT_MOD_Yf_TILED;
2464 }
2465 break;
2466 default:
2467 MISSING_CASE(tiling);
2468 goto error;
2469 }
2470
2471
2472
2473
2474
2475 switch (val & PLANE_CTL_ROTATE_MASK) {
2476 case PLANE_CTL_ROTATE_0:
2477 plane_config->rotation = DRM_MODE_ROTATE_0;
2478 break;
2479 case PLANE_CTL_ROTATE_90:
2480 plane_config->rotation = DRM_MODE_ROTATE_270;
2481 break;
2482 case PLANE_CTL_ROTATE_180:
2483 plane_config->rotation = DRM_MODE_ROTATE_180;
2484 break;
2485 case PLANE_CTL_ROTATE_270:
2486 plane_config->rotation = DRM_MODE_ROTATE_90;
2487 break;
2488 }
2489
2490 if (DISPLAY_VER(dev_priv) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
2491 plane_config->rotation |= DRM_MODE_REFLECT_X;
2492
2493
2494 if (drm_rotation_90_or_270(plane_config->rotation))
2495 goto error;
2496
2497 base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & PLANE_SURF_ADDR_MASK;
2498 plane_config->base = base;
2499
2500 offset = intel_de_read(dev_priv, PLANE_OFFSET(pipe, plane_id));
2501
2502 val = intel_de_read(dev_priv, PLANE_SIZE(pipe, plane_id));
2503 fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1;
2504 fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1;
2505
2506 val = intel_de_read(dev_priv, PLANE_STRIDE(pipe, plane_id));
2507 stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
2508
2509 fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult;
2510
2511 aligned_height = intel_fb_align_height(fb, 0, fb->height);
2512
2513 plane_config->size = fb->pitches[0] * aligned_height;
2514
2515 drm_dbg_kms(&dev_priv->drm,
2516 "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
2517 crtc->base.name, plane->base.name, fb->width, fb->height,
2518 fb->format->cpp[0] * 8, base, fb->pitches[0],
2519 plane_config->size);
2520
2521 plane_config->fb = intel_fb;
2522 return;
2523
2524 error:
2525 kfree(intel_fb);
2526 }