linux/drivers/gpu/drm/i915/display/i9xx_plane.c
<<
>>
Prefs
   1// SPDX-License-Identifier: MIT
   2/*
   3 * Copyright © 2020 Intel Corporation
   4 */
   5#include <linux/kernel.h>
   6
   7#include <drm/drm_atomic_helper.h>
   8#include <drm/drm_fourcc.h>
   9#include <drm/drm_plane_helper.h>
  10
  11#include "intel_atomic.h"
  12#include "intel_atomic_plane.h"
  13#include "intel_de.h"
  14#include "intel_display_types.h"
  15#include "intel_fb.h"
  16#include "intel_sprite.h"
  17#include "i9xx_plane.h"
  18
  19/* Primary plane formats for gen <= 3 */
  20static const u32 i8xx_primary_formats[] = {
  21        DRM_FORMAT_C8,
  22        DRM_FORMAT_XRGB1555,
  23        DRM_FORMAT_RGB565,
  24        DRM_FORMAT_XRGB8888,
  25};
  26
  27/* Primary plane formats for ivb (no fp16 due to hw issue) */
  28static const u32 ivb_primary_formats[] = {
  29        DRM_FORMAT_C8,
  30        DRM_FORMAT_RGB565,
  31        DRM_FORMAT_XRGB8888,
  32        DRM_FORMAT_XBGR8888,
  33        DRM_FORMAT_XRGB2101010,
  34        DRM_FORMAT_XBGR2101010,
  35};
  36
  37/* Primary plane formats for gen >= 4, except ivb */
  38static const u32 i965_primary_formats[] = {
  39        DRM_FORMAT_C8,
  40        DRM_FORMAT_RGB565,
  41        DRM_FORMAT_XRGB8888,
  42        DRM_FORMAT_XBGR8888,
  43        DRM_FORMAT_XRGB2101010,
  44        DRM_FORMAT_XBGR2101010,
  45        DRM_FORMAT_XBGR16161616F,
  46};
  47
  48/* Primary plane formats for vlv/chv */
  49static const u32 vlv_primary_formats[] = {
  50        DRM_FORMAT_C8,
  51        DRM_FORMAT_RGB565,
  52        DRM_FORMAT_XRGB8888,
  53        DRM_FORMAT_XBGR8888,
  54        DRM_FORMAT_ARGB8888,
  55        DRM_FORMAT_ABGR8888,
  56        DRM_FORMAT_XRGB2101010,
  57        DRM_FORMAT_XBGR2101010,
  58        DRM_FORMAT_ARGB2101010,
  59        DRM_FORMAT_ABGR2101010,
  60        DRM_FORMAT_XBGR16161616F,
  61};
  62
  63static const u64 i9xx_format_modifiers[] = {
  64        I915_FORMAT_MOD_X_TILED,
  65        DRM_FORMAT_MOD_LINEAR,
  66        DRM_FORMAT_MOD_INVALID
  67};
  68
  69static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
  70                                            u32 format, u64 modifier)
  71{
  72        switch (modifier) {
  73        case DRM_FORMAT_MOD_LINEAR:
  74        case I915_FORMAT_MOD_X_TILED:
  75                break;
  76        default:
  77                return false;
  78        }
  79
  80        switch (format) {
  81        case DRM_FORMAT_C8:
  82        case DRM_FORMAT_RGB565:
  83        case DRM_FORMAT_XRGB1555:
  84        case DRM_FORMAT_XRGB8888:
  85                return modifier == DRM_FORMAT_MOD_LINEAR ||
  86                        modifier == I915_FORMAT_MOD_X_TILED;
  87        default:
  88                return false;
  89        }
  90}
  91
  92static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
  93                                            u32 format, u64 modifier)
  94{
  95        switch (modifier) {
  96        case DRM_FORMAT_MOD_LINEAR:
  97        case I915_FORMAT_MOD_X_TILED:
  98                break;
  99        default:
 100                return false;
 101        }
 102
 103        switch (format) {
 104        case DRM_FORMAT_C8:
 105        case DRM_FORMAT_RGB565:
 106        case DRM_FORMAT_XRGB8888:
 107        case DRM_FORMAT_XBGR8888:
 108        case DRM_FORMAT_ARGB8888:
 109        case DRM_FORMAT_ABGR8888:
 110        case DRM_FORMAT_XRGB2101010:
 111        case DRM_FORMAT_XBGR2101010:
 112        case DRM_FORMAT_ARGB2101010:
 113        case DRM_FORMAT_ABGR2101010:
 114        case DRM_FORMAT_XBGR16161616F:
 115                return modifier == DRM_FORMAT_MOD_LINEAR ||
 116                        modifier == I915_FORMAT_MOD_X_TILED;
 117        default:
 118                return false;
 119        }
 120}
 121
 122static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
 123                               enum i9xx_plane_id i9xx_plane)
 124{
 125        if (!HAS_FBC(dev_priv))
 126                return false;
 127
 128        if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
 129                return i9xx_plane == PLANE_A; /* tied to pipe A */
 130        else if (IS_IVYBRIDGE(dev_priv))
 131                return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
 132                        i9xx_plane == PLANE_C;
 133        else if (DISPLAY_VER(dev_priv) >= 4)
 134                return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
 135        else
 136                return i9xx_plane == PLANE_A;
 137}
 138
 139static bool i9xx_plane_has_windowing(struct intel_plane *plane)
 140{
 141        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 142        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 143
 144        if (IS_CHERRYVIEW(dev_priv))
 145                return i9xx_plane == PLANE_B;
 146        else if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
 147                return false;
 148        else if (DISPLAY_VER(dev_priv) == 4)
 149                return i9xx_plane == PLANE_C;
 150        else
 151                return i9xx_plane == PLANE_B ||
 152                        i9xx_plane == PLANE_C;
 153}
 154
 155static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
 156                          const struct intel_plane_state *plane_state)
 157{
 158        struct drm_i915_private *dev_priv =
 159                to_i915(plane_state->uapi.plane->dev);
 160        const struct drm_framebuffer *fb = plane_state->hw.fb;
 161        unsigned int rotation = plane_state->hw.rotation;
 162        u32 dspcntr;
 163
 164        dspcntr = DISPLAY_PLANE_ENABLE;
 165
 166        if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) ||
 167            IS_SANDYBRIDGE(dev_priv) || IS_IVYBRIDGE(dev_priv))
 168                dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 169
 170        switch (fb->format->format) {
 171        case DRM_FORMAT_C8:
 172                dspcntr |= DISPPLANE_8BPP;
 173                break;
 174        case DRM_FORMAT_XRGB1555:
 175                dspcntr |= DISPPLANE_BGRX555;
 176                break;
 177        case DRM_FORMAT_ARGB1555:
 178                dspcntr |= DISPPLANE_BGRA555;
 179                break;
 180        case DRM_FORMAT_RGB565:
 181                dspcntr |= DISPPLANE_BGRX565;
 182                break;
 183        case DRM_FORMAT_XRGB8888:
 184                dspcntr |= DISPPLANE_BGRX888;
 185                break;
 186        case DRM_FORMAT_XBGR8888:
 187                dspcntr |= DISPPLANE_RGBX888;
 188                break;
 189        case DRM_FORMAT_ARGB8888:
 190                dspcntr |= DISPPLANE_BGRA888;
 191                break;
 192        case DRM_FORMAT_ABGR8888:
 193                dspcntr |= DISPPLANE_RGBA888;
 194                break;
 195        case DRM_FORMAT_XRGB2101010:
 196                dspcntr |= DISPPLANE_BGRX101010;
 197                break;
 198        case DRM_FORMAT_XBGR2101010:
 199                dspcntr |= DISPPLANE_RGBX101010;
 200                break;
 201        case DRM_FORMAT_ARGB2101010:
 202                dspcntr |= DISPPLANE_BGRA101010;
 203                break;
 204        case DRM_FORMAT_ABGR2101010:
 205                dspcntr |= DISPPLANE_RGBA101010;
 206                break;
 207        case DRM_FORMAT_XBGR16161616F:
 208                dspcntr |= DISPPLANE_RGBX161616;
 209                break;
 210        default:
 211                MISSING_CASE(fb->format->format);
 212                return 0;
 213        }
 214
 215        if (DISPLAY_VER(dev_priv) >= 4 &&
 216            fb->modifier == I915_FORMAT_MOD_X_TILED)
 217                dspcntr |= DISPPLANE_TILED;
 218
 219        if (rotation & DRM_MODE_ROTATE_180)
 220                dspcntr |= DISPPLANE_ROTATE_180;
 221
 222        if (rotation & DRM_MODE_REFLECT_X)
 223                dspcntr |= DISPPLANE_MIRROR;
 224
 225        return dspcntr;
 226}
 227
 228int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 229{
 230        struct drm_i915_private *dev_priv =
 231                to_i915(plane_state->uapi.plane->dev);
 232        const struct drm_framebuffer *fb = plane_state->hw.fb;
 233        int src_x, src_y, src_w;
 234        u32 offset;
 235        int ret;
 236
 237        ret = intel_plane_compute_gtt(plane_state);
 238        if (ret)
 239                return ret;
 240
 241        if (!plane_state->uapi.visible)
 242                return 0;
 243
 244        src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 245        src_x = plane_state->uapi.src.x1 >> 16;
 246        src_y = plane_state->uapi.src.y1 >> 16;
 247
 248        /* Undocumented hardware limit on i965/g4x/vlv/chv */
 249        if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048)
 250                return -EINVAL;
 251
 252        intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
 253
 254        if (DISPLAY_VER(dev_priv) >= 4)
 255                offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
 256                                                            plane_state, 0);
 257        else
 258                offset = 0;
 259
 260        /*
 261         * When using an X-tiled surface the plane starts to
 262         * misbehave if the x offset + width exceeds the stride.
 263         * hsw/bdw: underrun galore
 264         * ilk/snb/ivb: wrap to the next tile row mid scanout
 265         * i965/g4x: so far appear immune to this
 266         * vlv/chv: TODO check
 267         *
 268         * Linear surfaces seem to work just fine, even on hsw/bdw
 269         * despite them not using the linear offset anymore.
 270         */
 271        if (DISPLAY_VER(dev_priv) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) {
 272                u32 alignment = intel_surf_alignment(fb, 0);
 273                int cpp = fb->format->cpp[0];
 274
 275                while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].stride) {
 276                        if (offset == 0) {
 277                                drm_dbg_kms(&dev_priv->drm,
 278                                            "Unable to find suitable display surface offset due to X-tiling\n");
 279                                return -EINVAL;
 280                        }
 281
 282                        offset = intel_plane_adjust_aligned_offset(&src_x, &src_y, plane_state, 0,
 283                                                                   offset, offset - alignment);
 284                }
 285        }
 286
 287        /*
 288         * Put the final coordinates back so that the src
 289         * coordinate checks will see the right values.
 290         */
 291        drm_rect_translate_to(&plane_state->uapi.src,
 292                              src_x << 16, src_y << 16);
 293
 294        /* HSW/BDW do this automagically in hardware */
 295        if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
 296                unsigned int rotation = plane_state->hw.rotation;
 297                int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
 298                int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 299
 300                if (rotation & DRM_MODE_ROTATE_180) {
 301                        src_x += src_w - 1;
 302                        src_y += src_h - 1;
 303                } else if (rotation & DRM_MODE_REFLECT_X) {
 304                        src_x += src_w - 1;
 305                }
 306        }
 307
 308        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 309                drm_WARN_ON(&dev_priv->drm, src_x > 8191 || src_y > 4095);
 310        } else if (DISPLAY_VER(dev_priv) >= 4 &&
 311                   fb->modifier == I915_FORMAT_MOD_X_TILED) {
 312                drm_WARN_ON(&dev_priv->drm, src_x > 4095 || src_y > 4095);
 313        }
 314
 315        plane_state->view.color_plane[0].offset = offset;
 316        plane_state->view.color_plane[0].x = src_x;
 317        plane_state->view.color_plane[0].y = src_y;
 318
 319        return 0;
 320}
 321
 322static int
 323i9xx_plane_check(struct intel_crtc_state *crtc_state,
 324                 struct intel_plane_state *plane_state)
 325{
 326        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 327        int ret;
 328
 329        ret = chv_plane_check_rotation(plane_state);
 330        if (ret)
 331                return ret;
 332
 333        ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
 334                                                DRM_PLANE_HELPER_NO_SCALING,
 335                                                DRM_PLANE_HELPER_NO_SCALING,
 336                                                i9xx_plane_has_windowing(plane));
 337        if (ret)
 338                return ret;
 339
 340        ret = i9xx_check_plane_surface(plane_state);
 341        if (ret)
 342                return ret;
 343
 344        if (!plane_state->uapi.visible)
 345                return 0;
 346
 347        ret = intel_plane_check_src_coordinates(plane_state);
 348        if (ret)
 349                return ret;
 350
 351        plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
 352
 353        return 0;
 354}
 355
 356static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
 357{
 358        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 359        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 360        u32 dspcntr = 0;
 361
 362        if (crtc_state->gamma_enable)
 363                dspcntr |= DISPPLANE_GAMMA_ENABLE;
 364
 365        if (crtc_state->csc_enable)
 366                dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
 367
 368        if (DISPLAY_VER(dev_priv) < 5)
 369                dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
 370
 371        return dspcntr;
 372}
 373
 374static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
 375                             const struct intel_plane_state *plane_state,
 376                             unsigned int *num, unsigned int *den)
 377{
 378        const struct drm_framebuffer *fb = plane_state->hw.fb;
 379        unsigned int cpp = fb->format->cpp[0];
 380
 381        /*
 382         * g4x bspec says 64bpp pixel rate can't exceed 80%
 383         * of cdclk when the sprite plane is enabled on the
 384         * same pipe. ilk/snb bspec says 64bpp pixel rate is
 385         * never allowed to exceed 80% of cdclk. Let's just go
 386         * with the ilk/snb limit always.
 387         */
 388        if (cpp == 8) {
 389                *num = 10;
 390                *den = 8;
 391        } else {
 392                *num = 1;
 393                *den = 1;
 394        }
 395}
 396
 397static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
 398                                const struct intel_plane_state *plane_state)
 399{
 400        unsigned int pixel_rate;
 401        unsigned int num, den;
 402
 403        /*
 404         * Note that crtc_state->pixel_rate accounts for both
 405         * horizontal and vertical panel fitter downscaling factors.
 406         * Pre-HSW bspec tells us to only consider the horizontal
 407         * downscaling factor here. We ignore that and just consider
 408         * both for simplicity.
 409         */
 410        pixel_rate = crtc_state->pixel_rate;
 411
 412        i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
 413
 414        /* two pixels per clock with double wide pipe */
 415        if (crtc_state->double_wide)
 416                den *= 2;
 417
 418        return DIV_ROUND_UP(pixel_rate * num, den);
 419}
 420
 421static void i9xx_update_plane(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 i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 427        u32 linear_offset;
 428        int x = plane_state->view.color_plane[0].x;
 429        int y = plane_state->view.color_plane[0].y;
 430        int crtc_x = plane_state->uapi.dst.x1;
 431        int crtc_y = plane_state->uapi.dst.y1;
 432        int crtc_w = drm_rect_width(&plane_state->uapi.dst);
 433        int crtc_h = drm_rect_height(&plane_state->uapi.dst);
 434        unsigned long irqflags;
 435        u32 dspaddr_offset;
 436        u32 dspcntr;
 437
 438        dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
 439
 440        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 441
 442        if (DISPLAY_VER(dev_priv) >= 4)
 443                dspaddr_offset = plane_state->view.color_plane[0].offset;
 444        else
 445                dspaddr_offset = linear_offset;
 446
 447        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 448
 449        intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
 450                          plane_state->view.color_plane[0].stride);
 451
 452        if (DISPLAY_VER(dev_priv) < 4) {
 453                /*
 454                 * PLANE_A doesn't actually have a full window
 455                 * generator but let's assume we still need to
 456                 * program whatever is there.
 457                 */
 458                intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
 459                                  (crtc_y << 16) | crtc_x);
 460                intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
 461                                  ((crtc_h - 1) << 16) | (crtc_w - 1));
 462        } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
 463                intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
 464                                  (crtc_y << 16) | crtc_x);
 465                intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
 466                                  ((crtc_h - 1) << 16) | (crtc_w - 1));
 467                intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
 468        }
 469
 470        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 471                intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
 472                                  (y << 16) | x);
 473        } else if (DISPLAY_VER(dev_priv) >= 4) {
 474                intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
 475                                  linear_offset);
 476                intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
 477                                  (y << 16) | x);
 478        }
 479
 480        /*
 481         * The control register self-arms if the plane was previously
 482         * disabled. Try to make the plane enable atomic by writing
 483         * the control register just before the surface register.
 484         */
 485        intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
 486        if (DISPLAY_VER(dev_priv) >= 4)
 487                intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
 488                                  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
 489        else
 490                intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
 491                                  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
 492
 493        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 494}
 495
 496static void i9xx_disable_plane(struct intel_plane *plane,
 497                               const struct intel_crtc_state *crtc_state)
 498{
 499        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 500        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 501        unsigned long irqflags;
 502        u32 dspcntr;
 503
 504        /*
 505         * DSPCNTR pipe gamma enable on g4x+ and pipe csc
 506         * enable on ilk+ affect the pipe bottom color as
 507         * well, so we must configure them even if the plane
 508         * is disabled.
 509         *
 510         * On pre-g4x there is no way to gamma correct the
 511         * pipe bottom color but we'll keep on doing this
 512         * anyway so that the crtc state readout works correctly.
 513         */
 514        dspcntr = i9xx_plane_ctl_crtc(crtc_state);
 515
 516        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 517
 518        intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
 519        if (DISPLAY_VER(dev_priv) >= 4)
 520                intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
 521        else
 522                intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
 523
 524        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 525}
 526
 527static void
 528g4x_primary_async_flip(struct intel_plane *plane,
 529                       const struct intel_crtc_state *crtc_state,
 530                       const struct intel_plane_state *plane_state,
 531                       bool async_flip)
 532{
 533        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 534        u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
 535        u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
 536        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 537        unsigned long irqflags;
 538
 539        if (async_flip)
 540                dspcntr |= DISPPLANE_ASYNC_FLIP;
 541
 542        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 543        intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
 544        intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
 545                          intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
 546        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 547}
 548
 549static void
 550vlv_primary_async_flip(struct intel_plane *plane,
 551                       const struct intel_crtc_state *crtc_state,
 552                       const struct intel_plane_state *plane_state,
 553                       bool async_flip)
 554{
 555        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 556        u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
 557        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 558        unsigned long irqflags;
 559
 560        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 561        intel_de_write_fw(dev_priv, DSPADDR_VLV(i9xx_plane),
 562                          intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
 563        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 564}
 565
 566static void
 567bdw_primary_enable_flip_done(struct intel_plane *plane)
 568{
 569        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 570        enum pipe pipe = plane->pipe;
 571
 572        spin_lock_irq(&i915->irq_lock);
 573        bdw_enable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
 574        spin_unlock_irq(&i915->irq_lock);
 575}
 576
 577static void
 578bdw_primary_disable_flip_done(struct intel_plane *plane)
 579{
 580        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 581        enum pipe pipe = plane->pipe;
 582
 583        spin_lock_irq(&i915->irq_lock);
 584        bdw_disable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
 585        spin_unlock_irq(&i915->irq_lock);
 586}
 587
 588static void
 589ivb_primary_enable_flip_done(struct intel_plane *plane)
 590{
 591        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 592
 593        spin_lock_irq(&i915->irq_lock);
 594        ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
 595        spin_unlock_irq(&i915->irq_lock);
 596}
 597
 598static void
 599ivb_primary_disable_flip_done(struct intel_plane *plane)
 600{
 601        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 602
 603        spin_lock_irq(&i915->irq_lock);
 604        ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
 605        spin_unlock_irq(&i915->irq_lock);
 606}
 607
 608static void
 609ilk_primary_enable_flip_done(struct intel_plane *plane)
 610{
 611        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 612
 613        spin_lock_irq(&i915->irq_lock);
 614        ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
 615        spin_unlock_irq(&i915->irq_lock);
 616}
 617
 618static void
 619ilk_primary_disable_flip_done(struct intel_plane *plane)
 620{
 621        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 622
 623        spin_lock_irq(&i915->irq_lock);
 624        ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
 625        spin_unlock_irq(&i915->irq_lock);
 626}
 627
 628static void
 629vlv_primary_enable_flip_done(struct intel_plane *plane)
 630{
 631        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 632        enum pipe pipe = plane->pipe;
 633
 634        spin_lock_irq(&i915->irq_lock);
 635        i915_enable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
 636        spin_unlock_irq(&i915->irq_lock);
 637}
 638
 639static void
 640vlv_primary_disable_flip_done(struct intel_plane *plane)
 641{
 642        struct drm_i915_private *i915 = to_i915(plane->base.dev);
 643        enum pipe pipe = plane->pipe;
 644
 645        spin_lock_irq(&i915->irq_lock);
 646        i915_disable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
 647        spin_unlock_irq(&i915->irq_lock);
 648}
 649
 650static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
 651                                    enum pipe *pipe)
 652{
 653        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 654        enum intel_display_power_domain power_domain;
 655        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 656        intel_wakeref_t wakeref;
 657        bool ret;
 658        u32 val;
 659
 660        /*
 661         * Not 100% correct for planes that can move between pipes,
 662         * but that's only the case for gen2-4 which don't have any
 663         * display power wells.
 664         */
 665        power_domain = POWER_DOMAIN_PIPE(plane->pipe);
 666        wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
 667        if (!wakeref)
 668                return false;
 669
 670        val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
 671
 672        ret = val & DISPLAY_PLANE_ENABLE;
 673
 674        if (DISPLAY_VER(dev_priv) >= 5)
 675                *pipe = plane->pipe;
 676        else
 677                *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
 678                        DISPPLANE_SEL_PIPE_SHIFT;
 679
 680        intel_display_power_put(dev_priv, power_domain, wakeref);
 681
 682        return ret;
 683}
 684
 685static unsigned int
 686hsw_primary_max_stride(struct intel_plane *plane,
 687                       u32 pixel_format, u64 modifier,
 688                       unsigned int rotation)
 689{
 690        const struct drm_format_info *info = drm_format_info(pixel_format);
 691        int cpp = info->cpp[0];
 692
 693        /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
 694        return min(8192 * cpp, 32 * 1024);
 695}
 696
 697static unsigned int
 698ilk_primary_max_stride(struct intel_plane *plane,
 699                       u32 pixel_format, u64 modifier,
 700                       unsigned int rotation)
 701{
 702        const struct drm_format_info *info = drm_format_info(pixel_format);
 703        int cpp = info->cpp[0];
 704
 705        /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
 706        if (modifier == I915_FORMAT_MOD_X_TILED)
 707                return min(4096 * cpp, 32 * 1024);
 708        else
 709                return 32 * 1024;
 710}
 711
 712unsigned int
 713i965_plane_max_stride(struct intel_plane *plane,
 714                      u32 pixel_format, u64 modifier,
 715                      unsigned int rotation)
 716{
 717        const struct drm_format_info *info = drm_format_info(pixel_format);
 718        int cpp = info->cpp[0];
 719
 720        /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
 721        if (modifier == I915_FORMAT_MOD_X_TILED)
 722                return min(4096 * cpp, 16 * 1024);
 723        else
 724                return 32 * 1024;
 725}
 726
 727static unsigned int
 728i9xx_plane_max_stride(struct intel_plane *plane,
 729                      u32 pixel_format, u64 modifier,
 730                      unsigned int rotation)
 731{
 732        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 733
 734        if (DISPLAY_VER(dev_priv) >= 3) {
 735                if (modifier == I915_FORMAT_MOD_X_TILED)
 736                        return 8*1024;
 737                else
 738                        return 16*1024;
 739        } else {
 740                if (plane->i9xx_plane == PLANE_C)
 741                        return 4*1024;
 742                else
 743                        return 8*1024;
 744        }
 745}
 746
 747static const struct drm_plane_funcs i965_plane_funcs = {
 748        .update_plane = drm_atomic_helper_update_plane,
 749        .disable_plane = drm_atomic_helper_disable_plane,
 750        .destroy = intel_plane_destroy,
 751        .atomic_duplicate_state = intel_plane_duplicate_state,
 752        .atomic_destroy_state = intel_plane_destroy_state,
 753        .format_mod_supported = i965_plane_format_mod_supported,
 754};
 755
 756static const struct drm_plane_funcs i8xx_plane_funcs = {
 757        .update_plane = drm_atomic_helper_update_plane,
 758        .disable_plane = drm_atomic_helper_disable_plane,
 759        .destroy = intel_plane_destroy,
 760        .atomic_duplicate_state = intel_plane_duplicate_state,
 761        .atomic_destroy_state = intel_plane_destroy_state,
 762        .format_mod_supported = i8xx_plane_format_mod_supported,
 763};
 764
 765struct intel_plane *
 766intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 767{
 768        struct intel_plane *plane;
 769        const struct drm_plane_funcs *plane_funcs;
 770        unsigned int supported_rotations;
 771        const u32 *formats;
 772        int num_formats;
 773        int ret, zpos;
 774
 775        plane = intel_plane_alloc();
 776        if (IS_ERR(plane))
 777                return plane;
 778
 779        plane->pipe = pipe;
 780        /*
 781         * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
 782         * port is hooked to pipe B. Hence we want plane A feeding pipe B.
 783         */
 784        if (HAS_FBC(dev_priv) && DISPLAY_VER(dev_priv) < 4 &&
 785            INTEL_NUM_PIPES(dev_priv) == 2)
 786                plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
 787        else
 788                plane->i9xx_plane = (enum i9xx_plane_id) pipe;
 789        plane->id = PLANE_PRIMARY;
 790        plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
 791
 792        plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
 793        if (plane->has_fbc) {
 794                struct intel_fbc *fbc = &dev_priv->fbc;
 795
 796                fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
 797        }
 798
 799        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 800                formats = vlv_primary_formats;
 801                num_formats = ARRAY_SIZE(vlv_primary_formats);
 802        } else if (DISPLAY_VER(dev_priv) >= 4) {
 803                /*
 804                 * WaFP16GammaEnabling:ivb
 805                 * "Workaround : When using the 64-bit format, the plane
 806                 *  output on each color channel has one quarter amplitude.
 807                 *  It can be brought up to full amplitude by using pipe
 808                 *  gamma correction or pipe color space conversion to
 809                 *  multiply the plane output by four."
 810                 *
 811                 * There is no dedicated plane gamma for the primary plane,
 812                 * and using the pipe gamma/csc could conflict with other
 813                 * planes, so we choose not to expose fp16 on IVB primary
 814                 * planes. HSW primary planes no longer have this problem.
 815                 */
 816                if (IS_IVYBRIDGE(dev_priv)) {
 817                        formats = ivb_primary_formats;
 818                        num_formats = ARRAY_SIZE(ivb_primary_formats);
 819                } else {
 820                        formats = i965_primary_formats;
 821                        num_formats = ARRAY_SIZE(i965_primary_formats);
 822                }
 823        } else {
 824                formats = i8xx_primary_formats;
 825                num_formats = ARRAY_SIZE(i8xx_primary_formats);
 826        }
 827
 828        if (DISPLAY_VER(dev_priv) >= 4)
 829                plane_funcs = &i965_plane_funcs;
 830        else
 831                plane_funcs = &i8xx_plane_funcs;
 832
 833        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 834                plane->min_cdclk = vlv_plane_min_cdclk;
 835        else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
 836                plane->min_cdclk = hsw_plane_min_cdclk;
 837        else if (IS_IVYBRIDGE(dev_priv))
 838                plane->min_cdclk = ivb_plane_min_cdclk;
 839        else
 840                plane->min_cdclk = i9xx_plane_min_cdclk;
 841
 842        if (HAS_GMCH(dev_priv)) {
 843                if (DISPLAY_VER(dev_priv) >= 4)
 844                        plane->max_stride = i965_plane_max_stride;
 845                else
 846                        plane->max_stride = i9xx_plane_max_stride;
 847        } else {
 848                if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
 849                        plane->max_stride = hsw_primary_max_stride;
 850                else
 851                        plane->max_stride = ilk_primary_max_stride;
 852        }
 853
 854        plane->update_plane = i9xx_update_plane;
 855        plane->disable_plane = i9xx_disable_plane;
 856        plane->get_hw_state = i9xx_plane_get_hw_state;
 857        plane->check_plane = i9xx_plane_check;
 858
 859        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 860                plane->async_flip = vlv_primary_async_flip;
 861                plane->enable_flip_done = vlv_primary_enable_flip_done;
 862                plane->disable_flip_done = vlv_primary_disable_flip_done;
 863        } else if (IS_BROADWELL(dev_priv)) {
 864                plane->need_async_flip_disable_wa = true;
 865                plane->async_flip = g4x_primary_async_flip;
 866                plane->enable_flip_done = bdw_primary_enable_flip_done;
 867                plane->disable_flip_done = bdw_primary_disable_flip_done;
 868        } else if (DISPLAY_VER(dev_priv) >= 7) {
 869                plane->async_flip = g4x_primary_async_flip;
 870                plane->enable_flip_done = ivb_primary_enable_flip_done;
 871                plane->disable_flip_done = ivb_primary_disable_flip_done;
 872        } else if (DISPLAY_VER(dev_priv) >= 5) {
 873                plane->async_flip = g4x_primary_async_flip;
 874                plane->enable_flip_done = ilk_primary_enable_flip_done;
 875                plane->disable_flip_done = ilk_primary_disable_flip_done;
 876        }
 877
 878        if (DISPLAY_VER(dev_priv) >= 5 || IS_G4X(dev_priv))
 879                ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
 880                                               0, plane_funcs,
 881                                               formats, num_formats,
 882                                               i9xx_format_modifiers,
 883                                               DRM_PLANE_TYPE_PRIMARY,
 884                                               "primary %c", pipe_name(pipe));
 885        else
 886                ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
 887                                               0, plane_funcs,
 888                                               formats, num_formats,
 889                                               i9xx_format_modifiers,
 890                                               DRM_PLANE_TYPE_PRIMARY,
 891                                               "plane %c",
 892                                               plane_name(plane->i9xx_plane));
 893        if (ret)
 894                goto fail;
 895
 896        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
 897                supported_rotations =
 898                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
 899                        DRM_MODE_REFLECT_X;
 900        } else if (DISPLAY_VER(dev_priv) >= 4) {
 901                supported_rotations =
 902                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
 903        } else {
 904                supported_rotations = DRM_MODE_ROTATE_0;
 905        }
 906
 907        if (DISPLAY_VER(dev_priv) >= 4)
 908                drm_plane_create_rotation_property(&plane->base,
 909                                                   DRM_MODE_ROTATE_0,
 910                                                   supported_rotations);
 911
 912        zpos = 0;
 913        drm_plane_create_zpos_immutable_property(&plane->base, zpos);
 914
 915        intel_plane_helper_add(plane);
 916
 917        return plane;
 918
 919fail:
 920        intel_plane_free(plane);
 921
 922        return ERR_PTR(ret);
 923}
 924
 925static int i9xx_format_to_fourcc(int format)
 926{
 927        switch (format) {
 928        case DISPPLANE_8BPP:
 929                return DRM_FORMAT_C8;
 930        case DISPPLANE_BGRA555:
 931                return DRM_FORMAT_ARGB1555;
 932        case DISPPLANE_BGRX555:
 933                return DRM_FORMAT_XRGB1555;
 934        case DISPPLANE_BGRX565:
 935                return DRM_FORMAT_RGB565;
 936        default:
 937        case DISPPLANE_BGRX888:
 938                return DRM_FORMAT_XRGB8888;
 939        case DISPPLANE_RGBX888:
 940                return DRM_FORMAT_XBGR8888;
 941        case DISPPLANE_BGRA888:
 942                return DRM_FORMAT_ARGB8888;
 943        case DISPPLANE_RGBA888:
 944                return DRM_FORMAT_ABGR8888;
 945        case DISPPLANE_BGRX101010:
 946                return DRM_FORMAT_XRGB2101010;
 947        case DISPPLANE_RGBX101010:
 948                return DRM_FORMAT_XBGR2101010;
 949        case DISPPLANE_BGRA101010:
 950                return DRM_FORMAT_ARGB2101010;
 951        case DISPPLANE_RGBA101010:
 952                return DRM_FORMAT_ABGR2101010;
 953        case DISPPLANE_RGBX161616:
 954                return DRM_FORMAT_XBGR16161616F;
 955        }
 956}
 957
 958void
 959i9xx_get_initial_plane_config(struct intel_crtc *crtc,
 960                              struct intel_initial_plane_config *plane_config)
 961{
 962        struct drm_device *dev = crtc->base.dev;
 963        struct drm_i915_private *dev_priv = to_i915(dev);
 964        struct intel_plane *plane = to_intel_plane(crtc->base.primary);
 965        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
 966        enum pipe pipe;
 967        u32 val, base, offset;
 968        int fourcc, pixel_format;
 969        unsigned int aligned_height;
 970        struct drm_framebuffer *fb;
 971        struct intel_framebuffer *intel_fb;
 972
 973        if (!plane->get_hw_state(plane, &pipe))
 974                return;
 975
 976        drm_WARN_ON(dev, pipe != crtc->pipe);
 977
 978        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
 979        if (!intel_fb) {
 980                drm_dbg_kms(&dev_priv->drm, "failed to alloc fb\n");
 981                return;
 982        }
 983
 984        fb = &intel_fb->base;
 985
 986        fb->dev = dev;
 987
 988        val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
 989
 990        if (DISPLAY_VER(dev_priv) >= 4) {
 991                if (val & DISPPLANE_TILED) {
 992                        plane_config->tiling = I915_TILING_X;
 993                        fb->modifier = I915_FORMAT_MOD_X_TILED;
 994                }
 995
 996                if (val & DISPPLANE_ROTATE_180)
 997                        plane_config->rotation = DRM_MODE_ROTATE_180;
 998        }
 999
1000        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B &&
1001            val & DISPPLANE_MIRROR)
1002                plane_config->rotation |= DRM_MODE_REFLECT_X;
1003
1004        pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
1005        fourcc = i9xx_format_to_fourcc(pixel_format);
1006        fb->format = drm_format_info(fourcc);
1007
1008        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1009                offset = intel_de_read(dev_priv, DSPOFFSET(i9xx_plane));
1010                base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & 0xfffff000;
1011        } else if (DISPLAY_VER(dev_priv) >= 4) {
1012                if (plane_config->tiling)
1013                        offset = intel_de_read(dev_priv,
1014                                               DSPTILEOFF(i9xx_plane));
1015                else
1016                        offset = intel_de_read(dev_priv,
1017                                               DSPLINOFF(i9xx_plane));
1018                base = intel_de_read(dev_priv, DSPSURF(i9xx_plane)) & 0xfffff000;
1019        } else {
1020                base = intel_de_read(dev_priv, DSPADDR(i9xx_plane));
1021        }
1022        plane_config->base = base;
1023
1024        val = intel_de_read(dev_priv, PIPESRC(pipe));
1025        fb->width = ((val >> 16) & 0xfff) + 1;
1026        fb->height = ((val >> 0) & 0xfff) + 1;
1027
1028        val = intel_de_read(dev_priv, DSPSTRIDE(i9xx_plane));
1029        fb->pitches[0] = val & 0xffffffc0;
1030
1031        aligned_height = intel_fb_align_height(fb, 0, fb->height);
1032
1033        plane_config->size = fb->pitches[0] * aligned_height;
1034
1035        drm_dbg_kms(&dev_priv->drm,
1036                    "%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
1037                    crtc->base.name, plane->base.name, fb->width, fb->height,
1038                    fb->format->cpp[0] * 8, base, fb->pitches[0],
1039                    plane_config->size);
1040
1041        plane_config->fb = intel_fb;
1042}
1043