linux/drivers/gpu/drm/i915/display/intel_sprite.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2011 Intel Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 * SOFTWARE.
  22 *
  23 * Authors:
  24 *   Jesse Barnes <jbarnes@virtuousgeek.org>
  25 *
  26 * New plane/sprite handling.
  27 *
  28 * The older chips had a separate interface for programming plane related
  29 * registers; newer ones are much simpler and we can use the new DRM plane
  30 * support.
  31 */
  32
  33#include <drm/drm_atomic.h>
  34#include <drm/drm_atomic_helper.h>
  35#include <drm/drm_color_mgmt.h>
  36#include <drm/drm_crtc.h>
  37#include <drm/drm_fourcc.h>
  38#include <drm/drm_plane_helper.h>
  39#include <drm/drm_rect.h>
  40#include <drm/i915_drm.h>
  41
  42#include "i915_drv.h"
  43#include "i915_trace.h"
  44#include "intel_atomic_plane.h"
  45#include "intel_display_types.h"
  46#include "intel_frontbuffer.h"
  47#include "intel_pm.h"
  48#include "intel_psr.h"
  49#include "intel_sprite.h"
  50
  51int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
  52                             int usecs)
  53{
  54        /* paranoia */
  55        if (!adjusted_mode->crtc_htotal)
  56                return 1;
  57
  58        return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
  59                            1000 * adjusted_mode->crtc_htotal);
  60}
  61
  62/* FIXME: We should instead only take spinlocks once for the entire update
  63 * instead of once per mmio. */
  64#if IS_ENABLED(CONFIG_PROVE_LOCKING)
  65#define VBLANK_EVASION_TIME_US 250
  66#else
  67#define VBLANK_EVASION_TIME_US 100
  68#endif
  69
  70/**
  71 * intel_pipe_update_start() - start update of a set of display registers
  72 * @new_crtc_state: the new crtc state
  73 *
  74 * Mark the start of an update to pipe registers that should be updated
  75 * atomically regarding vblank. If the next vblank will happens within
  76 * the next 100 us, this function waits until the vblank passes.
  77 *
  78 * After a successful call to this function, interrupts will be disabled
  79 * until a subsequent call to intel_pipe_update_end(). That is done to
  80 * avoid random delays.
  81 */
  82void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
  83{
  84        struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
  85        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
  86        const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode;
  87        long timeout = msecs_to_jiffies_timeout(1);
  88        int scanline, min, max, vblank_start;
  89        wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
  90        bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
  91                intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
  92        DEFINE_WAIT(wait);
  93        u32 psr_status;
  94
  95        vblank_start = adjusted_mode->crtc_vblank_start;
  96        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
  97                vblank_start = DIV_ROUND_UP(vblank_start, 2);
  98
  99        /* FIXME needs to be calibrated sensibly */
 100        min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
 101                                                      VBLANK_EVASION_TIME_US);
 102        max = vblank_start - 1;
 103
 104        if (min <= 0 || max <= 0)
 105                goto irq_disable;
 106
 107        if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
 108                goto irq_disable;
 109
 110        /*
 111         * Wait for psr to idle out after enabling the VBL interrupts
 112         * VBL interrupts will start the PSR exit and prevent a PSR
 113         * re-entry as well.
 114         */
 115        if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
 116                DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
 117                          psr_status);
 118
 119        local_irq_disable();
 120
 121        crtc->debug.min_vbl = min;
 122        crtc->debug.max_vbl = max;
 123        trace_intel_pipe_update_start(crtc);
 124
 125        for (;;) {
 126                /*
 127                 * prepare_to_wait() has a memory barrier, which guarantees
 128                 * other CPUs can see the task state update by the time we
 129                 * read the scanline.
 130                 */
 131                prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
 132
 133                scanline = intel_get_crtc_scanline(crtc);
 134                if (scanline < min || scanline > max)
 135                        break;
 136
 137                if (!timeout) {
 138                        DRM_ERROR("Potential atomic update failure on pipe %c\n",
 139                                  pipe_name(crtc->pipe));
 140                        break;
 141                }
 142
 143                local_irq_enable();
 144
 145                timeout = schedule_timeout(timeout);
 146
 147                local_irq_disable();
 148        }
 149
 150        finish_wait(wq, &wait);
 151
 152        drm_crtc_vblank_put(&crtc->base);
 153
 154        /*
 155         * On VLV/CHV DSI the scanline counter would appear to
 156         * increment approx. 1/3 of a scanline before start of vblank.
 157         * The registers still get latched at start of vblank however.
 158         * This means we must not write any registers on the first
 159         * line of vblank (since not the whole line is actually in
 160         * vblank). And unfortunately we can't use the interrupt to
 161         * wait here since it will fire too soon. We could use the
 162         * frame start interrupt instead since it will fire after the
 163         * critical scanline, but that would require more changes
 164         * in the interrupt code. So for now we'll just do the nasty
 165         * thing and poll for the bad scanline to pass us by.
 166         *
 167         * FIXME figure out if BXT+ DSI suffers from this as well
 168         */
 169        while (need_vlv_dsi_wa && scanline == vblank_start)
 170                scanline = intel_get_crtc_scanline(crtc);
 171
 172        crtc->debug.scanline_start = scanline;
 173        crtc->debug.start_vbl_time = ktime_get();
 174        crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
 175
 176        trace_intel_pipe_update_vblank_evaded(crtc);
 177        return;
 178
 179irq_disable:
 180        local_irq_disable();
 181}
 182
 183/**
 184 * intel_pipe_update_end() - end update of a set of display registers
 185 * @new_crtc_state: the new crtc state
 186 *
 187 * Mark the end of an update started with intel_pipe_update_start(). This
 188 * re-enables interrupts and verifies the update was actually completed
 189 * before a vblank.
 190 */
 191void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
 192{
 193        struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
 194        enum pipe pipe = crtc->pipe;
 195        int scanline_end = intel_get_crtc_scanline(crtc);
 196        u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
 197        ktime_t end_vbl_time = ktime_get();
 198        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 199
 200        trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end);
 201
 202        /* We're still in the vblank-evade critical section, this can't race.
 203         * Would be slightly nice to just grab the vblank count and arm the
 204         * event outside of the critical section - the spinlock might spin for a
 205         * while ... */
 206        if (new_crtc_state->uapi.event) {
 207                WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
 208
 209                spin_lock(&crtc->base.dev->event_lock);
 210                drm_crtc_arm_vblank_event(&crtc->base,
 211                                          new_crtc_state->uapi.event);
 212                spin_unlock(&crtc->base.dev->event_lock);
 213
 214                new_crtc_state->uapi.event = NULL;
 215        }
 216
 217        local_irq_enable();
 218
 219        if (intel_vgpu_active(dev_priv))
 220                return;
 221
 222        if (crtc->debug.start_vbl_count &&
 223            crtc->debug.start_vbl_count != end_vbl_count) {
 224                DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
 225                          pipe_name(pipe), crtc->debug.start_vbl_count,
 226                          end_vbl_count,
 227                          ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
 228                          crtc->debug.min_vbl, crtc->debug.max_vbl,
 229                          crtc->debug.scanline_start, scanline_end);
 230        }
 231#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
 232        else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
 233                 VBLANK_EVASION_TIME_US)
 234                DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
 235                         pipe_name(pipe),
 236                         ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
 237                         VBLANK_EVASION_TIME_US);
 238#endif
 239}
 240
 241int intel_plane_check_stride(const struct intel_plane_state *plane_state)
 242{
 243        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 244        const struct drm_framebuffer *fb = plane_state->hw.fb;
 245        unsigned int rotation = plane_state->hw.rotation;
 246        u32 stride, max_stride;
 247
 248        /*
 249         * We ignore stride for all invisible planes that
 250         * can be remapped. Otherwise we could end up
 251         * with a false positive when the remapping didn't
 252         * kick in due the plane being invisible.
 253         */
 254        if (intel_plane_can_remap(plane_state) &&
 255            !plane_state->uapi.visible)
 256                return 0;
 257
 258        /* FIXME other color planes? */
 259        stride = plane_state->color_plane[0].stride;
 260        max_stride = plane->max_stride(plane, fb->format->format,
 261                                       fb->modifier, rotation);
 262
 263        if (stride > max_stride) {
 264                DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
 265                              fb->base.id, stride,
 266                              plane->base.base.id, plane->base.name, max_stride);
 267                return -EINVAL;
 268        }
 269
 270        return 0;
 271}
 272
 273int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
 274{
 275        const struct drm_framebuffer *fb = plane_state->hw.fb;
 276        struct drm_rect *src = &plane_state->uapi.src;
 277        u32 src_x, src_y, src_w, src_h, hsub, vsub;
 278        bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
 279
 280        /*
 281         * Hardware doesn't handle subpixel coordinates.
 282         * Adjust to (macro)pixel boundary, but be careful not to
 283         * increase the source viewport size, because that could
 284         * push the downscaling factor out of bounds.
 285         */
 286        src_x = src->x1 >> 16;
 287        src_w = drm_rect_width(src) >> 16;
 288        src_y = src->y1 >> 16;
 289        src_h = drm_rect_height(src) >> 16;
 290
 291        drm_rect_init(src, src_x << 16, src_y << 16,
 292                      src_w << 16, src_h << 16);
 293
 294        if (!fb->format->is_yuv)
 295                return 0;
 296
 297        /* YUV specific checks */
 298        if (!rotated) {
 299                hsub = fb->format->hsub;
 300                vsub = fb->format->vsub;
 301        } else {
 302                hsub = vsub = max(fb->format->hsub, fb->format->vsub);
 303        }
 304
 305        if (src_x % hsub || src_w % hsub) {
 306                DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
 307                              src_x, src_w, hsub, rotated ? "rotated " : "");
 308                return -EINVAL;
 309        }
 310
 311        if (src_y % vsub || src_h % vsub) {
 312                DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
 313                              src_y, src_h, vsub, rotated ? "rotated " : "");
 314                return -EINVAL;
 315        }
 316
 317        return 0;
 318}
 319
 320bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
 321{
 322        return INTEL_GEN(dev_priv) >= 11 &&
 323                icl_hdr_plane_mask() & BIT(plane_id);
 324}
 325
 326static void
 327skl_plane_ratio(const struct intel_crtc_state *crtc_state,
 328                const struct intel_plane_state *plane_state,
 329                unsigned int *num, unsigned int *den)
 330{
 331        struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
 332        const struct drm_framebuffer *fb = plane_state->hw.fb;
 333
 334        if (fb->format->cpp[0] == 8) {
 335                if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
 336                        *num = 10;
 337                        *den = 8;
 338                } else {
 339                        *num = 9;
 340                        *den = 8;
 341                }
 342        } else {
 343                *num = 1;
 344                *den = 1;
 345        }
 346}
 347
 348static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 349                               const struct intel_plane_state *plane_state)
 350{
 351        struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
 352        unsigned int pixel_rate = crtc_state->pixel_rate;
 353        unsigned int src_w, src_h, dst_w, dst_h;
 354        unsigned int num, den;
 355
 356        skl_plane_ratio(crtc_state, plane_state, &num, &den);
 357
 358        /* two pixels per clock on glk+ */
 359        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 360                den *= 2;
 361
 362        src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 363        src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 364        dst_w = drm_rect_width(&plane_state->uapi.dst);
 365        dst_h = drm_rect_height(&plane_state->uapi.dst);
 366
 367        /* Downscaling limits the maximum pixel rate */
 368        dst_w = min(src_w, dst_w);
 369        dst_h = min(src_h, dst_h);
 370
 371        return DIV64_U64_ROUND_UP(mul_u32_u32(pixel_rate * num, src_w * src_h),
 372                                  mul_u32_u32(den, dst_w * dst_h));
 373}
 374
 375static unsigned int
 376skl_plane_max_stride(struct intel_plane *plane,
 377                     u32 pixel_format, u64 modifier,
 378                     unsigned int rotation)
 379{
 380        const struct drm_format_info *info = drm_format_info(pixel_format);
 381        int cpp = info->cpp[0];
 382
 383        /*
 384         * "The stride in bytes must not exceed the
 385         * of the size of 8K pixels and 32K bytes."
 386         */
 387        if (drm_rotation_90_or_270(rotation))
 388                return min(8192, 32768 / cpp);
 389        else
 390                return min(8192 * cpp, 32768);
 391}
 392
 393static void
 394skl_program_scaler(struct intel_plane *plane,
 395                   const struct intel_crtc_state *crtc_state,
 396                   const struct intel_plane_state *plane_state)
 397{
 398        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 399        const struct drm_framebuffer *fb = plane_state->hw.fb;
 400        enum pipe pipe = plane->pipe;
 401        int scaler_id = plane_state->scaler_id;
 402        const struct intel_scaler *scaler =
 403                &crtc_state->scaler_state.scalers[scaler_id];
 404        int crtc_x = plane_state->uapi.dst.x1;
 405        int crtc_y = plane_state->uapi.dst.y1;
 406        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
 407        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
 408        u16 y_hphase, uv_rgb_hphase;
 409        u16 y_vphase, uv_rgb_vphase;
 410        int hscale, vscale;
 411
 412        hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
 413                                      &plane_state->uapi.dst,
 414                                      0, INT_MAX);
 415        vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
 416                                      &plane_state->uapi.dst,
 417                                      0, INT_MAX);
 418
 419        /* TODO: handle sub-pixel coordinates */
 420        if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
 421            !icl_is_hdr_plane(dev_priv, plane->id)) {
 422                y_hphase = skl_scaler_calc_phase(1, hscale, false);
 423                y_vphase = skl_scaler_calc_phase(1, vscale, false);
 424
 425                /* MPEG2 chroma siting convention */
 426                uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
 427                uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
 428        } else {
 429                /* not used */
 430                y_hphase = 0;
 431                y_vphase = 0;
 432
 433                uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
 434                uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
 435        }
 436
 437        I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
 438                      PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
 439        I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
 440                      PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
 441        I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
 442                      PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
 443        I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
 444        I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
 445}
 446
 447/* Preoffset values for YUV to RGB Conversion */
 448#define PREOFF_YUV_TO_RGB_HI            0x1800
 449#define PREOFF_YUV_TO_RGB_ME            0x1F00
 450#define PREOFF_YUV_TO_RGB_LO            0x1800
 451
 452#define  ROFF(x)          (((x) & 0xffff) << 16)
 453#define  GOFF(x)          (((x) & 0xffff) << 0)
 454#define  BOFF(x)          (((x) & 0xffff) << 16)
 455
 456static void
 457icl_program_input_csc(struct intel_plane *plane,
 458                      const struct intel_crtc_state *crtc_state,
 459                      const struct intel_plane_state *plane_state)
 460{
 461        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 462        enum pipe pipe = plane->pipe;
 463        enum plane_id plane_id = plane->id;
 464
 465        static const u16 input_csc_matrix[][9] = {
 466                /*
 467                 * BT.601 full range YCbCr -> full range RGB
 468                 * The matrix required is :
 469                 * [1.000, 0.000, 1.371,
 470                 *  1.000, -0.336, -0.698,
 471                 *  1.000, 1.732, 0.0000]
 472                 */
 473                [DRM_COLOR_YCBCR_BT601] = {
 474                        0x7AF8, 0x7800, 0x0,
 475                        0x8B28, 0x7800, 0x9AC0,
 476                        0x0, 0x7800, 0x7DD8,
 477                },
 478                /*
 479                 * BT.709 full range YCbCr -> full range RGB
 480                 * The matrix required is :
 481                 * [1.000, 0.000, 1.574,
 482                 *  1.000, -0.187, -0.468,
 483                 *  1.000, 1.855, 0.0000]
 484                 */
 485                [DRM_COLOR_YCBCR_BT709] = {
 486                        0x7C98, 0x7800, 0x0,
 487                        0x9EF8, 0x7800, 0xAC00,
 488                        0x0, 0x7800,  0x7ED8,
 489                },
 490                /*
 491                 * BT.2020 full range YCbCr -> full range RGB
 492                 * The matrix required is :
 493                 * [1.000, 0.000, 1.474,
 494                 *  1.000, -0.1645, -0.5713,
 495                 *  1.000, 1.8814, 0.0000]
 496                 */
 497                [DRM_COLOR_YCBCR_BT2020] = {
 498                        0x7BC8, 0x7800, 0x0,
 499                        0x8928, 0x7800, 0xAA88,
 500                        0x0, 0x7800, 0x7F10,
 501                },
 502        };
 503
 504        /* Matrix for Limited Range to Full Range Conversion */
 505        static const u16 input_csc_matrix_lr[][9] = {
 506                /*
 507                 * BT.601 Limted range YCbCr -> full range RGB
 508                 * The matrix required is :
 509                 * [1.164384, 0.000, 1.596027,
 510                 *  1.164384, -0.39175, -0.812813,
 511                 *  1.164384, 2.017232, 0.0000]
 512                 */
 513                [DRM_COLOR_YCBCR_BT601] = {
 514                        0x7CC8, 0x7950, 0x0,
 515                        0x8D00, 0x7950, 0x9C88,
 516                        0x0, 0x7950, 0x6810,
 517                },
 518                /*
 519                 * BT.709 Limited range YCbCr -> full range RGB
 520                 * The matrix required is :
 521                 * [1.164384, 0.000, 1.792741,
 522                 *  1.164384, -0.213249, -0.532909,
 523                 *  1.164384, 2.112402, 0.0000]
 524                 */
 525                [DRM_COLOR_YCBCR_BT709] = {
 526                        0x7E58, 0x7950, 0x0,
 527                        0x8888, 0x7950, 0xADA8,
 528                        0x0, 0x7950,  0x6870,
 529                },
 530                /*
 531                 * BT.2020 Limited range YCbCr -> full range RGB
 532                 * The matrix required is :
 533                 * [1.164, 0.000, 1.678,
 534                 *  1.164, -0.1873, -0.6504,
 535                 *  1.164, 2.1417, 0.0000]
 536                 */
 537                [DRM_COLOR_YCBCR_BT2020] = {
 538                        0x7D70, 0x7950, 0x0,
 539                        0x8A68, 0x7950, 0xAC00,
 540                        0x0, 0x7950, 0x6890,
 541                },
 542        };
 543        const u16 *csc;
 544
 545        if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 546                csc = input_csc_matrix[plane_state->hw.color_encoding];
 547        else
 548                csc = input_csc_matrix_lr[plane_state->hw.color_encoding];
 549
 550        I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
 551                      GOFF(csc[1]));
 552        I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
 553        I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
 554                      GOFF(csc[4]));
 555        I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
 556        I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
 557                      GOFF(csc[7]));
 558        I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
 559
 560        I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
 561                      PREOFF_YUV_TO_RGB_HI);
 562        if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
 563                I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0);
 564        else
 565                I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
 566                              PREOFF_YUV_TO_RGB_ME);
 567        I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
 568                      PREOFF_YUV_TO_RGB_LO);
 569        I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
 570        I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
 571        I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
 572}
 573
 574static void
 575skl_program_plane(struct intel_plane *plane,
 576                  const struct intel_crtc_state *crtc_state,
 577                  const struct intel_plane_state *plane_state,
 578                  int color_plane)
 579{
 580        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 581        enum plane_id plane_id = plane->id;
 582        enum pipe pipe = plane->pipe;
 583        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 584        u32 surf_addr = plane_state->color_plane[color_plane].offset;
 585        u32 stride = skl_plane_stride(plane_state, color_plane);
 586        const struct drm_framebuffer *fb = plane_state->hw.fb;
 587        int aux_plane = intel_main_to_aux_plane(fb, color_plane);
 588        u32 aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
 589        u32 aux_stride = skl_plane_stride(plane_state, aux_plane);
 590        int crtc_x = plane_state->uapi.dst.x1;
 591        int crtc_y = plane_state->uapi.dst.y1;
 592        u32 x = plane_state->color_plane[color_plane].x;
 593        u32 y = plane_state->color_plane[color_plane].y;
 594        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 595        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 596        u8 alpha = plane_state->hw.alpha >> 8;
 597        u32 plane_color_ctl = 0;
 598        unsigned long irqflags;
 599        u32 keymsk, keymax;
 600        u32 plane_ctl = plane_state->ctl;
 601
 602        plane_ctl |= skl_plane_ctl_crtc(crtc_state);
 603
 604        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 605                plane_color_ctl = plane_state->color_ctl |
 606                        glk_plane_color_ctl_crtc(crtc_state);
 607
 608        /* Sizes are 0 based */
 609        src_w--;
 610        src_h--;
 611
 612        keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
 613
 614        keymsk = key->channel_mask & 0x7ffffff;
 615        if (alpha < 0xff)
 616                keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
 617
 618        /* The scaler will handle the output position */
 619        if (plane_state->scaler_id >= 0) {
 620                crtc_x = 0;
 621                crtc_y = 0;
 622        }
 623
 624        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 625
 626        I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
 627        I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
 628        I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
 629
 630        if (INTEL_GEN(dev_priv) < 12)
 631                aux_dist |= aux_stride;
 632        I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), aux_dist);
 633
 634        if (icl_is_hdr_plane(dev_priv, plane_id))
 635                I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), plane_state->cus_ctl);
 636
 637        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 638                I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
 639
 640        if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
 641                icl_program_input_csc(plane, crtc_state, plane_state);
 642
 643        skl_write_plane_wm(plane, crtc_state);
 644
 645        I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
 646        I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
 647        I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
 648
 649        I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
 650
 651        if (INTEL_GEN(dev_priv) < 11)
 652                I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
 653                              (plane_state->color_plane[1].y << 16) |
 654                              plane_state->color_plane[1].x);
 655
 656        /*
 657         * The control register self-arms if the plane was previously
 658         * disabled. Try to make the plane enable atomic by writing
 659         * the control register just before the surface register.
 660         */
 661        I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
 662        I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
 663                      intel_plane_ggtt_offset(plane_state) + surf_addr);
 664
 665        if (plane_state->scaler_id >= 0)
 666                skl_program_scaler(plane, crtc_state, plane_state);
 667
 668        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 669}
 670
 671static void
 672skl_update_plane(struct intel_plane *plane,
 673                 const struct intel_crtc_state *crtc_state,
 674                 const struct intel_plane_state *plane_state)
 675{
 676        int color_plane = 0;
 677
 678        if (plane_state->planar_linked_plane && !plane_state->planar_slave)
 679                /* Program the UV plane on planar master */
 680                color_plane = 1;
 681
 682        skl_program_plane(plane, crtc_state, plane_state, color_plane);
 683}
 684static void
 685skl_disable_plane(struct intel_plane *plane,
 686                  const struct intel_crtc_state *crtc_state)
 687{
 688        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 689        enum plane_id plane_id = plane->id;
 690        enum pipe pipe = plane->pipe;
 691        unsigned long irqflags;
 692
 693        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 694
 695        if (icl_is_hdr_plane(dev_priv, plane_id))
 696                I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
 697
 698        skl_write_plane_wm(plane, crtc_state);
 699
 700        I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
 701        I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
 702
 703        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 704}
 705
 706static bool
 707skl_plane_get_hw_state(struct intel_plane *plane,
 708                       enum pipe *pipe)
 709{
 710        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 711        enum intel_display_power_domain power_domain;
 712        enum plane_id plane_id = plane->id;
 713        intel_wakeref_t wakeref;
 714        bool ret;
 715
 716        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 717        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 718        if (!wakeref)
 719                return false;
 720
 721        ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
 722
 723        *pipe = plane->pipe;
 724
 725        intel_display_power_put(dev_priv, power_domain, wakeref);
 726
 727        return ret;
 728}
 729
 730static void i9xx_plane_linear_gamma(u16 gamma[8])
 731{
 732        /* The points are not evenly spaced. */
 733        static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
 734        int i;
 735
 736        for (i = 0; i < 8; i++)
 737                gamma[i] = (in[i] << 8) / 32;
 738}
 739
 740static void
 741chv_update_csc(const struct intel_plane_state *plane_state)
 742{
 743        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 744        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 745        const struct drm_framebuffer *fb = plane_state->hw.fb;
 746        enum plane_id plane_id = plane->id;
 747        /*
 748         * |r|   | c0 c1 c2 |   |cr|
 749         * |g| = | c3 c4 c5 | x |y |
 750         * |b|   | c6 c7 c8 |   |cb|
 751         *
 752         * Coefficients are s3.12.
 753         *
 754         * Cb and Cr apparently come in as signed already, and
 755         * we always get full range data in on account of CLRC0/1.
 756         */
 757        static const s16 csc_matrix[][9] = {
 758                /* BT.601 full range YCbCr -> full range RGB */
 759                [DRM_COLOR_YCBCR_BT601] = {
 760                         5743, 4096,     0,
 761                        -2925, 4096, -1410,
 762                            0, 4096,  7258,
 763                },
 764                /* BT.709 full range YCbCr -> full range RGB */
 765                [DRM_COLOR_YCBCR_BT709] = {
 766                         6450, 4096,     0,
 767                        -1917, 4096,  -767,
 768                            0, 4096,  7601,
 769                },
 770        };
 771        const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
 772
 773        /* Seems RGB data bypasses the CSC always */
 774        if (!fb->format->is_yuv)
 775                return;
 776
 777        I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 778        I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 779        I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
 780
 781        I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
 782        I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
 783        I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
 784        I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
 785        I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
 786
 787        I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
 788        I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 789        I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
 790
 791        I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 792        I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 793        I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
 794}
 795
 796#define SIN_0 0
 797#define COS_0 1
 798
 799static void
 800vlv_update_clrc(const struct intel_plane_state *plane_state)
 801{
 802        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 803        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 804        const struct drm_framebuffer *fb = plane_state->hw.fb;
 805        enum pipe pipe = plane->pipe;
 806        enum plane_id plane_id = plane->id;
 807        int contrast, brightness, sh_scale, sh_sin, sh_cos;
 808
 809        if (fb->format->is_yuv &&
 810            plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
 811                /*
 812                 * Expand limited range to full range:
 813                 * Contrast is applied first and is used to expand Y range.
 814                 * Brightness is applied second and is used to remove the
 815                 * offset from Y. Saturation/hue is used to expand CbCr range.
 816                 */
 817                contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
 818                brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
 819                sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
 820                sh_sin = SIN_0 * sh_scale;
 821                sh_cos = COS_0 * sh_scale;
 822        } else {
 823                /* Pass-through everything. */
 824                contrast = 1 << 6;
 825                brightness = 0;
 826                sh_scale = 1 << 7;
 827                sh_sin = SIN_0 * sh_scale;
 828                sh_cos = COS_0 * sh_scale;
 829        }
 830
 831        /* FIXME these register are single buffered :( */
 832        I915_WRITE_FW(SPCLRC0(pipe, plane_id),
 833                      SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
 834        I915_WRITE_FW(SPCLRC1(pipe, plane_id),
 835                      SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
 836}
 837
 838static void
 839vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
 840                const struct intel_plane_state *plane_state,
 841                unsigned int *num, unsigned int *den)
 842{
 843        u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
 844        const struct drm_framebuffer *fb = plane_state->hw.fb;
 845        unsigned int cpp = fb->format->cpp[0];
 846
 847        /*
 848         * VLV bspec only considers cases where all three planes are
 849         * enabled, and cases where the primary and one sprite is enabled.
 850         * Let's assume the case with just two sprites enabled also
 851         * maps to the latter case.
 852         */
 853        if (hweight8(active_planes) == 3) {
 854                switch (cpp) {
 855                case 8:
 856                        *num = 11;
 857                        *den = 8;
 858                        break;
 859                case 4:
 860                        *num = 18;
 861                        *den = 16;
 862                        break;
 863                default:
 864                        *num = 1;
 865                        *den = 1;
 866                        break;
 867                }
 868        } else if (hweight8(active_planes) == 2) {
 869                switch (cpp) {
 870                case 8:
 871                        *num = 10;
 872                        *den = 8;
 873                        break;
 874                case 4:
 875                        *num = 17;
 876                        *den = 16;
 877                        break;
 878                default:
 879                        *num = 1;
 880                        *den = 1;
 881                        break;
 882                }
 883        } else {
 884                switch (cpp) {
 885                case 8:
 886                        *num = 10;
 887                        *den = 8;
 888                        break;
 889                default:
 890                        *num = 1;
 891                        *den = 1;
 892                        break;
 893                }
 894        }
 895}
 896
 897int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 898                        const struct intel_plane_state *plane_state)
 899{
 900        unsigned int pixel_rate;
 901        unsigned int num, den;
 902
 903        /*
 904         * Note that crtc_state->pixel_rate accounts for both
 905         * horizontal and vertical panel fitter downscaling factors.
 906         * Pre-HSW bspec tells us to only consider the horizontal
 907         * downscaling factor here. We ignore that and just consider
 908         * both for simplicity.
 909         */
 910        pixel_rate = crtc_state->pixel_rate;
 911
 912        vlv_plane_ratio(crtc_state, plane_state, &num, &den);
 913
 914        return DIV_ROUND_UP(pixel_rate * num, den);
 915}
 916
 917static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
 918{
 919        u32 sprctl = 0;
 920
 921        if (crtc_state->gamma_enable)
 922                sprctl |= SP_GAMMA_ENABLE;
 923
 924        return sprctl;
 925}
 926
 927static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
 928                          const struct intel_plane_state *plane_state)
 929{
 930        const struct drm_framebuffer *fb = plane_state->hw.fb;
 931        unsigned int rotation = plane_state->hw.rotation;
 932        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 933        u32 sprctl;
 934
 935        sprctl = SP_ENABLE;
 936
 937        switch (fb->format->format) {
 938        case DRM_FORMAT_YUYV:
 939                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
 940                break;
 941        case DRM_FORMAT_YVYU:
 942                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
 943                break;
 944        case DRM_FORMAT_UYVY:
 945                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
 946                break;
 947        case DRM_FORMAT_VYUY:
 948                sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
 949                break;
 950        case DRM_FORMAT_C8:
 951                sprctl |= SP_FORMAT_8BPP;
 952                break;
 953        case DRM_FORMAT_RGB565:
 954                sprctl |= SP_FORMAT_BGR565;
 955                break;
 956        case DRM_FORMAT_XRGB8888:
 957                sprctl |= SP_FORMAT_BGRX8888;
 958                break;
 959        case DRM_FORMAT_ARGB8888:
 960                sprctl |= SP_FORMAT_BGRA8888;
 961                break;
 962        case DRM_FORMAT_XBGR2101010:
 963                sprctl |= SP_FORMAT_RGBX1010102;
 964                break;
 965        case DRM_FORMAT_ABGR2101010:
 966                sprctl |= SP_FORMAT_RGBA1010102;
 967                break;
 968        case DRM_FORMAT_XRGB2101010:
 969                sprctl |= SP_FORMAT_BGRX1010102;
 970                break;
 971        case DRM_FORMAT_ARGB2101010:
 972                sprctl |= SP_FORMAT_BGRA1010102;
 973                break;
 974        case DRM_FORMAT_XBGR8888:
 975                sprctl |= SP_FORMAT_RGBX8888;
 976                break;
 977        case DRM_FORMAT_ABGR8888:
 978                sprctl |= SP_FORMAT_RGBA8888;
 979                break;
 980        default:
 981                MISSING_CASE(fb->format->format);
 982                return 0;
 983        }
 984
 985        if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
 986                sprctl |= SP_YUV_FORMAT_BT709;
 987
 988        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 989                sprctl |= SP_TILED;
 990
 991        if (rotation & DRM_MODE_ROTATE_180)
 992                sprctl |= SP_ROTATE_180;
 993
 994        if (rotation & DRM_MODE_REFLECT_X)
 995                sprctl |= SP_MIRROR;
 996
 997        if (key->flags & I915_SET_COLORKEY_SOURCE)
 998                sprctl |= SP_SOURCE_KEY;
 999
1000        return sprctl;
1001}
1002
1003static void vlv_update_gamma(const struct intel_plane_state *plane_state)
1004{
1005        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1006        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1007        const struct drm_framebuffer *fb = plane_state->hw.fb;
1008        enum pipe pipe = plane->pipe;
1009        enum plane_id plane_id = plane->id;
1010        u16 gamma[8];
1011        int i;
1012
1013        /* Seems RGB data bypasses the gamma always */
1014        if (!fb->format->is_yuv)
1015                return;
1016
1017        i9xx_plane_linear_gamma(gamma);
1018
1019        /* FIXME these register are single buffered :( */
1020        /* The two end points are implicit (0.0 and 1.0) */
1021        for (i = 1; i < 8 - 1; i++)
1022                I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
1023                              gamma[i] << 16 |
1024                              gamma[i] << 8 |
1025                              gamma[i]);
1026}
1027
1028static void
1029vlv_update_plane(struct intel_plane *plane,
1030                 const struct intel_crtc_state *crtc_state,
1031                 const struct intel_plane_state *plane_state)
1032{
1033        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1034        enum pipe pipe = plane->pipe;
1035        enum plane_id plane_id = plane->id;
1036        u32 sprsurf_offset = plane_state->color_plane[0].offset;
1037        u32 linear_offset;
1038        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1039        int crtc_x = plane_state->uapi.dst.x1;
1040        int crtc_y = plane_state->uapi.dst.y1;
1041        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1042        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1043        u32 x = plane_state->color_plane[0].x;
1044        u32 y = plane_state->color_plane[0].y;
1045        unsigned long irqflags;
1046        u32 sprctl;
1047
1048        sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
1049
1050        /* Sizes are 0 based */
1051        crtc_w--;
1052        crtc_h--;
1053
1054        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1055
1056        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1057
1058        I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
1059                      plane_state->color_plane[0].stride);
1060        I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
1061        I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
1062        I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
1063
1064        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
1065                chv_update_csc(plane_state);
1066
1067        if (key->flags) {
1068                I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
1069                I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
1070                I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
1071        }
1072
1073        I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
1074        I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
1075
1076        /*
1077         * The control register self-arms if the plane was previously
1078         * disabled. Try to make the plane enable atomic by writing
1079         * the control register just before the surface register.
1080         */
1081        I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
1082        I915_WRITE_FW(SPSURF(pipe, plane_id),
1083                      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1084
1085        vlv_update_clrc(plane_state);
1086        vlv_update_gamma(plane_state);
1087
1088        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1089}
1090
1091static void
1092vlv_disable_plane(struct intel_plane *plane,
1093                  const struct intel_crtc_state *crtc_state)
1094{
1095        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1096        enum pipe pipe = plane->pipe;
1097        enum plane_id plane_id = plane->id;
1098        unsigned long irqflags;
1099
1100        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1101
1102        I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
1103        I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
1104
1105        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1106}
1107
1108static bool
1109vlv_plane_get_hw_state(struct intel_plane *plane,
1110                       enum pipe *pipe)
1111{
1112        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1113        enum intel_display_power_domain power_domain;
1114        enum plane_id plane_id = plane->id;
1115        intel_wakeref_t wakeref;
1116        bool ret;
1117
1118        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1119        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1120        if (!wakeref)
1121                return false;
1122
1123        ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1124
1125        *pipe = plane->pipe;
1126
1127        intel_display_power_put(dev_priv, power_domain, wakeref);
1128
1129        return ret;
1130}
1131
1132static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
1133                            const struct intel_plane_state *plane_state,
1134                            unsigned int *num, unsigned int *den)
1135{
1136        u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1137        const struct drm_framebuffer *fb = plane_state->hw.fb;
1138        unsigned int cpp = fb->format->cpp[0];
1139
1140        if (hweight8(active_planes) == 2) {
1141                switch (cpp) {
1142                case 8:
1143                        *num = 10;
1144                        *den = 8;
1145                        break;
1146                case 4:
1147                        *num = 17;
1148                        *den = 16;
1149                        break;
1150                default:
1151                        *num = 1;
1152                        *den = 1;
1153                        break;
1154                }
1155        } else {
1156                switch (cpp) {
1157                case 8:
1158                        *num = 9;
1159                        *den = 8;
1160                        break;
1161                default:
1162                        *num = 1;
1163                        *den = 1;
1164                        break;
1165                }
1166        }
1167}
1168
1169static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
1170                                    const struct intel_plane_state *plane_state,
1171                                    unsigned int *num, unsigned int *den)
1172{
1173        const struct drm_framebuffer *fb = plane_state->hw.fb;
1174        unsigned int cpp = fb->format->cpp[0];
1175
1176        switch (cpp) {
1177        case 8:
1178                *num = 12;
1179                *den = 8;
1180                break;
1181        case 4:
1182                *num = 19;
1183                *den = 16;
1184                break;
1185        case 2:
1186                *num = 33;
1187                *den = 32;
1188                break;
1189        default:
1190                *num = 1;
1191                *den = 1;
1192                break;
1193        }
1194}
1195
1196int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1197                        const struct intel_plane_state *plane_state)
1198{
1199        unsigned int pixel_rate;
1200        unsigned int num, den;
1201
1202        /*
1203         * Note that crtc_state->pixel_rate accounts for both
1204         * horizontal and vertical panel fitter downscaling factors.
1205         * Pre-HSW bspec tells us to only consider the horizontal
1206         * downscaling factor here. We ignore that and just consider
1207         * both for simplicity.
1208         */
1209        pixel_rate = crtc_state->pixel_rate;
1210
1211        ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1212
1213        return DIV_ROUND_UP(pixel_rate * num, den);
1214}
1215
1216static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1217                                const struct intel_plane_state *plane_state)
1218{
1219        unsigned int src_w, dst_w, pixel_rate;
1220        unsigned int num, den;
1221
1222        /*
1223         * Note that crtc_state->pixel_rate accounts for both
1224         * horizontal and vertical panel fitter downscaling factors.
1225         * Pre-HSW bspec tells us to only consider the horizontal
1226         * downscaling factor here. We ignore that and just consider
1227         * both for simplicity.
1228         */
1229        pixel_rate = crtc_state->pixel_rate;
1230
1231        src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1232        dst_w = drm_rect_width(&plane_state->uapi.dst);
1233
1234        if (src_w != dst_w)
1235                ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
1236        else
1237                ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1238
1239        /* Horizontal downscaling limits the maximum pixel rate */
1240        dst_w = min(src_w, dst_w);
1241
1242        return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
1243                                den * dst_w);
1244}
1245
1246static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
1247                            const struct intel_plane_state *plane_state,
1248                            unsigned int *num, unsigned int *den)
1249{
1250        u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1251        const struct drm_framebuffer *fb = plane_state->hw.fb;
1252        unsigned int cpp = fb->format->cpp[0];
1253
1254        if (hweight8(active_planes) == 2) {
1255                switch (cpp) {
1256                case 8:
1257                        *num = 10;
1258                        *den = 8;
1259                        break;
1260                default:
1261                        *num = 1;
1262                        *den = 1;
1263                        break;
1264                }
1265        } else {
1266                switch (cpp) {
1267                case 8:
1268                        *num = 9;
1269                        *den = 8;
1270                        break;
1271                default:
1272                        *num = 1;
1273                        *den = 1;
1274                        break;
1275                }
1276        }
1277}
1278
1279int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1280                        const struct intel_plane_state *plane_state)
1281{
1282        unsigned int pixel_rate = crtc_state->pixel_rate;
1283        unsigned int num, den;
1284
1285        hsw_plane_ratio(crtc_state, plane_state, &num, &den);
1286
1287        return DIV_ROUND_UP(pixel_rate * num, den);
1288}
1289
1290static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1291{
1292        u32 sprctl = 0;
1293
1294        if (crtc_state->gamma_enable)
1295                sprctl |= SPRITE_GAMMA_ENABLE;
1296
1297        if (crtc_state->csc_enable)
1298                sprctl |= SPRITE_PIPE_CSC_ENABLE;
1299
1300        return sprctl;
1301}
1302
1303static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
1304{
1305        struct drm_i915_private *dev_priv =
1306                to_i915(plane_state->uapi.plane->dev);
1307        const struct drm_framebuffer *fb = plane_state->hw.fb;
1308
1309        return fb->format->cpp[0] == 8 &&
1310                (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
1311}
1312
1313static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1314                          const struct intel_plane_state *plane_state)
1315{
1316        struct drm_i915_private *dev_priv =
1317                to_i915(plane_state->uapi.plane->dev);
1318        const struct drm_framebuffer *fb = plane_state->hw.fb;
1319        unsigned int rotation = plane_state->hw.rotation;
1320        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1321        u32 sprctl;
1322
1323        sprctl = SPRITE_ENABLE;
1324
1325        if (IS_IVYBRIDGE(dev_priv))
1326                sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1327
1328        switch (fb->format->format) {
1329        case DRM_FORMAT_XBGR8888:
1330                sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1331                break;
1332        case DRM_FORMAT_XRGB8888:
1333                sprctl |= SPRITE_FORMAT_RGBX888;
1334                break;
1335        case DRM_FORMAT_XBGR2101010:
1336                sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
1337                break;
1338        case DRM_FORMAT_XRGB2101010:
1339                sprctl |= SPRITE_FORMAT_RGBX101010;
1340                break;
1341        case DRM_FORMAT_XBGR16161616F:
1342                sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
1343                break;
1344        case DRM_FORMAT_XRGB16161616F:
1345                sprctl |= SPRITE_FORMAT_RGBX161616;
1346                break;
1347        case DRM_FORMAT_YUYV:
1348                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1349                break;
1350        case DRM_FORMAT_YVYU:
1351                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1352                break;
1353        case DRM_FORMAT_UYVY:
1354                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1355                break;
1356        case DRM_FORMAT_VYUY:
1357                sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1358                break;
1359        default:
1360                MISSING_CASE(fb->format->format);
1361                return 0;
1362        }
1363
1364        if (!ivb_need_sprite_gamma(plane_state))
1365                sprctl |= SPRITE_INT_GAMMA_DISABLE;
1366
1367        if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1368                sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1369
1370        if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1371                sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1372
1373        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1374                sprctl |= SPRITE_TILED;
1375
1376        if (rotation & DRM_MODE_ROTATE_180)
1377                sprctl |= SPRITE_ROTATE_180;
1378
1379        if (key->flags & I915_SET_COLORKEY_DESTINATION)
1380                sprctl |= SPRITE_DEST_KEY;
1381        else if (key->flags & I915_SET_COLORKEY_SOURCE)
1382                sprctl |= SPRITE_SOURCE_KEY;
1383
1384        return sprctl;
1385}
1386
1387static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
1388                                    u16 gamma[18])
1389{
1390        int scale, i;
1391
1392        /*
1393         * WaFP16GammaEnabling:ivb,hsw
1394         * "Workaround : When using the 64-bit format, the sprite output
1395         *  on each color channel has one quarter amplitude. It can be
1396         *  brought up to full amplitude by using sprite internal gamma
1397         *  correction, pipe gamma correction, or pipe color space
1398         *  conversion to multiply the sprite output by four."
1399         */
1400        scale = 4;
1401
1402        for (i = 0; i < 16; i++)
1403                gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
1404
1405        gamma[i] = min((scale * i << 10) / 16, 1 << 10);
1406        i++;
1407
1408        gamma[i] = 3 << 10;
1409        i++;
1410}
1411
1412static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1413{
1414        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1415        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1416        enum pipe pipe = plane->pipe;
1417        u16 gamma[18];
1418        int i;
1419
1420        if (!ivb_need_sprite_gamma(plane_state))
1421                return;
1422
1423        ivb_sprite_linear_gamma(plane_state, gamma);
1424
1425        /* FIXME these register are single buffered :( */
1426        for (i = 0; i < 16; i++)
1427                I915_WRITE_FW(SPRGAMC(pipe, i),
1428                              gamma[i] << 20 |
1429                              gamma[i] << 10 |
1430                              gamma[i]);
1431
1432        I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
1433        I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
1434        I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
1435        i++;
1436
1437        I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
1438        I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
1439        I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
1440        i++;
1441}
1442
1443static void
1444ivb_update_plane(struct intel_plane *plane,
1445                 const struct intel_crtc_state *crtc_state,
1446                 const struct intel_plane_state *plane_state)
1447{
1448        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1449        enum pipe pipe = plane->pipe;
1450        u32 sprsurf_offset = plane_state->color_plane[0].offset;
1451        u32 linear_offset;
1452        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1453        int crtc_x = plane_state->uapi.dst.x1;
1454        int crtc_y = plane_state->uapi.dst.y1;
1455        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1456        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1457        u32 x = plane_state->color_plane[0].x;
1458        u32 y = plane_state->color_plane[0].y;
1459        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1460        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1461        u32 sprctl, sprscale = 0;
1462        unsigned long irqflags;
1463
1464        sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1465
1466        /* Sizes are 0 based */
1467        src_w--;
1468        src_h--;
1469        crtc_w--;
1470        crtc_h--;
1471
1472        if (crtc_w != src_w || crtc_h != src_h)
1473                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1474
1475        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1476
1477        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1478
1479        I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1480        I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1481        I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1482        if (IS_IVYBRIDGE(dev_priv))
1483                I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1484
1485        if (key->flags) {
1486                I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1487                I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1488                I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1489        }
1490
1491        /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1492         * register */
1493        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1494                I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1495        } else {
1496                I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1497                I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1498        }
1499
1500        /*
1501         * The control register self-arms if the plane was previously
1502         * disabled. Try to make the plane enable atomic by writing
1503         * the control register just before the surface register.
1504         */
1505        I915_WRITE_FW(SPRCTL(pipe), sprctl);
1506        I915_WRITE_FW(SPRSURF(pipe),
1507                      intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1508
1509        ivb_update_gamma(plane_state);
1510
1511        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1512}
1513
1514static void
1515ivb_disable_plane(struct intel_plane *plane,
1516                  const struct intel_crtc_state *crtc_state)
1517{
1518        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1519        enum pipe pipe = plane->pipe;
1520        unsigned long irqflags;
1521
1522        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1523
1524        I915_WRITE_FW(SPRCTL(pipe), 0);
1525        /* Disable the scaler */
1526        if (IS_IVYBRIDGE(dev_priv))
1527                I915_WRITE_FW(SPRSCALE(pipe), 0);
1528        I915_WRITE_FW(SPRSURF(pipe), 0);
1529
1530        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1531}
1532
1533static bool
1534ivb_plane_get_hw_state(struct intel_plane *plane,
1535                       enum pipe *pipe)
1536{
1537        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1538        enum intel_display_power_domain power_domain;
1539        intel_wakeref_t wakeref;
1540        bool ret;
1541
1542        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1543        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1544        if (!wakeref)
1545                return false;
1546
1547        ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1548
1549        *pipe = plane->pipe;
1550
1551        intel_display_power_put(dev_priv, power_domain, wakeref);
1552
1553        return ret;
1554}
1555
1556static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1557                                const struct intel_plane_state *plane_state)
1558{
1559        const struct drm_framebuffer *fb = plane_state->hw.fb;
1560        unsigned int hscale, pixel_rate;
1561        unsigned int limit, decimate;
1562
1563        /*
1564         * Note that crtc_state->pixel_rate accounts for both
1565         * horizontal and vertical panel fitter downscaling factors.
1566         * Pre-HSW bspec tells us to only consider the horizontal
1567         * downscaling factor here. We ignore that and just consider
1568         * both for simplicity.
1569         */
1570        pixel_rate = crtc_state->pixel_rate;
1571
1572        /* Horizontal downscaling limits the maximum pixel rate */
1573        hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
1574                                      &plane_state->uapi.dst,
1575                                      0, INT_MAX);
1576        if (hscale < 0x10000)
1577                return pixel_rate;
1578
1579        /* Decimation steps at 2x,4x,8x,16x */
1580        decimate = ilog2(hscale >> 16);
1581        hscale >>= decimate;
1582
1583        /* Starting limit is 90% of cdclk */
1584        limit = 9;
1585
1586        /* -10% per decimation step */
1587        limit -= decimate;
1588
1589        /* -10% for RGB */
1590        if (fb->format->cpp[0] >= 4)
1591                limit--; /* -10% for RGB */
1592
1593        /*
1594         * We should also do -10% if sprite scaling is enabled
1595         * on the other pipe, but we can't really check for that,
1596         * so we ignore it.
1597         */
1598
1599        return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
1600                                limit << 16);
1601}
1602
1603static unsigned int
1604g4x_sprite_max_stride(struct intel_plane *plane,
1605                      u32 pixel_format, u64 modifier,
1606                      unsigned int rotation)
1607{
1608        return 16384;
1609}
1610
1611static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1612{
1613        u32 dvscntr = 0;
1614
1615        if (crtc_state->gamma_enable)
1616                dvscntr |= DVS_GAMMA_ENABLE;
1617
1618        if (crtc_state->csc_enable)
1619                dvscntr |= DVS_PIPE_CSC_ENABLE;
1620
1621        return dvscntr;
1622}
1623
1624static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1625                          const struct intel_plane_state *plane_state)
1626{
1627        struct drm_i915_private *dev_priv =
1628                to_i915(plane_state->uapi.plane->dev);
1629        const struct drm_framebuffer *fb = plane_state->hw.fb;
1630        unsigned int rotation = plane_state->hw.rotation;
1631        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1632        u32 dvscntr;
1633
1634        dvscntr = DVS_ENABLE;
1635
1636        if (IS_GEN(dev_priv, 6))
1637                dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1638
1639        switch (fb->format->format) {
1640        case DRM_FORMAT_XBGR8888:
1641                dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1642                break;
1643        case DRM_FORMAT_XRGB8888:
1644                dvscntr |= DVS_FORMAT_RGBX888;
1645                break;
1646        case DRM_FORMAT_XBGR2101010:
1647                dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1648                break;
1649        case DRM_FORMAT_XRGB2101010:
1650                dvscntr |= DVS_FORMAT_RGBX101010;
1651                break;
1652        case DRM_FORMAT_XBGR16161616F:
1653                dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1654                break;
1655        case DRM_FORMAT_XRGB16161616F:
1656                dvscntr |= DVS_FORMAT_RGBX161616;
1657                break;
1658        case DRM_FORMAT_YUYV:
1659                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1660                break;
1661        case DRM_FORMAT_YVYU:
1662                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1663                break;
1664        case DRM_FORMAT_UYVY:
1665                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1666                break;
1667        case DRM_FORMAT_VYUY:
1668                dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1669                break;
1670        default:
1671                MISSING_CASE(fb->format->format);
1672                return 0;
1673        }
1674
1675        if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1676                dvscntr |= DVS_YUV_FORMAT_BT709;
1677
1678        if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1679                dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1680
1681        if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1682                dvscntr |= DVS_TILED;
1683
1684        if (rotation & DRM_MODE_ROTATE_180)
1685                dvscntr |= DVS_ROTATE_180;
1686
1687        if (key->flags & I915_SET_COLORKEY_DESTINATION)
1688                dvscntr |= DVS_DEST_KEY;
1689        else if (key->flags & I915_SET_COLORKEY_SOURCE)
1690                dvscntr |= DVS_SOURCE_KEY;
1691
1692        return dvscntr;
1693}
1694
1695static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1696{
1697        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1698        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1699        const struct drm_framebuffer *fb = plane_state->hw.fb;
1700        enum pipe pipe = plane->pipe;
1701        u16 gamma[8];
1702        int i;
1703
1704        /* Seems RGB data bypasses the gamma always */
1705        if (!fb->format->is_yuv)
1706                return;
1707
1708        i9xx_plane_linear_gamma(gamma);
1709
1710        /* FIXME these register are single buffered :( */
1711        /* The two end points are implicit (0.0 and 1.0) */
1712        for (i = 1; i < 8 - 1; i++)
1713                I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
1714                              gamma[i] << 16 |
1715                              gamma[i] << 8 |
1716                              gamma[i]);
1717}
1718
1719static void ilk_sprite_linear_gamma(u16 gamma[17])
1720{
1721        int i;
1722
1723        for (i = 0; i < 17; i++)
1724                gamma[i] = (i << 10) / 16;
1725}
1726
1727static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1728{
1729        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1730        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1731        const struct drm_framebuffer *fb = plane_state->hw.fb;
1732        enum pipe pipe = plane->pipe;
1733        u16 gamma[17];
1734        int i;
1735
1736        /* Seems RGB data bypasses the gamma always */
1737        if (!fb->format->is_yuv)
1738                return;
1739
1740        ilk_sprite_linear_gamma(gamma);
1741
1742        /* FIXME these register are single buffered :( */
1743        for (i = 0; i < 16; i++)
1744                I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
1745                              gamma[i] << 20 |
1746                              gamma[i] << 10 |
1747                              gamma[i]);
1748
1749        I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1750        I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1751        I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1752        i++;
1753}
1754
1755static void
1756g4x_update_plane(struct intel_plane *plane,
1757                 const struct intel_crtc_state *crtc_state,
1758                 const struct intel_plane_state *plane_state)
1759{
1760        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1761        enum pipe pipe = plane->pipe;
1762        u32 dvssurf_offset = plane_state->color_plane[0].offset;
1763        u32 linear_offset;
1764        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1765        int crtc_x = plane_state->uapi.dst.x1;
1766        int crtc_y = plane_state->uapi.dst.y1;
1767        u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1768        u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1769        u32 x = plane_state->color_plane[0].x;
1770        u32 y = plane_state->color_plane[0].y;
1771        u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1772        u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1773        u32 dvscntr, dvsscale = 0;
1774        unsigned long irqflags;
1775
1776        dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1777
1778        /* Sizes are 0 based */
1779        src_w--;
1780        src_h--;
1781        crtc_w--;
1782        crtc_h--;
1783
1784        if (crtc_w != src_w || crtc_h != src_h)
1785                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1786
1787        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1788
1789        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1790
1791        I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1792        I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1793        I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1794        I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1795
1796        if (key->flags) {
1797                I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1798                I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1799                I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1800        }
1801
1802        I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1803        I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1804
1805        /*
1806         * The control register self-arms if the plane was previously
1807         * disabled. Try to make the plane enable atomic by writing
1808         * the control register just before the surface register.
1809         */
1810        I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1811        I915_WRITE_FW(DVSSURF(pipe),
1812                      intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1813
1814        if (IS_G4X(dev_priv))
1815                g4x_update_gamma(plane_state);
1816        else
1817                ilk_update_gamma(plane_state);
1818
1819        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1820}
1821
1822static void
1823g4x_disable_plane(struct intel_plane *plane,
1824                  const struct intel_crtc_state *crtc_state)
1825{
1826        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1827        enum pipe pipe = plane->pipe;
1828        unsigned long irqflags;
1829
1830        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1831
1832        I915_WRITE_FW(DVSCNTR(pipe), 0);
1833        /* Disable the scaler */
1834        I915_WRITE_FW(DVSSCALE(pipe), 0);
1835        I915_WRITE_FW(DVSSURF(pipe), 0);
1836
1837        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1838}
1839
1840static bool
1841g4x_plane_get_hw_state(struct intel_plane *plane,
1842                       enum pipe *pipe)
1843{
1844        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1845        enum intel_display_power_domain power_domain;
1846        intel_wakeref_t wakeref;
1847        bool ret;
1848
1849        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1850        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1851        if (!wakeref)
1852                return false;
1853
1854        ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1855
1856        *pipe = plane->pipe;
1857
1858        intel_display_power_put(dev_priv, power_domain, wakeref);
1859
1860        return ret;
1861}
1862
1863static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1864{
1865        if (!fb)
1866                return false;
1867
1868        switch (fb->format->format) {
1869        case DRM_FORMAT_C8:
1870                return false;
1871        case DRM_FORMAT_XRGB16161616F:
1872        case DRM_FORMAT_ARGB16161616F:
1873        case DRM_FORMAT_XBGR16161616F:
1874        case DRM_FORMAT_ABGR16161616F:
1875                return INTEL_GEN(to_i915(fb->dev)) >= 11;
1876        default:
1877                return true;
1878        }
1879}
1880
1881static int
1882g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1883                         struct intel_plane_state *plane_state)
1884{
1885        const struct drm_framebuffer *fb = plane_state->hw.fb;
1886        const struct drm_rect *src = &plane_state->uapi.src;
1887        const struct drm_rect *dst = &plane_state->uapi.dst;
1888        int src_x, src_w, src_h, crtc_w, crtc_h;
1889        const struct drm_display_mode *adjusted_mode =
1890                &crtc_state->hw.adjusted_mode;
1891        unsigned int stride = plane_state->color_plane[0].stride;
1892        unsigned int cpp = fb->format->cpp[0];
1893        unsigned int width_bytes;
1894        int min_width, min_height;
1895
1896        crtc_w = drm_rect_width(dst);
1897        crtc_h = drm_rect_height(dst);
1898
1899        src_x = src->x1 >> 16;
1900        src_w = drm_rect_width(src) >> 16;
1901        src_h = drm_rect_height(src) >> 16;
1902
1903        if (src_w == crtc_w && src_h == crtc_h)
1904                return 0;
1905
1906        min_width = 3;
1907
1908        if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1909                if (src_h & 1) {
1910                        DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1911                        return -EINVAL;
1912                }
1913                min_height = 6;
1914        } else {
1915                min_height = 3;
1916        }
1917
1918        width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1919
1920        if (src_w < min_width || src_h < min_height ||
1921            src_w > 2048 || src_h > 2048) {
1922                DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1923                              src_w, src_h, min_width, min_height, 2048, 2048);
1924                return -EINVAL;
1925        }
1926
1927        if (width_bytes > 4096) {
1928                DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1929                              width_bytes, 4096);
1930                return -EINVAL;
1931        }
1932
1933        if (stride > 4096) {
1934                DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1935                              stride, 4096);
1936                return -EINVAL;
1937        }
1938
1939        return 0;
1940}
1941
1942static int
1943g4x_sprite_check(struct intel_crtc_state *crtc_state,
1944                 struct intel_plane_state *plane_state)
1945{
1946        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1947        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1948        int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1949        int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1950        int ret;
1951
1952        if (intel_fb_scalable(plane_state->hw.fb)) {
1953                if (INTEL_GEN(dev_priv) < 7) {
1954                        min_scale = 1;
1955                        max_scale = 16 << 16;
1956                } else if (IS_IVYBRIDGE(dev_priv)) {
1957                        min_scale = 1;
1958                        max_scale = 2 << 16;
1959                }
1960        }
1961
1962        ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
1963                                                  &crtc_state->uapi,
1964                                                  min_scale, max_scale,
1965                                                  true, true);
1966        if (ret)
1967                return ret;
1968
1969        ret = i9xx_check_plane_surface(plane_state);
1970        if (ret)
1971                return ret;
1972
1973        if (!plane_state->uapi.visible)
1974                return 0;
1975
1976        ret = intel_plane_check_src_coordinates(plane_state);
1977        if (ret)
1978                return ret;
1979
1980        ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1981        if (ret)
1982                return ret;
1983
1984        if (INTEL_GEN(dev_priv) >= 7)
1985                plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1986        else
1987                plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1988
1989        return 0;
1990}
1991
1992int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1993{
1994        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1995        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1996        unsigned int rotation = plane_state->hw.rotation;
1997
1998        /* CHV ignores the mirror bit when the rotate bit is set :( */
1999        if (IS_CHERRYVIEW(dev_priv) &&
2000            rotation & DRM_MODE_ROTATE_180 &&
2001            rotation & DRM_MODE_REFLECT_X) {
2002                DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
2003                return -EINVAL;
2004        }
2005
2006        return 0;
2007}
2008
2009static int
2010vlv_sprite_check(struct intel_crtc_state *crtc_state,
2011                 struct intel_plane_state *plane_state)
2012{
2013        int ret;
2014
2015        ret = chv_plane_check_rotation(plane_state);
2016        if (ret)
2017                return ret;
2018
2019        ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2020                                                  &crtc_state->uapi,
2021                                                  DRM_PLANE_HELPER_NO_SCALING,
2022                                                  DRM_PLANE_HELPER_NO_SCALING,
2023                                                  true, true);
2024        if (ret)
2025                return ret;
2026
2027        ret = i9xx_check_plane_surface(plane_state);
2028        if (ret)
2029                return ret;
2030
2031        if (!plane_state->uapi.visible)
2032                return 0;
2033
2034        ret = intel_plane_check_src_coordinates(plane_state);
2035        if (ret)
2036                return ret;
2037
2038        plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
2039
2040        return 0;
2041}
2042
2043static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
2044                              const struct intel_plane_state *plane_state)
2045{
2046        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2047        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2048        const struct drm_framebuffer *fb = plane_state->hw.fb;
2049        unsigned int rotation = plane_state->hw.rotation;
2050        struct drm_format_name_buf format_name;
2051
2052        if (!fb)
2053                return 0;
2054
2055        if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
2056            is_ccs_modifier(fb->modifier)) {
2057                DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
2058                              rotation);
2059                return -EINVAL;
2060        }
2061
2062        if (rotation & DRM_MODE_REFLECT_X &&
2063            fb->modifier == DRM_FORMAT_MOD_LINEAR) {
2064                DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
2065                return -EINVAL;
2066        }
2067
2068        if (drm_rotation_90_or_270(rotation)) {
2069                if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
2070                    fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
2071                        DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
2072                        return -EINVAL;
2073                }
2074
2075                /*
2076                 * 90/270 is not allowed with RGB64 16:16:16:16 and
2077                 * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
2078                 */
2079                switch (fb->format->format) {
2080                case DRM_FORMAT_RGB565:
2081                        if (INTEL_GEN(dev_priv) >= 11)
2082                                break;
2083                        /* fall through */
2084                case DRM_FORMAT_C8:
2085                case DRM_FORMAT_XRGB16161616F:
2086                case DRM_FORMAT_XBGR16161616F:
2087                case DRM_FORMAT_ARGB16161616F:
2088                case DRM_FORMAT_ABGR16161616F:
2089                case DRM_FORMAT_Y210:
2090                case DRM_FORMAT_Y212:
2091                case DRM_FORMAT_Y216:
2092                case DRM_FORMAT_XVYU12_16161616:
2093                case DRM_FORMAT_XVYU16161616:
2094                        DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
2095                                      drm_get_format_name(fb->format->format,
2096                                                          &format_name));
2097                        return -EINVAL;
2098                default:
2099                        break;
2100                }
2101        }
2102
2103        /* Y-tiling is not supported in IF-ID Interlace mode */
2104        if (crtc_state->hw.enable &&
2105            crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
2106            (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
2107             fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
2108             fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
2109             fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
2110             fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
2111             fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
2112                DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
2113                return -EINVAL;
2114        }
2115
2116        return 0;
2117}
2118
2119static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
2120                                           const struct intel_plane_state *plane_state)
2121{
2122        struct drm_i915_private *dev_priv =
2123                to_i915(plane_state->uapi.plane->dev);
2124        int crtc_x = plane_state->uapi.dst.x1;
2125        int crtc_w = drm_rect_width(&plane_state->uapi.dst);
2126        int pipe_src_w = crtc_state->pipe_src_w;
2127
2128        /*
2129         * Display WA #1175: cnl,glk
2130         * Planes other than the cursor may cause FIFO underflow and display
2131         * corruption if starting less than 4 pixels from the right edge of
2132         * the screen.
2133         * Besides the above WA fix the similar problem, where planes other
2134         * than the cursor ending less than 4 pixels from the left edge of the
2135         * screen may cause FIFO underflow and display corruption.
2136         */
2137        if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
2138            (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
2139                DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
2140                              crtc_x + crtc_w < 4 ? "end" : "start",
2141                              crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
2142                              4, pipe_src_w - 4);
2143                return -ERANGE;
2144        }
2145
2146        return 0;
2147}
2148
2149static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
2150{
2151        const struct drm_framebuffer *fb = plane_state->hw.fb;
2152        unsigned int rotation = plane_state->hw.rotation;
2153        int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
2154
2155        /* Display WA #1106 */
2156        if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2157            src_w & 3 &&
2158            (rotation == DRM_MODE_ROTATE_270 ||
2159             rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
2160                DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
2161                return -EINVAL;
2162        }
2163
2164        return 0;
2165}
2166
2167static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
2168                               const struct drm_framebuffer *fb)
2169{
2170        /*
2171         * We don't yet know the final source width nor
2172         * whether we can use the HQ scaler mode. Assume
2173         * the best case.
2174         * FIXME need to properly check this later.
2175         */
2176        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
2177            !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
2178                return 0x30000 - 1;
2179        else
2180                return 0x20000 - 1;
2181}
2182
2183static int skl_plane_check(struct intel_crtc_state *crtc_state,
2184                           struct intel_plane_state *plane_state)
2185{
2186        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2187        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2188        const struct drm_framebuffer *fb = plane_state->hw.fb;
2189        int min_scale = DRM_PLANE_HELPER_NO_SCALING;
2190        int max_scale = DRM_PLANE_HELPER_NO_SCALING;
2191        int ret;
2192
2193        ret = skl_plane_check_fb(crtc_state, plane_state);
2194        if (ret)
2195                return ret;
2196
2197        /* use scaler when colorkey is not required */
2198        if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
2199                min_scale = 1;
2200                max_scale = skl_plane_max_scale(dev_priv, fb);
2201        }
2202
2203        ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2204                                                  &crtc_state->uapi,
2205                                                  min_scale, max_scale,
2206                                                  true, true);
2207        if (ret)
2208                return ret;
2209
2210        ret = skl_check_plane_surface(plane_state);
2211        if (ret)
2212                return ret;
2213
2214        if (!plane_state->uapi.visible)
2215                return 0;
2216
2217        ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2218        if (ret)
2219                return ret;
2220
2221        ret = intel_plane_check_src_coordinates(plane_state);
2222        if (ret)
2223                return ret;
2224
2225        ret = skl_plane_check_nv12_rotation(plane_state);
2226        if (ret)
2227                return ret;
2228
2229        /* HW only has 8 bits pixel precision, disable plane if invisible */
2230        if (!(plane_state->hw.alpha >> 8))
2231                plane_state->uapi.visible = false;
2232
2233        plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
2234
2235        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2236                plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
2237                                                             plane_state);
2238
2239        if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2240            icl_is_hdr_plane(dev_priv, plane->id))
2241                /* Enable and use MPEG-2 chroma siting */
2242                plane_state->cus_ctl = PLANE_CUS_ENABLE |
2243                        PLANE_CUS_HPHASE_0 |
2244                        PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2245        else
2246                plane_state->cus_ctl = 0;
2247
2248        return 0;
2249}
2250
2251static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
2252{
2253        return INTEL_GEN(dev_priv) >= 9;
2254}
2255
2256static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
2257                                 const struct drm_intel_sprite_colorkey *set)
2258{
2259        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2260        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2261        struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
2262
2263        *key = *set;
2264
2265        /*
2266         * We want src key enabled on the
2267         * sprite and not on the primary.
2268         */
2269        if (plane->id == PLANE_PRIMARY &&
2270            set->flags & I915_SET_COLORKEY_SOURCE)
2271                key->flags = 0;
2272
2273        /*
2274         * On SKL+ we want dst key enabled on
2275         * the primary and not on the sprite.
2276         */
2277        if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
2278            set->flags & I915_SET_COLORKEY_DESTINATION)
2279                key->flags = 0;
2280}
2281
2282int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
2283                                    struct drm_file *file_priv)
2284{
2285        struct drm_i915_private *dev_priv = to_i915(dev);
2286        struct drm_intel_sprite_colorkey *set = data;
2287        struct drm_plane *plane;
2288        struct drm_plane_state *plane_state;
2289        struct drm_atomic_state *state;
2290        struct drm_modeset_acquire_ctx ctx;
2291        int ret = 0;
2292
2293        /* ignore the pointless "none" flag */
2294        set->flags &= ~I915_SET_COLORKEY_NONE;
2295
2296        if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2297                return -EINVAL;
2298
2299        /* Make sure we don't try to enable both src & dest simultaneously */
2300        if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2301                return -EINVAL;
2302
2303        if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
2304            set->flags & I915_SET_COLORKEY_DESTINATION)
2305                return -EINVAL;
2306
2307        plane = drm_plane_find(dev, file_priv, set->plane_id);
2308        if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
2309                return -ENOENT;
2310
2311        /*
2312         * SKL+ only plane 2 can do destination keying against plane 1.
2313         * Also multiple planes can't do destination keying on the same
2314         * pipe simultaneously.
2315         */
2316        if (INTEL_GEN(dev_priv) >= 9 &&
2317            to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
2318            set->flags & I915_SET_COLORKEY_DESTINATION)
2319                return -EINVAL;
2320
2321        drm_modeset_acquire_init(&ctx, 0);
2322
2323        state = drm_atomic_state_alloc(plane->dev);
2324        if (!state) {
2325                ret = -ENOMEM;
2326                goto out;
2327        }
2328        state->acquire_ctx = &ctx;
2329
2330        while (1) {
2331                plane_state = drm_atomic_get_plane_state(state, plane);
2332                ret = PTR_ERR_OR_ZERO(plane_state);
2333                if (!ret)
2334                        intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2335
2336                /*
2337                 * On some platforms we have to configure
2338                 * the dst colorkey on the primary plane.
2339                 */
2340                if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
2341                        struct intel_crtc *crtc =
2342                                intel_get_crtc_for_pipe(dev_priv,
2343                                                        to_intel_plane(plane)->pipe);
2344
2345                        plane_state = drm_atomic_get_plane_state(state,
2346                                                                 crtc->base.primary);
2347                        ret = PTR_ERR_OR_ZERO(plane_state);
2348                        if (!ret)
2349                                intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2350                }
2351
2352                if (!ret)
2353                        ret = drm_atomic_commit(state);
2354
2355                if (ret != -EDEADLK)
2356                        break;
2357
2358                drm_atomic_state_clear(state);
2359                drm_modeset_backoff(&ctx);
2360        }
2361
2362        drm_atomic_state_put(state);
2363out:
2364        drm_modeset_drop_locks(&ctx);
2365        drm_modeset_acquire_fini(&ctx);
2366        return ret;
2367}
2368
2369static const u32 g4x_plane_formats[] = {
2370        DRM_FORMAT_XRGB8888,
2371        DRM_FORMAT_YUYV,
2372        DRM_FORMAT_YVYU,
2373        DRM_FORMAT_UYVY,
2374        DRM_FORMAT_VYUY,
2375};
2376
2377static const u64 i9xx_plane_format_modifiers[] = {
2378        I915_FORMAT_MOD_X_TILED,
2379        DRM_FORMAT_MOD_LINEAR,
2380        DRM_FORMAT_MOD_INVALID
2381};
2382
2383static const u32 snb_plane_formats[] = {
2384        DRM_FORMAT_XRGB8888,
2385        DRM_FORMAT_XBGR8888,
2386        DRM_FORMAT_XRGB2101010,
2387        DRM_FORMAT_XBGR2101010,
2388        DRM_FORMAT_XRGB16161616F,
2389        DRM_FORMAT_XBGR16161616F,
2390        DRM_FORMAT_YUYV,
2391        DRM_FORMAT_YVYU,
2392        DRM_FORMAT_UYVY,
2393        DRM_FORMAT_VYUY,
2394};
2395
2396static const u32 vlv_plane_formats[] = {
2397        DRM_FORMAT_C8,
2398        DRM_FORMAT_RGB565,
2399        DRM_FORMAT_XRGB8888,
2400        DRM_FORMAT_XBGR8888,
2401        DRM_FORMAT_ARGB8888,
2402        DRM_FORMAT_ABGR8888,
2403        DRM_FORMAT_XBGR2101010,
2404        DRM_FORMAT_ABGR2101010,
2405        DRM_FORMAT_YUYV,
2406        DRM_FORMAT_YVYU,
2407        DRM_FORMAT_UYVY,
2408        DRM_FORMAT_VYUY,
2409};
2410
2411static const u32 chv_pipe_b_sprite_formats[] = {
2412        DRM_FORMAT_C8,
2413        DRM_FORMAT_RGB565,
2414        DRM_FORMAT_XRGB8888,
2415        DRM_FORMAT_XBGR8888,
2416        DRM_FORMAT_ARGB8888,
2417        DRM_FORMAT_ABGR8888,
2418        DRM_FORMAT_XRGB2101010,
2419        DRM_FORMAT_XBGR2101010,
2420        DRM_FORMAT_ARGB2101010,
2421        DRM_FORMAT_ABGR2101010,
2422        DRM_FORMAT_YUYV,
2423        DRM_FORMAT_YVYU,
2424        DRM_FORMAT_UYVY,
2425        DRM_FORMAT_VYUY,
2426};
2427
2428static const u32 skl_plane_formats[] = {
2429        DRM_FORMAT_C8,
2430        DRM_FORMAT_RGB565,
2431        DRM_FORMAT_XRGB8888,
2432        DRM_FORMAT_XBGR8888,
2433        DRM_FORMAT_ARGB8888,
2434        DRM_FORMAT_ABGR8888,
2435        DRM_FORMAT_XRGB2101010,
2436        DRM_FORMAT_XBGR2101010,
2437        DRM_FORMAT_XRGB16161616F,
2438        DRM_FORMAT_XBGR16161616F,
2439        DRM_FORMAT_YUYV,
2440        DRM_FORMAT_YVYU,
2441        DRM_FORMAT_UYVY,
2442        DRM_FORMAT_VYUY,
2443};
2444
2445static const u32 skl_planar_formats[] = {
2446        DRM_FORMAT_C8,
2447        DRM_FORMAT_RGB565,
2448        DRM_FORMAT_XRGB8888,
2449        DRM_FORMAT_XBGR8888,
2450        DRM_FORMAT_ARGB8888,
2451        DRM_FORMAT_ABGR8888,
2452        DRM_FORMAT_XRGB2101010,
2453        DRM_FORMAT_XBGR2101010,
2454        DRM_FORMAT_XRGB16161616F,
2455        DRM_FORMAT_XBGR16161616F,
2456        DRM_FORMAT_YUYV,
2457        DRM_FORMAT_YVYU,
2458        DRM_FORMAT_UYVY,
2459        DRM_FORMAT_VYUY,
2460        DRM_FORMAT_NV12,
2461};
2462
2463static const u32 glk_planar_formats[] = {
2464        DRM_FORMAT_C8,
2465        DRM_FORMAT_RGB565,
2466        DRM_FORMAT_XRGB8888,
2467        DRM_FORMAT_XBGR8888,
2468        DRM_FORMAT_ARGB8888,
2469        DRM_FORMAT_ABGR8888,
2470        DRM_FORMAT_XRGB2101010,
2471        DRM_FORMAT_XBGR2101010,
2472        DRM_FORMAT_XRGB16161616F,
2473        DRM_FORMAT_XBGR16161616F,
2474        DRM_FORMAT_YUYV,
2475        DRM_FORMAT_YVYU,
2476        DRM_FORMAT_UYVY,
2477        DRM_FORMAT_VYUY,
2478        DRM_FORMAT_NV12,
2479        DRM_FORMAT_P010,
2480        DRM_FORMAT_P012,
2481        DRM_FORMAT_P016,
2482};
2483
2484static const u32 icl_sdr_y_plane_formats[] = {
2485        DRM_FORMAT_C8,
2486        DRM_FORMAT_RGB565,
2487        DRM_FORMAT_XRGB8888,
2488        DRM_FORMAT_XBGR8888,
2489        DRM_FORMAT_ARGB8888,
2490        DRM_FORMAT_ABGR8888,
2491        DRM_FORMAT_XRGB2101010,
2492        DRM_FORMAT_XBGR2101010,
2493        DRM_FORMAT_ARGB2101010,
2494        DRM_FORMAT_ABGR2101010,
2495        DRM_FORMAT_YUYV,
2496        DRM_FORMAT_YVYU,
2497        DRM_FORMAT_UYVY,
2498        DRM_FORMAT_VYUY,
2499        DRM_FORMAT_Y210,
2500        DRM_FORMAT_Y212,
2501        DRM_FORMAT_Y216,
2502        DRM_FORMAT_XVYU2101010,
2503        DRM_FORMAT_XVYU12_16161616,
2504        DRM_FORMAT_XVYU16161616,
2505};
2506
2507static const u32 icl_sdr_uv_plane_formats[] = {
2508        DRM_FORMAT_C8,
2509        DRM_FORMAT_RGB565,
2510        DRM_FORMAT_XRGB8888,
2511        DRM_FORMAT_XBGR8888,
2512        DRM_FORMAT_ARGB8888,
2513        DRM_FORMAT_ABGR8888,
2514        DRM_FORMAT_XRGB2101010,
2515        DRM_FORMAT_XBGR2101010,
2516        DRM_FORMAT_ARGB2101010,
2517        DRM_FORMAT_ABGR2101010,
2518        DRM_FORMAT_YUYV,
2519        DRM_FORMAT_YVYU,
2520        DRM_FORMAT_UYVY,
2521        DRM_FORMAT_VYUY,
2522        DRM_FORMAT_NV12,
2523        DRM_FORMAT_P010,
2524        DRM_FORMAT_P012,
2525        DRM_FORMAT_P016,
2526        DRM_FORMAT_Y210,
2527        DRM_FORMAT_Y212,
2528        DRM_FORMAT_Y216,
2529        DRM_FORMAT_XVYU2101010,
2530        DRM_FORMAT_XVYU12_16161616,
2531        DRM_FORMAT_XVYU16161616,
2532};
2533
2534static const u32 icl_hdr_plane_formats[] = {
2535        DRM_FORMAT_C8,
2536        DRM_FORMAT_RGB565,
2537        DRM_FORMAT_XRGB8888,
2538        DRM_FORMAT_XBGR8888,
2539        DRM_FORMAT_ARGB8888,
2540        DRM_FORMAT_ABGR8888,
2541        DRM_FORMAT_XRGB2101010,
2542        DRM_FORMAT_XBGR2101010,
2543        DRM_FORMAT_ARGB2101010,
2544        DRM_FORMAT_ABGR2101010,
2545        DRM_FORMAT_XRGB16161616F,
2546        DRM_FORMAT_XBGR16161616F,
2547        DRM_FORMAT_ARGB16161616F,
2548        DRM_FORMAT_ABGR16161616F,
2549        DRM_FORMAT_YUYV,
2550        DRM_FORMAT_YVYU,
2551        DRM_FORMAT_UYVY,
2552        DRM_FORMAT_VYUY,
2553        DRM_FORMAT_NV12,
2554        DRM_FORMAT_P010,
2555        DRM_FORMAT_P012,
2556        DRM_FORMAT_P016,
2557        DRM_FORMAT_Y210,
2558        DRM_FORMAT_Y212,
2559        DRM_FORMAT_Y216,
2560        DRM_FORMAT_XVYU2101010,
2561        DRM_FORMAT_XVYU12_16161616,
2562        DRM_FORMAT_XVYU16161616,
2563};
2564
2565static const u64 skl_plane_format_modifiers_noccs[] = {
2566        I915_FORMAT_MOD_Yf_TILED,
2567        I915_FORMAT_MOD_Y_TILED,
2568        I915_FORMAT_MOD_X_TILED,
2569        DRM_FORMAT_MOD_LINEAR,
2570        DRM_FORMAT_MOD_INVALID
2571};
2572
2573static const u64 skl_plane_format_modifiers_ccs[] = {
2574        I915_FORMAT_MOD_Yf_TILED_CCS,
2575        I915_FORMAT_MOD_Y_TILED_CCS,
2576        I915_FORMAT_MOD_Yf_TILED,
2577        I915_FORMAT_MOD_Y_TILED,
2578        I915_FORMAT_MOD_X_TILED,
2579        DRM_FORMAT_MOD_LINEAR,
2580        DRM_FORMAT_MOD_INVALID
2581};
2582
2583static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
2584        I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
2585        I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2586        I915_FORMAT_MOD_Y_TILED,
2587        I915_FORMAT_MOD_X_TILED,
2588        DRM_FORMAT_MOD_LINEAR,
2589        DRM_FORMAT_MOD_INVALID
2590};
2591
2592static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
2593        I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2594        I915_FORMAT_MOD_Y_TILED,
2595        I915_FORMAT_MOD_X_TILED,
2596        DRM_FORMAT_MOD_LINEAR,
2597        DRM_FORMAT_MOD_INVALID
2598};
2599
2600static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2601                                            u32 format, u64 modifier)
2602{
2603        switch (modifier) {
2604        case DRM_FORMAT_MOD_LINEAR:
2605        case I915_FORMAT_MOD_X_TILED:
2606                break;
2607        default:
2608                return false;
2609        }
2610
2611        switch (format) {
2612        case DRM_FORMAT_XRGB8888:
2613        case DRM_FORMAT_YUYV:
2614        case DRM_FORMAT_YVYU:
2615        case DRM_FORMAT_UYVY:
2616        case DRM_FORMAT_VYUY:
2617                if (modifier == DRM_FORMAT_MOD_LINEAR ||
2618                    modifier == I915_FORMAT_MOD_X_TILED)
2619                        return true;
2620                /* fall through */
2621        default:
2622                return false;
2623        }
2624}
2625
2626static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2627                                            u32 format, u64 modifier)
2628{
2629        switch (modifier) {
2630        case DRM_FORMAT_MOD_LINEAR:
2631        case I915_FORMAT_MOD_X_TILED:
2632                break;
2633        default:
2634                return false;
2635        }
2636
2637        switch (format) {
2638        case DRM_FORMAT_XRGB8888:
2639        case DRM_FORMAT_XBGR8888:
2640        case DRM_FORMAT_XRGB2101010:
2641        case DRM_FORMAT_XBGR2101010:
2642        case DRM_FORMAT_XRGB16161616F:
2643        case DRM_FORMAT_XBGR16161616F:
2644        case DRM_FORMAT_YUYV:
2645        case DRM_FORMAT_YVYU:
2646        case DRM_FORMAT_UYVY:
2647        case DRM_FORMAT_VYUY:
2648                if (modifier == DRM_FORMAT_MOD_LINEAR ||
2649                    modifier == I915_FORMAT_MOD_X_TILED)
2650                        return true;
2651                /* fall through */
2652        default:
2653                return false;
2654        }
2655}
2656
2657static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2658                                            u32 format, u64 modifier)
2659{
2660        switch (modifier) {
2661        case DRM_FORMAT_MOD_LINEAR:
2662        case I915_FORMAT_MOD_X_TILED:
2663                break;
2664        default:
2665                return false;
2666        }
2667
2668        switch (format) {
2669        case DRM_FORMAT_C8:
2670        case DRM_FORMAT_RGB565:
2671        case DRM_FORMAT_ABGR8888:
2672        case DRM_FORMAT_ARGB8888:
2673        case DRM_FORMAT_XBGR8888:
2674        case DRM_FORMAT_XRGB8888:
2675        case DRM_FORMAT_XBGR2101010:
2676        case DRM_FORMAT_ABGR2101010:
2677        case DRM_FORMAT_XRGB2101010:
2678        case DRM_FORMAT_ARGB2101010:
2679        case DRM_FORMAT_YUYV:
2680        case DRM_FORMAT_YVYU:
2681        case DRM_FORMAT_UYVY:
2682        case DRM_FORMAT_VYUY:
2683                if (modifier == DRM_FORMAT_MOD_LINEAR ||
2684                    modifier == I915_FORMAT_MOD_X_TILED)
2685                        return true;
2686                /* fall through */
2687        default:
2688                return false;
2689        }
2690}
2691
2692static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2693                                           u32 format, u64 modifier)
2694{
2695        struct intel_plane *plane = to_intel_plane(_plane);
2696
2697        switch (modifier) {
2698        case DRM_FORMAT_MOD_LINEAR:
2699        case I915_FORMAT_MOD_X_TILED:
2700        case I915_FORMAT_MOD_Y_TILED:
2701        case I915_FORMAT_MOD_Yf_TILED:
2702                break;
2703        case I915_FORMAT_MOD_Y_TILED_CCS:
2704        case I915_FORMAT_MOD_Yf_TILED_CCS:
2705                if (!plane->has_ccs)
2706                        return false;
2707                break;
2708        default:
2709                return false;
2710        }
2711
2712        switch (format) {
2713        case DRM_FORMAT_XRGB8888:
2714        case DRM_FORMAT_XBGR8888:
2715        case DRM_FORMAT_ARGB8888:
2716        case DRM_FORMAT_ABGR8888:
2717                if (is_ccs_modifier(modifier))
2718                        return true;
2719                /* fall through */
2720        case DRM_FORMAT_RGB565:
2721        case DRM_FORMAT_XRGB2101010:
2722        case DRM_FORMAT_XBGR2101010:
2723        case DRM_FORMAT_ARGB2101010:
2724        case DRM_FORMAT_ABGR2101010:
2725        case DRM_FORMAT_YUYV:
2726        case DRM_FORMAT_YVYU:
2727        case DRM_FORMAT_UYVY:
2728        case DRM_FORMAT_VYUY:
2729        case DRM_FORMAT_NV12:
2730        case DRM_FORMAT_P010:
2731        case DRM_FORMAT_P012:
2732        case DRM_FORMAT_P016:
2733        case DRM_FORMAT_XVYU2101010:
2734                if (modifier == I915_FORMAT_MOD_Yf_TILED)
2735                        return true;
2736                /* fall through */
2737        case DRM_FORMAT_C8:
2738        case DRM_FORMAT_XBGR16161616F:
2739        case DRM_FORMAT_ABGR16161616F:
2740        case DRM_FORMAT_XRGB16161616F:
2741        case DRM_FORMAT_ARGB16161616F:
2742        case DRM_FORMAT_Y210:
2743        case DRM_FORMAT_Y212:
2744        case DRM_FORMAT_Y216:
2745        case DRM_FORMAT_XVYU12_16161616:
2746        case DRM_FORMAT_XVYU16161616:
2747                if (modifier == DRM_FORMAT_MOD_LINEAR ||
2748                    modifier == I915_FORMAT_MOD_X_TILED ||
2749                    modifier == I915_FORMAT_MOD_Y_TILED)
2750                        return true;
2751                /* fall through */
2752        default:
2753                return false;
2754        }
2755}
2756
2757static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv,
2758                                        enum plane_id plane_id)
2759{
2760        /* Wa_14010477008:tgl[a0..c0] */
2761        if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0))
2762                return false;
2763
2764        return plane_id < PLANE_SPRITE4;
2765}
2766
2767static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
2768                                             u32 format, u64 modifier)
2769{
2770        struct drm_i915_private *dev_priv = to_i915(_plane->dev);
2771        struct intel_plane *plane = to_intel_plane(_plane);
2772
2773        switch (modifier) {
2774        case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
2775                if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id))
2776                        return false;
2777                /* fall through */
2778        case DRM_FORMAT_MOD_LINEAR:
2779        case I915_FORMAT_MOD_X_TILED:
2780        case I915_FORMAT_MOD_Y_TILED:
2781        case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
2782                break;
2783        default:
2784                return false;
2785        }
2786
2787        switch (format) {
2788        case DRM_FORMAT_XRGB8888:
2789        case DRM_FORMAT_XBGR8888:
2790        case DRM_FORMAT_ARGB8888:
2791        case DRM_FORMAT_ABGR8888:
2792                if (is_ccs_modifier(modifier))
2793                        return true;
2794                /* fall through */
2795        case DRM_FORMAT_YUYV:
2796        case DRM_FORMAT_YVYU:
2797        case DRM_FORMAT_UYVY:
2798        case DRM_FORMAT_VYUY:
2799        case DRM_FORMAT_NV12:
2800        case DRM_FORMAT_P010:
2801        case DRM_FORMAT_P012:
2802        case DRM_FORMAT_P016:
2803                if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
2804                        return true;
2805                /* fall through */
2806        case DRM_FORMAT_RGB565:
2807        case DRM_FORMAT_XRGB2101010:
2808        case DRM_FORMAT_XBGR2101010:
2809        case DRM_FORMAT_ARGB2101010:
2810        case DRM_FORMAT_ABGR2101010:
2811        case DRM_FORMAT_XVYU2101010:
2812        case DRM_FORMAT_C8:
2813        case DRM_FORMAT_XBGR16161616F:
2814        case DRM_FORMAT_ABGR16161616F:
2815        case DRM_FORMAT_XRGB16161616F:
2816        case DRM_FORMAT_ARGB16161616F:
2817        case DRM_FORMAT_Y210:
2818        case DRM_FORMAT_Y212:
2819        case DRM_FORMAT_Y216:
2820        case DRM_FORMAT_XVYU12_16161616:
2821        case DRM_FORMAT_XVYU16161616:
2822                if (modifier == DRM_FORMAT_MOD_LINEAR ||
2823                    modifier == I915_FORMAT_MOD_X_TILED ||
2824                    modifier == I915_FORMAT_MOD_Y_TILED)
2825                        return true;
2826                /* fall through */
2827        default:
2828                return false;
2829        }
2830}
2831
2832static const struct drm_plane_funcs g4x_sprite_funcs = {
2833        .update_plane = drm_atomic_helper_update_plane,
2834        .disable_plane = drm_atomic_helper_disable_plane,
2835        .destroy = intel_plane_destroy,
2836        .atomic_duplicate_state = intel_plane_duplicate_state,
2837        .atomic_destroy_state = intel_plane_destroy_state,
2838        .format_mod_supported = g4x_sprite_format_mod_supported,
2839};
2840
2841static const struct drm_plane_funcs snb_sprite_funcs = {
2842        .update_plane = drm_atomic_helper_update_plane,
2843        .disable_plane = drm_atomic_helper_disable_plane,
2844        .destroy = intel_plane_destroy,
2845        .atomic_duplicate_state = intel_plane_duplicate_state,
2846        .atomic_destroy_state = intel_plane_destroy_state,
2847        .format_mod_supported = snb_sprite_format_mod_supported,
2848};
2849
2850static const struct drm_plane_funcs vlv_sprite_funcs = {
2851        .update_plane = drm_atomic_helper_update_plane,
2852        .disable_plane = drm_atomic_helper_disable_plane,
2853        .destroy = intel_plane_destroy,
2854        .atomic_duplicate_state = intel_plane_duplicate_state,
2855        .atomic_destroy_state = intel_plane_destroy_state,
2856        .format_mod_supported = vlv_sprite_format_mod_supported,
2857};
2858
2859static const struct drm_plane_funcs skl_plane_funcs = {
2860        .update_plane = drm_atomic_helper_update_plane,
2861        .disable_plane = drm_atomic_helper_disable_plane,
2862        .destroy = intel_plane_destroy,
2863        .atomic_duplicate_state = intel_plane_duplicate_state,
2864        .atomic_destroy_state = intel_plane_destroy_state,
2865        .format_mod_supported = skl_plane_format_mod_supported,
2866};
2867
2868static const struct drm_plane_funcs gen12_plane_funcs = {
2869        .update_plane = drm_atomic_helper_update_plane,
2870        .disable_plane = drm_atomic_helper_disable_plane,
2871        .destroy = intel_plane_destroy,
2872        .atomic_duplicate_state = intel_plane_duplicate_state,
2873        .atomic_destroy_state = intel_plane_destroy_state,
2874        .format_mod_supported = gen12_plane_format_mod_supported,
2875};
2876
2877static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2878                              enum pipe pipe, enum plane_id plane_id)
2879{
2880        if (!HAS_FBC(dev_priv))
2881                return false;
2882
2883        return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2884}
2885
2886static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2887                                 enum pipe pipe, enum plane_id plane_id)
2888{
2889        /* Display WA #0870: skl, bxt */
2890        if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2891                return false;
2892
2893        if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
2894                return false;
2895
2896        if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2897                return false;
2898
2899        return true;
2900}
2901
2902static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2903                                        enum pipe pipe, enum plane_id plane_id,
2904                                        int *num_formats)
2905{
2906        if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2907                *num_formats = ARRAY_SIZE(skl_planar_formats);
2908                return skl_planar_formats;
2909        } else {
2910                *num_formats = ARRAY_SIZE(skl_plane_formats);
2911                return skl_plane_formats;
2912        }
2913}
2914
2915static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2916                                        enum pipe pipe, enum plane_id plane_id,
2917                                        int *num_formats)
2918{
2919        if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2920                *num_formats = ARRAY_SIZE(glk_planar_formats);
2921                return glk_planar_formats;
2922        } else {
2923                *num_formats = ARRAY_SIZE(skl_plane_formats);
2924                return skl_plane_formats;
2925        }
2926}
2927
2928static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2929                                        enum pipe pipe, enum plane_id plane_id,
2930                                        int *num_formats)
2931{
2932        if (icl_is_hdr_plane(dev_priv, plane_id)) {
2933                *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2934                return icl_hdr_plane_formats;
2935        } else if (icl_is_nv12_y_plane(plane_id)) {
2936                *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2937                return icl_sdr_y_plane_formats;
2938        } else {
2939                *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2940                return icl_sdr_uv_plane_formats;
2941        }
2942}
2943
2944static const u64 *gen12_get_plane_modifiers(struct drm_i915_private *dev_priv,
2945                                            enum plane_id plane_id)
2946{
2947        if (gen12_plane_supports_mc_ccs(dev_priv, plane_id))
2948                return gen12_plane_format_modifiers_mc_ccs;
2949        else
2950                return gen12_plane_format_modifiers_rc_ccs;
2951}
2952
2953static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2954                              enum pipe pipe, enum plane_id plane_id)
2955{
2956        if (plane_id == PLANE_CURSOR)
2957                return false;
2958
2959        if (INTEL_GEN(dev_priv) >= 10)
2960                return true;
2961
2962        if (IS_GEMINILAKE(dev_priv))
2963                return pipe != PIPE_C;
2964
2965        return pipe != PIPE_C &&
2966                (plane_id == PLANE_PRIMARY ||
2967                 plane_id == PLANE_SPRITE0);
2968}
2969
2970struct intel_plane *
2971skl_universal_plane_create(struct drm_i915_private *dev_priv,
2972                           enum pipe pipe, enum plane_id plane_id)
2973{
2974        const struct drm_plane_funcs *plane_funcs;
2975        struct intel_plane *plane;
2976        enum drm_plane_type plane_type;
2977        unsigned int supported_rotations;
2978        unsigned int possible_crtcs;
2979        const u64 *modifiers;
2980        const u32 *formats;
2981        int num_formats;
2982        int ret;
2983
2984        plane = intel_plane_alloc();
2985        if (IS_ERR(plane))
2986                return plane;
2987
2988        plane->pipe = pipe;
2989        plane->id = plane_id;
2990        plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2991
2992        plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2993        if (plane->has_fbc) {
2994                struct intel_fbc *fbc = &dev_priv->fbc;
2995
2996                fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2997        }
2998
2999        plane->max_stride = skl_plane_max_stride;
3000        plane->update_plane = skl_update_plane;
3001        plane->disable_plane = skl_disable_plane;
3002        plane->get_hw_state = skl_plane_get_hw_state;
3003        plane->check_plane = skl_plane_check;
3004        plane->min_cdclk = skl_plane_min_cdclk;
3005
3006        if (INTEL_GEN(dev_priv) >= 11)
3007                formats = icl_get_plane_formats(dev_priv, pipe,
3008                                                plane_id, &num_formats);
3009        else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
3010                formats = glk_get_plane_formats(dev_priv, pipe,
3011                                                plane_id, &num_formats);
3012        else
3013                formats = skl_get_plane_formats(dev_priv, pipe,
3014                                                plane_id, &num_formats);
3015
3016        plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
3017        if (INTEL_GEN(dev_priv) >= 12) {
3018                modifiers = gen12_get_plane_modifiers(dev_priv, plane_id);
3019                plane_funcs = &gen12_plane_funcs;
3020        } else {
3021                if (plane->has_ccs)
3022                        modifiers = skl_plane_format_modifiers_ccs;
3023                else
3024                        modifiers = skl_plane_format_modifiers_noccs;
3025                plane_funcs = &skl_plane_funcs;
3026        }
3027
3028        if (plane_id == PLANE_PRIMARY)
3029                plane_type = DRM_PLANE_TYPE_PRIMARY;
3030        else
3031                plane_type = DRM_PLANE_TYPE_OVERLAY;
3032
3033        possible_crtcs = BIT(pipe);
3034
3035        ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3036                                       possible_crtcs, plane_funcs,
3037                                       formats, num_formats, modifiers,
3038                                       plane_type,
3039                                       "plane %d%c", plane_id + 1,
3040                                       pipe_name(pipe));
3041        if (ret)
3042                goto fail;
3043
3044        supported_rotations =
3045                DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
3046                DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
3047
3048        if (INTEL_GEN(dev_priv) >= 10)
3049                supported_rotations |= DRM_MODE_REFLECT_X;
3050
3051        drm_plane_create_rotation_property(&plane->base,
3052                                           DRM_MODE_ROTATE_0,
3053                                           supported_rotations);
3054
3055        drm_plane_create_color_properties(&plane->base,
3056                                          BIT(DRM_COLOR_YCBCR_BT601) |
3057                                          BIT(DRM_COLOR_YCBCR_BT709),
3058                                          BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3059                                          BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3060                                          DRM_COLOR_YCBCR_BT709,
3061                                          DRM_COLOR_YCBCR_LIMITED_RANGE);
3062
3063        drm_plane_create_alpha_property(&plane->base);
3064        drm_plane_create_blend_mode_property(&plane->base,
3065                                             BIT(DRM_MODE_BLEND_PIXEL_NONE) |
3066                                             BIT(DRM_MODE_BLEND_PREMULTI) |
3067                                             BIT(DRM_MODE_BLEND_COVERAGE));
3068
3069        drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
3070
3071        drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3072
3073        return plane;
3074
3075fail:
3076        intel_plane_free(plane);
3077
3078        return ERR_PTR(ret);
3079}
3080
3081struct intel_plane *
3082intel_sprite_plane_create(struct drm_i915_private *dev_priv,
3083                          enum pipe pipe, int sprite)
3084{
3085        struct intel_plane *plane;
3086        const struct drm_plane_funcs *plane_funcs;
3087        unsigned long possible_crtcs;
3088        unsigned int supported_rotations;
3089        const u64 *modifiers;
3090        const u32 *formats;
3091        int num_formats;
3092        int ret, zpos;
3093
3094        if (INTEL_GEN(dev_priv) >= 9)
3095                return skl_universal_plane_create(dev_priv, pipe,
3096                                                  PLANE_SPRITE0 + sprite);
3097
3098        plane = intel_plane_alloc();
3099        if (IS_ERR(plane))
3100                return plane;
3101
3102        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
3103                plane->max_stride = i9xx_plane_max_stride;
3104                plane->update_plane = vlv_update_plane;
3105                plane->disable_plane = vlv_disable_plane;
3106                plane->get_hw_state = vlv_plane_get_hw_state;
3107                plane->check_plane = vlv_sprite_check;
3108                plane->min_cdclk = vlv_plane_min_cdclk;
3109
3110                if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3111                        formats = chv_pipe_b_sprite_formats;
3112                        num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
3113                } else {
3114                        formats = vlv_plane_formats;
3115                        num_formats = ARRAY_SIZE(vlv_plane_formats);
3116                }
3117                modifiers = i9xx_plane_format_modifiers;
3118
3119                plane_funcs = &vlv_sprite_funcs;
3120        } else if (INTEL_GEN(dev_priv) >= 7) {
3121                plane->max_stride = g4x_sprite_max_stride;
3122                plane->update_plane = ivb_update_plane;
3123                plane->disable_plane = ivb_disable_plane;
3124                plane->get_hw_state = ivb_plane_get_hw_state;
3125                plane->check_plane = g4x_sprite_check;
3126
3127                if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
3128                        plane->min_cdclk = hsw_plane_min_cdclk;
3129                else
3130                        plane->min_cdclk = ivb_sprite_min_cdclk;
3131
3132                formats = snb_plane_formats;
3133                num_formats = ARRAY_SIZE(snb_plane_formats);
3134                modifiers = i9xx_plane_format_modifiers;
3135
3136                plane_funcs = &snb_sprite_funcs;
3137        } else {
3138                plane->max_stride = g4x_sprite_max_stride;
3139                plane->update_plane = g4x_update_plane;
3140                plane->disable_plane = g4x_disable_plane;
3141                plane->get_hw_state = g4x_plane_get_hw_state;
3142                plane->check_plane = g4x_sprite_check;
3143                plane->min_cdclk = g4x_sprite_min_cdclk;
3144
3145                modifiers = i9xx_plane_format_modifiers;
3146                if (IS_GEN(dev_priv, 6)) {
3147                        formats = snb_plane_formats;
3148                        num_formats = ARRAY_SIZE(snb_plane_formats);
3149
3150                        plane_funcs = &snb_sprite_funcs;
3151                } else {
3152                        formats = g4x_plane_formats;
3153                        num_formats = ARRAY_SIZE(g4x_plane_formats);
3154
3155                        plane_funcs = &g4x_sprite_funcs;
3156                }
3157        }
3158
3159        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3160                supported_rotations =
3161                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
3162                        DRM_MODE_REFLECT_X;
3163        } else {
3164                supported_rotations =
3165                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
3166        }
3167
3168        plane->pipe = pipe;
3169        plane->id = PLANE_SPRITE0 + sprite;
3170        plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
3171
3172        possible_crtcs = BIT(pipe);
3173
3174        ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3175                                       possible_crtcs, plane_funcs,
3176                                       formats, num_formats, modifiers,
3177                                       DRM_PLANE_TYPE_OVERLAY,
3178                                       "sprite %c", sprite_name(pipe, sprite));
3179        if (ret)
3180                goto fail;
3181
3182        drm_plane_create_rotation_property(&plane->base,
3183                                           DRM_MODE_ROTATE_0,
3184                                           supported_rotations);
3185
3186        drm_plane_create_color_properties(&plane->base,
3187                                          BIT(DRM_COLOR_YCBCR_BT601) |
3188                                          BIT(DRM_COLOR_YCBCR_BT709),
3189                                          BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3190                                          BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3191                                          DRM_COLOR_YCBCR_BT709,
3192                                          DRM_COLOR_YCBCR_LIMITED_RANGE);
3193
3194        zpos = sprite + 1;
3195        drm_plane_create_zpos_immutable_property(&plane->base, zpos);
3196
3197        drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3198
3199        return plane;
3200
3201fail:
3202        intel_plane_free(plane);
3203
3204        return ERR_PTR(ret);
3205}
3206