linux/drivers/gpu/drm/i915/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#include <drm/drmP.h>
  33#include <drm/drm_crtc.h>
  34#include <drm/drm_fourcc.h>
  35#include <drm/drm_rect.h>
  36#include <drm/drm_atomic.h>
  37#include <drm/drm_plane_helper.h>
  38#include "intel_drv.h"
  39#include "intel_frontbuffer.h"
  40#include <drm/i915_drm.h>
  41#include "i915_drv.h"
  42
  43static bool
  44format_is_yuv(uint32_t format)
  45{
  46        switch (format) {
  47        case DRM_FORMAT_YUYV:
  48        case DRM_FORMAT_UYVY:
  49        case DRM_FORMAT_VYUY:
  50        case DRM_FORMAT_YVYU:
  51                return true;
  52        default:
  53                return false;
  54        }
  55}
  56
  57int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
  58                             int usecs)
  59{
  60        /* paranoia */
  61        if (!adjusted_mode->crtc_htotal)
  62                return 1;
  63
  64        return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
  65                            1000 * adjusted_mode->crtc_htotal);
  66}
  67
  68/**
  69 * intel_pipe_update_start() - start update of a set of display registers
  70 * @crtc: the crtc of which the registers are going to be updated
  71 * @start_vbl_count: vblank counter return pointer used for error checking
  72 *
  73 * Mark the start of an update to pipe registers that should be updated
  74 * atomically regarding vblank. If the next vblank will happens within
  75 * the next 100 us, this function waits until the vblank passes.
  76 *
  77 * After a successful call to this function, interrupts will be disabled
  78 * until a subsequent call to intel_pipe_update_end(). That is done to
  79 * avoid random delays. The value written to @start_vbl_count should be
  80 * supplied to intel_pipe_update_end() for error checking.
  81 */
  82void intel_pipe_update_start(struct intel_crtc *crtc)
  83{
  84        const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
  85        long timeout = msecs_to_jiffies_timeout(1);
  86        int scanline, min, max, vblank_start;
  87        wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
  88        DEFINE_WAIT(wait);
  89
  90        vblank_start = adjusted_mode->crtc_vblank_start;
  91        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
  92                vblank_start = DIV_ROUND_UP(vblank_start, 2);
  93
  94        /* FIXME needs to be calibrated sensibly */
  95        min = vblank_start - intel_usecs_to_scanlines(adjusted_mode, 100);
  96        max = vblank_start - 1;
  97
  98        local_irq_disable();
  99
 100        if (min <= 0 || max <= 0)
 101                return;
 102
 103        if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
 104                return;
 105
 106        crtc->debug.min_vbl = min;
 107        crtc->debug.max_vbl = max;
 108        trace_i915_pipe_update_start(crtc);
 109
 110        for (;;) {
 111                /*
 112                 * prepare_to_wait() has a memory barrier, which guarantees
 113                 * other CPUs can see the task state update by the time we
 114                 * read the scanline.
 115                 */
 116                prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
 117
 118                scanline = intel_get_crtc_scanline(crtc);
 119                if (scanline < min || scanline > max)
 120                        break;
 121
 122                if (timeout <= 0) {
 123                        DRM_ERROR("Potential atomic update failure on pipe %c\n",
 124                                  pipe_name(crtc->pipe));
 125                        break;
 126                }
 127
 128                local_irq_enable();
 129
 130                timeout = schedule_timeout(timeout);
 131
 132                local_irq_disable();
 133        }
 134
 135        finish_wait(wq, &wait);
 136
 137        drm_crtc_vblank_put(&crtc->base);
 138
 139        crtc->debug.scanline_start = scanline;
 140        crtc->debug.start_vbl_time = ktime_get();
 141        crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
 142
 143        trace_i915_pipe_update_vblank_evaded(crtc);
 144}
 145
 146/**
 147 * intel_pipe_update_end() - end update of a set of display registers
 148 * @crtc: the crtc of which the registers were updated
 149 * @start_vbl_count: start vblank counter (used for error checking)
 150 *
 151 * Mark the end of an update started with intel_pipe_update_start(). This
 152 * re-enables interrupts and verifies the update was actually completed
 153 * before a vblank using the value of @start_vbl_count.
 154 */
 155void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work)
 156{
 157        enum pipe pipe = crtc->pipe;
 158        int scanline_end = intel_get_crtc_scanline(crtc);
 159        u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
 160        ktime_t end_vbl_time = ktime_get();
 161
 162        if (work) {
 163                work->flip_queued_vblank = end_vbl_count;
 164                smp_mb__before_atomic();
 165                atomic_set(&work->pending, 1);
 166        }
 167
 168        trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
 169
 170        /* We're still in the vblank-evade critical section, this can't race.
 171         * Would be slightly nice to just grab the vblank count and arm the
 172         * event outside of the critical section - the spinlock might spin for a
 173         * while ... */
 174        if (crtc->base.state->event) {
 175                WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
 176
 177                spin_lock(&crtc->base.dev->event_lock);
 178                drm_crtc_arm_vblank_event(&crtc->base, crtc->base.state->event);
 179                spin_unlock(&crtc->base.dev->event_lock);
 180
 181                crtc->base.state->event = NULL;
 182        }
 183
 184        local_irq_enable();
 185
 186        if (crtc->debug.start_vbl_count &&
 187            crtc->debug.start_vbl_count != end_vbl_count) {
 188                DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
 189                          pipe_name(pipe), crtc->debug.start_vbl_count,
 190                          end_vbl_count,
 191                          ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
 192                          crtc->debug.min_vbl, crtc->debug.max_vbl,
 193                          crtc->debug.scanline_start, scanline_end);
 194        }
 195}
 196
 197static void
 198skl_update_plane(struct drm_plane *drm_plane,
 199                 const struct intel_crtc_state *crtc_state,
 200                 const struct intel_plane_state *plane_state)
 201{
 202        struct drm_device *dev = drm_plane->dev;
 203        struct drm_i915_private *dev_priv = to_i915(dev);
 204        struct intel_plane *intel_plane = to_intel_plane(drm_plane);
 205        struct drm_framebuffer *fb = plane_state->base.fb;
 206        enum plane_id plane_id = intel_plane->id;
 207        enum pipe pipe = intel_plane->pipe;
 208        u32 plane_ctl;
 209        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 210        u32 surf_addr = plane_state->main.offset;
 211        unsigned int rotation = plane_state->base.rotation;
 212        u32 stride = skl_plane_stride(fb, 0, rotation);
 213        int crtc_x = plane_state->base.dst.x1;
 214        int crtc_y = plane_state->base.dst.y1;
 215        uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
 216        uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
 217        uint32_t x = plane_state->main.x;
 218        uint32_t y = plane_state->main.y;
 219        uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
 220        uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
 221
 222        plane_ctl = PLANE_CTL_ENABLE |
 223                PLANE_CTL_PIPE_GAMMA_ENABLE |
 224                PLANE_CTL_PIPE_CSC_ENABLE;
 225
 226        plane_ctl |= skl_plane_ctl_format(fb->format->format);
 227        plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
 228
 229        plane_ctl |= skl_plane_ctl_rotation(rotation);
 230
 231        if (key->flags) {
 232                I915_WRITE(PLANE_KEYVAL(pipe, plane_id), key->min_value);
 233                I915_WRITE(PLANE_KEYMAX(pipe, plane_id), key->max_value);
 234                I915_WRITE(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
 235        }
 236
 237        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 238                plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
 239        else if (key->flags & I915_SET_COLORKEY_SOURCE)
 240                plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
 241
 242        /* Sizes are 0 based */
 243        src_w--;
 244        src_h--;
 245        crtc_w--;
 246        crtc_h--;
 247
 248        I915_WRITE(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
 249        I915_WRITE(PLANE_STRIDE(pipe, plane_id), stride);
 250        I915_WRITE(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
 251
 252        /* program plane scaler */
 253        if (plane_state->scaler_id >= 0) {
 254                int scaler_id = plane_state->scaler_id;
 255                const struct intel_scaler *scaler;
 256
 257                scaler = &crtc_state->scaler_state.scalers[scaler_id];
 258
 259                I915_WRITE(SKL_PS_CTRL(pipe, scaler_id),
 260                           PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
 261                I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
 262                I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
 263                I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id),
 264                        ((crtc_w + 1) << 16)|(crtc_h + 1));
 265
 266                I915_WRITE(PLANE_POS(pipe, plane_id), 0);
 267        } else {
 268                I915_WRITE(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
 269        }
 270
 271        I915_WRITE(PLANE_CTL(pipe, plane_id), plane_ctl);
 272        I915_WRITE(PLANE_SURF(pipe, plane_id),
 273                   intel_plane_ggtt_offset(plane_state) + surf_addr);
 274        POSTING_READ(PLANE_SURF(pipe, plane_id));
 275}
 276
 277static void
 278skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 279{
 280        struct drm_device *dev = dplane->dev;
 281        struct drm_i915_private *dev_priv = to_i915(dev);
 282        struct intel_plane *intel_plane = to_intel_plane(dplane);
 283        enum plane_id plane_id = intel_plane->id;
 284        enum pipe pipe = intel_plane->pipe;
 285
 286        I915_WRITE(PLANE_CTL(pipe, plane_id), 0);
 287
 288        I915_WRITE(PLANE_SURF(pipe, plane_id), 0);
 289        POSTING_READ(PLANE_SURF(pipe, plane_id));
 290}
 291
 292static void
 293chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
 294{
 295        struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
 296        enum plane_id plane_id = intel_plane->id;
 297
 298        /* Seems RGB data bypasses the CSC always */
 299        if (!format_is_yuv(format))
 300                return;
 301
 302        /*
 303         * BT.601 limited range YCbCr -> full range RGB
 304         *
 305         * |r|   | 6537 4769     0|   |cr  |
 306         * |g| = |-3330 4769 -1605| x |y-64|
 307         * |b|   |    0 4769  8263|   |cb  |
 308         *
 309         * Cb and Cr apparently come in as signed already, so no
 310         * need for any offset. For Y we need to remove the offset.
 311         */
 312        I915_WRITE(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
 313        I915_WRITE(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 314        I915_WRITE(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 315
 316        I915_WRITE(SPCSCC01(plane_id), SPCSC_C1(4769) | SPCSC_C0(6537));
 317        I915_WRITE(SPCSCC23(plane_id), SPCSC_C1(-3330) | SPCSC_C0(0));
 318        I915_WRITE(SPCSCC45(plane_id), SPCSC_C1(-1605) | SPCSC_C0(4769));
 319        I915_WRITE(SPCSCC67(plane_id), SPCSC_C1(4769) | SPCSC_C0(0));
 320        I915_WRITE(SPCSCC8(plane_id), SPCSC_C0(8263));
 321
 322        I915_WRITE(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(940) | SPCSC_IMIN(64));
 323        I915_WRITE(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
 324        I915_WRITE(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
 325
 326        I915_WRITE(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 327        I915_WRITE(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 328        I915_WRITE(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 329}
 330
 331static void
 332vlv_update_plane(struct drm_plane *dplane,
 333                 const struct intel_crtc_state *crtc_state,
 334                 const struct intel_plane_state *plane_state)
 335{
 336        struct drm_device *dev = dplane->dev;
 337        struct drm_i915_private *dev_priv = to_i915(dev);
 338        struct intel_plane *intel_plane = to_intel_plane(dplane);
 339        struct drm_framebuffer *fb = plane_state->base.fb;
 340        enum pipe pipe = intel_plane->pipe;
 341        enum plane_id plane_id = intel_plane->id;
 342        u32 sprctl;
 343        u32 sprsurf_offset, linear_offset;
 344        unsigned int rotation = plane_state->base.rotation;
 345        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 346        int crtc_x = plane_state->base.dst.x1;
 347        int crtc_y = plane_state->base.dst.y1;
 348        uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
 349        uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
 350        uint32_t x = plane_state->base.src.x1 >> 16;
 351        uint32_t y = plane_state->base.src.y1 >> 16;
 352        uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
 353        uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
 354
 355        sprctl = SP_ENABLE;
 356
 357        switch (fb->format->format) {
 358        case DRM_FORMAT_YUYV:
 359                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
 360                break;
 361        case DRM_FORMAT_YVYU:
 362                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
 363                break;
 364        case DRM_FORMAT_UYVY:
 365                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
 366                break;
 367        case DRM_FORMAT_VYUY:
 368                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
 369                break;
 370        case DRM_FORMAT_RGB565:
 371                sprctl |= SP_FORMAT_BGR565;
 372                break;
 373        case DRM_FORMAT_XRGB8888:
 374                sprctl |= SP_FORMAT_BGRX8888;
 375                break;
 376        case DRM_FORMAT_ARGB8888:
 377                sprctl |= SP_FORMAT_BGRA8888;
 378                break;
 379        case DRM_FORMAT_XBGR2101010:
 380                sprctl |= SP_FORMAT_RGBX1010102;
 381                break;
 382        case DRM_FORMAT_ABGR2101010:
 383                sprctl |= SP_FORMAT_RGBA1010102;
 384                break;
 385        case DRM_FORMAT_XBGR8888:
 386                sprctl |= SP_FORMAT_RGBX8888;
 387                break;
 388        case DRM_FORMAT_ABGR8888:
 389                sprctl |= SP_FORMAT_RGBA8888;
 390                break;
 391        default:
 392                /*
 393                 * If we get here one of the upper layers failed to filter
 394                 * out the unsupported plane formats
 395                 */
 396                BUG();
 397                break;
 398        }
 399
 400        /*
 401         * Enable gamma to match primary/cursor plane behaviour.
 402         * FIXME should be user controllable via propertiesa.
 403         */
 404        sprctl |= SP_GAMMA_ENABLE;
 405
 406        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 407                sprctl |= SP_TILED;
 408
 409        if (rotation & DRM_ROTATE_180)
 410                sprctl |= SP_ROTATE_180;
 411
 412        if (rotation & DRM_REFLECT_X)
 413                sprctl |= SP_MIRROR;
 414
 415        /* Sizes are 0 based */
 416        src_w--;
 417        src_h--;
 418        crtc_w--;
 419        crtc_h--;
 420
 421        intel_add_fb_offsets(&x, &y, plane_state, 0);
 422        sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
 423
 424        if (rotation & DRM_ROTATE_180) {
 425                x += src_w;
 426                y += src_h;
 427        } else if (rotation & DRM_REFLECT_X) {
 428                x += src_w;
 429        }
 430
 431        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 432
 433        if (key->flags) {
 434                I915_WRITE(SPKEYMINVAL(pipe, plane_id), key->min_value);
 435                I915_WRITE(SPKEYMAXVAL(pipe, plane_id), key->max_value);
 436                I915_WRITE(SPKEYMSK(pipe, plane_id), key->channel_mask);
 437        }
 438
 439        if (key->flags & I915_SET_COLORKEY_SOURCE)
 440                sprctl |= SP_SOURCE_KEY;
 441
 442        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
 443                chv_update_csc(intel_plane, fb->format->format);
 444
 445        I915_WRITE(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
 446        I915_WRITE(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
 447
 448        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 449                I915_WRITE(SPTILEOFF(pipe, plane_id), (y << 16) | x);
 450        else
 451                I915_WRITE(SPLINOFF(pipe, plane_id), linear_offset);
 452
 453        I915_WRITE(SPCONSTALPHA(pipe, plane_id), 0);
 454
 455        I915_WRITE(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
 456        I915_WRITE(SPCNTR(pipe, plane_id), sprctl);
 457        I915_WRITE(SPSURF(pipe, plane_id),
 458                   intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 459        POSTING_READ(SPSURF(pipe, plane_id));
 460}
 461
 462static void
 463vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 464{
 465        struct drm_device *dev = dplane->dev;
 466        struct drm_i915_private *dev_priv = to_i915(dev);
 467        struct intel_plane *intel_plane = to_intel_plane(dplane);
 468        enum pipe pipe = intel_plane->pipe;
 469        enum plane_id plane_id = intel_plane->id;
 470
 471        I915_WRITE(SPCNTR(pipe, plane_id), 0);
 472
 473        I915_WRITE(SPSURF(pipe, plane_id), 0);
 474        POSTING_READ(SPSURF(pipe, plane_id));
 475}
 476
 477static void
 478ivb_update_plane(struct drm_plane *plane,
 479                 const struct intel_crtc_state *crtc_state,
 480                 const struct intel_plane_state *plane_state)
 481{
 482        struct drm_device *dev = plane->dev;
 483        struct drm_i915_private *dev_priv = to_i915(dev);
 484        struct intel_plane *intel_plane = to_intel_plane(plane);
 485        struct drm_framebuffer *fb = plane_state->base.fb;
 486        enum pipe pipe = intel_plane->pipe;
 487        u32 sprctl, sprscale = 0;
 488        u32 sprsurf_offset, linear_offset;
 489        unsigned int rotation = plane_state->base.rotation;
 490        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 491        int crtc_x = plane_state->base.dst.x1;
 492        int crtc_y = plane_state->base.dst.y1;
 493        uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
 494        uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
 495        uint32_t x = plane_state->base.src.x1 >> 16;
 496        uint32_t y = plane_state->base.src.y1 >> 16;
 497        uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
 498        uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
 499
 500        sprctl = SPRITE_ENABLE;
 501
 502        switch (fb->format->format) {
 503        case DRM_FORMAT_XBGR8888:
 504                sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
 505                break;
 506        case DRM_FORMAT_XRGB8888:
 507                sprctl |= SPRITE_FORMAT_RGBX888;
 508                break;
 509        case DRM_FORMAT_YUYV:
 510                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
 511                break;
 512        case DRM_FORMAT_YVYU:
 513                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
 514                break;
 515        case DRM_FORMAT_UYVY:
 516                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
 517                break;
 518        case DRM_FORMAT_VYUY:
 519                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
 520                break;
 521        default:
 522                BUG();
 523        }
 524
 525        /*
 526         * Enable gamma to match primary/cursor plane behaviour.
 527         * FIXME should be user controllable via propertiesa.
 528         */
 529        sprctl |= SPRITE_GAMMA_ENABLE;
 530
 531        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 532                sprctl |= SPRITE_TILED;
 533
 534        if (rotation & DRM_ROTATE_180)
 535                sprctl |= SPRITE_ROTATE_180;
 536
 537        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 538                sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
 539        else
 540                sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
 541
 542        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 543                sprctl |= SPRITE_PIPE_CSC_ENABLE;
 544
 545        /* Sizes are 0 based */
 546        src_w--;
 547        src_h--;
 548        crtc_w--;
 549        crtc_h--;
 550
 551        if (crtc_w != src_w || crtc_h != src_h)
 552                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 553
 554        intel_add_fb_offsets(&x, &y, plane_state, 0);
 555        sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
 556
 557        /* HSW+ does this automagically in hardware */
 558        if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv) &&
 559            rotation & DRM_ROTATE_180) {
 560                x += src_w;
 561                y += src_h;
 562        }
 563
 564        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 565
 566        if (key->flags) {
 567                I915_WRITE(SPRKEYVAL(pipe), key->min_value);
 568                I915_WRITE(SPRKEYMAX(pipe), key->max_value);
 569                I915_WRITE(SPRKEYMSK(pipe), key->channel_mask);
 570        }
 571
 572        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 573                sprctl |= SPRITE_DEST_KEY;
 574        else if (key->flags & I915_SET_COLORKEY_SOURCE)
 575                sprctl |= SPRITE_SOURCE_KEY;
 576
 577        I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
 578        I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 579
 580        /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
 581         * register */
 582        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 583                I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
 584        else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 585                I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
 586        else
 587                I915_WRITE(SPRLINOFF(pipe), linear_offset);
 588
 589        I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
 590        if (intel_plane->can_scale)
 591                I915_WRITE(SPRSCALE(pipe), sprscale);
 592        I915_WRITE(SPRCTL(pipe), sprctl);
 593        I915_WRITE(SPRSURF(pipe),
 594                   intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 595        POSTING_READ(SPRSURF(pipe));
 596}
 597
 598static void
 599ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 600{
 601        struct drm_device *dev = plane->dev;
 602        struct drm_i915_private *dev_priv = to_i915(dev);
 603        struct intel_plane *intel_plane = to_intel_plane(plane);
 604        int pipe = intel_plane->pipe;
 605
 606        I915_WRITE(SPRCTL(pipe), 0);
 607        /* Can't leave the scaler enabled... */
 608        if (intel_plane->can_scale)
 609                I915_WRITE(SPRSCALE(pipe), 0);
 610
 611        I915_WRITE(SPRSURF(pipe), 0);
 612        POSTING_READ(SPRSURF(pipe));
 613}
 614
 615static void
 616ilk_update_plane(struct drm_plane *plane,
 617                 const struct intel_crtc_state *crtc_state,
 618                 const struct intel_plane_state *plane_state)
 619{
 620        struct drm_device *dev = plane->dev;
 621        struct drm_i915_private *dev_priv = to_i915(dev);
 622        struct intel_plane *intel_plane = to_intel_plane(plane);
 623        struct drm_framebuffer *fb = plane_state->base.fb;
 624        int pipe = intel_plane->pipe;
 625        u32 dvscntr, dvsscale;
 626        u32 dvssurf_offset, linear_offset;
 627        unsigned int rotation = plane_state->base.rotation;
 628        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 629        int crtc_x = plane_state->base.dst.x1;
 630        int crtc_y = plane_state->base.dst.y1;
 631        uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
 632        uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
 633        uint32_t x = plane_state->base.src.x1 >> 16;
 634        uint32_t y = plane_state->base.src.y1 >> 16;
 635        uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
 636        uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
 637
 638        dvscntr = DVS_ENABLE;
 639
 640        switch (fb->format->format) {
 641        case DRM_FORMAT_XBGR8888:
 642                dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
 643                break;
 644        case DRM_FORMAT_XRGB8888:
 645                dvscntr |= DVS_FORMAT_RGBX888;
 646                break;
 647        case DRM_FORMAT_YUYV:
 648                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
 649                break;
 650        case DRM_FORMAT_YVYU:
 651                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
 652                break;
 653        case DRM_FORMAT_UYVY:
 654                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
 655                break;
 656        case DRM_FORMAT_VYUY:
 657                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
 658                break;
 659        default:
 660                BUG();
 661        }
 662
 663        /*
 664         * Enable gamma to match primary/cursor plane behaviour.
 665         * FIXME should be user controllable via propertiesa.
 666         */
 667        dvscntr |= DVS_GAMMA_ENABLE;
 668
 669        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 670                dvscntr |= DVS_TILED;
 671
 672        if (rotation & DRM_ROTATE_180)
 673                dvscntr |= DVS_ROTATE_180;
 674
 675        if (IS_GEN6(dev_priv))
 676                dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 677
 678        /* Sizes are 0 based */
 679        src_w--;
 680        src_h--;
 681        crtc_w--;
 682        crtc_h--;
 683
 684        dvsscale = 0;
 685        if (crtc_w != src_w || crtc_h != src_h)
 686                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 687
 688        intel_add_fb_offsets(&x, &y, plane_state, 0);
 689        dvssurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
 690
 691        if (rotation & DRM_ROTATE_180) {
 692                x += src_w;
 693                y += src_h;
 694        }
 695
 696        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 697
 698        if (key->flags) {
 699                I915_WRITE(DVSKEYVAL(pipe), key->min_value);
 700                I915_WRITE(DVSKEYMAX(pipe), key->max_value);
 701                I915_WRITE(DVSKEYMSK(pipe), key->channel_mask);
 702        }
 703
 704        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 705                dvscntr |= DVS_DEST_KEY;
 706        else if (key->flags & I915_SET_COLORKEY_SOURCE)
 707                dvscntr |= DVS_SOURCE_KEY;
 708
 709        I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
 710        I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
 711
 712        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 713                I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
 714        else
 715                I915_WRITE(DVSLINOFF(pipe), linear_offset);
 716
 717        I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
 718        I915_WRITE(DVSSCALE(pipe), dvsscale);
 719        I915_WRITE(DVSCNTR(pipe), dvscntr);
 720        I915_WRITE(DVSSURF(pipe),
 721                   intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
 722        POSTING_READ(DVSSURF(pipe));
 723}
 724
 725static void
 726ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 727{
 728        struct drm_device *dev = plane->dev;
 729        struct drm_i915_private *dev_priv = to_i915(dev);
 730        struct intel_plane *intel_plane = to_intel_plane(plane);
 731        int pipe = intel_plane->pipe;
 732
 733        I915_WRITE(DVSCNTR(pipe), 0);
 734        /* Disable the scaler */
 735        I915_WRITE(DVSSCALE(pipe), 0);
 736
 737        I915_WRITE(DVSSURF(pipe), 0);
 738        POSTING_READ(DVSSURF(pipe));
 739}
 740
 741static int
 742intel_check_sprite_plane(struct drm_plane *plane,
 743                         struct intel_crtc_state *crtc_state,
 744                         struct intel_plane_state *state)
 745{
 746        struct drm_i915_private *dev_priv = to_i915(plane->dev);
 747        struct drm_crtc *crtc = state->base.crtc;
 748        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 749        struct intel_plane *intel_plane = to_intel_plane(plane);
 750        struct drm_framebuffer *fb = state->base.fb;
 751        int crtc_x, crtc_y;
 752        unsigned int crtc_w, crtc_h;
 753        uint32_t src_x, src_y, src_w, src_h;
 754        struct drm_rect *src = &state->base.src;
 755        struct drm_rect *dst = &state->base.dst;
 756        const struct drm_rect *clip = &state->clip;
 757        int hscale, vscale;
 758        int max_scale, min_scale;
 759        bool can_scale;
 760        int ret;
 761
 762        *src = drm_plane_state_src(&state->base);
 763        *dst = drm_plane_state_dest(&state->base);
 764
 765        if (!fb) {
 766                state->base.visible = false;
 767                return 0;
 768        }
 769
 770        /* Don't modify another pipe's plane */
 771        if (intel_plane->pipe != intel_crtc->pipe) {
 772                DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
 773                return -EINVAL;
 774        }
 775
 776        /* FIXME check all gen limits */
 777        if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
 778                DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
 779                return -EINVAL;
 780        }
 781
 782        /* setup can_scale, min_scale, max_scale */
 783        if (INTEL_GEN(dev_priv) >= 9) {
 784                /* use scaler when colorkey is not required */
 785                if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
 786                        can_scale = 1;
 787                        min_scale = 1;
 788                        max_scale = skl_max_scale(intel_crtc, crtc_state);
 789                } else {
 790                        can_scale = 0;
 791                        min_scale = DRM_PLANE_HELPER_NO_SCALING;
 792                        max_scale = DRM_PLANE_HELPER_NO_SCALING;
 793                }
 794        } else {
 795                can_scale = intel_plane->can_scale;
 796                max_scale = intel_plane->max_downscale << 16;
 797                min_scale = intel_plane->can_scale ? 1 : (1 << 16);
 798        }
 799
 800        /*
 801         * FIXME the following code does a bunch of fuzzy adjustments to the
 802         * coordinates and sizes. We probably need some way to decide whether
 803         * more strict checking should be done instead.
 804         */
 805        drm_rect_rotate(src, fb->width << 16, fb->height << 16,
 806                        state->base.rotation);
 807
 808        hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
 809        BUG_ON(hscale < 0);
 810
 811        vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
 812        BUG_ON(vscale < 0);
 813
 814        state->base.visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
 815
 816        crtc_x = dst->x1;
 817        crtc_y = dst->y1;
 818        crtc_w = drm_rect_width(dst);
 819        crtc_h = drm_rect_height(dst);
 820
 821        if (state->base.visible) {
 822                /* check again in case clipping clamped the results */
 823                hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
 824                if (hscale < 0) {
 825                        DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
 826                        drm_rect_debug_print("src: ", src, true);
 827                        drm_rect_debug_print("dst: ", dst, false);
 828
 829                        return hscale;
 830                }
 831
 832                vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
 833                if (vscale < 0) {
 834                        DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
 835                        drm_rect_debug_print("src: ", src, true);
 836                        drm_rect_debug_print("dst: ", dst, false);
 837
 838                        return vscale;
 839                }
 840
 841                /* Make the source viewport size an exact multiple of the scaling factors. */
 842                drm_rect_adjust_size(src,
 843                                     drm_rect_width(dst) * hscale - drm_rect_width(src),
 844                                     drm_rect_height(dst) * vscale - drm_rect_height(src));
 845
 846                drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
 847                                    state->base.rotation);
 848
 849                /* sanity check to make sure the src viewport wasn't enlarged */
 850                WARN_ON(src->x1 < (int) state->base.src_x ||
 851                        src->y1 < (int) state->base.src_y ||
 852                        src->x2 > (int) state->base.src_x + state->base.src_w ||
 853                        src->y2 > (int) state->base.src_y + state->base.src_h);
 854
 855                /*
 856                 * Hardware doesn't handle subpixel coordinates.
 857                 * Adjust to (macro)pixel boundary, but be careful not to
 858                 * increase the source viewport size, because that could
 859                 * push the downscaling factor out of bounds.
 860                 */
 861                src_x = src->x1 >> 16;
 862                src_w = drm_rect_width(src) >> 16;
 863                src_y = src->y1 >> 16;
 864                src_h = drm_rect_height(src) >> 16;
 865
 866                if (format_is_yuv(fb->format->format)) {
 867                        src_x &= ~1;
 868                        src_w &= ~1;
 869
 870                        /*
 871                         * Must keep src and dst the
 872                         * same if we can't scale.
 873                         */
 874                        if (!can_scale)
 875                                crtc_w &= ~1;
 876
 877                        if (crtc_w == 0)
 878                                state->base.visible = false;
 879                }
 880        }
 881
 882        /* Check size restrictions when scaling */
 883        if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) {
 884                unsigned int width_bytes;
 885                int cpp = fb->format->cpp[0];
 886
 887                WARN_ON(!can_scale);
 888
 889                /* FIXME interlacing min height is 6 */
 890
 891                if (crtc_w < 3 || crtc_h < 3)
 892                        state->base.visible = false;
 893
 894                if (src_w < 3 || src_h < 3)
 895                        state->base.visible = false;
 896
 897                width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
 898
 899                if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
 900                    width_bytes > 4096 || fb->pitches[0] > 4096)) {
 901                        DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
 902                        return -EINVAL;
 903                }
 904        }
 905
 906        if (state->base.visible) {
 907                src->x1 = src_x << 16;
 908                src->x2 = (src_x + src_w) << 16;
 909                src->y1 = src_y << 16;
 910                src->y2 = (src_y + src_h) << 16;
 911        }
 912
 913        dst->x1 = crtc_x;
 914        dst->x2 = crtc_x + crtc_w;
 915        dst->y1 = crtc_y;
 916        dst->y2 = crtc_y + crtc_h;
 917
 918        if (INTEL_GEN(dev_priv) >= 9) {
 919                ret = skl_check_plane_surface(state);
 920                if (ret)
 921                        return ret;
 922        }
 923
 924        return 0;
 925}
 926
 927int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 928                              struct drm_file *file_priv)
 929{
 930        struct drm_i915_private *dev_priv = to_i915(dev);
 931        struct drm_intel_sprite_colorkey *set = data;
 932        struct drm_plane *plane;
 933        struct drm_plane_state *plane_state;
 934        struct drm_atomic_state *state;
 935        struct drm_modeset_acquire_ctx ctx;
 936        int ret = 0;
 937
 938        /* Make sure we don't try to enable both src & dest simultaneously */
 939        if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
 940                return -EINVAL;
 941
 942        if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 943            set->flags & I915_SET_COLORKEY_DESTINATION)
 944                return -EINVAL;
 945
 946        plane = drm_plane_find(dev, set->plane_id);
 947        if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
 948                return -ENOENT;
 949
 950        drm_modeset_acquire_init(&ctx, 0);
 951
 952        state = drm_atomic_state_alloc(plane->dev);
 953        if (!state) {
 954                ret = -ENOMEM;
 955                goto out;
 956        }
 957        state->acquire_ctx = &ctx;
 958
 959        while (1) {
 960                plane_state = drm_atomic_get_plane_state(state, plane);
 961                ret = PTR_ERR_OR_ZERO(plane_state);
 962                if (!ret) {
 963                        to_intel_plane_state(plane_state)->ckey = *set;
 964                        ret = drm_atomic_commit(state);
 965                }
 966
 967                if (ret != -EDEADLK)
 968                        break;
 969
 970                drm_atomic_state_clear(state);
 971                drm_modeset_backoff(&ctx);
 972        }
 973
 974        drm_atomic_state_put(state);
 975out:
 976        drm_modeset_drop_locks(&ctx);
 977        drm_modeset_acquire_fini(&ctx);
 978        return ret;
 979}
 980
 981static const uint32_t ilk_plane_formats[] = {
 982        DRM_FORMAT_XRGB8888,
 983        DRM_FORMAT_YUYV,
 984        DRM_FORMAT_YVYU,
 985        DRM_FORMAT_UYVY,
 986        DRM_FORMAT_VYUY,
 987};
 988
 989static const uint32_t snb_plane_formats[] = {
 990        DRM_FORMAT_XBGR8888,
 991        DRM_FORMAT_XRGB8888,
 992        DRM_FORMAT_YUYV,
 993        DRM_FORMAT_YVYU,
 994        DRM_FORMAT_UYVY,
 995        DRM_FORMAT_VYUY,
 996};
 997
 998static const uint32_t vlv_plane_formats[] = {
 999        DRM_FORMAT_RGB565,
1000        DRM_FORMAT_ABGR8888,
1001        DRM_FORMAT_ARGB8888,
1002        DRM_FORMAT_XBGR8888,
1003        DRM_FORMAT_XRGB8888,
1004        DRM_FORMAT_XBGR2101010,
1005        DRM_FORMAT_ABGR2101010,
1006        DRM_FORMAT_YUYV,
1007        DRM_FORMAT_YVYU,
1008        DRM_FORMAT_UYVY,
1009        DRM_FORMAT_VYUY,
1010};
1011
1012static uint32_t skl_plane_formats[] = {
1013        DRM_FORMAT_RGB565,
1014        DRM_FORMAT_ABGR8888,
1015        DRM_FORMAT_ARGB8888,
1016        DRM_FORMAT_XBGR8888,
1017        DRM_FORMAT_XRGB8888,
1018        DRM_FORMAT_YUYV,
1019        DRM_FORMAT_YVYU,
1020        DRM_FORMAT_UYVY,
1021        DRM_FORMAT_VYUY,
1022};
1023
1024struct intel_plane *
1025intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1026                          enum pipe pipe, int plane)
1027{
1028        struct intel_plane *intel_plane = NULL;
1029        struct intel_plane_state *state = NULL;
1030        unsigned long possible_crtcs;
1031        const uint32_t *plane_formats;
1032        unsigned int supported_rotations;
1033        int num_plane_formats;
1034        int ret;
1035
1036        intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1037        if (!intel_plane) {
1038                ret = -ENOMEM;
1039                goto fail;
1040        }
1041
1042        state = intel_create_plane_state(&intel_plane->base);
1043        if (!state) {
1044                ret = -ENOMEM;
1045                goto fail;
1046        }
1047        intel_plane->base.state = &state->base;
1048
1049        if (INTEL_GEN(dev_priv) >= 9) {
1050                intel_plane->can_scale = true;
1051                state->scaler_id = -1;
1052
1053                intel_plane->update_plane = skl_update_plane;
1054                intel_plane->disable_plane = skl_disable_plane;
1055
1056                plane_formats = skl_plane_formats;
1057                num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1058        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1059                intel_plane->can_scale = false;
1060                intel_plane->max_downscale = 1;
1061
1062                intel_plane->update_plane = vlv_update_plane;
1063                intel_plane->disable_plane = vlv_disable_plane;
1064
1065                plane_formats = vlv_plane_formats;
1066                num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1067        } else if (INTEL_GEN(dev_priv) >= 7) {
1068                if (IS_IVYBRIDGE(dev_priv)) {
1069                        intel_plane->can_scale = true;
1070                        intel_plane->max_downscale = 2;
1071                } else {
1072                        intel_plane->can_scale = false;
1073                        intel_plane->max_downscale = 1;
1074                }
1075
1076                intel_plane->update_plane = ivb_update_plane;
1077                intel_plane->disable_plane = ivb_disable_plane;
1078
1079                plane_formats = snb_plane_formats;
1080                num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1081        } else {
1082                intel_plane->can_scale = true;
1083                intel_plane->max_downscale = 16;
1084
1085                intel_plane->update_plane = ilk_update_plane;
1086                intel_plane->disable_plane = ilk_disable_plane;
1087
1088                if (IS_GEN6(dev_priv)) {
1089                        plane_formats = snb_plane_formats;
1090                        num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1091                } else {
1092                        plane_formats = ilk_plane_formats;
1093                        num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1094                }
1095        }
1096
1097        if (INTEL_GEN(dev_priv) >= 9) {
1098                supported_rotations =
1099                        DRM_ROTATE_0 | DRM_ROTATE_90 |
1100                        DRM_ROTATE_180 | DRM_ROTATE_270;
1101        } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1102                supported_rotations =
1103                        DRM_ROTATE_0 | DRM_ROTATE_180 |
1104                        DRM_REFLECT_X;
1105        } else {
1106                supported_rotations =
1107                        DRM_ROTATE_0 | DRM_ROTATE_180;
1108        }
1109
1110        intel_plane->pipe = pipe;
1111        intel_plane->plane = plane;
1112        intel_plane->id = PLANE_SPRITE0 + plane;
1113        intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
1114        intel_plane->check_plane = intel_check_sprite_plane;
1115
1116        possible_crtcs = (1 << pipe);
1117
1118        if (INTEL_GEN(dev_priv) >= 9)
1119                ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1120                                               possible_crtcs, &intel_plane_funcs,
1121                                               plane_formats, num_plane_formats,
1122                                               DRM_PLANE_TYPE_OVERLAY,
1123                                               "plane %d%c", plane + 2, pipe_name(pipe));
1124        else
1125                ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
1126                                               possible_crtcs, &intel_plane_funcs,
1127                                               plane_formats, num_plane_formats,
1128                                               DRM_PLANE_TYPE_OVERLAY,
1129                                               "sprite %c", sprite_name(pipe, plane));
1130        if (ret)
1131                goto fail;
1132
1133        drm_plane_create_rotation_property(&intel_plane->base,
1134                                           DRM_ROTATE_0,
1135                                           supported_rotations);
1136
1137        drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
1138
1139        return intel_plane;
1140
1141fail:
1142        kfree(state);
1143        kfree(intel_plane);
1144
1145        return ERR_PTR(ret);
1146}
1147