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