linux/drivers/gpu/drm/i915/display/intel_sprite.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2011 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 * SOFTWARE.
  22 *
  23 * Authors:
  24 *   Jesse Barnes <jbarnes@virtuousgeek.org>
  25 *
  26 * New plane/sprite handling.
  27 *
  28 * The older chips had a separate interface for programming plane related
  29 * registers; newer ones are much simpler and we can use the new DRM plane
  30 * support.
  31 */
  32
  33#include <drm/drm_atomic.h>
  34#include <drm/drm_atomic_helper.h>
  35#include <drm/drm_color_mgmt.h>
  36#include <drm/drm_crtc.h>
  37#include <drm/drm_damage_helper.h>
  38#include <drm/drm_fourcc.h>
  39#include <drm/drm_plane_helper.h>
  40#include <drm/drm_rect.h>
  41
  42#include "i915_drv.h"
  43#include "i915_trace.h"
  44#include "i915_vgpu.h"
  45#include "intel_atomic_plane.h"
  46#include "intel_de.h"
  47#include "intel_display_types.h"
  48#include "intel_fb.h"
  49#include "intel_frontbuffer.h"
  50#include "intel_sprite.h"
  51#include "i9xx_plane.h"
  52#include "intel_vrr.h"
  53
  54int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
  55{
  56        const struct drm_framebuffer *fb = plane_state->hw.fb;
  57        struct drm_rect *src = &plane_state->uapi.src;
  58        u32 src_x, src_y, src_w, src_h, hsub, vsub;
  59        bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
  60
  61        /*
  62         * FIXME hsub/vsub vs. block size is a mess. Pre-tgl CCS
  63         * abuses hsub/vsub so we can't use them here. But as they
  64         * are limited to 32bpp RGB formats we don't actually need
  65         * to check anything.
  66         */
  67        if (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
  68            fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)
  69                return 0;
  70
  71        /*
  72         * Hardware doesn't handle subpixel coordinates.
  73         * Adjust to (macro)pixel boundary, but be careful not to
  74         * increase the source viewport size, because that could
  75         * push the downscaling factor out of bounds.
  76         */
  77        src_x = src->x1 >> 16;
  78        src_w = drm_rect_width(src) >> 16;
  79        src_y = src->y1 >> 16;
  80        src_h = drm_rect_height(src) >> 16;
  81
  82        drm_rect_init(src, src_x << 16, src_y << 16,
  83                      src_w << 16, src_h << 16);
  84
  85        if (fb->format->format == DRM_FORMAT_RGB565 && rotated) {
  86                hsub = 2;
  87                vsub = 2;
  88        } else {
  89                hsub = fb->format->hsub;
  90                vsub = fb->format->vsub;
  91        }
  92
  93        if (rotated)
  94                hsub = vsub = max(hsub, vsub);
  95
  96        if (src_x % hsub || src_w % hsub) {
  97                DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n",
  98                              src_x, src_w, hsub, yesno(rotated));
  99                return -EINVAL;
 100        }
 101
 102        if (src_y % vsub || src_h % vsub) {
 103                DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n",
 104                              src_y, src_h, vsub, yesno(rotated));
 105                return -EINVAL;
 106        }
 107
 108        return 0;
 109}
 110
 111static void i9xx_plane_linear_gamma(u16 gamma[8])
 112{
 113        /* The points are not evenly spaced. */
 114        static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
 115        int i;
 116
 117        for (i = 0; i < 8; i++)
 118                gamma[i] = (in[i] << 8) / 32;
 119}
 120
 121static void
 122chv_update_csc(const struct intel_plane_state *plane_state)
 123{
 124        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 125        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 126        const struct drm_framebuffer *fb = plane_state->hw.fb;
 127        enum plane_id plane_id = plane->id;
 128        /*
 129         * |r|   | c0 c1 c2 |   |cr|
 130         * |g| = | c3 c4 c5 | x |y |
 131         * |b|   | c6 c7 c8 |   |cb|
 132         *
 133         * Coefficients are s3.12.
 134         *
 135         * Cb and Cr apparently come in as signed already, and
 136         * we always get full range data in on account of CLRC0/1.
 137         */
 138        static const s16 csc_matrix[][9] = {
 139                /* BT.601 full range YCbCr -> full range RGB */
 140                [DRM_COLOR_YCBCR_BT601] = {
 141                         5743, 4096,     0,
 142                        -2925, 4096, -1410,
 143                            0, 4096,  7258,
 144                },
 145                /* BT.709 full range YCbCr -> full range RGB */
 146                [DRM_COLOR_YCBCR_BT709] = {
 147                         6450, 4096,     0,
 148                        -1917, 4096,  -767,
 149                            0, 4096,  7601,
 150                },
 151        };
 152        const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
 153
 154        /* Seems RGB data bypasses the CSC always */
 155        if (!fb->format->is_yuv)
 156                return;
 157
 158        intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
 159                          SPCSC_OOFF(0) | SPCSC_IOFF(0));
 160        intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
 161                          SPCSC_OOFF(0) | SPCSC_IOFF(0));
 162        intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
 163                          SPCSC_OOFF(0) | SPCSC_IOFF(0));
 164
 165        intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
 166                          SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
 167        intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
 168                          SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
 169        intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
 170                          SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
 171        intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
 172                          SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
 173        intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
 174
 175        intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
 176                          SPCSC_IMAX(1023) | SPCSC_IMIN(0));
 177        intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
 178                          SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 179        intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
 180                          SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 181
 182        intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
 183                          SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 184        intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
 185                          SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 186        intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
 187                          SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 188}
 189
 190#define SIN_0 0
 191#define COS_0 1
 192
 193static void
 194vlv_update_clrc(const struct intel_plane_state *plane_state)
 195{
 196        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 197        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 198        const struct drm_framebuffer *fb = plane_state->hw.fb;
 199        enum pipe pipe = plane->pipe;
 200        enum plane_id plane_id = plane->id;
 201        int contrast, brightness, sh_scale, sh_sin, sh_cos;
 202
 203        if (fb->format->is_yuv &&
 204            plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
 205                /*
 206                 * Expand limited range to full range:
 207                 * Contrast is applied first and is used to expand Y range.
 208                 * Brightness is applied second and is used to remove the
 209                 * offset from Y. Saturation/hue is used to expand CbCr range.
 210                 */
 211                contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
 212                brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
 213                sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
 214                sh_sin = SIN_0 * sh_scale;
 215                sh_cos = COS_0 * sh_scale;
 216        } else {
 217                /* Pass-through everything. */
 218                contrast = 1 << 6;
 219                brightness = 0;
 220                sh_scale = 1 << 7;
 221                sh_sin = SIN_0 * sh_scale;
 222                sh_cos = COS_0 * sh_scale;
 223        }
 224
 225        /* FIXME these register are single buffered :( */
 226        intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
 227                          SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
 228        intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
 229                          SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
 230}
 231
 232static void
 233vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
 234                const struct intel_plane_state *plane_state,
 235                unsigned int *num, unsigned int *den)
 236{
 237        u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 238        const struct drm_framebuffer *fb = plane_state->hw.fb;
 239        unsigned int cpp = fb->format->cpp[0];
 240
 241        /*
 242         * VLV bspec only considers cases where all three planes are
 243         * enabled, and cases where the primary and one sprite is enabled.
 244         * Let's assume the case with just two sprites enabled also
 245         * maps to the latter case.
 246         */
 247        if (hweight8(active_planes) == 3) {
 248                switch (cpp) {
 249                case 8:
 250                        *num = 11;
 251                        *den = 8;
 252                        break;
 253                case 4:
 254                        *num = 18;
 255                        *den = 16;
 256                        break;
 257                default:
 258                        *num = 1;
 259                        *den = 1;
 260                        break;
 261                }
 262        } else if (hweight8(active_planes) == 2) {
 263                switch (cpp) {
 264                case 8:
 265                        *num = 10;
 266                        *den = 8;
 267                        break;
 268                case 4:
 269                        *num = 17;
 270                        *den = 16;
 271                        break;
 272                default:
 273                        *num = 1;
 274                        *den = 1;
 275                        break;
 276                }
 277        } else {
 278                switch (cpp) {
 279                case 8:
 280                        *num = 10;
 281                        *den = 8;
 282                        break;
 283                default:
 284                        *num = 1;
 285                        *den = 1;
 286                        break;
 287                }
 288        }
 289}
 290
 291int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 292                        const struct intel_plane_state *plane_state)
 293{
 294        unsigned int pixel_rate;
 295        unsigned int num, den;
 296
 297        /*
 298         * Note that crtc_state->pixel_rate accounts for both
 299         * horizontal and vertical panel fitter downscaling factors.
 300         * Pre-HSW bspec tells us to only consider the horizontal
 301         * downscaling factor here. We ignore that and just consider
 302         * both for simplicity.
 303         */
 304        pixel_rate = crtc_state->pixel_rate;
 305
 306        vlv_plane_ratio(crtc_state, plane_state, &num, &den);
 307
 308        return DIV_ROUND_UP(pixel_rate * num, den);
 309}
 310
 311static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
 312{
 313        u32 sprctl = 0;
 314
 315        if (crtc_state->gamma_enable)
 316                sprctl |= SP_GAMMA_ENABLE;
 317
 318        return sprctl;
 319}
 320
 321static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
 322                          const struct intel_plane_state *plane_state)
 323{
 324        const struct drm_framebuffer *fb = plane_state->hw.fb;
 325        unsigned int rotation = plane_state->hw.rotation;
 326        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 327        u32 sprctl;
 328
 329        sprctl = SP_ENABLE;
 330
 331        switch (fb->format->format) {
 332        case DRM_FORMAT_YUYV:
 333                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
 334                break;
 335        case DRM_FORMAT_YVYU:
 336                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
 337                break;
 338        case DRM_FORMAT_UYVY:
 339                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
 340                break;
 341        case DRM_FORMAT_VYUY:
 342                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
 343                break;
 344        case DRM_FORMAT_C8:
 345                sprctl |= SP_FORMAT_8BPP;
 346                break;
 347        case DRM_FORMAT_RGB565:
 348                sprctl |= SP_FORMAT_BGR565;
 349                break;
 350        case DRM_FORMAT_XRGB8888:
 351                sprctl |= SP_FORMAT_BGRX8888;
 352                break;
 353        case DRM_FORMAT_ARGB8888:
 354                sprctl |= SP_FORMAT_BGRA8888;
 355                break;
 356        case DRM_FORMAT_XBGR2101010:
 357                sprctl |= SP_FORMAT_RGBX1010102;
 358                break;
 359        case DRM_FORMAT_ABGR2101010:
 360                sprctl |= SP_FORMAT_RGBA1010102;
 361                break;
 362        case DRM_FORMAT_XRGB2101010:
 363                sprctl |= SP_FORMAT_BGRX1010102;
 364                break;
 365        case DRM_FORMAT_ARGB2101010:
 366                sprctl |= SP_FORMAT_BGRA1010102;
 367                break;
 368        case DRM_FORMAT_XBGR8888:
 369                sprctl |= SP_FORMAT_RGBX8888;
 370                break;
 371        case DRM_FORMAT_ABGR8888:
 372                sprctl |= SP_FORMAT_RGBA8888;
 373                break;
 374        default:
 375                MISSING_CASE(fb->format->format);
 376                return 0;
 377        }
 378
 379        if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
 380                sprctl |= SP_YUV_FORMAT_BT709;
 381
 382        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 383                sprctl |= SP_TILED;
 384
 385        if (rotation & DRM_MODE_ROTATE_180)
 386                sprctl |= SP_ROTATE_180;
 387
 388        if (rotation & DRM_MODE_REFLECT_X)
 389                sprctl |= SP_MIRROR;
 390
 391        if (key->flags & I915_SET_COLORKEY_SOURCE)
 392                sprctl |= SP_SOURCE_KEY;
 393
 394        return sprctl;
 395}
 396
 397static void vlv_update_gamma(const struct intel_plane_state *plane_state)
 398{
 399        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 400        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 401        const struct drm_framebuffer *fb = plane_state->hw.fb;
 402        enum pipe pipe = plane->pipe;
 403        enum plane_id plane_id = plane->id;
 404        u16 gamma[8];
 405        int i;
 406
 407        /* Seems RGB data bypasses the gamma always */
 408        if (!fb->format->is_yuv)
 409                return;
 410
 411        i9xx_plane_linear_gamma(gamma);
 412
 413        /* FIXME these register are single buffered :( */
 414        /* The two end points are implicit (0.0 and 1.0) */
 415        for (i = 1; i < 8 - 1; i++)
 416                intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
 417                                  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
 418}
 419
 420static void
 421vlv_update_plane(struct intel_plane *plane,
 422                 const struct intel_crtc_state *crtc_state,
 423                 const struct intel_plane_state *plane_state)
 424{
 425        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 426        enum pipe pipe = plane->pipe;
 427        enum plane_id plane_id = plane->id;
 428        u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
 429        u32 linear_offset;
 430        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 431        int crtc_x = plane_state->uapi.dst.x1;
 432        int crtc_y = plane_state->uapi.dst.y1;
 433        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
 434        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
 435        u32 x = plane_state->view.color_plane[0].x;
 436        u32 y = plane_state->view.color_plane[0].y;
 437        unsigned long irqflags;
 438        u32 sprctl;
 439
 440        sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
 441
 442        /* Sizes are 0 based */
 443        crtc_w--;
 444        crtc_h--;
 445
 446        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 447
 448        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 449
 450        intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
 451                          plane_state->view.color_plane[0].mapping_stride);
 452        intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
 453                          (crtc_y << 16) | crtc_x);
 454        intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
 455                          (crtc_h << 16) | crtc_w);
 456        intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
 457
 458        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
 459                chv_update_csc(plane_state);
 460
 461        if (key->flags) {
 462                intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
 463                                  key->min_value);
 464                intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
 465                                  key->channel_mask);
 466                intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
 467                                  key->max_value);
 468        }
 469
 470        intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
 471        intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id), (y << 16) | x);
 472
 473        /*
 474         * The control register self-arms if the plane was previously
 475         * disabled. Try to make the plane enable atomic by writing
 476         * the control register just before the surface register.
 477         */
 478        intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
 479        intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
 480                          intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 481
 482        vlv_update_clrc(plane_state);
 483        vlv_update_gamma(plane_state);
 484
 485        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 486}
 487
 488static void
 489vlv_disable_plane(struct intel_plane *plane,
 490                  const struct intel_crtc_state *crtc_state)
 491{
 492        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 493        enum pipe pipe = plane->pipe;
 494        enum plane_id plane_id = plane->id;
 495        unsigned long irqflags;
 496
 497        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 498
 499        intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
 500        intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
 501
 502        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 503}
 504
 505static bool
 506vlv_plane_get_hw_state(struct intel_plane *plane,
 507                       enum pipe *pipe)
 508{
 509        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 510        enum intel_display_power_domain power_domain;
 511        enum plane_id plane_id = plane->id;
 512        intel_wakeref_t wakeref;
 513        bool ret;
 514
 515        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 516        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 517        if (!wakeref)
 518                return false;
 519
 520        ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
 521
 522        *pipe = plane->pipe;
 523
 524        intel_display_power_put(dev_priv, power_domain, wakeref);
 525
 526        return ret;
 527}
 528
 529static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
 530                            const struct intel_plane_state *plane_state,
 531                            unsigned int *num, unsigned int *den)
 532{
 533        u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 534        const struct drm_framebuffer *fb = plane_state->hw.fb;
 535        unsigned int cpp = fb->format->cpp[0];
 536
 537        if (hweight8(active_planes) == 2) {
 538                switch (cpp) {
 539                case 8:
 540                        *num = 10;
 541                        *den = 8;
 542                        break;
 543                case 4:
 544                        *num = 17;
 545                        *den = 16;
 546                        break;
 547                default:
 548                        *num = 1;
 549                        *den = 1;
 550                        break;
 551                }
 552        } else {
 553                switch (cpp) {
 554                case 8:
 555                        *num = 9;
 556                        *den = 8;
 557                        break;
 558                default:
 559                        *num = 1;
 560                        *den = 1;
 561                        break;
 562                }
 563        }
 564}
 565
 566static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
 567                                    const struct intel_plane_state *plane_state,
 568                                    unsigned int *num, unsigned int *den)
 569{
 570        const struct drm_framebuffer *fb = plane_state->hw.fb;
 571        unsigned int cpp = fb->format->cpp[0];
 572
 573        switch (cpp) {
 574        case 8:
 575                *num = 12;
 576                *den = 8;
 577                break;
 578        case 4:
 579                *num = 19;
 580                *den = 16;
 581                break;
 582        case 2:
 583                *num = 33;
 584                *den = 32;
 585                break;
 586        default:
 587                *num = 1;
 588                *den = 1;
 589                break;
 590        }
 591}
 592
 593int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 594                        const struct intel_plane_state *plane_state)
 595{
 596        unsigned int pixel_rate;
 597        unsigned int num, den;
 598
 599        /*
 600         * Note that crtc_state->pixel_rate accounts for both
 601         * horizontal and vertical panel fitter downscaling factors.
 602         * Pre-HSW bspec tells us to only consider the horizontal
 603         * downscaling factor here. We ignore that and just consider
 604         * both for simplicity.
 605         */
 606        pixel_rate = crtc_state->pixel_rate;
 607
 608        ivb_plane_ratio(crtc_state, plane_state, &num, &den);
 609
 610        return DIV_ROUND_UP(pixel_rate * num, den);
 611}
 612
 613static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
 614                                const struct intel_plane_state *plane_state)
 615{
 616        unsigned int src_w, dst_w, pixel_rate;
 617        unsigned int num, den;
 618
 619        /*
 620         * Note that crtc_state->pixel_rate accounts for both
 621         * horizontal and vertical panel fitter downscaling factors.
 622         * Pre-HSW bspec tells us to only consider the horizontal
 623         * downscaling factor here. We ignore that and just consider
 624         * both for simplicity.
 625         */
 626        pixel_rate = crtc_state->pixel_rate;
 627
 628        src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 629        dst_w = drm_rect_width(&plane_state->uapi.dst);
 630
 631        if (src_w != dst_w)
 632                ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
 633        else
 634                ivb_plane_ratio(crtc_state, plane_state, &num, &den);
 635
 636        /* Horizontal downscaling limits the maximum pixel rate */
 637        dst_w = min(src_w, dst_w);
 638
 639        return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
 640                                den * dst_w);
 641}
 642
 643static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
 644                            const struct intel_plane_state *plane_state,
 645                            unsigned int *num, unsigned int *den)
 646{
 647        u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 648        const struct drm_framebuffer *fb = plane_state->hw.fb;
 649        unsigned int cpp = fb->format->cpp[0];
 650
 651        if (hweight8(active_planes) == 2) {
 652                switch (cpp) {
 653                case 8:
 654                        *num = 10;
 655                        *den = 8;
 656                        break;
 657                default:
 658                        *num = 1;
 659                        *den = 1;
 660                        break;
 661                }
 662        } else {
 663                switch (cpp) {
 664                case 8:
 665                        *num = 9;
 666                        *den = 8;
 667                        break;
 668                default:
 669                        *num = 1;
 670                        *den = 1;
 671                        break;
 672                }
 673        }
 674}
 675
 676int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 677                        const struct intel_plane_state *plane_state)
 678{
 679        unsigned int pixel_rate = crtc_state->pixel_rate;
 680        unsigned int num, den;
 681
 682        hsw_plane_ratio(crtc_state, plane_state, &num, &den);
 683
 684        return DIV_ROUND_UP(pixel_rate * num, den);
 685}
 686
 687static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
 688{
 689        u32 sprctl = 0;
 690
 691        if (crtc_state->gamma_enable)
 692                sprctl |= SPRITE_GAMMA_ENABLE;
 693
 694        if (crtc_state->csc_enable)
 695                sprctl |= SPRITE_PIPE_CSC_ENABLE;
 696
 697        return sprctl;
 698}
 699
 700static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
 701{
 702        struct drm_i915_private *dev_priv =
 703                to_i915(plane_state->uapi.plane->dev);
 704        const struct drm_framebuffer *fb = plane_state->hw.fb;
 705
 706        return fb->format->cpp[0] == 8 &&
 707                (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
 708}
 709
 710static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
 711                          const struct intel_plane_state *plane_state)
 712{
 713        struct drm_i915_private *dev_priv =
 714                to_i915(plane_state->uapi.plane->dev);
 715        const struct drm_framebuffer *fb = plane_state->hw.fb;
 716        unsigned int rotation = plane_state->hw.rotation;
 717        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 718        u32 sprctl;
 719
 720        sprctl = SPRITE_ENABLE;
 721
 722        if (IS_IVYBRIDGE(dev_priv))
 723                sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
 724
 725        switch (fb->format->format) {
 726        case DRM_FORMAT_XBGR8888:
 727                sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
 728                break;
 729        case DRM_FORMAT_XRGB8888:
 730                sprctl |= SPRITE_FORMAT_RGBX888;
 731                break;
 732        case DRM_FORMAT_XBGR2101010:
 733                sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
 734                break;
 735        case DRM_FORMAT_XRGB2101010:
 736                sprctl |= SPRITE_FORMAT_RGBX101010;
 737                break;
 738        case DRM_FORMAT_XBGR16161616F:
 739                sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
 740                break;
 741        case DRM_FORMAT_XRGB16161616F:
 742                sprctl |= SPRITE_FORMAT_RGBX161616;
 743                break;
 744        case DRM_FORMAT_YUYV:
 745                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
 746                break;
 747        case DRM_FORMAT_YVYU:
 748                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
 749                break;
 750        case DRM_FORMAT_UYVY:
 751                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
 752                break;
 753        case DRM_FORMAT_VYUY:
 754                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
 755                break;
 756        default:
 757                MISSING_CASE(fb->format->format);
 758                return 0;
 759        }
 760
 761        if (!ivb_need_sprite_gamma(plane_state))
 762                sprctl |= SPRITE_INT_GAMMA_DISABLE;
 763
 764        if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
 765                sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
 766
 767        if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 768                sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
 769
 770        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 771                sprctl |= SPRITE_TILED;
 772
 773        if (rotation & DRM_MODE_ROTATE_180)
 774                sprctl |= SPRITE_ROTATE_180;
 775
 776        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 777                sprctl |= SPRITE_DEST_KEY;
 778        else if (key->flags & I915_SET_COLORKEY_SOURCE)
 779                sprctl |= SPRITE_SOURCE_KEY;
 780
 781        return sprctl;
 782}
 783
 784static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
 785                                    u16 gamma[18])
 786{
 787        int scale, i;
 788
 789        /*
 790         * WaFP16GammaEnabling:ivb,hsw
 791         * "Workaround : When using the 64-bit format, the sprite output
 792         *  on each color channel has one quarter amplitude. It can be
 793         *  brought up to full amplitude by using sprite internal gamma
 794         *  correction, pipe gamma correction, or pipe color space
 795         *  conversion to multiply the sprite output by four."
 796         */
 797        scale = 4;
 798
 799        for (i = 0; i < 16; i++)
 800                gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
 801
 802        gamma[i] = min((scale * i << 10) / 16, 1 << 10);
 803        i++;
 804
 805        gamma[i] = 3 << 10;
 806        i++;
 807}
 808
 809static void ivb_update_gamma(const struct intel_plane_state *plane_state)
 810{
 811        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 812        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 813        enum pipe pipe = plane->pipe;
 814        u16 gamma[18];
 815        int i;
 816
 817        if (!ivb_need_sprite_gamma(plane_state))
 818                return;
 819
 820        ivb_sprite_linear_gamma(plane_state, gamma);
 821
 822        /* FIXME these register are single buffered :( */
 823        for (i = 0; i < 16; i++)
 824                intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
 825                                  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
 826
 827        intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
 828        intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
 829        intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
 830        i++;
 831
 832        intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
 833        intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
 834        intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
 835        i++;
 836}
 837
 838static void
 839ivb_update_plane(struct intel_plane *plane,
 840                 const struct intel_crtc_state *crtc_state,
 841                 const struct intel_plane_state *plane_state)
 842{
 843        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 844        enum pipe pipe = plane->pipe;
 845        u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
 846        u32 linear_offset;
 847        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 848        int crtc_x = plane_state->uapi.dst.x1;
 849        int crtc_y = plane_state->uapi.dst.y1;
 850        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
 851        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
 852        u32 x = plane_state->view.color_plane[0].x;
 853        u32 y = plane_state->view.color_plane[0].y;
 854        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 855        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 856        u32 sprctl, sprscale = 0;
 857        unsigned long irqflags;
 858
 859        sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
 860
 861        /* Sizes are 0 based */
 862        src_w--;
 863        src_h--;
 864        crtc_w--;
 865        crtc_h--;
 866
 867        if (crtc_w != src_w || crtc_h != src_h)
 868                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 869
 870        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 871
 872        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 873
 874        intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
 875                          plane_state->view.color_plane[0].mapping_stride);
 876        intel_de_write_fw(dev_priv, SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 877        intel_de_write_fw(dev_priv, SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
 878        if (IS_IVYBRIDGE(dev_priv))
 879                intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
 880
 881        if (key->flags) {
 882                intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
 883                intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
 884                                  key->channel_mask);
 885                intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
 886        }
 887
 888        /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
 889         * register */
 890        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 891                intel_de_write_fw(dev_priv, SPROFFSET(pipe), (y << 16) | x);
 892        } else {
 893                intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
 894                intel_de_write_fw(dev_priv, SPRTILEOFF(pipe), (y << 16) | x);
 895        }
 896
 897        /*
 898         * The control register self-arms if the plane was previously
 899         * disabled. Try to make the plane enable atomic by writing
 900         * the control register just before the surface register.
 901         */
 902        intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
 903        intel_de_write_fw(dev_priv, SPRSURF(pipe),
 904                          intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 905
 906        ivb_update_gamma(plane_state);
 907
 908        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 909}
 910
 911static void
 912ivb_disable_plane(struct intel_plane *plane,
 913                  const struct intel_crtc_state *crtc_state)
 914{
 915        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 916        enum pipe pipe = plane->pipe;
 917        unsigned long irqflags;
 918
 919        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 920
 921        intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
 922        /* Disable the scaler */
 923        if (IS_IVYBRIDGE(dev_priv))
 924                intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
 925        intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
 926
 927        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 928}
 929
 930static bool
 931ivb_plane_get_hw_state(struct intel_plane *plane,
 932                       enum pipe *pipe)
 933{
 934        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 935        enum intel_display_power_domain power_domain;
 936        intel_wakeref_t wakeref;
 937        bool ret;
 938
 939        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 940        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 941        if (!wakeref)
 942                return false;
 943
 944        ret =  intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
 945
 946        *pipe = plane->pipe;
 947
 948        intel_display_power_put(dev_priv, power_domain, wakeref);
 949
 950        return ret;
 951}
 952
 953static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
 954                                const struct intel_plane_state *plane_state)
 955{
 956        const struct drm_framebuffer *fb = plane_state->hw.fb;
 957        unsigned int hscale, pixel_rate;
 958        unsigned int limit, decimate;
 959
 960        /*
 961         * Note that crtc_state->pixel_rate accounts for both
 962         * horizontal and vertical panel fitter downscaling factors.
 963         * Pre-HSW bspec tells us to only consider the horizontal
 964         * downscaling factor here. We ignore that and just consider
 965         * both for simplicity.
 966         */
 967        pixel_rate = crtc_state->pixel_rate;
 968
 969        /* Horizontal downscaling limits the maximum pixel rate */
 970        hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
 971                                      &plane_state->uapi.dst,
 972                                      0, INT_MAX);
 973        hscale = max(hscale, 0x10000u);
 974
 975        /* Decimation steps at 2x,4x,8x,16x */
 976        decimate = ilog2(hscale >> 16);
 977        hscale >>= decimate;
 978
 979        /* Starting limit is 90% of cdclk */
 980        limit = 9;
 981
 982        /* -10% per decimation step */
 983        limit -= decimate;
 984
 985        /* -10% for RGB */
 986        if (!fb->format->is_yuv)
 987                limit--;
 988
 989        /*
 990         * We should also do -10% if sprite scaling is enabled
 991         * on the other pipe, but we can't really check for that,
 992         * so we ignore it.
 993         */
 994
 995        return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
 996                                limit << 16);
 997}
 998
 999static unsigned int
1000g4x_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
1014static unsigned int
1015hsw_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
1026static 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_GAMMA_ENABLE;
1032
1033        if (crtc_state->csc_enable)
1034                dvscntr |= DVS_PIPE_CSC_ENABLE;
1035
1036        return dvscntr;
1037}
1038
1039static 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
1110static void g4x_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
1132static 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
1140static void ilk_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
1166static void
1167g4x_update_plane(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        u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1174        u32 linear_offset;
1175        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1176        int crtc_x = plane_state->uapi.dst.x1;
1177        int crtc_y = plane_state->uapi.dst.y1;
1178        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1179        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1180        u32 x = plane_state->view.color_plane[0].x;
1181        u32 y = plane_state->view.color_plane[0].y;
1182        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1183        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1184        u32 dvscntr, dvsscale = 0;
1185        unsigned long irqflags;
1186
1187        dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1188
1189        /* Sizes are 0 based */
1190        src_w--;
1191        src_h--;
1192        crtc_w--;
1193        crtc_h--;
1194
1195        if (crtc_w != src_w || crtc_h != src_h)
1196                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1197
1198        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1199
1200        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1201
1202        intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1203                          plane_state->view.color_plane[0].mapping_stride);
1204        intel_de_write_fw(dev_priv, DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1205        intel_de_write_fw(dev_priv, DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1206        intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1207
1208        if (key->flags) {
1209                intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1210                intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1211                                  key->channel_mask);
1212                intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1213        }
1214
1215        intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1216        intel_de_write_fw(dev_priv, DVSTILEOFF(pipe), (y << 16) | x);
1217
1218        /*
1219         * The control register self-arms if the plane was previously
1220         * disabled. Try to make the plane enable atomic by writing
1221         * the control register just before the surface register.
1222         */
1223        intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1224        intel_de_write_fw(dev_priv, DVSSURF(pipe),
1225                          intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1226
1227        if (IS_G4X(dev_priv))
1228                g4x_update_gamma(plane_state);
1229        else
1230                ilk_update_gamma(plane_state);
1231
1232        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1233}
1234
1235static void
1236g4x_disable_plane(struct intel_plane *plane,
1237                  const struct intel_crtc_state *crtc_state)
1238{
1239        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1240        enum pipe pipe = plane->pipe;
1241        unsigned long irqflags;
1242
1243        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1244
1245        intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1246        /* Disable the scaler */
1247        intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1248        intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1249
1250        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1251}
1252
1253static bool
1254g4x_plane_get_hw_state(struct intel_plane *plane,
1255                       enum pipe *pipe)
1256{
1257        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1258        enum intel_display_power_domain power_domain;
1259        intel_wakeref_t wakeref;
1260        bool ret;
1261
1262        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1263        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1264        if (!wakeref)
1265                return false;
1266
1267        ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1268
1269        *pipe = plane->pipe;
1270
1271        intel_display_power_put(dev_priv, power_domain, wakeref);
1272
1273        return ret;
1274}
1275
1276static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1277{
1278        if (!fb)
1279                return false;
1280
1281        switch (fb->format->format) {
1282        case DRM_FORMAT_C8:
1283        case DRM_FORMAT_XRGB16161616F:
1284        case DRM_FORMAT_ARGB16161616F:
1285        case DRM_FORMAT_XBGR16161616F:
1286        case DRM_FORMAT_ABGR16161616F:
1287                return false;
1288        default:
1289                return true;
1290        }
1291}
1292
1293static int
1294g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1295                         struct intel_plane_state *plane_state)
1296{
1297        const struct drm_framebuffer *fb = plane_state->hw.fb;
1298        const struct drm_rect *src = &plane_state->uapi.src;
1299        const struct drm_rect *dst = &plane_state->uapi.dst;
1300        int src_x, src_w, src_h, crtc_w, crtc_h;
1301        const struct drm_display_mode *adjusted_mode =
1302                &crtc_state->hw.adjusted_mode;
1303        unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1304        unsigned int cpp = fb->format->cpp[0];
1305        unsigned int width_bytes;
1306        int min_width, min_height;
1307
1308        crtc_w = drm_rect_width(dst);
1309        crtc_h = drm_rect_height(dst);
1310
1311        src_x = src->x1 >> 16;
1312        src_w = drm_rect_width(src) >> 16;
1313        src_h = drm_rect_height(src) >> 16;
1314
1315        if (src_w == crtc_w && src_h == crtc_h)
1316                return 0;
1317
1318        min_width = 3;
1319
1320        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1321                if (src_h & 1) {
1322                        DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1323                        return -EINVAL;
1324                }
1325                min_height = 6;
1326        } else {
1327                min_height = 3;
1328        }
1329
1330        width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1331
1332        if (src_w < min_width || src_h < min_height ||
1333            src_w > 2048 || src_h > 2048) {
1334                DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1335                              src_w, src_h, min_width, min_height, 2048, 2048);
1336                return -EINVAL;
1337        }
1338
1339        if (width_bytes > 4096) {
1340                DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1341                              width_bytes, 4096);
1342                return -EINVAL;
1343        }
1344
1345        if (stride > 4096) {
1346                DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1347                              stride, 4096);
1348                return -EINVAL;
1349        }
1350
1351        return 0;
1352}
1353
1354static int
1355g4x_sprite_check(struct intel_crtc_state *crtc_state,
1356                 struct intel_plane_state *plane_state)
1357{
1358        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1359        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1360        int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1361        int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1362        int ret;
1363
1364        if (g4x_fb_scalable(plane_state->hw.fb)) {
1365                if (DISPLAY_VER(dev_priv) < 7) {
1366                        min_scale = 1;
1367                        max_scale = 16 << 16;
1368                } else if (IS_IVYBRIDGE(dev_priv)) {
1369                        min_scale = 1;
1370                        max_scale = 2 << 16;
1371                }
1372        }
1373
1374        ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1375                                                min_scale, max_scale, true);
1376        if (ret)
1377                return ret;
1378
1379        ret = i9xx_check_plane_surface(plane_state);
1380        if (ret)
1381                return ret;
1382
1383        if (!plane_state->uapi.visible)
1384                return 0;
1385
1386        ret = intel_plane_check_src_coordinates(plane_state);
1387        if (ret)
1388                return ret;
1389
1390        ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1391        if (ret)
1392                return ret;
1393
1394        if (DISPLAY_VER(dev_priv) >= 7)
1395                plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1396        else
1397                plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1398
1399        return 0;
1400}
1401
1402int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1403{
1404        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1405        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1406        unsigned int rotation = plane_state->hw.rotation;
1407
1408        /* CHV ignores the mirror bit when the rotate bit is set :( */
1409        if (IS_CHERRYVIEW(dev_priv) &&
1410            rotation & DRM_MODE_ROTATE_180 &&
1411            rotation & DRM_MODE_REFLECT_X) {
1412                drm_dbg_kms(&dev_priv->drm,
1413                            "Cannot rotate and reflect at the same time\n");
1414                return -EINVAL;
1415        }
1416
1417        return 0;
1418}
1419
1420static int
1421vlv_sprite_check(struct intel_crtc_state *crtc_state,
1422                 struct intel_plane_state *plane_state)
1423{
1424        int ret;
1425
1426        ret = chv_plane_check_rotation(plane_state);
1427        if (ret)
1428                return ret;
1429
1430        ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1431                                                DRM_PLANE_HELPER_NO_SCALING,
1432                                                DRM_PLANE_HELPER_NO_SCALING,
1433                                                true);
1434        if (ret)
1435                return ret;
1436
1437        ret = i9xx_check_plane_surface(plane_state);
1438        if (ret)
1439                return ret;
1440
1441        if (!plane_state->uapi.visible)
1442                return 0;
1443
1444        ret = intel_plane_check_src_coordinates(plane_state);
1445        if (ret)
1446                return ret;
1447
1448        plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1449
1450        return 0;
1451}
1452
1453static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1454{
1455        return DISPLAY_VER(dev_priv) >= 9;
1456}
1457
1458static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1459                                 const struct drm_intel_sprite_colorkey *set)
1460{
1461        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1462        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1463        struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1464
1465        *key = *set;
1466
1467        /*
1468         * We want src key enabled on the
1469         * sprite and not on the primary.
1470         */
1471        if (plane->id == PLANE_PRIMARY &&
1472            set->flags & I915_SET_COLORKEY_SOURCE)
1473                key->flags = 0;
1474
1475        /*
1476         * On SKL+ we want dst key enabled on
1477         * the primary and not on the sprite.
1478         */
1479        if (DISPLAY_VER(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1480            set->flags & I915_SET_COLORKEY_DESTINATION)
1481                key->flags = 0;
1482}
1483
1484int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1485                                    struct drm_file *file_priv)
1486{
1487        struct drm_i915_private *dev_priv = to_i915(dev);
1488        struct drm_intel_sprite_colorkey *set = data;
1489        struct drm_plane *plane;
1490        struct drm_plane_state *plane_state;
1491        struct drm_atomic_state *state;
1492        struct drm_modeset_acquire_ctx ctx;
1493        int ret = 0;
1494
1495        /* ignore the pointless "none" flag */
1496        set->flags &= ~I915_SET_COLORKEY_NONE;
1497
1498        if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1499                return -EINVAL;
1500
1501        /* Make sure we don't try to enable both src & dest simultaneously */
1502        if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1503                return -EINVAL;
1504
1505        if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1506            set->flags & I915_SET_COLORKEY_DESTINATION)
1507                return -EINVAL;
1508
1509        plane = drm_plane_find(dev, file_priv, set->plane_id);
1510        if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1511                return -ENOENT;
1512
1513        /*
1514         * SKL+ only plane 2 can do destination keying against plane 1.
1515         * Also multiple planes can't do destination keying on the same
1516         * pipe simultaneously.
1517         */
1518        if (DISPLAY_VER(dev_priv) >= 9 &&
1519            to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1520            set->flags & I915_SET_COLORKEY_DESTINATION)
1521                return -EINVAL;
1522
1523        drm_modeset_acquire_init(&ctx, 0);
1524
1525        state = drm_atomic_state_alloc(plane->dev);
1526        if (!state) {
1527                ret = -ENOMEM;
1528                goto out;
1529        }
1530        state->acquire_ctx = &ctx;
1531
1532        while (1) {
1533                plane_state = drm_atomic_get_plane_state(state, plane);
1534                ret = PTR_ERR_OR_ZERO(plane_state);
1535                if (!ret)
1536                        intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1537
1538                /*
1539                 * On some platforms we have to configure
1540                 * the dst colorkey on the primary plane.
1541                 */
1542                if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1543                        struct intel_crtc *crtc =
1544                                intel_get_crtc_for_pipe(dev_priv,
1545                                                        to_intel_plane(plane)->pipe);
1546
1547                        plane_state = drm_atomic_get_plane_state(state,
1548                                                                 crtc->base.primary);
1549                        ret = PTR_ERR_OR_ZERO(plane_state);
1550                        if (!ret)
1551                                intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1552                }
1553
1554                if (!ret)
1555                        ret = drm_atomic_commit(state);
1556
1557                if (ret != -EDEADLK)
1558                        break;
1559
1560                drm_atomic_state_clear(state);
1561                drm_modeset_backoff(&ctx);
1562        }
1563
1564        drm_atomic_state_put(state);
1565out:
1566        drm_modeset_drop_locks(&ctx);
1567        drm_modeset_acquire_fini(&ctx);
1568        return ret;
1569}
1570
1571static const u32 g4x_plane_formats[] = {
1572        DRM_FORMAT_XRGB8888,
1573        DRM_FORMAT_YUYV,
1574        DRM_FORMAT_YVYU,
1575        DRM_FORMAT_UYVY,
1576        DRM_FORMAT_VYUY,
1577};
1578
1579static const u32 snb_plane_formats[] = {
1580        DRM_FORMAT_XRGB8888,
1581        DRM_FORMAT_XBGR8888,
1582        DRM_FORMAT_XRGB2101010,
1583        DRM_FORMAT_XBGR2101010,
1584        DRM_FORMAT_XRGB16161616F,
1585        DRM_FORMAT_XBGR16161616F,
1586        DRM_FORMAT_YUYV,
1587        DRM_FORMAT_YVYU,
1588        DRM_FORMAT_UYVY,
1589        DRM_FORMAT_VYUY,
1590};
1591
1592static const u32 vlv_plane_formats[] = {
1593        DRM_FORMAT_C8,
1594        DRM_FORMAT_RGB565,
1595        DRM_FORMAT_XRGB8888,
1596        DRM_FORMAT_XBGR8888,
1597        DRM_FORMAT_ARGB8888,
1598        DRM_FORMAT_ABGR8888,
1599        DRM_FORMAT_XBGR2101010,
1600        DRM_FORMAT_ABGR2101010,
1601        DRM_FORMAT_YUYV,
1602        DRM_FORMAT_YVYU,
1603        DRM_FORMAT_UYVY,
1604        DRM_FORMAT_VYUY,
1605};
1606
1607static const u32 chv_pipe_b_sprite_formats[] = {
1608        DRM_FORMAT_C8,
1609        DRM_FORMAT_RGB565,
1610        DRM_FORMAT_XRGB8888,
1611        DRM_FORMAT_XBGR8888,
1612        DRM_FORMAT_ARGB8888,
1613        DRM_FORMAT_ABGR8888,
1614        DRM_FORMAT_XRGB2101010,
1615        DRM_FORMAT_XBGR2101010,
1616        DRM_FORMAT_ARGB2101010,
1617        DRM_FORMAT_ABGR2101010,
1618        DRM_FORMAT_YUYV,
1619        DRM_FORMAT_YVYU,
1620        DRM_FORMAT_UYVY,
1621        DRM_FORMAT_VYUY,
1622};
1623
1624static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1625                                            u32 format, u64 modifier)
1626{
1627        if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1628                return false;
1629
1630        switch (format) {
1631        case DRM_FORMAT_XRGB8888:
1632        case DRM_FORMAT_YUYV:
1633        case DRM_FORMAT_YVYU:
1634        case DRM_FORMAT_UYVY:
1635        case DRM_FORMAT_VYUY:
1636                if (modifier == DRM_FORMAT_MOD_LINEAR ||
1637                    modifier == I915_FORMAT_MOD_X_TILED)
1638                        return true;
1639                fallthrough;
1640        default:
1641                return false;
1642        }
1643}
1644
1645static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1646                                            u32 format, u64 modifier)
1647{
1648        if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1649                return false;
1650
1651        switch (format) {
1652        case DRM_FORMAT_XRGB8888:
1653        case DRM_FORMAT_XBGR8888:
1654        case DRM_FORMAT_XRGB2101010:
1655        case DRM_FORMAT_XBGR2101010:
1656        case DRM_FORMAT_XRGB16161616F:
1657        case DRM_FORMAT_XBGR16161616F:
1658        case DRM_FORMAT_YUYV:
1659        case DRM_FORMAT_YVYU:
1660        case DRM_FORMAT_UYVY:
1661        case DRM_FORMAT_VYUY:
1662                if (modifier == DRM_FORMAT_MOD_LINEAR ||
1663                    modifier == I915_FORMAT_MOD_X_TILED)
1664                        return true;
1665                fallthrough;
1666        default:
1667                return false;
1668        }
1669}
1670
1671static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1672                                            u32 format, u64 modifier)
1673{
1674        if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1675                return false;
1676
1677        switch (format) {
1678        case DRM_FORMAT_C8:
1679        case DRM_FORMAT_RGB565:
1680        case DRM_FORMAT_ABGR8888:
1681        case DRM_FORMAT_ARGB8888:
1682        case DRM_FORMAT_XBGR8888:
1683        case DRM_FORMAT_XRGB8888:
1684        case DRM_FORMAT_XBGR2101010:
1685        case DRM_FORMAT_ABGR2101010:
1686        case DRM_FORMAT_XRGB2101010:
1687        case DRM_FORMAT_ARGB2101010:
1688        case DRM_FORMAT_YUYV:
1689        case DRM_FORMAT_YVYU:
1690        case DRM_FORMAT_UYVY:
1691        case DRM_FORMAT_VYUY:
1692                if (modifier == DRM_FORMAT_MOD_LINEAR ||
1693                    modifier == I915_FORMAT_MOD_X_TILED)
1694                        return true;
1695                fallthrough;
1696        default:
1697                return false;
1698        }
1699}
1700
1701static const struct drm_plane_funcs g4x_sprite_funcs = {
1702        .update_plane = drm_atomic_helper_update_plane,
1703        .disable_plane = drm_atomic_helper_disable_plane,
1704        .destroy = intel_plane_destroy,
1705        .atomic_duplicate_state = intel_plane_duplicate_state,
1706        .atomic_destroy_state = intel_plane_destroy_state,
1707        .format_mod_supported = g4x_sprite_format_mod_supported,
1708};
1709
1710static const struct drm_plane_funcs snb_sprite_funcs = {
1711        .update_plane = drm_atomic_helper_update_plane,
1712        .disable_plane = drm_atomic_helper_disable_plane,
1713        .destroy = intel_plane_destroy,
1714        .atomic_duplicate_state = intel_plane_duplicate_state,
1715        .atomic_destroy_state = intel_plane_destroy_state,
1716        .format_mod_supported = snb_sprite_format_mod_supported,
1717};
1718
1719static const struct drm_plane_funcs vlv_sprite_funcs = {
1720        .update_plane = drm_atomic_helper_update_plane,
1721        .disable_plane = drm_atomic_helper_disable_plane,
1722        .destroy = intel_plane_destroy,
1723        .atomic_duplicate_state = intel_plane_duplicate_state,
1724        .atomic_destroy_state = intel_plane_destroy_state,
1725        .format_mod_supported = vlv_sprite_format_mod_supported,
1726};
1727
1728struct intel_plane *
1729intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1730                          enum pipe pipe, int sprite)
1731{
1732        struct intel_plane *plane;
1733        const struct drm_plane_funcs *plane_funcs;
1734        unsigned int supported_rotations;
1735        const u64 *modifiers;
1736        const u32 *formats;
1737        int num_formats;
1738        int ret, zpos;
1739
1740        plane = intel_plane_alloc();
1741        if (IS_ERR(plane))
1742                return plane;
1743
1744        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1745                plane->update_plane = vlv_update_plane;
1746                plane->disable_plane = vlv_disable_plane;
1747                plane->get_hw_state = vlv_plane_get_hw_state;
1748                plane->check_plane = vlv_sprite_check;
1749                plane->max_stride = i965_plane_max_stride;
1750                plane->min_cdclk = vlv_plane_min_cdclk;
1751
1752                if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1753                        formats = chv_pipe_b_sprite_formats;
1754                        num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1755                } else {
1756                        formats = vlv_plane_formats;
1757                        num_formats = ARRAY_SIZE(vlv_plane_formats);
1758                }
1759
1760                plane_funcs = &vlv_sprite_funcs;
1761        } else if (DISPLAY_VER(dev_priv) >= 7) {
1762                plane->update_plane = ivb_update_plane;
1763                plane->disable_plane = ivb_disable_plane;
1764                plane->get_hw_state = ivb_plane_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_plane_formats;
1776                num_formats = ARRAY_SIZE(snb_plane_formats);
1777
1778                plane_funcs = &snb_sprite_funcs;
1779        } else {
1780                plane->update_plane = g4x_update_plane;
1781                plane->disable_plane = g4x_disable_plane;
1782                plane->get_hw_state = g4x_plane_get_hw_state;
1783                plane->check_plane = g4x_sprite_check;
1784                plane->max_stride = g4x_sprite_max_stride;
1785                plane->min_cdclk = g4x_sprite_min_cdclk;
1786
1787                if (IS_SANDYBRIDGE(dev_priv)) {
1788                        formats = snb_plane_formats;
1789                        num_formats = ARRAY_SIZE(snb_plane_formats);
1790
1791                        plane_funcs = &snb_sprite_funcs;
1792                } else {
1793                        formats = g4x_plane_formats;
1794                        num_formats = ARRAY_SIZE(g4x_plane_formats);
1795
1796                        plane_funcs = &g4x_sprite_funcs;
1797                }
1798        }
1799
1800        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1801                supported_rotations =
1802                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1803                        DRM_MODE_REFLECT_X;
1804        } else {
1805                supported_rotations =
1806                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1807        }
1808
1809        plane->pipe = pipe;
1810        plane->id = PLANE_SPRITE0 + sprite;
1811        plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1812
1813        modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1814
1815        ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1816                                       0, plane_funcs,
1817                                       formats, num_formats, modifiers,
1818                                       DRM_PLANE_TYPE_OVERLAY,
1819                                       "sprite %c", sprite_name(pipe, sprite));
1820        kfree(modifiers);
1821
1822        if (ret)
1823                goto fail;
1824
1825        drm_plane_create_rotation_property(&plane->base,
1826                                           DRM_MODE_ROTATE_0,
1827                                           supported_rotations);
1828
1829        drm_plane_create_color_properties(&plane->base,
1830                                          BIT(DRM_COLOR_YCBCR_BT601) |
1831                                          BIT(DRM_COLOR_YCBCR_BT709),
1832                                          BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1833                                          BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1834                                          DRM_COLOR_YCBCR_BT709,
1835                                          DRM_COLOR_YCBCR_LIMITED_RANGE);
1836
1837        zpos = sprite + 1;
1838        drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1839
1840        drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
1841
1842        return plane;
1843
1844fail:
1845        intel_plane_free(plane);
1846
1847        return ERR_PTR(ret);
1848}
1849