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