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 "intel_drv.h"
  37#include <drm/i915_drm.h>
  38#include "i915_drv.h"
  39
  40static bool
  41format_is_yuv(uint32_t format)
  42{
  43        switch (format) {
  44        case DRM_FORMAT_YUYV:
  45        case DRM_FORMAT_UYVY:
  46        case DRM_FORMAT_VYUY:
  47        case DRM_FORMAT_YVYU:
  48                return true;
  49        default:
  50                return false;
  51        }
  52}
  53
  54static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs)
  55{
  56        /* paranoia */
  57        if (!mode->crtc_htotal)
  58                return 1;
  59
  60        return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal);
  61}
  62
  63/**
  64 * intel_pipe_update_start() - start update of a set of display registers
  65 * @crtc: the crtc of which the registers are going to be updated
  66 * @start_vbl_count: vblank counter return pointer used for error checking
  67 *
  68 * Mark the start of an update to pipe registers that should be updated
  69 * atomically regarding vblank. If the next vblank will happens within
  70 * the next 100 us, this function waits until the vblank passes.
  71 *
  72 * After a successful call to this function, interrupts will be disabled
  73 * until a subsequent call to intel_pipe_update_end(). That is done to
  74 * avoid random delays. The value written to @start_vbl_count should be
  75 * supplied to intel_pipe_update_end() for error checking.
  76 *
  77 * Return: true if the call was successful
  78 */
  79bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count)
  80{
  81        struct drm_device *dev = crtc->base.dev;
  82        const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
  83        enum pipe pipe = crtc->pipe;
  84        long timeout = msecs_to_jiffies_timeout(1);
  85        int scanline, min, max, vblank_start;
  86        wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
  87        DEFINE_WAIT(wait);
  88
  89        vblank_start = mode->crtc_vblank_start;
  90        if (mode->flags & DRM_MODE_FLAG_INTERLACE)
  91                vblank_start = DIV_ROUND_UP(vblank_start, 2);
  92
  93        /* FIXME needs to be calibrated sensibly */
  94        min = vblank_start - usecs_to_scanlines(mode, 100);
  95        max = vblank_start - 1;
  96
  97        if (min <= 0 || max <= 0)
  98                return false;
  99
 100        if (WARN_ON(drm_vblank_get(dev, pipe)))
 101                return false;
 102
 103        local_irq_disable();
 104
 105        trace_i915_pipe_update_start(crtc, min, max);
 106
 107        for (;;) {
 108                /*
 109                 * prepare_to_wait() has a memory barrier, which guarantees
 110                 * other CPUs can see the task state update by the time we
 111                 * read the scanline.
 112                 */
 113                prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
 114
 115                scanline = intel_get_crtc_scanline(crtc);
 116                if (scanline < min || scanline > max)
 117                        break;
 118
 119                if (timeout <= 0) {
 120                        DRM_ERROR("Potential atomic update failure on pipe %c\n",
 121                                  pipe_name(crtc->pipe));
 122                        break;
 123                }
 124
 125                local_irq_enable();
 126
 127                timeout = schedule_timeout(timeout);
 128
 129                local_irq_disable();
 130        }
 131
 132        finish_wait(wq, &wait);
 133
 134        drm_vblank_put(dev, pipe);
 135
 136        *start_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
 137
 138        trace_i915_pipe_update_vblank_evaded(crtc, min, max, *start_vbl_count);
 139
 140        return true;
 141}
 142
 143/**
 144 * intel_pipe_update_end() - end update of a set of display registers
 145 * @crtc: the crtc of which the registers were updated
 146 * @start_vbl_count: start vblank counter (used for error checking)
 147 *
 148 * Mark the end of an update started with intel_pipe_update_start(). This
 149 * re-enables interrupts and verifies the update was actually completed
 150 * before a vblank using the value of @start_vbl_count.
 151 */
 152void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count)
 153{
 154        struct drm_device *dev = crtc->base.dev;
 155        enum pipe pipe = crtc->pipe;
 156        u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe);
 157
 158        trace_i915_pipe_update_end(crtc, end_vbl_count);
 159
 160        local_irq_enable();
 161
 162        if (start_vbl_count != end_vbl_count)
 163                DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u)\n",
 164                          pipe_name(pipe), start_vbl_count, end_vbl_count);
 165}
 166
 167static void intel_update_primary_plane(struct intel_crtc *crtc)
 168{
 169        struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 170        int reg = DSPCNTR(crtc->plane);
 171
 172        if (crtc->primary_enabled)
 173                I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
 174        else
 175                I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
 176}
 177
 178static void
 179skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 180                 struct drm_framebuffer *fb,
 181                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 182                 unsigned int crtc_w, unsigned int crtc_h,
 183                 uint32_t x, uint32_t y,
 184                 uint32_t src_w, uint32_t src_h)
 185{
 186        struct drm_device *dev = drm_plane->dev;
 187        struct drm_i915_private *dev_priv = dev->dev_private;
 188        struct intel_plane *intel_plane = to_intel_plane(drm_plane);
 189        const int pipe = intel_plane->pipe;
 190        const int plane = intel_plane->plane + 1;
 191        u32 plane_ctl, stride;
 192        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 193
 194        plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
 195
 196        /* Mask out pixel format bits in case we change it */
 197        plane_ctl &= ~PLANE_CTL_FORMAT_MASK;
 198        plane_ctl &= ~PLANE_CTL_ORDER_RGBX;
 199        plane_ctl &= ~PLANE_CTL_YUV422_ORDER_MASK;
 200        plane_ctl &= ~PLANE_CTL_TILED_MASK;
 201        plane_ctl &= ~PLANE_CTL_ALPHA_MASK;
 202        plane_ctl &= ~PLANE_CTL_ROTATE_MASK;
 203
 204        /* Trickle feed has to be enabled */
 205        plane_ctl &= ~PLANE_CTL_TRICKLE_FEED_DISABLE;
 206
 207        switch (fb->pixel_format) {
 208        case DRM_FORMAT_RGB565:
 209                plane_ctl |= PLANE_CTL_FORMAT_RGB_565;
 210                break;
 211        case DRM_FORMAT_XBGR8888:
 212                plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
 213                break;
 214        case DRM_FORMAT_XRGB8888:
 215                plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888;
 216                break;
 217        /*
 218         * XXX: For ARBG/ABGR formats we default to expecting scanout buffers
 219         * to be already pre-multiplied. We need to add a knob (or a different
 220         * DRM_FORMAT) for user-space to configure that.
 221         */
 222        case DRM_FORMAT_ABGR8888:
 223                plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
 224                             PLANE_CTL_ORDER_RGBX |
 225                             PLANE_CTL_ALPHA_SW_PREMULTIPLY;
 226                break;
 227        case DRM_FORMAT_ARGB8888:
 228                plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888 |
 229                             PLANE_CTL_ALPHA_SW_PREMULTIPLY;
 230                break;
 231        case DRM_FORMAT_YUYV:
 232                plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
 233                break;
 234        case DRM_FORMAT_YVYU:
 235                plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YVYU;
 236                break;
 237        case DRM_FORMAT_UYVY:
 238                plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_UYVY;
 239                break;
 240        case DRM_FORMAT_VYUY:
 241                plane_ctl |= PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
 242                break;
 243        default:
 244                BUG();
 245        }
 246
 247        switch (obj->tiling_mode) {
 248        case I915_TILING_NONE:
 249                stride = fb->pitches[0] >> 6;
 250                break;
 251        case I915_TILING_X:
 252                plane_ctl |= PLANE_CTL_TILED_X;
 253                stride = fb->pitches[0] >> 9;
 254                break;
 255        default:
 256                BUG();
 257        }
 258        if (intel_plane->rotation == BIT(DRM_ROTATE_180))
 259                plane_ctl |= PLANE_CTL_ROTATE_180;
 260
 261        plane_ctl |= PLANE_CTL_ENABLE;
 262        plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
 263
 264        intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h,
 265                                       pixel_size, true,
 266                                       src_w != crtc_w || src_h != crtc_h);
 267
 268        /* Sizes are 0 based */
 269        src_w--;
 270        src_h--;
 271        crtc_w--;
 272        crtc_h--;
 273
 274        I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
 275        I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
 276        I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
 277        I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
 278        I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
 279        I915_WRITE(PLANE_SURF(pipe, plane), i915_gem_obj_ggtt_offset(obj));
 280        POSTING_READ(PLANE_SURF(pipe, plane));
 281}
 282
 283static void
 284skl_disable_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc)
 285{
 286        struct drm_device *dev = drm_plane->dev;
 287        struct drm_i915_private *dev_priv = dev->dev_private;
 288        struct intel_plane *intel_plane = to_intel_plane(drm_plane);
 289        const int pipe = intel_plane->pipe;
 290        const int plane = intel_plane->plane + 1;
 291
 292        I915_WRITE(PLANE_CTL(pipe, plane),
 293                   I915_READ(PLANE_CTL(pipe, plane)) & ~PLANE_CTL_ENABLE);
 294
 295        /* Activate double buffered register update */
 296        I915_WRITE(PLANE_CTL(pipe, plane), 0);
 297        POSTING_READ(PLANE_CTL(pipe, plane));
 298
 299        intel_update_sprite_watermarks(drm_plane, crtc, 0, 0, 0, false, false);
 300}
 301
 302static int
 303skl_update_colorkey(struct drm_plane *drm_plane,
 304                    struct drm_intel_sprite_colorkey *key)
 305{
 306        struct drm_device *dev = drm_plane->dev;
 307        struct drm_i915_private *dev_priv = dev->dev_private;
 308        struct intel_plane *intel_plane = to_intel_plane(drm_plane);
 309        const int pipe = intel_plane->pipe;
 310        const int plane = intel_plane->plane;
 311        u32 plane_ctl;
 312
 313        I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
 314        I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
 315        I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
 316
 317        plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
 318        plane_ctl &= ~PLANE_CTL_KEY_ENABLE_MASK;
 319        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 320                plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
 321        else if (key->flags & I915_SET_COLORKEY_SOURCE)
 322                plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
 323        I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
 324
 325        POSTING_READ(PLANE_CTL(pipe, plane));
 326
 327        return 0;
 328}
 329
 330static void
 331skl_get_colorkey(struct drm_plane *drm_plane,
 332                 struct drm_intel_sprite_colorkey *key)
 333{
 334        struct drm_device *dev = drm_plane->dev;
 335        struct drm_i915_private *dev_priv = dev->dev_private;
 336        struct intel_plane *intel_plane = to_intel_plane(drm_plane);
 337        const int pipe = intel_plane->pipe;
 338        const int plane = intel_plane->plane;
 339        u32 plane_ctl;
 340
 341        key->min_value = I915_READ(PLANE_KEYVAL(pipe, plane));
 342        key->max_value = I915_READ(PLANE_KEYMAX(pipe, plane));
 343        key->channel_mask = I915_READ(PLANE_KEYMSK(pipe, plane));
 344
 345        plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
 346
 347        switch (plane_ctl & PLANE_CTL_KEY_ENABLE_MASK) {
 348        case PLANE_CTL_KEY_ENABLE_DESTINATION:
 349                key->flags = I915_SET_COLORKEY_DESTINATION;
 350                break;
 351        case PLANE_CTL_KEY_ENABLE_SOURCE:
 352                key->flags = I915_SET_COLORKEY_SOURCE;
 353                break;
 354        default:
 355                key->flags = I915_SET_COLORKEY_NONE;
 356        }
 357}
 358
 359static void
 360chv_update_csc(struct intel_plane *intel_plane, uint32_t format)
 361{
 362        struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private;
 363        int plane = intel_plane->plane;
 364
 365        /* Seems RGB data bypasses the CSC always */
 366        if (!format_is_yuv(format))
 367                return;
 368
 369        /*
 370         * BT.601 limited range YCbCr -> full range RGB
 371         *
 372         * |r|   | 6537 4769     0|   |cr  |
 373         * |g| = |-3330 4769 -1605| x |y-64|
 374         * |b|   |    0 4769  8263|   |cb  |
 375         *
 376         * Cb and Cr apparently come in as signed already, so no
 377         * need for any offset. For Y we need to remove the offset.
 378         */
 379        I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64));
 380        I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 381        I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 382
 383        I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537));
 384        I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0));
 385        I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769));
 386        I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0));
 387        I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263));
 388
 389        I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64));
 390        I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
 391        I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448));
 392
 393        I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 394        I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 395        I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 396}
 397
 398static void
 399vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
 400                 struct drm_framebuffer *fb,
 401                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 402                 unsigned int crtc_w, unsigned int crtc_h,
 403                 uint32_t x, uint32_t y,
 404                 uint32_t src_w, uint32_t src_h)
 405{
 406        struct drm_device *dev = dplane->dev;
 407        struct drm_i915_private *dev_priv = dev->dev_private;
 408        struct intel_plane *intel_plane = to_intel_plane(dplane);
 409        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 410        int pipe = intel_plane->pipe;
 411        int plane = intel_plane->plane;
 412        u32 sprctl;
 413        unsigned long sprsurf_offset, linear_offset;
 414        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 415        u32 start_vbl_count;
 416        bool atomic_update;
 417
 418        sprctl = I915_READ(SPCNTR(pipe, plane));
 419
 420        /* Mask out pixel format bits in case we change it */
 421        sprctl &= ~SP_PIXFORMAT_MASK;
 422        sprctl &= ~SP_YUV_BYTE_ORDER_MASK;
 423        sprctl &= ~SP_TILED;
 424        sprctl &= ~SP_ROTATE_180;
 425
 426        switch (fb->pixel_format) {
 427        case DRM_FORMAT_YUYV:
 428                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
 429                break;
 430        case DRM_FORMAT_YVYU:
 431                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
 432                break;
 433        case DRM_FORMAT_UYVY:
 434                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
 435                break;
 436        case DRM_FORMAT_VYUY:
 437                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
 438                break;
 439        case DRM_FORMAT_RGB565:
 440                sprctl |= SP_FORMAT_BGR565;
 441                break;
 442        case DRM_FORMAT_XRGB8888:
 443                sprctl |= SP_FORMAT_BGRX8888;
 444                break;
 445        case DRM_FORMAT_ARGB8888:
 446                sprctl |= SP_FORMAT_BGRA8888;
 447                break;
 448        case DRM_FORMAT_XBGR2101010:
 449                sprctl |= SP_FORMAT_RGBX1010102;
 450                break;
 451        case DRM_FORMAT_ABGR2101010:
 452                sprctl |= SP_FORMAT_RGBA1010102;
 453                break;
 454        case DRM_FORMAT_XBGR8888:
 455                sprctl |= SP_FORMAT_RGBX8888;
 456                break;
 457        case DRM_FORMAT_ABGR8888:
 458                sprctl |= SP_FORMAT_RGBA8888;
 459                break;
 460        default:
 461                /*
 462                 * If we get here one of the upper layers failed to filter
 463                 * out the unsupported plane formats
 464                 */
 465                BUG();
 466                break;
 467        }
 468
 469        /*
 470         * Enable gamma to match primary/cursor plane behaviour.
 471         * FIXME should be user controllable via propertiesa.
 472         */
 473        sprctl |= SP_GAMMA_ENABLE;
 474
 475        if (obj->tiling_mode != I915_TILING_NONE)
 476                sprctl |= SP_TILED;
 477
 478        sprctl |= SP_ENABLE;
 479
 480        intel_update_sprite_watermarks(dplane, crtc, src_w, src_h,
 481                                       pixel_size, true,
 482                                       src_w != crtc_w || src_h != crtc_h);
 483
 484        /* Sizes are 0 based */
 485        src_w--;
 486        src_h--;
 487        crtc_w--;
 488        crtc_h--;
 489
 490        linear_offset = y * fb->pitches[0] + x * pixel_size;
 491        sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
 492                                                        obj->tiling_mode,
 493                                                        pixel_size,
 494                                                        fb->pitches[0]);
 495        linear_offset -= sprsurf_offset;
 496
 497        if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
 498                sprctl |= SP_ROTATE_180;
 499
 500                x += src_w;
 501                y += src_h;
 502                linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
 503        }
 504
 505        atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 506
 507        intel_update_primary_plane(intel_crtc);
 508
 509        if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
 510                chv_update_csc(intel_plane, fb->pixel_format);
 511
 512        I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
 513        I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
 514
 515        if (obj->tiling_mode != I915_TILING_NONE)
 516                I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
 517        else
 518                I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
 519
 520        I915_WRITE(SPCONSTALPHA(pipe, plane), 0);
 521
 522        I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
 523        I915_WRITE(SPCNTR(pipe, plane), sprctl);
 524        I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
 525                   sprsurf_offset);
 526
 527        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 528
 529        if (atomic_update)
 530                intel_pipe_update_end(intel_crtc, start_vbl_count);
 531}
 532
 533static void
 534vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 535{
 536        struct drm_device *dev = dplane->dev;
 537        struct drm_i915_private *dev_priv = dev->dev_private;
 538        struct intel_plane *intel_plane = to_intel_plane(dplane);
 539        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 540        int pipe = intel_plane->pipe;
 541        int plane = intel_plane->plane;
 542        u32 start_vbl_count;
 543        bool atomic_update;
 544
 545        atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 546
 547        intel_update_primary_plane(intel_crtc);
 548
 549        I915_WRITE(SPCNTR(pipe, plane), I915_READ(SPCNTR(pipe, plane)) &
 550                   ~SP_ENABLE);
 551        /* Activate double buffered register update */
 552        I915_WRITE(SPSURF(pipe, plane), 0);
 553
 554        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 555
 556        if (atomic_update)
 557                intel_pipe_update_end(intel_crtc, start_vbl_count);
 558
 559        intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false);
 560}
 561
 562static int
 563vlv_update_colorkey(struct drm_plane *dplane,
 564                    struct drm_intel_sprite_colorkey *key)
 565{
 566        struct drm_device *dev = dplane->dev;
 567        struct drm_i915_private *dev_priv = dev->dev_private;
 568        struct intel_plane *intel_plane = to_intel_plane(dplane);
 569        int pipe = intel_plane->pipe;
 570        int plane = intel_plane->plane;
 571        u32 sprctl;
 572
 573        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 574                return -EINVAL;
 575
 576        I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
 577        I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
 578        I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask);
 579
 580        sprctl = I915_READ(SPCNTR(pipe, plane));
 581        sprctl &= ~SP_SOURCE_KEY;
 582        if (key->flags & I915_SET_COLORKEY_SOURCE)
 583                sprctl |= SP_SOURCE_KEY;
 584        I915_WRITE(SPCNTR(pipe, plane), sprctl);
 585
 586        POSTING_READ(SPKEYMSK(pipe, plane));
 587
 588        return 0;
 589}
 590
 591static void
 592vlv_get_colorkey(struct drm_plane *dplane,
 593                 struct drm_intel_sprite_colorkey *key)
 594{
 595        struct drm_device *dev = dplane->dev;
 596        struct drm_i915_private *dev_priv = dev->dev_private;
 597        struct intel_plane *intel_plane = to_intel_plane(dplane);
 598        int pipe = intel_plane->pipe;
 599        int plane = intel_plane->plane;
 600        u32 sprctl;
 601
 602        key->min_value = I915_READ(SPKEYMINVAL(pipe, plane));
 603        key->max_value = I915_READ(SPKEYMAXVAL(pipe, plane));
 604        key->channel_mask = I915_READ(SPKEYMSK(pipe, plane));
 605
 606        sprctl = I915_READ(SPCNTR(pipe, plane));
 607        if (sprctl & SP_SOURCE_KEY)
 608                key->flags = I915_SET_COLORKEY_SOURCE;
 609        else
 610                key->flags = I915_SET_COLORKEY_NONE;
 611}
 612
 613static void
 614ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 615                 struct drm_framebuffer *fb,
 616                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 617                 unsigned int crtc_w, unsigned int crtc_h,
 618                 uint32_t x, uint32_t y,
 619                 uint32_t src_w, uint32_t src_h)
 620{
 621        struct drm_device *dev = plane->dev;
 622        struct drm_i915_private *dev_priv = dev->dev_private;
 623        struct intel_plane *intel_plane = to_intel_plane(plane);
 624        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 625        int pipe = intel_plane->pipe;
 626        u32 sprctl, sprscale = 0;
 627        unsigned long sprsurf_offset, linear_offset;
 628        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 629        u32 start_vbl_count;
 630        bool atomic_update;
 631
 632        sprctl = I915_READ(SPRCTL(pipe));
 633
 634        /* Mask out pixel format bits in case we change it */
 635        sprctl &= ~SPRITE_PIXFORMAT_MASK;
 636        sprctl &= ~SPRITE_RGB_ORDER_RGBX;
 637        sprctl &= ~SPRITE_YUV_BYTE_ORDER_MASK;
 638        sprctl &= ~SPRITE_TILED;
 639        sprctl &= ~SPRITE_ROTATE_180;
 640
 641        switch (fb->pixel_format) {
 642        case DRM_FORMAT_XBGR8888:
 643                sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
 644                break;
 645        case DRM_FORMAT_XRGB8888:
 646                sprctl |= SPRITE_FORMAT_RGBX888;
 647                break;
 648        case DRM_FORMAT_YUYV:
 649                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
 650                break;
 651        case DRM_FORMAT_YVYU:
 652                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
 653                break;
 654        case DRM_FORMAT_UYVY:
 655                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
 656                break;
 657        case DRM_FORMAT_VYUY:
 658                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
 659                break;
 660        default:
 661                BUG();
 662        }
 663
 664        /*
 665         * Enable gamma to match primary/cursor plane behaviour.
 666         * FIXME should be user controllable via propertiesa.
 667         */
 668        sprctl |= SPRITE_GAMMA_ENABLE;
 669
 670        if (obj->tiling_mode != I915_TILING_NONE)
 671                sprctl |= SPRITE_TILED;
 672
 673        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 674                sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
 675        else
 676                sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
 677
 678        sprctl |= SPRITE_ENABLE;
 679
 680        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 681                sprctl |= SPRITE_PIPE_CSC_ENABLE;
 682
 683        intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size,
 684                                       true,
 685                                       src_w != crtc_w || src_h != crtc_h);
 686
 687        /* Sizes are 0 based */
 688        src_w--;
 689        src_h--;
 690        crtc_w--;
 691        crtc_h--;
 692
 693        if (crtc_w != src_w || crtc_h != src_h)
 694                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 695
 696        linear_offset = y * fb->pitches[0] + x * pixel_size;
 697        sprsurf_offset =
 698                intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
 699                                               pixel_size, fb->pitches[0]);
 700        linear_offset -= sprsurf_offset;
 701
 702        if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
 703                sprctl |= SPRITE_ROTATE_180;
 704
 705                /* HSW and BDW does this automagically in hardware */
 706                if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
 707                        x += src_w;
 708                        y += src_h;
 709                        linear_offset += src_h * fb->pitches[0] +
 710                                src_w * pixel_size;
 711                }
 712        }
 713
 714        atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 715
 716        intel_update_primary_plane(intel_crtc);
 717
 718        I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
 719        I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 720
 721        /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
 722         * register */
 723        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 724                I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
 725        else if (obj->tiling_mode != I915_TILING_NONE)
 726                I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
 727        else
 728                I915_WRITE(SPRLINOFF(pipe), linear_offset);
 729
 730        I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
 731        if (intel_plane->can_scale)
 732                I915_WRITE(SPRSCALE(pipe), sprscale);
 733        I915_WRITE(SPRCTL(pipe), sprctl);
 734        I915_WRITE(SPRSURF(pipe),
 735                   i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
 736
 737        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 738
 739        if (atomic_update)
 740                intel_pipe_update_end(intel_crtc, start_vbl_count);
 741}
 742
 743static void
 744ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 745{
 746        struct drm_device *dev = plane->dev;
 747        struct drm_i915_private *dev_priv = dev->dev_private;
 748        struct intel_plane *intel_plane = to_intel_plane(plane);
 749        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 750        int pipe = intel_plane->pipe;
 751        u32 start_vbl_count;
 752        bool atomic_update;
 753
 754        atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 755
 756        intel_update_primary_plane(intel_crtc);
 757
 758        I915_WRITE(SPRCTL(pipe), I915_READ(SPRCTL(pipe)) & ~SPRITE_ENABLE);
 759        /* Can't leave the scaler enabled... */
 760        if (intel_plane->can_scale)
 761                I915_WRITE(SPRSCALE(pipe), 0);
 762        /* Activate double buffered register update */
 763        I915_WRITE(SPRSURF(pipe), 0);
 764
 765        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 766
 767        if (atomic_update)
 768                intel_pipe_update_end(intel_crtc, start_vbl_count);
 769
 770        /*
 771         * Avoid underruns when disabling the sprite.
 772         * FIXME remove once watermark updates are done properly.
 773         */
 774        intel_wait_for_vblank(dev, pipe);
 775
 776        intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
 777}
 778
 779static int
 780ivb_update_colorkey(struct drm_plane *plane,
 781                    struct drm_intel_sprite_colorkey *key)
 782{
 783        struct drm_device *dev = plane->dev;
 784        struct drm_i915_private *dev_priv = dev->dev_private;
 785        struct intel_plane *intel_plane;
 786        u32 sprctl;
 787        int ret = 0;
 788
 789        intel_plane = to_intel_plane(plane);
 790
 791        I915_WRITE(SPRKEYVAL(intel_plane->pipe), key->min_value);
 792        I915_WRITE(SPRKEYMAX(intel_plane->pipe), key->max_value);
 793        I915_WRITE(SPRKEYMSK(intel_plane->pipe), key->channel_mask);
 794
 795        sprctl = I915_READ(SPRCTL(intel_plane->pipe));
 796        sprctl &= ~(SPRITE_SOURCE_KEY | SPRITE_DEST_KEY);
 797        if (key->flags & I915_SET_COLORKEY_DESTINATION)
 798                sprctl |= SPRITE_DEST_KEY;
 799        else if (key->flags & I915_SET_COLORKEY_SOURCE)
 800                sprctl |= SPRITE_SOURCE_KEY;
 801        I915_WRITE(SPRCTL(intel_plane->pipe), sprctl);
 802
 803        POSTING_READ(SPRKEYMSK(intel_plane->pipe));
 804
 805        return ret;
 806}
 807
 808static void
 809ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 810{
 811        struct drm_device *dev = plane->dev;
 812        struct drm_i915_private *dev_priv = dev->dev_private;
 813        struct intel_plane *intel_plane;
 814        u32 sprctl;
 815
 816        intel_plane = to_intel_plane(plane);
 817
 818        key->min_value = I915_READ(SPRKEYVAL(intel_plane->pipe));
 819        key->max_value = I915_READ(SPRKEYMAX(intel_plane->pipe));
 820        key->channel_mask = I915_READ(SPRKEYMSK(intel_plane->pipe));
 821        key->flags = 0;
 822
 823        sprctl = I915_READ(SPRCTL(intel_plane->pipe));
 824
 825        if (sprctl & SPRITE_DEST_KEY)
 826                key->flags = I915_SET_COLORKEY_DESTINATION;
 827        else if (sprctl & SPRITE_SOURCE_KEY)
 828                key->flags = I915_SET_COLORKEY_SOURCE;
 829        else
 830                key->flags = I915_SET_COLORKEY_NONE;
 831}
 832
 833static void
 834ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
 835                 struct drm_framebuffer *fb,
 836                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
 837                 unsigned int crtc_w, unsigned int crtc_h,
 838                 uint32_t x, uint32_t y,
 839                 uint32_t src_w, uint32_t src_h)
 840{
 841        struct drm_device *dev = plane->dev;
 842        struct drm_i915_private *dev_priv = dev->dev_private;
 843        struct intel_plane *intel_plane = to_intel_plane(plane);
 844        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 845        int pipe = intel_plane->pipe;
 846        unsigned long dvssurf_offset, linear_offset;
 847        u32 dvscntr, dvsscale;
 848        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 849        u32 start_vbl_count;
 850        bool atomic_update;
 851
 852        dvscntr = I915_READ(DVSCNTR(pipe));
 853
 854        /* Mask out pixel format bits in case we change it */
 855        dvscntr &= ~DVS_PIXFORMAT_MASK;
 856        dvscntr &= ~DVS_RGB_ORDER_XBGR;
 857        dvscntr &= ~DVS_YUV_BYTE_ORDER_MASK;
 858        dvscntr &= ~DVS_TILED;
 859        dvscntr &= ~DVS_ROTATE_180;
 860
 861        switch (fb->pixel_format) {
 862        case DRM_FORMAT_XBGR8888:
 863                dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
 864                break;
 865        case DRM_FORMAT_XRGB8888:
 866                dvscntr |= DVS_FORMAT_RGBX888;
 867                break;
 868        case DRM_FORMAT_YUYV:
 869                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
 870                break;
 871        case DRM_FORMAT_YVYU:
 872                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
 873                break;
 874        case DRM_FORMAT_UYVY:
 875                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
 876                break;
 877        case DRM_FORMAT_VYUY:
 878                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
 879                break;
 880        default:
 881                BUG();
 882        }
 883
 884        /*
 885         * Enable gamma to match primary/cursor plane behaviour.
 886         * FIXME should be user controllable via propertiesa.
 887         */
 888        dvscntr |= DVS_GAMMA_ENABLE;
 889
 890        if (obj->tiling_mode != I915_TILING_NONE)
 891                dvscntr |= DVS_TILED;
 892
 893        if (IS_GEN6(dev))
 894                dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 895        dvscntr |= DVS_ENABLE;
 896
 897        intel_update_sprite_watermarks(plane, crtc, src_w, src_h,
 898                                       pixel_size, true,
 899                                       src_w != crtc_w || src_h != crtc_h);
 900
 901        /* Sizes are 0 based */
 902        src_w--;
 903        src_h--;
 904        crtc_w--;
 905        crtc_h--;
 906
 907        dvsscale = 0;
 908        if (crtc_w != src_w || crtc_h != src_h)
 909                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 910
 911        linear_offset = y * fb->pitches[0] + x * pixel_size;
 912        dvssurf_offset =
 913                intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
 914                                               pixel_size, fb->pitches[0]);
 915        linear_offset -= dvssurf_offset;
 916
 917        if (intel_plane->rotation == BIT(DRM_ROTATE_180)) {
 918                dvscntr |= DVS_ROTATE_180;
 919
 920                x += src_w;
 921                y += src_h;
 922                linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
 923        }
 924
 925        atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 926
 927        intel_update_primary_plane(intel_crtc);
 928
 929        I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
 930        I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
 931
 932        if (obj->tiling_mode != I915_TILING_NONE)
 933                I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
 934        else
 935                I915_WRITE(DVSLINOFF(pipe), linear_offset);
 936
 937        I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
 938        I915_WRITE(DVSSCALE(pipe), dvsscale);
 939        I915_WRITE(DVSCNTR(pipe), dvscntr);
 940        I915_WRITE(DVSSURF(pipe),
 941                   i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
 942
 943        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 944
 945        if (atomic_update)
 946                intel_pipe_update_end(intel_crtc, start_vbl_count);
 947}
 948
 949static void
 950ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 951{
 952        struct drm_device *dev = plane->dev;
 953        struct drm_i915_private *dev_priv = dev->dev_private;
 954        struct intel_plane *intel_plane = to_intel_plane(plane);
 955        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 956        int pipe = intel_plane->pipe;
 957        u32 start_vbl_count;
 958        bool atomic_update;
 959
 960        atomic_update = intel_pipe_update_start(intel_crtc, &start_vbl_count);
 961
 962        intel_update_primary_plane(intel_crtc);
 963
 964        I915_WRITE(DVSCNTR(pipe), I915_READ(DVSCNTR(pipe)) & ~DVS_ENABLE);
 965        /* Disable the scaler */
 966        I915_WRITE(DVSSCALE(pipe), 0);
 967        /* Flush double buffered register updates */
 968        I915_WRITE(DVSSURF(pipe), 0);
 969
 970        intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 971
 972        if (atomic_update)
 973                intel_pipe_update_end(intel_crtc, start_vbl_count);
 974
 975        /*
 976         * Avoid underruns when disabling the sprite.
 977         * FIXME remove once watermark updates are done properly.
 978         */
 979        intel_wait_for_vblank(dev, pipe);
 980
 981        intel_update_sprite_watermarks(plane, crtc, 0, 0, 0, false, false);
 982}
 983
 984static void
 985intel_post_enable_primary(struct drm_crtc *crtc)
 986{
 987        struct drm_device *dev = crtc->dev;
 988        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 989
 990        /*
 991         * BDW signals flip done immediately if the plane
 992         * is disabled, even if the plane enable is already
 993         * armed to occur at the next vblank :(
 994         */
 995        if (IS_BROADWELL(dev))
 996                intel_wait_for_vblank(dev, intel_crtc->pipe);
 997
 998        /*
 999         * FIXME IPS should be fine as long as one plane is
1000         * enabled, but in practice it seems to have problems
1001         * when going from primary only to sprite only and vice
1002         * versa.
1003         */
1004        hsw_enable_ips(intel_crtc);
1005
1006        mutex_lock(&dev->struct_mutex);
1007        intel_update_fbc(dev);
1008        mutex_unlock(&dev->struct_mutex);
1009}
1010
1011static void
1012intel_pre_disable_primary(struct drm_crtc *crtc)
1013{
1014        struct drm_device *dev = crtc->dev;
1015        struct drm_i915_private *dev_priv = dev->dev_private;
1016        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1017
1018        mutex_lock(&dev->struct_mutex);
1019        if (dev_priv->fbc.plane == intel_crtc->plane)
1020                intel_disable_fbc(dev);
1021        mutex_unlock(&dev->struct_mutex);
1022
1023        /*
1024         * FIXME IPS should be fine as long as one plane is
1025         * enabled, but in practice it seems to have problems
1026         * when going from primary only to sprite only and vice
1027         * versa.
1028         */
1029        hsw_disable_ips(intel_crtc);
1030}
1031
1032static int
1033ilk_update_colorkey(struct drm_plane *plane,
1034                    struct drm_intel_sprite_colorkey *key)
1035{
1036        struct drm_device *dev = plane->dev;
1037        struct drm_i915_private *dev_priv = dev->dev_private;
1038        struct intel_plane *intel_plane;
1039        u32 dvscntr;
1040        int ret = 0;
1041
1042        intel_plane = to_intel_plane(plane);
1043
1044        I915_WRITE(DVSKEYVAL(intel_plane->pipe), key->min_value);
1045        I915_WRITE(DVSKEYMAX(intel_plane->pipe), key->max_value);
1046        I915_WRITE(DVSKEYMSK(intel_plane->pipe), key->channel_mask);
1047
1048        dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
1049        dvscntr &= ~(DVS_SOURCE_KEY | DVS_DEST_KEY);
1050        if (key->flags & I915_SET_COLORKEY_DESTINATION)
1051                dvscntr |= DVS_DEST_KEY;
1052        else if (key->flags & I915_SET_COLORKEY_SOURCE)
1053                dvscntr |= DVS_SOURCE_KEY;
1054        I915_WRITE(DVSCNTR(intel_plane->pipe), dvscntr);
1055
1056        POSTING_READ(DVSKEYMSK(intel_plane->pipe));
1057
1058        return ret;
1059}
1060
1061static void
1062ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
1063{
1064        struct drm_device *dev = plane->dev;
1065        struct drm_i915_private *dev_priv = dev->dev_private;
1066        struct intel_plane *intel_plane;
1067        u32 dvscntr;
1068
1069        intel_plane = to_intel_plane(plane);
1070
1071        key->min_value = I915_READ(DVSKEYVAL(intel_plane->pipe));
1072        key->max_value = I915_READ(DVSKEYMAX(intel_plane->pipe));
1073        key->channel_mask = I915_READ(DVSKEYMSK(intel_plane->pipe));
1074        key->flags = 0;
1075
1076        dvscntr = I915_READ(DVSCNTR(intel_plane->pipe));
1077
1078        if (dvscntr & DVS_DEST_KEY)
1079                key->flags = I915_SET_COLORKEY_DESTINATION;
1080        else if (dvscntr & DVS_SOURCE_KEY)
1081                key->flags = I915_SET_COLORKEY_SOURCE;
1082        else
1083                key->flags = I915_SET_COLORKEY_NONE;
1084}
1085
1086static bool colorkey_enabled(struct intel_plane *intel_plane)
1087{
1088        struct drm_intel_sprite_colorkey key;
1089
1090        intel_plane->get_colorkey(&intel_plane->base, &key);
1091
1092        return key.flags != I915_SET_COLORKEY_NONE;
1093}
1094
1095static int
1096intel_check_sprite_plane(struct drm_plane *plane,
1097                         struct intel_plane_state *state)
1098{
1099        struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc);
1100        struct intel_plane *intel_plane = to_intel_plane(plane);
1101        struct drm_framebuffer *fb = state->fb;
1102        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1103        int crtc_x, crtc_y;
1104        unsigned int crtc_w, crtc_h;
1105        uint32_t src_x, src_y, src_w, src_h;
1106        struct drm_rect *src = &state->src;
1107        struct drm_rect *dst = &state->dst;
1108        struct drm_rect *orig_src = &state->orig_src;
1109        const struct drm_rect *clip = &state->clip;
1110        int hscale, vscale;
1111        int max_scale, min_scale;
1112        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
1113
1114        /* Don't modify another pipe's plane */
1115        if (intel_plane->pipe != intel_crtc->pipe) {
1116                DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
1117                return -EINVAL;
1118        }
1119
1120        /* FIXME check all gen limits */
1121        if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) {
1122                DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
1123                return -EINVAL;
1124        }
1125
1126        /* Sprite planes can be linear or x-tiled surfaces */
1127        switch (obj->tiling_mode) {
1128                case I915_TILING_NONE:
1129                case I915_TILING_X:
1130                        break;
1131                default:
1132                        DRM_DEBUG_KMS("Unsupported tiling mode\n");
1133                        return -EINVAL;
1134        }
1135
1136        /*
1137         * FIXME the following code does a bunch of fuzzy adjustments to the
1138         * coordinates and sizes. We probably need some way to decide whether
1139         * more strict checking should be done instead.
1140         */
1141        max_scale = intel_plane->max_downscale << 16;
1142        min_scale = intel_plane->can_scale ? 1 : (1 << 16);
1143
1144        drm_rect_rotate(src, fb->width << 16, fb->height << 16,
1145                        intel_plane->rotation);
1146
1147        hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
1148        BUG_ON(hscale < 0);
1149
1150        vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
1151        BUG_ON(vscale < 0);
1152
1153        state->visible =  drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
1154
1155        crtc_x = dst->x1;
1156        crtc_y = dst->y1;
1157        crtc_w = drm_rect_width(dst);
1158        crtc_h = drm_rect_height(dst);
1159
1160        if (state->visible) {
1161                /* check again in case clipping clamped the results */
1162                hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
1163                if (hscale < 0) {
1164                        DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
1165                        drm_rect_debug_print(src, true);
1166                        drm_rect_debug_print(dst, false);
1167
1168                        return hscale;
1169                }
1170
1171                vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
1172                if (vscale < 0) {
1173                        DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
1174                        drm_rect_debug_print(src, true);
1175                        drm_rect_debug_print(dst, false);
1176
1177                        return vscale;
1178                }
1179
1180                /* Make the source viewport size an exact multiple of the scaling factors. */
1181                drm_rect_adjust_size(src,
1182                                     drm_rect_width(dst) * hscale - drm_rect_width(src),
1183                                     drm_rect_height(dst) * vscale - drm_rect_height(src));
1184
1185                drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
1186                                    intel_plane->rotation);
1187
1188                /* sanity check to make sure the src viewport wasn't enlarged */
1189                WARN_ON(src->x1 < (int) orig_src->x1 ||
1190                        src->y1 < (int) orig_src->y1 ||
1191                        src->x2 > (int) orig_src->x2 ||
1192                        src->y2 > (int) orig_src->y2);
1193
1194                /*
1195                 * Hardware doesn't handle subpixel coordinates.
1196                 * Adjust to (macro)pixel boundary, but be careful not to
1197                 * increase the source viewport size, because that could
1198                 * push the downscaling factor out of bounds.
1199                 */
1200                src_x = src->x1 >> 16;
1201                src_w = drm_rect_width(src) >> 16;
1202                src_y = src->y1 >> 16;
1203                src_h = drm_rect_height(src) >> 16;
1204
1205                if (format_is_yuv(fb->pixel_format)) {
1206                        src_x &= ~1;
1207                        src_w &= ~1;
1208
1209                        /*
1210                         * Must keep src and dst the
1211                         * same if we can't scale.
1212                         */
1213                        if (!intel_plane->can_scale)
1214                                crtc_w &= ~1;
1215
1216                        if (crtc_w == 0)
1217                                state->visible = false;
1218                }
1219        }
1220
1221        /* Check size restrictions when scaling */
1222        if (state->visible && (src_w != crtc_w || src_h != crtc_h)) {
1223                unsigned int width_bytes;
1224
1225                WARN_ON(!intel_plane->can_scale);
1226
1227                /* FIXME interlacing min height is 6 */
1228
1229                if (crtc_w < 3 || crtc_h < 3)
1230                        state->visible = false;
1231
1232                if (src_w < 3 || src_h < 3)
1233                        state->visible = false;
1234
1235                width_bytes = ((src_x * pixel_size) & 63) +
1236                                        src_w * pixel_size;
1237
1238                if (src_w > 2048 || src_h > 2048 ||
1239                    width_bytes > 4096 || fb->pitches[0] > 4096) {
1240                        DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
1241                        return -EINVAL;
1242                }
1243        }
1244
1245        if (state->visible) {
1246                src->x1 = src_x;
1247                src->x2 = src_x + src_w;
1248                src->y1 = src_y;
1249                src->y2 = src_y + src_h;
1250        }
1251
1252        dst->x1 = crtc_x;
1253        dst->x2 = crtc_x + crtc_w;
1254        dst->y1 = crtc_y;
1255        dst->y2 = crtc_y + crtc_h;
1256
1257        return 0;
1258}
1259
1260static int
1261intel_prepare_sprite_plane(struct drm_plane *plane,
1262                           struct intel_plane_state *state)
1263{
1264        struct drm_device *dev = plane->dev;
1265        struct drm_crtc *crtc = state->crtc;
1266        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1267        struct intel_plane *intel_plane = to_intel_plane(plane);
1268        enum pipe pipe = intel_crtc->pipe;
1269        struct drm_framebuffer *fb = state->fb;
1270        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1271        struct drm_i915_gem_object *old_obj = intel_plane->obj;
1272        int ret;
1273
1274        if (old_obj != obj) {
1275                mutex_lock(&dev->struct_mutex);
1276
1277                /* Note that this will apply the VT-d workaround for scanouts,
1278                 * which is more restrictive than required for sprites. (The
1279                 * primary plane requires 256KiB alignment with 64 PTE padding,
1280                 * the sprite planes only require 128KiB alignment and 32 PTE
1281                 * padding.
1282                 */
1283                ret = intel_pin_and_fence_fb_obj(plane, fb, NULL);
1284                if (ret == 0)
1285                        i915_gem_track_fb(old_obj, obj,
1286                                          INTEL_FRONTBUFFER_SPRITE(pipe));
1287                mutex_unlock(&dev->struct_mutex);
1288                if (ret)
1289                        return ret;
1290        }
1291
1292        return 0;
1293}
1294
1295static void
1296intel_commit_sprite_plane(struct drm_plane *plane,
1297                          struct intel_plane_state *state)
1298{
1299        struct drm_device *dev = plane->dev;
1300        struct drm_crtc *crtc = state->crtc;
1301        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1302        struct intel_plane *intel_plane = to_intel_plane(plane);
1303        enum pipe pipe = intel_crtc->pipe;
1304        struct drm_framebuffer *fb = state->fb;
1305        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
1306        struct drm_i915_gem_object *old_obj = intel_plane->obj;
1307        int crtc_x, crtc_y;
1308        unsigned int crtc_w, crtc_h;
1309        uint32_t src_x, src_y, src_w, src_h;
1310        struct drm_rect *dst = &state->dst;
1311        const struct drm_rect *clip = &state->clip;
1312        bool primary_enabled;
1313
1314        /*
1315         * If the sprite is completely covering the primary plane,
1316         * we can disable the primary and save power.
1317         */
1318        primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
1319        WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
1320
1321        intel_plane->crtc_x = state->orig_dst.x1;
1322        intel_plane->crtc_y = state->orig_dst.y1;
1323        intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
1324        intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
1325        intel_plane->src_x = state->orig_src.x1;
1326        intel_plane->src_y = state->orig_src.y1;
1327        intel_plane->src_w = drm_rect_width(&state->orig_src);
1328        intel_plane->src_h = drm_rect_height(&state->orig_src);
1329        intel_plane->obj = obj;
1330
1331        if (intel_crtc->active) {
1332                bool primary_was_enabled = intel_crtc->primary_enabled;
1333
1334                intel_crtc->primary_enabled = primary_enabled;
1335
1336                if (primary_was_enabled != primary_enabled)
1337                        intel_crtc_wait_for_pending_flips(crtc);
1338
1339                if (primary_was_enabled && !primary_enabled)
1340                        intel_pre_disable_primary(crtc);
1341
1342                if (state->visible) {
1343                        crtc_x = state->dst.x1;
1344                        crtc_y = state->dst.y1;
1345                        crtc_w = drm_rect_width(&state->dst);
1346                        crtc_h = drm_rect_height(&state->dst);
1347                        src_x = state->src.x1;
1348                        src_y = state->src.y1;
1349                        src_w = drm_rect_width(&state->src);
1350                        src_h = drm_rect_height(&state->src);
1351                        intel_plane->update_plane(plane, crtc, fb, obj,
1352                                                  crtc_x, crtc_y, crtc_w, crtc_h,
1353                                                  src_x, src_y, src_w, src_h);
1354                } else {
1355                        intel_plane->disable_plane(plane, crtc);
1356                }
1357
1358
1359                intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
1360
1361                if (!primary_was_enabled && primary_enabled)
1362                        intel_post_enable_primary(crtc);
1363        }
1364
1365        /* Unpin old obj after new one is active to avoid ugliness */
1366        if (old_obj && old_obj != obj) {
1367
1368                /*
1369                 * It's fairly common to simply update the position of
1370                 * an existing object.  In that case, we don't need to
1371                 * wait for vblank to avoid ugliness, we only need to
1372                 * do the pin & ref bookkeeping.
1373                 */
1374                if (intel_crtc->active)
1375                        intel_wait_for_vblank(dev, intel_crtc->pipe);
1376
1377                mutex_lock(&dev->struct_mutex);
1378                intel_unpin_fb_obj(old_obj);
1379                mutex_unlock(&dev->struct_mutex);
1380        }
1381}
1382
1383static int
1384intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
1385                   struct drm_framebuffer *fb, int crtc_x, int crtc_y,
1386                   unsigned int crtc_w, unsigned int crtc_h,
1387                   uint32_t src_x, uint32_t src_y,
1388                   uint32_t src_w, uint32_t src_h)
1389{
1390        struct intel_plane_state state;
1391        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1392        int ret;
1393
1394        state.crtc = crtc;
1395        state.fb = fb;
1396
1397        /* sample coordinates in 16.16 fixed point */
1398        state.src.x1 = src_x;
1399        state.src.x2 = src_x + src_w;
1400        state.src.y1 = src_y;
1401        state.src.y2 = src_y + src_h;
1402
1403        /* integer pixels */
1404        state.dst.x1 = crtc_x;
1405        state.dst.x2 = crtc_x + crtc_w;
1406        state.dst.y1 = crtc_y;
1407        state.dst.y2 = crtc_y + crtc_h;
1408
1409        state.clip.x1 = 0;
1410        state.clip.y1 = 0;
1411        state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
1412        state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
1413        state.orig_src = state.src;
1414        state.orig_dst = state.dst;
1415
1416        ret = intel_check_sprite_plane(plane, &state);
1417        if (ret)
1418                return ret;
1419
1420        ret = intel_prepare_sprite_plane(plane, &state);
1421        if (ret)
1422                return ret;
1423
1424        intel_commit_sprite_plane(plane, &state);
1425        return 0;
1426}
1427
1428static int
1429intel_disable_plane(struct drm_plane *plane)
1430{
1431        struct drm_device *dev = plane->dev;
1432        struct intel_plane *intel_plane = to_intel_plane(plane);
1433        struct intel_crtc *intel_crtc;
1434        enum pipe pipe;
1435
1436        if (!plane->fb)
1437                return 0;
1438
1439        if (WARN_ON(!plane->crtc))
1440                return -EINVAL;
1441
1442        intel_crtc = to_intel_crtc(plane->crtc);
1443        pipe = intel_crtc->pipe;
1444
1445        if (intel_crtc->active) {
1446                bool primary_was_enabled = intel_crtc->primary_enabled;
1447
1448                intel_crtc->primary_enabled = true;
1449
1450                intel_plane->disable_plane(plane, plane->crtc);
1451
1452                if (!primary_was_enabled && intel_crtc->primary_enabled)
1453                        intel_post_enable_primary(plane->crtc);
1454        }
1455
1456        if (intel_plane->obj) {
1457                if (intel_crtc->active)
1458                        intel_wait_for_vblank(dev, intel_plane->pipe);
1459
1460                mutex_lock(&dev->struct_mutex);
1461                intel_unpin_fb_obj(intel_plane->obj);
1462                i915_gem_track_fb(intel_plane->obj, NULL,
1463                                  INTEL_FRONTBUFFER_SPRITE(pipe));
1464                mutex_unlock(&dev->struct_mutex);
1465
1466                intel_plane->obj = NULL;
1467        }
1468
1469        return 0;
1470}
1471
1472static void intel_destroy_plane(struct drm_plane *plane)
1473{
1474        struct intel_plane *intel_plane = to_intel_plane(plane);
1475        intel_disable_plane(plane);
1476        drm_plane_cleanup(plane);
1477        kfree(intel_plane);
1478}
1479
1480int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
1481                              struct drm_file *file_priv)
1482{
1483        struct drm_intel_sprite_colorkey *set = data;
1484        struct drm_plane *plane;
1485        struct intel_plane *intel_plane;
1486        int ret = 0;
1487
1488        if (!drm_core_check_feature(dev, DRIVER_MODESET))
1489                return -ENODEV;
1490
1491        /* Make sure we don't try to enable both src & dest simultaneously */
1492        if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1493                return -EINVAL;
1494
1495        drm_modeset_lock_all(dev);
1496
1497        plane = drm_plane_find(dev, set->plane_id);
1498        if (!plane) {
1499                ret = -ENOENT;
1500                goto out_unlock;
1501        }
1502
1503        intel_plane = to_intel_plane(plane);
1504        ret = intel_plane->update_colorkey(plane, set);
1505
1506out_unlock:
1507        drm_modeset_unlock_all(dev);
1508        return ret;
1509}
1510
1511int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
1512                              struct drm_file *file_priv)
1513{
1514        struct drm_intel_sprite_colorkey *get = data;
1515        struct drm_plane *plane;
1516        struct intel_plane *intel_plane;
1517        int ret = 0;
1518
1519        if (!drm_core_check_feature(dev, DRIVER_MODESET))
1520                return -ENODEV;
1521
1522        drm_modeset_lock_all(dev);
1523
1524        plane = drm_plane_find(dev, get->plane_id);
1525        if (!plane) {
1526                ret = -ENOENT;
1527                goto out_unlock;
1528        }
1529
1530        intel_plane = to_intel_plane(plane);
1531        intel_plane->get_colorkey(plane, get);
1532
1533out_unlock:
1534        drm_modeset_unlock_all(dev);
1535        return ret;
1536}
1537
1538int intel_plane_set_property(struct drm_plane *plane,
1539                             struct drm_property *prop,
1540                             uint64_t val)
1541{
1542        struct drm_device *dev = plane->dev;
1543        struct intel_plane *intel_plane = to_intel_plane(plane);
1544        uint64_t old_val;
1545        int ret = -ENOENT;
1546
1547        if (prop == dev->mode_config.rotation_property) {
1548                /* exactly one rotation angle please */
1549                if (hweight32(val & 0xf) != 1)
1550                        return -EINVAL;
1551
1552                if (intel_plane->rotation == val)
1553                        return 0;
1554
1555                old_val = intel_plane->rotation;
1556                intel_plane->rotation = val;
1557                ret = intel_plane_restore(plane);
1558                if (ret)
1559                        intel_plane->rotation = old_val;
1560        }
1561
1562        return ret;
1563}
1564
1565int intel_plane_restore(struct drm_plane *plane)
1566{
1567        struct intel_plane *intel_plane = to_intel_plane(plane);
1568
1569        if (!plane->crtc || !plane->fb)
1570                return 0;
1571
1572        return plane->funcs->update_plane(plane, plane->crtc, plane->fb,
1573                                  intel_plane->crtc_x, intel_plane->crtc_y,
1574                                  intel_plane->crtc_w, intel_plane->crtc_h,
1575                                  intel_plane->src_x, intel_plane->src_y,
1576                                  intel_plane->src_w, intel_plane->src_h);
1577}
1578
1579void intel_plane_disable(struct drm_plane *plane)
1580{
1581        if (!plane->crtc || !plane->fb)
1582                return;
1583
1584        intel_disable_plane(plane);
1585}
1586
1587static const struct drm_plane_funcs intel_plane_funcs = {
1588        .update_plane = intel_update_plane,
1589        .disable_plane = intel_disable_plane,
1590        .destroy = intel_destroy_plane,
1591        .set_property = intel_plane_set_property,
1592};
1593
1594static uint32_t ilk_plane_formats[] = {
1595        DRM_FORMAT_XRGB8888,
1596        DRM_FORMAT_YUYV,
1597        DRM_FORMAT_YVYU,
1598        DRM_FORMAT_UYVY,
1599        DRM_FORMAT_VYUY,
1600};
1601
1602static uint32_t snb_plane_formats[] = {
1603        DRM_FORMAT_XBGR8888,
1604        DRM_FORMAT_XRGB8888,
1605        DRM_FORMAT_YUYV,
1606        DRM_FORMAT_YVYU,
1607        DRM_FORMAT_UYVY,
1608        DRM_FORMAT_VYUY,
1609};
1610
1611static uint32_t vlv_plane_formats[] = {
1612        DRM_FORMAT_RGB565,
1613        DRM_FORMAT_ABGR8888,
1614        DRM_FORMAT_ARGB8888,
1615        DRM_FORMAT_XBGR8888,
1616        DRM_FORMAT_XRGB8888,
1617        DRM_FORMAT_XBGR2101010,
1618        DRM_FORMAT_ABGR2101010,
1619        DRM_FORMAT_YUYV,
1620        DRM_FORMAT_YVYU,
1621        DRM_FORMAT_UYVY,
1622        DRM_FORMAT_VYUY,
1623};
1624
1625static uint32_t skl_plane_formats[] = {
1626        DRM_FORMAT_RGB565,
1627        DRM_FORMAT_ABGR8888,
1628        DRM_FORMAT_ARGB8888,
1629        DRM_FORMAT_XBGR8888,
1630        DRM_FORMAT_XRGB8888,
1631        DRM_FORMAT_YUYV,
1632        DRM_FORMAT_YVYU,
1633        DRM_FORMAT_UYVY,
1634        DRM_FORMAT_VYUY,
1635};
1636
1637int
1638intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1639{
1640        struct intel_plane *intel_plane;
1641        unsigned long possible_crtcs;
1642        const uint32_t *plane_formats;
1643        int num_plane_formats;
1644        int ret;
1645
1646        if (INTEL_INFO(dev)->gen < 5)
1647                return -ENODEV;
1648
1649        intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
1650        if (!intel_plane)
1651                return -ENOMEM;
1652
1653        switch (INTEL_INFO(dev)->gen) {
1654        case 5:
1655        case 6:
1656                intel_plane->can_scale = true;
1657                intel_plane->max_downscale = 16;
1658                intel_plane->update_plane = ilk_update_plane;
1659                intel_plane->disable_plane = ilk_disable_plane;
1660                intel_plane->update_colorkey = ilk_update_colorkey;
1661                intel_plane->get_colorkey = ilk_get_colorkey;
1662
1663                if (IS_GEN6(dev)) {
1664                        plane_formats = snb_plane_formats;
1665                        num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1666                } else {
1667                        plane_formats = ilk_plane_formats;
1668                        num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
1669                }
1670                break;
1671
1672        case 7:
1673        case 8:
1674                if (IS_IVYBRIDGE(dev)) {
1675                        intel_plane->can_scale = true;
1676                        intel_plane->max_downscale = 2;
1677                } else {
1678                        intel_plane->can_scale = false;
1679                        intel_plane->max_downscale = 1;
1680                }
1681
1682                if (IS_VALLEYVIEW(dev)) {
1683                        intel_plane->update_plane = vlv_update_plane;
1684                        intel_plane->disable_plane = vlv_disable_plane;
1685                        intel_plane->update_colorkey = vlv_update_colorkey;
1686                        intel_plane->get_colorkey = vlv_get_colorkey;
1687
1688                        plane_formats = vlv_plane_formats;
1689                        num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
1690                } else {
1691                        intel_plane->update_plane = ivb_update_plane;
1692                        intel_plane->disable_plane = ivb_disable_plane;
1693                        intel_plane->update_colorkey = ivb_update_colorkey;
1694                        intel_plane->get_colorkey = ivb_get_colorkey;
1695
1696                        plane_formats = snb_plane_formats;
1697                        num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1698                }
1699                break;
1700        case 9:
1701                /*
1702                 * FIXME: Skylake planes can be scaled (with some restrictions),
1703                 * but this is for another time.
1704                 */
1705                intel_plane->can_scale = false;
1706                intel_plane->max_downscale = 1;
1707                intel_plane->update_plane = skl_update_plane;
1708                intel_plane->disable_plane = skl_disable_plane;
1709                intel_plane->update_colorkey = skl_update_colorkey;
1710                intel_plane->get_colorkey = skl_get_colorkey;
1711
1712                plane_formats = skl_plane_formats;
1713                num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1714                break;
1715        default:
1716                kfree(intel_plane);
1717                return -ENODEV;
1718        }
1719
1720        intel_plane->pipe = pipe;
1721        intel_plane->plane = plane;
1722        intel_plane->rotation = BIT(DRM_ROTATE_0);
1723        possible_crtcs = (1 << pipe);
1724        ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
1725                                       &intel_plane_funcs,
1726                                       plane_formats, num_plane_formats,
1727                                       DRM_PLANE_TYPE_OVERLAY);
1728        if (ret) {
1729                kfree(intel_plane);
1730                goto out;
1731        }
1732
1733        if (!dev->mode_config.rotation_property)
1734                dev->mode_config.rotation_property =
1735                        drm_mode_create_rotation_property(dev,
1736                                                          BIT(DRM_ROTATE_0) |
1737                                                          BIT(DRM_ROTATE_180));
1738
1739        if (dev->mode_config.rotation_property)
1740                drm_object_attach_property(&intel_plane->base.base,
1741                                           dev->mode_config.rotation_property,
1742                                           intel_plane->rotation);
1743
1744 out:
1745        return ret;
1746}
1747