Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Copyright © 2020 Intel Corporation
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     /* two pixels per clock */
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     /* two pixels per clock */
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          * Validated limit is 4k, but has 5k should
0329          * work apart from the following features:
0330          * - Ytile (already limited to 4k)
0331          * - FP16 (already limited to 4k)
0332          * - render compression (already limited to 4k)
0333          * - KVMR sprite and cursor (don't care)
0334          * - horizontal panning (TODO verify this)
0335          * - pipe and plane scaling (TODO verify this)
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         /* FIXME AUX plane? */
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         /* FIXME AUX plane? */
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     /* Wa_14011264657, Wa_14011050563: gen11+ */
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          * The stride in bytes must not exceed of the size
0470          * of 128K bytes. For pixel formats of 64bpp will allow
0471          * for a 16K pixel surface.
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          * "The stride in bytes must not exceed the
0481          * of the size of 8K pixels and 32K bytes."
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 /* Preoffset values for YUV to RGB Conversion */
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  * Programs the input color space conversion stage for ICL HDR planes.
0504  * Note that it is assumed that this stage always happens after YUV
0505  * range correction. Thus, the input to this stage is assumed to be
0506  * in full-range YCbCr.
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          * BT.601 full range YCbCr -> full range RGB
0520          * The matrix required is :
0521          * [1.000, 0.000, 1.371,
0522          *  1.000, -0.336, -0.698,
0523          *  1.000, 1.732, 0.0000]
0524          */
0525         [DRM_COLOR_YCBCR_BT601] = {
0526             0x7AF8, 0x7800, 0x0,
0527             0x8B28, 0x7800, 0x9AC0,
0528             0x0, 0x7800, 0x7DD8,
0529         },
0530         /*
0531          * BT.709 full range YCbCr -> full range RGB
0532          * The matrix required is :
0533          * [1.000, 0.000, 1.574,
0534          *  1.000, -0.187, -0.468,
0535          *  1.000, 1.855, 0.0000]
0536          */
0537         [DRM_COLOR_YCBCR_BT709] = {
0538             0x7C98, 0x7800, 0x0,
0539             0x9EF8, 0x7800, 0xAC00,
0540             0x0, 0x7800,  0x7ED8,
0541         },
0542         /*
0543          * BT.2020 full range YCbCr -> full range RGB
0544          * The matrix required is :
0545          * [1.000, 0.000, 1.474,
0546          *  1.000, -0.1645, -0.5713,
0547          *  1.000, 1.8814, 0.0000]
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      * The stride is either expressed as a multiple of 64 bytes chunks for
0589      * linear buffers or in number of tiles for tiled buffers.
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      * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
0814      * while i915 HW rotation is clockwise, thats why this swapping.
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     /* Wa_22012358565:adl-p */
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          * The DPT object contains only one vma, so the VMA's offset
0993          * within the DPT is always 0.
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     /* Program the UV plane on planar master */
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     /* The scaler will handle the output position */
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      * Enable the scaler before the plane so that we don't
1167      * get a catastrophic underrun even if the two operations
1168      * end up happening in two different frames.
1169      *
1170      * TODO: split into noarm+arm pair
1171      */
1172     if (plane_state->scaler_id >= 0)
1173         skl_program_plane_scaler(plane, crtc_state, plane_state);
1174 
1175     /*
1176      * The control register self-arms if the plane was previously
1177      * disabled. Try to make the plane enable atomic by writing
1178      * the control register just before the surface register.
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     /* The scaler will handle the output position */
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     /* FLAT CCS doesn't need to program AUX_DIST */
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      * FIXME: pxp session invalidation can hit any time even at time of commit
1252      * or after the commit, display content will be garbage.
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      * Enable the scaler before the plane so that we don't
1276      * get a catastrophic underrun even if the two operations
1277      * end up happening in two different frames.
1278      *
1279      * TODO: split into noarm+arm pair
1280      */
1281     if (plane_state->scaler_id >= 0)
1282         skl_program_plane_scaler(plane, crtc_state, plane_state);
1283 
1284     /*
1285      * The control register self-arms if the plane was previously
1286      * disabled. Try to make the plane enable atomic by writing
1287      * the control register just before the surface register.
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          * 90/270 is not allowed with RGB64 16:16:16:16 and
1362          * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
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     /* Y-tiling is not supported in IF-ID Interlace mode */
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     /* Wa_1606054188:tgl,adl-s */
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      * Display WA #1175: glk
1421      * Planes other than the cursor may cause FIFO underflow and display
1422      * corruption if starting less than 4 pixels from the right edge of
1423      * the screen.
1424      * Besides the above WA fix the similar problem, where planes other
1425      * than the cursor ending less than 4 pixels from the left edge of the
1426      * screen may cause FIFO underflow and display corruption.
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     /* Display WA #1106 */
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      * We don't yet know the final source width nor
1465      * whether we can use the HQ scaler mode. Assume
1466      * the best case.
1467      * FIXME need to properly check this later.
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      * AUX surface offset is specified as the distance from the
1573      * main surface offset, and it must be non-negative. Make
1574      * sure that is what we will get.
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      * When using an X-tiled surface, the plane blows up
1583      * if the x offset + width exceed the stride.
1584      *
1585      * TODO: linear and Y-tiled seem fine, Yf untested,
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      * CCS AUX surface doesn't have its own x/y offsets, we must make sure
1637      * they match with the main surface x/y offsets. On DG2
1638      * there's no aux plane on fb so skip this checking.
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      * Put the final coordinates back so that the src
1669      * coordinate checks will see the right values.
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     /* FIXME not quite sure how/if these apply to the chroma plane */
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      * Handle the AUX surface first since the main surface setup depends on
1801      * it.
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     /* use scaler when colorkey is not required */
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     /* HW only has 8 bits pixel precision, disable plane if invisible */
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         /* Enable and use MPEG-2 chroma siting */
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     /* Display WA #0870: skl, bxt */
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     /* Wa_22011186057 */
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     /* Wa_14010477008:tgl[a0..c0],rkl[all],dg1[all] */
2178     if (IS_DG1(i915) || IS_ROCKETLAKE(i915) ||
2179         IS_TGL_DISPLAY_STEP(i915, STEP_A0, STEP_D0))
2180         return false;
2181 
2182     /* Wa_22011186057 */
2183     if (IS_ADLP_DISPLAY_STEP(i915, STEP_A0, STEP_B0))
2184         return false;
2185 
2186     /* Wa_14013215631 */
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: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
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      * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
2473      * while i915 HW rotation is clockwise, thats why this swapping.
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     /* 90/270 degree rotation would require extra work */
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 }