Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2011 Intel Corporation
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice (including the next
0012  * paragraph) shall be included in all copies or substantial portions of the
0013  * Software.
0014  *
0015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0020  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0021  * SOFTWARE.
0022  *
0023  * Authors:
0024  *   Jesse Barnes <jbarnes@virtuousgeek.org>
0025  *
0026  * New plane/sprite handling.
0027  *
0028  * The older chips had a separate interface for programming plane related
0029  * registers; newer ones are much simpler and we can use the new DRM plane
0030  * support.
0031  */
0032 
0033 #include <linux/string_helpers.h>
0034 
0035 #include <drm/drm_atomic.h>
0036 #include <drm/drm_atomic_helper.h>
0037 #include <drm/drm_blend.h>
0038 #include <drm/drm_color_mgmt.h>
0039 #include <drm/drm_crtc.h>
0040 #include <drm/drm_damage_helper.h>
0041 #include <drm/drm_fourcc.h>
0042 #include <drm/drm_plane_helper.h>
0043 #include <drm/drm_rect.h>
0044 
0045 #include "i915_drv.h"
0046 #include "i915_vgpu.h"
0047 #include "i9xx_plane.h"
0048 #include "intel_atomic_plane.h"
0049 #include "intel_crtc.h"
0050 #include "intel_de.h"
0051 #include "intel_display_types.h"
0052 #include "intel_fb.h"
0053 #include "intel_frontbuffer.h"
0054 #include "intel_sprite.h"
0055 #include "intel_vrr.h"
0056 
0057 int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
0058 {
0059     struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
0060     const struct drm_framebuffer *fb = plane_state->hw.fb;
0061     struct drm_rect *src = &plane_state->uapi.src;
0062     u32 src_x, src_y, src_w, src_h, hsub, vsub;
0063     bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
0064 
0065     /*
0066      * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
0067      * abuses hsub/vsub so we can't use them here. But as they
0068      * are limited to 32bpp RGB formats we don't actually need
0069      * to check anything.
0070      */
0071     if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
0072         fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
0073         return 0;
0074 
0075     /*
0076      * Hardware doesn't handle subpixel coordinates.
0077      * Adjust to (macro)pixel boundary, but be careful not to
0078      * increase the source viewport size, because that could
0079      * push the downscaling factor out of bounds.
0080      */
0081     src_x = src->x1 >> 16;
0082     src_w = drm_rect_width(src) >> 16;
0083     src_y = src->y1 >> 16;
0084     src_h = drm_rect_height(src) >> 16;
0085 
0086     drm_rect_init(src, src_x << 16, src_y << 16,
0087               src_w << 16, src_h << 16);
0088 
0089     if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
0090         hsub = 2;
0091         vsub = 2;
0092     } else {
0093         hsub = fb->format->hsub;
0094         vsub = fb->format->vsub;
0095     }
0096 
0097     if (rotated)
0098         hsub = vsub = max(hsub, vsub);
0099 
0100     if (src_x % hsub || src_w % hsub) {
0101         drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
0102                 src_x, src_w, hsub, str_yes_no(rotated));
0103         return -EINVAL;
0104     }
0105 
0106     if (src_y % vsub || src_h % vsub) {
0107         drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
0108                 src_y, src_h, vsub, str_yes_no(rotated));
0109         return -EINVAL;
0110     }
0111 
0112     return 0;
0113 }
0114 
0115 static void i9xx_plane_linear_gamma(u16 gamma[8])
0116 {
0117     /* The points are not evenly spaced. */
0118     static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
0119     int i;
0120 
0121     for (i = 0; i < 8; i++)
0122         gamma[i] = (in[i] << 8) / 32;
0123 }
0124 
0125 static void
0126 chv_sprite_update_csc(const struct intel_plane_state *plane_state)
0127 {
0128     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0129     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0130     const struct drm_framebuffer *fb = plane_state->hw.fb;
0131     enum plane_id plane_id = plane->id;
0132     /*
0133      * |r|   | c0 c1 c2 |   |cr|
0134      * |g| = | c3 c4 c5 | x |y |
0135      * |b|   | c6 c7 c8 |   |cb|
0136      *
0137      * Coefficients are s3.12.
0138      *
0139      * Cb and Cr apparently come in as signed already, and
0140      * we always get full range data in on account of CLRC0/1.
0141      */
0142     static const s16 csc_matrix[][9] = {
0143         /* BT.601 full range YCbCr -> full range RGB */
0144         [DRM_COLOR_YCBCR_BT601] = {
0145              5743, 4096,     0,
0146             -2925, 4096, -1410,
0147                 0, 4096,  7258,
0148         },
0149         /* BT.709 full range YCbCr -> full range RGB */
0150         [DRM_COLOR_YCBCR_BT709] = {
0151              6450, 4096,     0,
0152             -1917, 4096,  -767,
0153                 0, 4096,  7601,
0154         },
0155     };
0156     const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
0157 
0158     /* Seems RGB data bypasses the CSC always */
0159     if (!fb->format->is_yuv)
0160         return;
0161 
0162     intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
0163               SPCSC_OOFF(0) | SPCSC_IOFF(0));
0164     intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
0165               SPCSC_OOFF(0) | SPCSC_IOFF(0));
0166     intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
0167               SPCSC_OOFF(0) | SPCSC_IOFF(0));
0168 
0169     intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
0170               SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
0171     intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
0172               SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
0173     intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
0174               SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
0175     intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
0176               SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
0177     intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
0178 
0179     intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
0180               SPCSC_IMAX(1023) | SPCSC_IMIN(0));
0181     intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
0182               SPCSC_IMAX(512) | SPCSC_IMIN(-512));
0183     intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
0184               SPCSC_IMAX(512) | SPCSC_IMIN(-512));
0185 
0186     intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
0187               SPCSC_OMAX(1023) | SPCSC_OMIN(0));
0188     intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
0189               SPCSC_OMAX(1023) | SPCSC_OMIN(0));
0190     intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
0191               SPCSC_OMAX(1023) | SPCSC_OMIN(0));
0192 }
0193 
0194 #define SIN_0 0
0195 #define COS_0 1
0196 
0197 static void
0198 vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
0199 {
0200     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0201     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0202     const struct drm_framebuffer *fb = plane_state->hw.fb;
0203     enum pipe pipe = plane->pipe;
0204     enum plane_id plane_id = plane->id;
0205     int contrast, brightness, sh_scale, sh_sin, sh_cos;
0206 
0207     if (fb->format->is_yuv &&
0208         plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
0209         /*
0210          * Expand limited range to full range:
0211          * Contrast is applied first and is used to expand Y range.
0212          * Brightness is applied second and is used to remove the
0213          * offset from Y. Saturation/hue is used to expand CbCr range.
0214          */
0215         contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
0216         brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
0217         sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
0218         sh_sin = SIN_0 * sh_scale;
0219         sh_cos = COS_0 * sh_scale;
0220     } else {
0221         /* Pass-through everything. */
0222         contrast = 1 << 6;
0223         brightness = 0;
0224         sh_scale = 1 << 7;
0225         sh_sin = SIN_0 * sh_scale;
0226         sh_cos = COS_0 * sh_scale;
0227     }
0228 
0229     /* FIXME these register are single buffered :( */
0230     intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
0231               SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
0232     intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
0233               SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
0234 }
0235 
0236 static void
0237 vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
0238         const struct intel_plane_state *plane_state,
0239         unsigned int *num, unsigned int *den)
0240 {
0241     u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
0242     const struct drm_framebuffer *fb = plane_state->hw.fb;
0243     unsigned int cpp = fb->format->cpp[0];
0244 
0245     /*
0246      * VLV bspec only considers cases where all three planes are
0247      * enabled, and cases where the primary and one sprite is enabled.
0248      * Let's assume the case with just two sprites enabled also
0249      * maps to the latter case.
0250      */
0251     if (hweight8(active_planes) == 3) {
0252         switch (cpp) {
0253         case 8:
0254             *num = 11;
0255             *den = 8;
0256             break;
0257         case 4:
0258             *num = 18;
0259             *den = 16;
0260             break;
0261         default:
0262             *num = 1;
0263             *den = 1;
0264             break;
0265         }
0266     } else if (hweight8(active_planes) == 2) {
0267         switch (cpp) {
0268         case 8:
0269             *num = 10;
0270             *den = 8;
0271             break;
0272         case 4:
0273             *num = 17;
0274             *den = 16;
0275             break;
0276         default:
0277             *num = 1;
0278             *den = 1;
0279             break;
0280         }
0281     } else {
0282         switch (cpp) {
0283         case 8:
0284             *num = 10;
0285             *den = 8;
0286             break;
0287         default:
0288             *num = 1;
0289             *den = 1;
0290             break;
0291         }
0292     }
0293 }
0294 
0295 int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0296             const struct intel_plane_state *plane_state)
0297 {
0298     unsigned int pixel_rate;
0299     unsigned int num, den;
0300 
0301     /*
0302      * Note that crtc_state->pixel_rate accounts for both
0303      * horizontal and vertical panel fitter downscaling factors.
0304      * Pre-HSW bspec tells us to only consider the horizontal
0305      * downscaling factor here. We ignore that and just consider
0306      * both for simplicity.
0307      */
0308     pixel_rate = crtc_state->pixel_rate;
0309 
0310     vlv_plane_ratio(crtc_state, plane_state, &num, &den);
0311 
0312     return DIV_ROUND_UP(pixel_rate * num, den);
0313 }
0314 
0315 static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
0316 {
0317     u32 sprctl = 0;
0318 
0319     if (crtc_state->gamma_enable)
0320         sprctl |= SP_PIPE_GAMMA_ENABLE;
0321 
0322     return sprctl;
0323 }
0324 
0325 static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
0326               const struct intel_plane_state *plane_state)
0327 {
0328     const struct drm_framebuffer *fb = plane_state->hw.fb;
0329     unsigned int rotation = plane_state->hw.rotation;
0330     const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0331     u32 sprctl;
0332 
0333     sprctl = SP_ENABLE;
0334 
0335     switch (fb->format->format) {
0336     case DRM_FORMAT_YUYV:
0337         sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
0338         break;
0339     case DRM_FORMAT_YVYU:
0340         sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
0341         break;
0342     case DRM_FORMAT_UYVY:
0343         sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
0344         break;
0345     case DRM_FORMAT_VYUY:
0346         sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
0347         break;
0348     case DRM_FORMAT_C8:
0349         sprctl |= SP_FORMAT_8BPP;
0350         break;
0351     case DRM_FORMAT_RGB565:
0352         sprctl |= SP_FORMAT_BGR565;
0353         break;
0354     case DRM_FORMAT_XRGB8888:
0355         sprctl |= SP_FORMAT_BGRX8888;
0356         break;
0357     case DRM_FORMAT_ARGB8888:
0358         sprctl |= SP_FORMAT_BGRA8888;
0359         break;
0360     case DRM_FORMAT_XBGR2101010:
0361         sprctl |= SP_FORMAT_RGBX1010102;
0362         break;
0363     case DRM_FORMAT_ABGR2101010:
0364         sprctl |= SP_FORMAT_RGBA1010102;
0365         break;
0366     case DRM_FORMAT_XRGB2101010:
0367         sprctl |= SP_FORMAT_BGRX1010102;
0368         break;
0369     case DRM_FORMAT_ARGB2101010:
0370         sprctl |= SP_FORMAT_BGRA1010102;
0371         break;
0372     case DRM_FORMAT_XBGR8888:
0373         sprctl |= SP_FORMAT_RGBX8888;
0374         break;
0375     case DRM_FORMAT_ABGR8888:
0376         sprctl |= SP_FORMAT_RGBA8888;
0377         break;
0378     default:
0379         MISSING_CASE(fb->format->format);
0380         return 0;
0381     }
0382 
0383     if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
0384         sprctl |= SP_YUV_FORMAT_BT709;
0385 
0386     if (fb->modifier == I915_FORMAT_MOD_X_TILED)
0387         sprctl |= SP_TILED;
0388 
0389     if (rotation & DRM_MODE_ROTATE_180)
0390         sprctl |= SP_ROTATE_180;
0391 
0392     if (rotation & DRM_MODE_REFLECT_X)
0393         sprctl |= SP_MIRROR;
0394 
0395     if (key->flags & I915_SET_COLORKEY_SOURCE)
0396         sprctl |= SP_SOURCE_KEY;
0397 
0398     return sprctl;
0399 }
0400 
0401 static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
0402 {
0403     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0404     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0405     const struct drm_framebuffer *fb = plane_state->hw.fb;
0406     enum pipe pipe = plane->pipe;
0407     enum plane_id plane_id = plane->id;
0408     u16 gamma[8];
0409     int i;
0410 
0411     /* Seems RGB data bypasses the gamma always */
0412     if (!fb->format->is_yuv)
0413         return;
0414 
0415     i9xx_plane_linear_gamma(gamma);
0416 
0417     /* FIXME these register are single buffered :( */
0418     /* The two end points are implicit (0.0 and 1.0) */
0419     for (i = 1; i < 8 - 1; i++)
0420         intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
0421                   gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
0422 }
0423 
0424 static void
0425 vlv_sprite_update_noarm(struct intel_plane *plane,
0426             const struct intel_crtc_state *crtc_state,
0427             const struct intel_plane_state *plane_state)
0428 {
0429     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0430     enum pipe pipe = plane->pipe;
0431     enum plane_id plane_id = plane->id;
0432     int crtc_x = plane_state->uapi.dst.x1;
0433     int crtc_y = plane_state->uapi.dst.y1;
0434     u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
0435     u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
0436 
0437     intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
0438               plane_state->view.color_plane[0].mapping_stride);
0439     intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
0440               SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
0441     intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
0442               SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
0443 }
0444 
0445 static void
0446 vlv_sprite_update_arm(struct intel_plane *plane,
0447               const struct intel_crtc_state *crtc_state,
0448               const struct intel_plane_state *plane_state)
0449 {
0450     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0451     enum pipe pipe = plane->pipe;
0452     enum plane_id plane_id = plane->id;
0453     const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0454     u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
0455     u32 x = plane_state->view.color_plane[0].x;
0456     u32 y = plane_state->view.color_plane[0].y;
0457     u32 sprctl, linear_offset;
0458 
0459     sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
0460 
0461     linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
0462 
0463     if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
0464         chv_sprite_update_csc(plane_state);
0465 
0466     if (key->flags) {
0467         intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
0468                   key->min_value);
0469         intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
0470                   key->channel_mask);
0471         intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
0472                   key->max_value);
0473     }
0474 
0475     intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
0476 
0477     intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
0478     intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id),
0479               SP_OFFSET_Y(y) | SP_OFFSET_X(x));
0480 
0481     /*
0482      * The control register self-arms if the plane was previously
0483      * disabled. Try to make the plane enable atomic by writing
0484      * the control register just before the surface register.
0485      */
0486     intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
0487     intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
0488               intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
0489 
0490     vlv_sprite_update_clrc(plane_state);
0491     vlv_sprite_update_gamma(plane_state);
0492 }
0493 
0494 static void
0495 vlv_sprite_disable_arm(struct intel_plane *plane,
0496                const struct intel_crtc_state *crtc_state)
0497 {
0498     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0499     enum pipe pipe = plane->pipe;
0500     enum plane_id plane_id = plane->id;
0501 
0502     intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
0503     intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
0504 }
0505 
0506 static bool
0507 vlv_sprite_get_hw_state(struct intel_plane *plane,
0508             enum pipe *pipe)
0509 {
0510     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0511     enum intel_display_power_domain power_domain;
0512     enum plane_id plane_id = plane->id;
0513     intel_wakeref_t wakeref;
0514     bool ret;
0515 
0516     power_domain = POWER_DOMAIN_PIPE(plane->pipe);
0517     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0518     if (!wakeref)
0519         return false;
0520 
0521     ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
0522 
0523     *pipe = plane->pipe;
0524 
0525     intel_display_power_put(dev_priv, power_domain, wakeref);
0526 
0527     return ret;
0528 }
0529 
0530 static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
0531                 const struct intel_plane_state *plane_state,
0532                 unsigned int *num, unsigned int *den)
0533 {
0534     u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
0535     const struct drm_framebuffer *fb = plane_state->hw.fb;
0536     unsigned int cpp = fb->format->cpp[0];
0537 
0538     if (hweight8(active_planes) == 2) {
0539         switch (cpp) {
0540         case 8:
0541             *num = 10;
0542             *den = 8;
0543             break;
0544         case 4:
0545             *num = 17;
0546             *den = 16;
0547             break;
0548         default:
0549             *num = 1;
0550             *den = 1;
0551             break;
0552         }
0553     } else {
0554         switch (cpp) {
0555         case 8:
0556             *num = 9;
0557             *den = 8;
0558             break;
0559         default:
0560             *num = 1;
0561             *den = 1;
0562             break;
0563         }
0564     }
0565 }
0566 
0567 static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
0568                     const struct intel_plane_state *plane_state,
0569                     unsigned int *num, unsigned int *den)
0570 {
0571     const struct drm_framebuffer *fb = plane_state->hw.fb;
0572     unsigned int cpp = fb->format->cpp[0];
0573 
0574     switch (cpp) {
0575     case 8:
0576         *num = 12;
0577         *den = 8;
0578         break;
0579     case 4:
0580         *num = 19;
0581         *den = 16;
0582         break;
0583     case 2:
0584         *num = 33;
0585         *den = 32;
0586         break;
0587     default:
0588         *num = 1;
0589         *den = 1;
0590         break;
0591     }
0592 }
0593 
0594 int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0595             const struct intel_plane_state *plane_state)
0596 {
0597     unsigned int pixel_rate;
0598     unsigned int num, den;
0599 
0600     /*
0601      * Note that crtc_state->pixel_rate accounts for both
0602      * horizontal and vertical panel fitter downscaling factors.
0603      * Pre-HSW bspec tells us to only consider the horizontal
0604      * downscaling factor here. We ignore that and just consider
0605      * both for simplicity.
0606      */
0607     pixel_rate = crtc_state->pixel_rate;
0608 
0609     ivb_plane_ratio(crtc_state, plane_state, &num, &den);
0610 
0611     return DIV_ROUND_UP(pixel_rate * num, den);
0612 }
0613 
0614 static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
0615                 const struct intel_plane_state *plane_state)
0616 {
0617     unsigned int src_w, dst_w, pixel_rate;
0618     unsigned int num, den;
0619 
0620     /*
0621      * Note that crtc_state->pixel_rate accounts for both
0622      * horizontal and vertical panel fitter downscaling factors.
0623      * Pre-HSW bspec tells us to only consider the horizontal
0624      * downscaling factor here. We ignore that and just consider
0625      * both for simplicity.
0626      */
0627     pixel_rate = crtc_state->pixel_rate;
0628 
0629     src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
0630     dst_w = drm_rect_width(&plane_state->uapi.dst);
0631 
0632     if (src_w != dst_w)
0633         ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
0634     else
0635         ivb_plane_ratio(crtc_state, plane_state, &num, &den);
0636 
0637     /* Horizontal downscaling limits the maximum pixel rate */
0638     dst_w = min(src_w, dst_w);
0639 
0640     return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
0641                 den * dst_w);
0642 }
0643 
0644 static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
0645                 const struct intel_plane_state *plane_state,
0646                 unsigned int *num, unsigned int *den)
0647 {
0648     u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
0649     const struct drm_framebuffer *fb = plane_state->hw.fb;
0650     unsigned int cpp = fb->format->cpp[0];
0651 
0652     if (hweight8(active_planes) == 2) {
0653         switch (cpp) {
0654         case 8:
0655             *num = 10;
0656             *den = 8;
0657             break;
0658         default:
0659             *num = 1;
0660             *den = 1;
0661             break;
0662         }
0663     } else {
0664         switch (cpp) {
0665         case 8:
0666             *num = 9;
0667             *den = 8;
0668             break;
0669         default:
0670             *num = 1;
0671             *den = 1;
0672             break;
0673         }
0674     }
0675 }
0676 
0677 int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
0678             const struct intel_plane_state *plane_state)
0679 {
0680     unsigned int pixel_rate = crtc_state->pixel_rate;
0681     unsigned int num, den;
0682 
0683     hsw_plane_ratio(crtc_state, plane_state, &num, &den);
0684 
0685     return DIV_ROUND_UP(pixel_rate * num, den);
0686 }
0687 
0688 static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
0689 {
0690     u32 sprctl = 0;
0691 
0692     if (crtc_state->gamma_enable)
0693         sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
0694 
0695     if (crtc_state->csc_enable)
0696         sprctl |= SPRITE_PIPE_CSC_ENABLE;
0697 
0698     return sprctl;
0699 }
0700 
0701 static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
0702 {
0703     struct drm_i915_private *dev_priv =
0704         to_i915(plane_state->uapi.plane->dev);
0705     const struct drm_framebuffer *fb = plane_state->hw.fb;
0706 
0707     return fb->format->cpp[0] == 8 &&
0708         (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
0709 }
0710 
0711 static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
0712               const struct intel_plane_state *plane_state)
0713 {
0714     struct drm_i915_private *dev_priv =
0715         to_i915(plane_state->uapi.plane->dev);
0716     const struct drm_framebuffer *fb = plane_state->hw.fb;
0717     unsigned int rotation = plane_state->hw.rotation;
0718     const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0719     u32 sprctl;
0720 
0721     sprctl = SPRITE_ENABLE;
0722 
0723     if (IS_IVYBRIDGE(dev_priv))
0724         sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
0725 
0726     switch (fb->format->format) {
0727     case DRM_FORMAT_XBGR8888:
0728         sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
0729         break;
0730     case DRM_FORMAT_XRGB8888:
0731         sprctl |= SPRITE_FORMAT_RGBX888;
0732         break;
0733     case DRM_FORMAT_XBGR2101010:
0734         sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
0735         break;
0736     case DRM_FORMAT_XRGB2101010:
0737         sprctl |= SPRITE_FORMAT_RGBX101010;
0738         break;
0739     case DRM_FORMAT_XBGR16161616F:
0740         sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
0741         break;
0742     case DRM_FORMAT_XRGB16161616F:
0743         sprctl |= SPRITE_FORMAT_RGBX161616;
0744         break;
0745     case DRM_FORMAT_YUYV:
0746         sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
0747         break;
0748     case DRM_FORMAT_YVYU:
0749         sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
0750         break;
0751     case DRM_FORMAT_UYVY:
0752         sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
0753         break;
0754     case DRM_FORMAT_VYUY:
0755         sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
0756         break;
0757     default:
0758         MISSING_CASE(fb->format->format);
0759         return 0;
0760     }
0761 
0762     if (!ivb_need_sprite_gamma(plane_state))
0763         sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
0764 
0765     if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
0766         sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
0767 
0768     if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
0769         sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
0770 
0771     if (fb->modifier == I915_FORMAT_MOD_X_TILED)
0772         sprctl |= SPRITE_TILED;
0773 
0774     if (rotation & DRM_MODE_ROTATE_180)
0775         sprctl |= SPRITE_ROTATE_180;
0776 
0777     if (key->flags & I915_SET_COLORKEY_DESTINATION)
0778         sprctl |= SPRITE_DEST_KEY;
0779     else if (key->flags & I915_SET_COLORKEY_SOURCE)
0780         sprctl |= SPRITE_SOURCE_KEY;
0781 
0782     return sprctl;
0783 }
0784 
0785 static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
0786                     u16 gamma[18])
0787 {
0788     int scale, i;
0789 
0790     /*
0791      * WaFP16GammaEnabling:ivb,hsw
0792      * "Workaround : When using the 64-bit format, the sprite output
0793      *  on each color channel has one quarter amplitude. It can be
0794      *  brought up to full amplitude by using sprite internal gamma
0795      *  correction, pipe gamma correction, or pipe color space
0796      *  conversion to multiply the sprite output by four."
0797      */
0798     scale = 4;
0799 
0800     for (i = 0; i < 16; i++)
0801         gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
0802 
0803     gamma[i] = min((scale * i << 10) / 16, 1 << 10);
0804     i++;
0805 
0806     gamma[i] = 3 << 10;
0807     i++;
0808 }
0809 
0810 static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
0811 {
0812     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
0813     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0814     enum pipe pipe = plane->pipe;
0815     u16 gamma[18];
0816     int i;
0817 
0818     if (!ivb_need_sprite_gamma(plane_state))
0819         return;
0820 
0821     ivb_sprite_linear_gamma(plane_state, gamma);
0822 
0823     /* FIXME these register are single buffered :( */
0824     for (i = 0; i < 16; i++)
0825         intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
0826                   gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
0827 
0828     intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
0829     intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
0830     intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
0831     i++;
0832 
0833     intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
0834     intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
0835     intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
0836     i++;
0837 }
0838 
0839 static void
0840 ivb_sprite_update_noarm(struct intel_plane *plane,
0841             const struct intel_crtc_state *crtc_state,
0842             const struct intel_plane_state *plane_state)
0843 {
0844     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0845     enum pipe pipe = plane->pipe;
0846     int crtc_x = plane_state->uapi.dst.x1;
0847     int crtc_y = plane_state->uapi.dst.y1;
0848     u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
0849     u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
0850     u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
0851     u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
0852     u32 sprscale = 0;
0853 
0854     if (crtc_w != src_w || crtc_h != src_h)
0855         sprscale = SPRITE_SCALE_ENABLE |
0856             SPRITE_SRC_WIDTH(src_w - 1) |
0857             SPRITE_SRC_HEIGHT(src_h - 1);
0858 
0859     intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
0860               plane_state->view.color_plane[0].mapping_stride);
0861     intel_de_write_fw(dev_priv, SPRPOS(pipe),
0862               SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
0863     intel_de_write_fw(dev_priv, SPRSIZE(pipe),
0864               SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
0865     if (IS_IVYBRIDGE(dev_priv))
0866         intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
0867 }
0868 
0869 static void
0870 ivb_sprite_update_arm(struct intel_plane *plane,
0871               const struct intel_crtc_state *crtc_state,
0872               const struct intel_plane_state *plane_state)
0873 {
0874     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0875     enum pipe pipe = plane->pipe;
0876     const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0877     u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
0878     u32 x = plane_state->view.color_plane[0].x;
0879     u32 y = plane_state->view.color_plane[0].y;
0880     u32 sprctl, linear_offset;
0881 
0882     sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
0883 
0884     linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
0885 
0886     if (key->flags) {
0887         intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
0888         intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
0889                   key->channel_mask);
0890         intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
0891     }
0892 
0893     /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
0894      * register */
0895     if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
0896         intel_de_write_fw(dev_priv, SPROFFSET(pipe),
0897                   SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
0898     } else {
0899         intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
0900         intel_de_write_fw(dev_priv, SPRTILEOFF(pipe),
0901                   SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
0902     }
0903 
0904     /*
0905      * The control register self-arms if the plane was previously
0906      * disabled. Try to make the plane enable atomic by writing
0907      * the control register just before the surface register.
0908      */
0909     intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
0910     intel_de_write_fw(dev_priv, SPRSURF(pipe),
0911               intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
0912 
0913     ivb_sprite_update_gamma(plane_state);
0914 }
0915 
0916 static void
0917 ivb_sprite_disable_arm(struct intel_plane *plane,
0918                const struct intel_crtc_state *crtc_state)
0919 {
0920     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0921     enum pipe pipe = plane->pipe;
0922 
0923     intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
0924     /* Disable the scaler */
0925     if (IS_IVYBRIDGE(dev_priv))
0926         intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
0927     intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
0928 }
0929 
0930 static bool
0931 ivb_sprite_get_hw_state(struct intel_plane *plane,
0932             enum pipe *pipe)
0933 {
0934     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
0935     enum intel_display_power_domain power_domain;
0936     intel_wakeref_t wakeref;
0937     bool ret;
0938 
0939     power_domain = POWER_DOMAIN_PIPE(plane->pipe);
0940     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0941     if (!wakeref)
0942         return false;
0943 
0944     ret =  intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
0945 
0946     *pipe = plane->pipe;
0947 
0948     intel_display_power_put(dev_priv, power_domain, wakeref);
0949 
0950     return ret;
0951 }
0952 
0953 static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
0954                 const struct intel_plane_state *plane_state)
0955 {
0956     const struct drm_framebuffer *fb = plane_state->hw.fb;
0957     unsigned int hscale, pixel_rate;
0958     unsigned int limit, decimate;
0959 
0960     /*
0961      * Note that crtc_state->pixel_rate accounts for both
0962      * horizontal and vertical panel fitter downscaling factors.
0963      * Pre-HSW bspec tells us to only consider the horizontal
0964      * downscaling factor here. We ignore that and just consider
0965      * both for simplicity.
0966      */
0967     pixel_rate = crtc_state->pixel_rate;
0968 
0969     /* Horizontal downscaling limits the maximum pixel rate */
0970     hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
0971                       &plane_state->uapi.dst,
0972                       0, INT_MAX);
0973     hscale = max(hscale, 0x10000u);
0974 
0975     /* Decimation steps at 2x,4x,8x,16x */
0976     decimate = ilog2(hscale >> 16);
0977     hscale >>= decimate;
0978 
0979     /* Starting limit is 90% of cdclk */
0980     limit = 9;
0981 
0982     /* -10% per decimation step */
0983     limit -= decimate;
0984 
0985     /* -10% for RGB */
0986     if (!fb->format->is_yuv)
0987         limit--;
0988 
0989     /*
0990      * We should also do -10% if sprite scaling is enabled
0991      * on the other pipe, but we can't really check for that,
0992      * so we ignore it.
0993      */
0994 
0995     return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
0996                 limit << 16);
0997 }
0998 
0999 static unsigned int
1000 g4x_sprite_max_stride(struct intel_plane *plane,
1001               u32 pixel_format, u64 modifier,
1002               unsigned int rotation)
1003 {
1004     const struct drm_format_info *info = drm_format_info(pixel_format);
1005     int cpp = info->cpp[0];
1006 
1007     /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
1008     if (modifier == I915_FORMAT_MOD_X_TILED)
1009         return min(4096 * cpp, 16 * 1024);
1010     else
1011         return 16 * 1024;
1012 }
1013 
1014 static unsigned int
1015 hsw_sprite_max_stride(struct intel_plane *plane,
1016               u32 pixel_format, u64 modifier,
1017               unsigned int rotation)
1018 {
1019     const struct drm_format_info *info = drm_format_info(pixel_format);
1020     int cpp = info->cpp[0];
1021 
1022     /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
1023     return min(8192 * cpp, 16 * 1024);
1024 }
1025 
1026 static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1027 {
1028     u32 dvscntr = 0;
1029 
1030     if (crtc_state->gamma_enable)
1031         dvscntr |= DVS_PIPE_GAMMA_ENABLE;
1032 
1033     if (crtc_state->csc_enable)
1034         dvscntr |= DVS_PIPE_CSC_ENABLE;
1035 
1036     return dvscntr;
1037 }
1038 
1039 static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1040               const struct intel_plane_state *plane_state)
1041 {
1042     struct drm_i915_private *dev_priv =
1043         to_i915(plane_state->uapi.plane->dev);
1044     const struct drm_framebuffer *fb = plane_state->hw.fb;
1045     unsigned int rotation = plane_state->hw.rotation;
1046     const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1047     u32 dvscntr;
1048 
1049     dvscntr = DVS_ENABLE;
1050 
1051     if (IS_SANDYBRIDGE(dev_priv))
1052         dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1053 
1054     switch (fb->format->format) {
1055     case DRM_FORMAT_XBGR8888:
1056         dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1057         break;
1058     case DRM_FORMAT_XRGB8888:
1059         dvscntr |= DVS_FORMAT_RGBX888;
1060         break;
1061     case DRM_FORMAT_XBGR2101010:
1062         dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1063         break;
1064     case DRM_FORMAT_XRGB2101010:
1065         dvscntr |= DVS_FORMAT_RGBX101010;
1066         break;
1067     case DRM_FORMAT_XBGR16161616F:
1068         dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1069         break;
1070     case DRM_FORMAT_XRGB16161616F:
1071         dvscntr |= DVS_FORMAT_RGBX161616;
1072         break;
1073     case DRM_FORMAT_YUYV:
1074         dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1075         break;
1076     case DRM_FORMAT_YVYU:
1077         dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1078         break;
1079     case DRM_FORMAT_UYVY:
1080         dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1081         break;
1082     case DRM_FORMAT_VYUY:
1083         dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1084         break;
1085     default:
1086         MISSING_CASE(fb->format->format);
1087         return 0;
1088     }
1089 
1090     if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1091         dvscntr |= DVS_YUV_FORMAT_BT709;
1092 
1093     if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1094         dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1095 
1096     if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1097         dvscntr |= DVS_TILED;
1098 
1099     if (rotation & DRM_MODE_ROTATE_180)
1100         dvscntr |= DVS_ROTATE_180;
1101 
1102     if (key->flags & I915_SET_COLORKEY_DESTINATION)
1103         dvscntr |= DVS_DEST_KEY;
1104     else if (key->flags & I915_SET_COLORKEY_SOURCE)
1105         dvscntr |= DVS_SOURCE_KEY;
1106 
1107     return dvscntr;
1108 }
1109 
1110 static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state)
1111 {
1112     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1113     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1114     const struct drm_framebuffer *fb = plane_state->hw.fb;
1115     enum pipe pipe = plane->pipe;
1116     u16 gamma[8];
1117     int i;
1118 
1119     /* Seems RGB data bypasses the gamma always */
1120     if (!fb->format->is_yuv)
1121         return;
1122 
1123     i9xx_plane_linear_gamma(gamma);
1124 
1125     /* FIXME these register are single buffered :( */
1126     /* The two end points are implicit (0.0 and 1.0) */
1127     for (i = 1; i < 8 - 1; i++)
1128         intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1129                   gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1130 }
1131 
1132 static void ilk_sprite_linear_gamma(u16 gamma[17])
1133 {
1134     int i;
1135 
1136     for (i = 0; i < 17; i++)
1137         gamma[i] = (i << 10) / 16;
1138 }
1139 
1140 static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state)
1141 {
1142     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1143     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1144     const struct drm_framebuffer *fb = plane_state->hw.fb;
1145     enum pipe pipe = plane->pipe;
1146     u16 gamma[17];
1147     int i;
1148 
1149     /* Seems RGB data bypasses the gamma always */
1150     if (!fb->format->is_yuv)
1151         return;
1152 
1153     ilk_sprite_linear_gamma(gamma);
1154 
1155     /* FIXME these register are single buffered :( */
1156     for (i = 0; i < 16; i++)
1157         intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1158                   gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1159 
1160     intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1161     intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1162     intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1163     i++;
1164 }
1165 
1166 static void
1167 g4x_sprite_update_noarm(struct intel_plane *plane,
1168             const struct intel_crtc_state *crtc_state,
1169             const struct intel_plane_state *plane_state)
1170 {
1171     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1172     enum pipe pipe = plane->pipe;
1173     int crtc_x = plane_state->uapi.dst.x1;
1174     int crtc_y = plane_state->uapi.dst.y1;
1175     u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1176     u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1177     u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1178     u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1179     u32 dvsscale = 0;
1180 
1181     if (crtc_w != src_w || crtc_h != src_h)
1182         dvsscale = DVS_SCALE_ENABLE |
1183             DVS_SRC_WIDTH(src_w - 1) |
1184             DVS_SRC_HEIGHT(src_h - 1);
1185 
1186     intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1187               plane_state->view.color_plane[0].mapping_stride);
1188     intel_de_write_fw(dev_priv, DVSPOS(pipe),
1189               DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
1190     intel_de_write_fw(dev_priv, DVSSIZE(pipe),
1191               DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
1192     intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1193 }
1194 
1195 static void
1196 g4x_sprite_update_arm(struct intel_plane *plane,
1197               const struct intel_crtc_state *crtc_state,
1198               const struct intel_plane_state *plane_state)
1199 {
1200     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1201     enum pipe pipe = plane->pipe;
1202     const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1203     u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1204     u32 x = plane_state->view.color_plane[0].x;
1205     u32 y = plane_state->view.color_plane[0].y;
1206     u32 dvscntr, linear_offset;
1207 
1208     dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1209 
1210     linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1211 
1212     if (key->flags) {
1213         intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1214         intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1215                   key->channel_mask);
1216         intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1217     }
1218 
1219     intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1220     intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
1221 
1222     /*
1223      * The control register self-arms if the plane was previously
1224      * disabled. Try to make the plane enable atomic by writing
1225      * the control register just before the surface register.
1226      */
1227     intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1228     intel_de_write_fw(dev_priv, DVSSURF(pipe),
1229               intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1230 
1231     if (IS_G4X(dev_priv))
1232         g4x_sprite_update_gamma(plane_state);
1233     else
1234         ilk_sprite_update_gamma(plane_state);
1235 }
1236 
1237 static void
1238 g4x_sprite_disable_arm(struct intel_plane *plane,
1239                const struct intel_crtc_state *crtc_state)
1240 {
1241     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1242     enum pipe pipe = plane->pipe;
1243 
1244     intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1245     /* Disable the scaler */
1246     intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1247     intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1248 }
1249 
1250 static bool
1251 g4x_sprite_get_hw_state(struct intel_plane *plane,
1252             enum pipe *pipe)
1253 {
1254     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1255     enum intel_display_power_domain power_domain;
1256     intel_wakeref_t wakeref;
1257     bool ret;
1258 
1259     power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1260     wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1261     if (!wakeref)
1262         return false;
1263 
1264     ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1265 
1266     *pipe = plane->pipe;
1267 
1268     intel_display_power_put(dev_priv, power_domain, wakeref);
1269 
1270     return ret;
1271 }
1272 
1273 static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1274 {
1275     if (!fb)
1276         return false;
1277 
1278     switch (fb->format->format) {
1279     case DRM_FORMAT_C8:
1280     case DRM_FORMAT_XRGB16161616F:
1281     case DRM_FORMAT_ARGB16161616F:
1282     case DRM_FORMAT_XBGR16161616F:
1283     case DRM_FORMAT_ABGR16161616F:
1284         return false;
1285     default:
1286         return true;
1287     }
1288 }
1289 
1290 static int
1291 g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1292              struct intel_plane_state *plane_state)
1293 {
1294     struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1295     const struct drm_framebuffer *fb = plane_state->hw.fb;
1296     const struct drm_rect *src = &plane_state->uapi.src;
1297     const struct drm_rect *dst = &plane_state->uapi.dst;
1298     int src_x, src_w, src_h, crtc_w, crtc_h;
1299     const struct drm_display_mode *adjusted_mode =
1300         &crtc_state->hw.adjusted_mode;
1301     unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1302     unsigned int cpp = fb->format->cpp[0];
1303     unsigned int width_bytes;
1304     int min_width, min_height;
1305 
1306     crtc_w = drm_rect_width(dst);
1307     crtc_h = drm_rect_height(dst);
1308 
1309     src_x = src->x1 >> 16;
1310     src_w = drm_rect_width(src) >> 16;
1311     src_h = drm_rect_height(src) >> 16;
1312 
1313     if (src_w == crtc_w && src_h == crtc_h)
1314         return 0;
1315 
1316     min_width = 3;
1317 
1318     if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1319         if (src_h & 1) {
1320             drm_dbg_kms(&i915->drm, "Source height must be even with interlaced modes\n");
1321             return -EINVAL;
1322         }
1323         min_height = 6;
1324     } else {
1325         min_height = 3;
1326     }
1327 
1328     width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1329 
1330     if (src_w < min_width || src_h < min_height ||
1331         src_w > 2048 || src_h > 2048) {
1332         drm_dbg_kms(&i915->drm, "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1333                 src_w, src_h, min_width, min_height, 2048, 2048);
1334         return -EINVAL;
1335     }
1336 
1337     if (width_bytes > 4096) {
1338         drm_dbg_kms(&i915->drm, "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1339                 width_bytes, 4096);
1340         return -EINVAL;
1341     }
1342 
1343     if (stride > 4096) {
1344         drm_dbg_kms(&i915->drm, "Stride (%u) exceeds hardware max with scaling (%u)\n",
1345                 stride, 4096);
1346         return -EINVAL;
1347     }
1348 
1349     return 0;
1350 }
1351 
1352 static int
1353 g4x_sprite_check(struct intel_crtc_state *crtc_state,
1354          struct intel_plane_state *plane_state)
1355 {
1356     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1357     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1358     int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1359     int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1360     int ret;
1361 
1362     if (g4x_fb_scalable(plane_state->hw.fb)) {
1363         if (DISPLAY_VER(dev_priv) < 7) {
1364             min_scale = 1;
1365             max_scale = 16 << 16;
1366         } else if (IS_IVYBRIDGE(dev_priv)) {
1367             min_scale = 1;
1368             max_scale = 2 << 16;
1369         }
1370     }
1371 
1372     ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1373                         min_scale, max_scale, true);
1374     if (ret)
1375         return ret;
1376 
1377     ret = i9xx_check_plane_surface(plane_state);
1378     if (ret)
1379         return ret;
1380 
1381     if (!plane_state->uapi.visible)
1382         return 0;
1383 
1384     ret = intel_plane_check_src_coordinates(plane_state);
1385     if (ret)
1386         return ret;
1387 
1388     ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1389     if (ret)
1390         return ret;
1391 
1392     if (DISPLAY_VER(dev_priv) >= 7)
1393         plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1394     else
1395         plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1396 
1397     return 0;
1398 }
1399 
1400 int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1401 {
1402     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1403     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1404     unsigned int rotation = plane_state->hw.rotation;
1405 
1406     /* CHV ignores the mirror bit when the rotate bit is set :( */
1407     if (IS_CHERRYVIEW(dev_priv) &&
1408         rotation & DRM_MODE_ROTATE_180 &&
1409         rotation & DRM_MODE_REFLECT_X) {
1410         drm_dbg_kms(&dev_priv->drm,
1411                 "Cannot rotate and reflect at the same time\n");
1412         return -EINVAL;
1413     }
1414 
1415     return 0;
1416 }
1417 
1418 static int
1419 vlv_sprite_check(struct intel_crtc_state *crtc_state,
1420          struct intel_plane_state *plane_state)
1421 {
1422     int ret;
1423 
1424     ret = chv_plane_check_rotation(plane_state);
1425     if (ret)
1426         return ret;
1427 
1428     ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1429                         DRM_PLANE_HELPER_NO_SCALING,
1430                         DRM_PLANE_HELPER_NO_SCALING,
1431                         true);
1432     if (ret)
1433         return ret;
1434 
1435     ret = i9xx_check_plane_surface(plane_state);
1436     if (ret)
1437         return ret;
1438 
1439     if (!plane_state->uapi.visible)
1440         return 0;
1441 
1442     ret = intel_plane_check_src_coordinates(plane_state);
1443     if (ret)
1444         return ret;
1445 
1446     plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1447 
1448     return 0;
1449 }
1450 
1451 static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1452 {
1453     return DISPLAY_VER(dev_priv) >= 9;
1454 }
1455 
1456 static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1457                  const struct drm_intel_sprite_colorkey *set)
1458 {
1459     struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1460     struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1461     struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1462 
1463     *key = *set;
1464 
1465     /*
1466      * We want src key enabled on the
1467      * sprite and not on the primary.
1468      */
1469     if (plane->id == PLANE_PRIMARY &&
1470         set->flags & I915_SET_COLORKEY_SOURCE)
1471         key->flags = 0;
1472 
1473     /*
1474      * On SKL+ we want dst key enabled on
1475      * the primary and not on the sprite.
1476      */
1477     if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1478         set->flags & I915_SET_COLORKEY_DESTINATION)
1479         key->flags = 0;
1480 }
1481 
1482 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1483                     struct drm_file *file_priv)
1484 {
1485     struct drm_i915_private *dev_priv = to_i915(dev);
1486     struct drm_intel_sprite_colorkey *set = data;
1487     struct drm_plane *plane;
1488     struct drm_plane_state *plane_state;
1489     struct drm_atomic_state *state;
1490     struct drm_modeset_acquire_ctx ctx;
1491     int ret = 0;
1492 
1493     /* ignore the pointless "none" flag */
1494     set->flags &= ~I915_SET_COLORKEY_NONE;
1495 
1496     if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1497         return -EINVAL;
1498 
1499     /* Make sure we don't try to enable both src & dest simultaneously */
1500     if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1501         return -EINVAL;
1502 
1503     if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1504         set->flags & I915_SET_COLORKEY_DESTINATION)
1505         return -EINVAL;
1506 
1507     plane = drm_plane_find(dev, file_priv, set->plane_id);
1508     if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1509         return -ENOENT;
1510 
1511     /*
1512      * SKL+ only plane 2 can do destination keying against plane 1.
1513      * Also multiple planes can't do destination keying on the same
1514      * pipe simultaneously.
1515      */
1516     if (DISPLAY_VER(dev_priv) >= 9 &&
1517         to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1518         set->flags & I915_SET_COLORKEY_DESTINATION)
1519         return -EINVAL;
1520 
1521     drm_modeset_acquire_init(&ctx, 0);
1522 
1523     state = drm_atomic_state_alloc(plane->dev);
1524     if (!state) {
1525         ret = -ENOMEM;
1526         goto out;
1527     }
1528     state->acquire_ctx = &ctx;
1529 
1530     while (1) {
1531         plane_state = drm_atomic_get_plane_state(state, plane);
1532         ret = PTR_ERR_OR_ZERO(plane_state);
1533         if (!ret)
1534             intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1535 
1536         /*
1537          * On some platforms we have to configure
1538          * the dst colorkey on the primary plane.
1539          */
1540         if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1541             struct intel_crtc *crtc =
1542                 intel_crtc_for_pipe(dev_priv,
1543                             to_intel_plane(plane)->pipe);
1544 
1545             plane_state = drm_atomic_get_plane_state(state,
1546                                  crtc->base.primary);
1547             ret = PTR_ERR_OR_ZERO(plane_state);
1548             if (!ret)
1549                 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1550         }
1551 
1552         if (!ret)
1553             ret = drm_atomic_commit(state);
1554 
1555         if (ret != -EDEADLK)
1556             break;
1557 
1558         drm_atomic_state_clear(state);
1559         drm_modeset_backoff(&ctx);
1560     }
1561 
1562     drm_atomic_state_put(state);
1563 out:
1564     drm_modeset_drop_locks(&ctx);
1565     drm_modeset_acquire_fini(&ctx);
1566     return ret;
1567 }
1568 
1569 static const u32 g4x_sprite_formats[] = {
1570     DRM_FORMAT_XRGB8888,
1571     DRM_FORMAT_YUYV,
1572     DRM_FORMAT_YVYU,
1573     DRM_FORMAT_UYVY,
1574     DRM_FORMAT_VYUY,
1575 };
1576 
1577 static const u32 snb_sprite_formats[] = {
1578     DRM_FORMAT_XRGB8888,
1579     DRM_FORMAT_XBGR8888,
1580     DRM_FORMAT_XRGB2101010,
1581     DRM_FORMAT_XBGR2101010,
1582     DRM_FORMAT_XRGB16161616F,
1583     DRM_FORMAT_XBGR16161616F,
1584     DRM_FORMAT_YUYV,
1585     DRM_FORMAT_YVYU,
1586     DRM_FORMAT_UYVY,
1587     DRM_FORMAT_VYUY,
1588 };
1589 
1590 static const u32 vlv_sprite_formats[] = {
1591     DRM_FORMAT_C8,
1592     DRM_FORMAT_RGB565,
1593     DRM_FORMAT_XRGB8888,
1594     DRM_FORMAT_XBGR8888,
1595     DRM_FORMAT_ARGB8888,
1596     DRM_FORMAT_ABGR8888,
1597     DRM_FORMAT_XBGR2101010,
1598     DRM_FORMAT_ABGR2101010,
1599     DRM_FORMAT_YUYV,
1600     DRM_FORMAT_YVYU,
1601     DRM_FORMAT_UYVY,
1602     DRM_FORMAT_VYUY,
1603 };
1604 
1605 static const u32 chv_pipe_b_sprite_formats[] = {
1606     DRM_FORMAT_C8,
1607     DRM_FORMAT_RGB565,
1608     DRM_FORMAT_XRGB8888,
1609     DRM_FORMAT_XBGR8888,
1610     DRM_FORMAT_ARGB8888,
1611     DRM_FORMAT_ABGR8888,
1612     DRM_FORMAT_XRGB2101010,
1613     DRM_FORMAT_XBGR2101010,
1614     DRM_FORMAT_ARGB2101010,
1615     DRM_FORMAT_ABGR2101010,
1616     DRM_FORMAT_YUYV,
1617     DRM_FORMAT_YVYU,
1618     DRM_FORMAT_UYVY,
1619     DRM_FORMAT_VYUY,
1620 };
1621 
1622 static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1623                         u32 format, u64 modifier)
1624 {
1625     if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1626         return false;
1627 
1628     switch (format) {
1629     case DRM_FORMAT_XRGB8888:
1630     case DRM_FORMAT_YUYV:
1631     case DRM_FORMAT_YVYU:
1632     case DRM_FORMAT_UYVY:
1633     case DRM_FORMAT_VYUY:
1634         if (modifier == DRM_FORMAT_MOD_LINEAR ||
1635             modifier == I915_FORMAT_MOD_X_TILED)
1636             return true;
1637         fallthrough;
1638     default:
1639         return false;
1640     }
1641 }
1642 
1643 static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1644                         u32 format, u64 modifier)
1645 {
1646     if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1647         return false;
1648 
1649     switch (format) {
1650     case DRM_FORMAT_XRGB8888:
1651     case DRM_FORMAT_XBGR8888:
1652     case DRM_FORMAT_XRGB2101010:
1653     case DRM_FORMAT_XBGR2101010:
1654     case DRM_FORMAT_XRGB16161616F:
1655     case DRM_FORMAT_XBGR16161616F:
1656     case DRM_FORMAT_YUYV:
1657     case DRM_FORMAT_YVYU:
1658     case DRM_FORMAT_UYVY:
1659     case DRM_FORMAT_VYUY:
1660         if (modifier == DRM_FORMAT_MOD_LINEAR ||
1661             modifier == I915_FORMAT_MOD_X_TILED)
1662             return true;
1663         fallthrough;
1664     default:
1665         return false;
1666     }
1667 }
1668 
1669 static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1670                         u32 format, u64 modifier)
1671 {
1672     if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1673         return false;
1674 
1675     switch (format) {
1676     case DRM_FORMAT_C8:
1677     case DRM_FORMAT_RGB565:
1678     case DRM_FORMAT_ABGR8888:
1679     case DRM_FORMAT_ARGB8888:
1680     case DRM_FORMAT_XBGR8888:
1681     case DRM_FORMAT_XRGB8888:
1682     case DRM_FORMAT_XBGR2101010:
1683     case DRM_FORMAT_ABGR2101010:
1684     case DRM_FORMAT_XRGB2101010:
1685     case DRM_FORMAT_ARGB2101010:
1686     case DRM_FORMAT_YUYV:
1687     case DRM_FORMAT_YVYU:
1688     case DRM_FORMAT_UYVY:
1689     case DRM_FORMAT_VYUY:
1690         if (modifier == DRM_FORMAT_MOD_LINEAR ||
1691             modifier == I915_FORMAT_MOD_X_TILED)
1692             return true;
1693         fallthrough;
1694     default:
1695         return false;
1696     }
1697 }
1698 
1699 static const struct drm_plane_funcs g4x_sprite_funcs = {
1700     .update_plane = drm_atomic_helper_update_plane,
1701     .disable_plane = drm_atomic_helper_disable_plane,
1702     .destroy = intel_plane_destroy,
1703     .atomic_duplicate_state = intel_plane_duplicate_state,
1704     .atomic_destroy_state = intel_plane_destroy_state,
1705     .format_mod_supported = g4x_sprite_format_mod_supported,
1706 };
1707 
1708 static const struct drm_plane_funcs snb_sprite_funcs = {
1709     .update_plane = drm_atomic_helper_update_plane,
1710     .disable_plane = drm_atomic_helper_disable_plane,
1711     .destroy = intel_plane_destroy,
1712     .atomic_duplicate_state = intel_plane_duplicate_state,
1713     .atomic_destroy_state = intel_plane_destroy_state,
1714     .format_mod_supported = snb_sprite_format_mod_supported,
1715 };
1716 
1717 static const struct drm_plane_funcs vlv_sprite_funcs = {
1718     .update_plane = drm_atomic_helper_update_plane,
1719     .disable_plane = drm_atomic_helper_disable_plane,
1720     .destroy = intel_plane_destroy,
1721     .atomic_duplicate_state = intel_plane_duplicate_state,
1722     .atomic_destroy_state = intel_plane_destroy_state,
1723     .format_mod_supported = vlv_sprite_format_mod_supported,
1724 };
1725 
1726 struct intel_plane *
1727 intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1728               enum pipe pipe, int sprite)
1729 {
1730     struct intel_plane *plane;
1731     const struct drm_plane_funcs *plane_funcs;
1732     unsigned int supported_rotations;
1733     const u64 *modifiers;
1734     const u32 *formats;
1735     int num_formats;
1736     int ret, zpos;
1737 
1738     plane = intel_plane_alloc();
1739     if (IS_ERR(plane))
1740         return plane;
1741 
1742     if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1743         plane->update_noarm = vlv_sprite_update_noarm;
1744         plane->update_arm = vlv_sprite_update_arm;
1745         plane->disable_arm = vlv_sprite_disable_arm;
1746         plane->get_hw_state = vlv_sprite_get_hw_state;
1747         plane->check_plane = vlv_sprite_check;
1748         plane->max_stride = i965_plane_max_stride;
1749         plane->min_cdclk = vlv_plane_min_cdclk;
1750 
1751         if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1752             formats = chv_pipe_b_sprite_formats;
1753             num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1754         } else {
1755             formats = vlv_sprite_formats;
1756             num_formats = ARRAY_SIZE(vlv_sprite_formats);
1757         }
1758 
1759         plane_funcs = &vlv_sprite_funcs;
1760     } else if (DISPLAY_VER(dev_priv) >= 7) {
1761         plane->update_noarm = ivb_sprite_update_noarm;
1762         plane->update_arm = ivb_sprite_update_arm;
1763         plane->disable_arm = ivb_sprite_disable_arm;
1764         plane->get_hw_state = ivb_sprite_get_hw_state;
1765         plane->check_plane = g4x_sprite_check;
1766 
1767         if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1768             plane->max_stride = hsw_sprite_max_stride;
1769             plane->min_cdclk = hsw_plane_min_cdclk;
1770         } else {
1771             plane->max_stride = g4x_sprite_max_stride;
1772             plane->min_cdclk = ivb_sprite_min_cdclk;
1773         }
1774 
1775         formats = snb_sprite_formats;
1776         num_formats = ARRAY_SIZE(snb_sprite_formats);
1777 
1778         plane_funcs = &snb_sprite_funcs;
1779     } else {
1780         plane->update_noarm = g4x_sprite_update_noarm;
1781         plane->update_arm = g4x_sprite_update_arm;
1782         plane->disable_arm = g4x_sprite_disable_arm;
1783         plane->get_hw_state = g4x_sprite_get_hw_state;
1784         plane->check_plane = g4x_sprite_check;
1785         plane->max_stride = g4x_sprite_max_stride;
1786         plane->min_cdclk = g4x_sprite_min_cdclk;
1787 
1788         if (IS_SANDYBRIDGE(dev_priv)) {
1789             formats = snb_sprite_formats;
1790             num_formats = ARRAY_SIZE(snb_sprite_formats);
1791 
1792             plane_funcs = &snb_sprite_funcs;
1793         } else {
1794             formats = g4x_sprite_formats;
1795             num_formats = ARRAY_SIZE(g4x_sprite_formats);
1796 
1797             plane_funcs = &g4x_sprite_funcs;
1798         }
1799     }
1800 
1801     if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1802         supported_rotations =
1803             DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1804             DRM_MODE_REFLECT_X;
1805     } else {
1806         supported_rotations =
1807             DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1808     }
1809 
1810     plane->pipe = pipe;
1811     plane->id = PLANE_SPRITE0 + sprite;
1812     plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1813 
1814     modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1815 
1816     ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1817                        0, plane_funcs,
1818                        formats, num_formats, modifiers,
1819                        DRM_PLANE_TYPE_OVERLAY,
1820                        "sprite %c", sprite_name(pipe, sprite));
1821     kfree(modifiers);
1822 
1823     if (ret)
1824         goto fail;
1825 
1826     drm_plane_create_rotation_property(&plane->base,
1827                        DRM_MODE_ROTATE_0,
1828                        supported_rotations);
1829 
1830     drm_plane_create_color_properties(&plane->base,
1831                       BIT(DRM_COLOR_YCBCR_BT601) |
1832                       BIT(DRM_COLOR_YCBCR_BT709),
1833                       BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1834                       BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1835                       DRM_COLOR_YCBCR_BT709,
1836                       DRM_COLOR_YCBCR_LIMITED_RANGE);
1837 
1838     zpos = sprite + 1;
1839     drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1840 
1841     intel_plane_helper_add(plane);
1842 
1843     return plane;
1844 
1845 fail:
1846     intel_plane_free(plane);
1847 
1848     return ERR_PTR(ret);
1849 }