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