diff mbox series

[2/4] drm/i915: refactor some crtc code out of intel display.

Message ID 20201209042144.2281-3-airlied@gmail.com (mailing list archive)
State New, archived
Headers show
Series [1/4] drm/i915: refactor cursor code out of i915_display.c | expand

Commit Message

Dave Airlie Dec. 9, 2020, 4:21 a.m. UTC
From: Dave Airlie <airlied@redhat.com>

There may be more crtc code that can be pulled out, but this
is a good start.

RFC: maybe call the new file something different

Signed-off-by: Dave Airlie <airlied@redhat.com>
---
 drivers/gpu/drm/i915/Makefile                |   1 +
 drivers/gpu/drm/i915/display/intel_crtc.c    | 951 +++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_display.c | 932 ------------------
 drivers/gpu/drm/i915/display/intel_display.h |   7 +
 4 files changed, 959 insertions(+), 932 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_crtc.c

Comments

Daniel Vetter Dec. 9, 2020, 11:03 a.m. UTC | #1
On Wed, Dec 9, 2020 at 5:21 AM Dave Airlie <airlied@gmail.com> wrote:
>
> From: Dave Airlie <airlied@redhat.com>
>
> There may be more crtc code that can be pulled out, but this
> is a good start.
>
> RFC: maybe call the new file something different

I think the only problem is that it also contains a bunch of plane
stuff. Which is split up in all kinds of funny ways. I think a good
way to resplit the plane stuff would be

intel_plane.c: cross platform plane stuff
intel_cursor.c: legacy cursor plane
intel_i9xx_plane.c: pre-gen9 primary plane
intel_sprite_plane.c: pre-gen9 sprite planes
intel_gen9_plane: gen9+ universal planes

atm these are wildly mixed all over between intel_sprite.c,
intel_display.c, intel_atomic_plane.c and maybe some other places I
missed.

Also this isn't all the crtc code, there's intel_pipe_update_start/end
which should also be here, plus probably intel_usecs_to_scanlines too.

Since it's such a mess moving some of the plane stuff with the crtc
doesn't seem too bad since it's not really making anything worse. But
at least all the crtc stuff should be collected here.
-Daniel


> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
>  drivers/gpu/drm/i915/Makefile                |   1 +
>  drivers/gpu/drm/i915/display/intel_crtc.c    | 951 +++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_display.c | 932 ------------------
>  drivers/gpu/drm/i915/display/intel_display.h |   7 +
>  4 files changed, 959 insertions(+), 932 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_crtc.c
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 98a35b939052..ffec257702af 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -196,6 +196,7 @@ i915-y += \
>         display/intel_color.o \
>         display/intel_combo_phy.o \
>         display/intel_connector.o \
> +       display/intel_crtc.o \
>         display/intel_csr.o \
>         display/intel_cursor.o \
>         display/intel_display.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> new file mode 100644
> index 000000000000..75a79f18cee2
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> @@ -0,0 +1,951 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_fourcc.h>
> +#include <drm/drm_plane.h>
> +#include <drm/drm_plane_helper.h>
> +
> +#include "intel_atomic.h"
> +#include "intel_atomic_plane.h"
> +#include "intel_color.h"
> +#include "intel_display_debugfs.h"
> +#include "intel_display_types.h"
> +#include "intel_pipe_crc.h"
> +#include "intel_sprite.h"
> +
> +/* Primary plane formats for gen <= 3 */
> +static const u32 i8xx_primary_formats[] = {
> +       DRM_FORMAT_C8,
> +       DRM_FORMAT_XRGB1555,
> +       DRM_FORMAT_RGB565,
> +       DRM_FORMAT_XRGB8888,
> +};
> +
> +/* Primary plane formats for ivb (no fp16 due to hw issue) */
> +static const u32 ivb_primary_formats[] = {
> +       DRM_FORMAT_C8,
> +       DRM_FORMAT_RGB565,
> +       DRM_FORMAT_XRGB8888,
> +       DRM_FORMAT_XBGR8888,
> +       DRM_FORMAT_XRGB2101010,
> +       DRM_FORMAT_XBGR2101010,
> +};
> +
> +/* Primary plane formats for gen >= 4, except ivb */
> +static const u32 i965_primary_formats[] = {
> +       DRM_FORMAT_C8,
> +       DRM_FORMAT_RGB565,
> +       DRM_FORMAT_XRGB8888,
> +       DRM_FORMAT_XBGR8888,
> +       DRM_FORMAT_XRGB2101010,
> +       DRM_FORMAT_XBGR2101010,
> +       DRM_FORMAT_XBGR16161616F,
> +};
> +
> +/* Primary plane formats for vlv/chv */
> +static const u32 vlv_primary_formats[] = {
> +       DRM_FORMAT_C8,
> +       DRM_FORMAT_RGB565,
> +       DRM_FORMAT_XRGB8888,
> +       DRM_FORMAT_XBGR8888,
> +       DRM_FORMAT_ARGB8888,
> +       DRM_FORMAT_ABGR8888,
> +       DRM_FORMAT_XRGB2101010,
> +       DRM_FORMAT_XBGR2101010,
> +       DRM_FORMAT_ARGB2101010,
> +       DRM_FORMAT_ABGR2101010,
> +       DRM_FORMAT_XBGR16161616F,
> +};
> +
> +static const u64 i9xx_format_modifiers[] = {
> +       I915_FORMAT_MOD_X_TILED,
> +       DRM_FORMAT_MOD_LINEAR,
> +       DRM_FORMAT_MOD_INVALID
> +};
> +
> +static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
> +                                           u32 format, u64 modifier)
> +{
> +       switch (modifier) {
> +       case DRM_FORMAT_MOD_LINEAR:
> +       case I915_FORMAT_MOD_X_TILED:
> +               break;
> +       default:
> +               return false;
> +       }
> +
> +       switch (format) {
> +       case DRM_FORMAT_C8:
> +       case DRM_FORMAT_RGB565:
> +       case DRM_FORMAT_XRGB1555:
> +       case DRM_FORMAT_XRGB8888:
> +               return modifier == DRM_FORMAT_MOD_LINEAR ||
> +                       modifier == I915_FORMAT_MOD_X_TILED;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
> +                                           u32 format, u64 modifier)
> +{
> +       switch (modifier) {
> +       case DRM_FORMAT_MOD_LINEAR:
> +       case I915_FORMAT_MOD_X_TILED:
> +               break;
> +       default:
> +               return false;
> +       }
> +
> +       switch (format) {
> +       case DRM_FORMAT_C8:
> +       case DRM_FORMAT_RGB565:
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_XBGR8888:
> +       case DRM_FORMAT_ARGB8888:
> +       case DRM_FORMAT_ABGR8888:
> +       case DRM_FORMAT_XRGB2101010:
> +       case DRM_FORMAT_XBGR2101010:
> +       case DRM_FORMAT_ARGB2101010:
> +       case DRM_FORMAT_ABGR2101010:
> +       case DRM_FORMAT_XBGR16161616F:
> +               return modifier == DRM_FORMAT_MOD_LINEAR ||
> +                       modifier == I915_FORMAT_MOD_X_TILED;
> +       default:
> +               return false;
> +       }
> +}
> +
> +static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
> +                              enum i9xx_plane_id i9xx_plane)
> +{
> +       if (!HAS_FBC(dev_priv))
> +               return false;
> +
> +       if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> +               return i9xx_plane == PLANE_A; /* tied to pipe A */
> +       else if (IS_IVYBRIDGE(dev_priv))
> +               return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
> +                       i9xx_plane == PLANE_C;
> +       else if (INTEL_GEN(dev_priv) >= 4)
> +               return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
> +       else
> +               return i9xx_plane == PLANE_A;
> +}
> +
> +static void assert_vblank_disabled(struct drm_crtc *crtc)
> +{
> +       if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
> +               drm_crtc_vblank_put(crtc);
> +}
> +
> +u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
> +{
> +       struct drm_device *dev = crtc->base.dev;
> +       struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
> +
> +       if (!vblank->max_vblank_count)
> +               return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
> +
> +       return crtc->base.funcs->get_vblank_counter(&crtc->base);
> +}
> +
> +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +       u32 mode_flags = crtc->mode_flags;
> +
> +       /*
> +        * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
> +        * have updated at the beginning of TE, if we want to use
> +        * the hw counter, then we would find it updated in only
> +        * the next TE, hence switching to sw counter.
> +        */
> +       if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
> +               return 0;
> +
> +       /*
> +        * On i965gm the hardware frame counter reads
> +        * zero when the TV encoder is enabled :(
> +        */
> +       if (IS_I965GM(dev_priv) &&
> +           (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
> +               return 0;
> +
> +       if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> +               return 0xffffffff; /* full 32 bit counter */
> +       else if (INTEL_GEN(dev_priv) >= 3)
> +               return 0xffffff; /* only 24 bits of frame count */
> +       else
> +               return 0; /* Gen2 doesn't have a hardware frame counter */
> +}
> +
> +void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
> +{
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> +       assert_vblank_disabled(&crtc->base);
> +       drm_crtc_set_max_vblank_count(&crtc->base,
> +                                     intel_crtc_max_vblank_count(crtc_state));
> +       drm_crtc_vblank_on(&crtc->base);
> +}
> +
> +void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
> +{
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> +       drm_crtc_vblank_off(&crtc->base);
> +       assert_vblank_disabled(&crtc->base);
> +}
> +
> +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
> +{
> +       struct intel_crtc_state *crtc_state;
> +
> +       crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
> +
> +       if (crtc_state)
> +               intel_crtc_state_reset(crtc_state, crtc);
> +
> +       return crtc_state;
> +}
> +
> +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> +                           struct intel_crtc *crtc)
> +{
> +       memset(crtc_state, 0, sizeof(*crtc_state));
> +
> +       __drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
> +
> +       crtc_state->cpu_transcoder = INVALID_TRANSCODER;
> +       crtc_state->master_transcoder = INVALID_TRANSCODER;
> +       crtc_state->hsw_workaround_pipe = INVALID_PIPE;
> +       crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
> +       crtc_state->scaler_state.scaler_id = -1;
> +       crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> +}
> +
> +static bool i9xx_plane_has_windowing(struct intel_plane *plane)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +
> +       if (IS_CHERRYVIEW(dev_priv))
> +               return i9xx_plane == PLANE_B;
> +       else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> +               return false;
> +       else if (IS_GEN(dev_priv, 4))
> +               return i9xx_plane == PLANE_C;
> +       else
> +               return i9xx_plane == PLANE_B ||
> +                       i9xx_plane == PLANE_C;
> +}
> +
> +static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
> +                         const struct intel_plane_state *plane_state)
> +{
> +       struct drm_i915_private *dev_priv =
> +               to_i915(plane_state->uapi.plane->dev);
> +       const struct drm_framebuffer *fb = plane_state->hw.fb;
> +       unsigned int rotation = plane_state->hw.rotation;
> +       u32 dspcntr;
> +
> +       dspcntr = DISPLAY_PLANE_ENABLE;
> +
> +       if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
> +           IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> +               dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> +
> +       switch (fb->format->format) {
> +       case DRM_FORMAT_C8:
> +               dspcntr |= DISPPLANE_8BPP;
> +               break;
> +       case DRM_FORMAT_XRGB1555:
> +               dspcntr |= DISPPLANE_BGRX555;
> +               break;
> +       case DRM_FORMAT_ARGB1555:
> +               dspcntr |= DISPPLANE_BGRA555;
> +               break;
> +       case DRM_FORMAT_RGB565:
> +               dspcntr |= DISPPLANE_BGRX565;
> +               break;
> +       case DRM_FORMAT_XRGB8888:
> +               dspcntr |= DISPPLANE_BGRX888;
> +               break;
> +       case DRM_FORMAT_XBGR8888:
> +               dspcntr |= DISPPLANE_RGBX888;
> +               break;
> +       case DRM_FORMAT_ARGB8888:
> +               dspcntr |= DISPPLANE_BGRA888;
> +               break;
> +       case DRM_FORMAT_ABGR8888:
> +               dspcntr |= DISPPLANE_RGBA888;
> +               break;
> +       case DRM_FORMAT_XRGB2101010:
> +               dspcntr |= DISPPLANE_BGRX101010;
> +               break;
> +       case DRM_FORMAT_XBGR2101010:
> +               dspcntr |= DISPPLANE_RGBX101010;
> +               break;
> +       case DRM_FORMAT_ARGB2101010:
> +               dspcntr |= DISPPLANE_BGRA101010;
> +               break;
> +       case DRM_FORMAT_ABGR2101010:
> +               dspcntr |= DISPPLANE_RGBA101010;
> +               break;
> +       case DRM_FORMAT_XBGR16161616F:
> +               dspcntr |= DISPPLANE_RGBX161616;
> +               break;
> +       default:
> +               MISSING_CASE(fb->format->format);
> +               return 0;
> +       }
> +
> +       if (INTEL_GEN(dev_priv) >= 4 &&
> +           fb->modifier == I915_FORMAT_MOD_X_TILED)
> +               dspcntr |= DISPPLANE_TILED;
> +
> +       if (rotation & DRM_MODE_ROTATE_180)
> +               dspcntr |= DISPPLANE_ROTATE_180;
> +
> +       if (rotation & DRM_MODE_REFLECT_X)
> +               dspcntr |= DISPPLANE_MIRROR;
> +
> +       return dspcntr;
> +}
> +
> +static int
> +i9xx_plane_check(struct intel_crtc_state *crtc_state,
> +                struct intel_plane_state *plane_state)
> +{
> +       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> +       int ret;
> +
> +       ret = chv_plane_check_rotation(plane_state);
> +       if (ret)
> +               return ret;
> +
> +       ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> +                                               DRM_PLANE_HELPER_NO_SCALING,
> +                                               DRM_PLANE_HELPER_NO_SCALING,
> +                                               i9xx_plane_has_windowing(plane));
> +       if (ret)
> +               return ret;
> +
> +       ret = i9xx_check_plane_surface(plane_state);
> +       if (ret)
> +               return ret;
> +
> +       if (!plane_state->uapi.visible)
> +               return 0;
> +
> +       ret = intel_plane_check_src_coordinates(plane_state);
> +       if (ret)
> +               return ret;
> +
> +       plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
> +
> +       return 0;
> +}
> +
> +static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
> +{
> +       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +       u32 dspcntr = 0;
> +
> +       if (crtc_state->gamma_enable)
> +               dspcntr |= DISPPLANE_GAMMA_ENABLE;
> +
> +       if (crtc_state->csc_enable)
> +               dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
> +
> +       if (INTEL_GEN(dev_priv) < 5)
> +               dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
> +
> +       return dspcntr;
> +}
> +
> +static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
> +                            const struct intel_plane_state *plane_state,
> +                            unsigned int *num, unsigned int *den)
> +{
> +       const struct drm_framebuffer *fb = plane_state->hw.fb;
> +       unsigned int cpp = fb->format->cpp[0];
> +
> +       /*
> +        * g4x bspec says 64bpp pixel rate can't exceed 80%
> +        * of cdclk when the sprite plane is enabled on the
> +        * same pipe. ilk/snb bspec says 64bpp pixel rate is
> +        * never allowed to exceed 80% of cdclk. Let's just go
> +        * with the ilk/snb limit always.
> +        */
> +       if (cpp == 8) {
> +               *num = 10;
> +               *den = 8;
> +       } else {
> +               *num = 1;
> +               *den = 1;
> +       }
> +}
> +
> +static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
> +                               const struct intel_plane_state *plane_state)
> +{
> +       unsigned int pixel_rate;
> +       unsigned int num, den;
> +
> +       /*
> +        * Note that crtc_state->pixel_rate accounts for both
> +        * horizontal and vertical panel fitter downscaling factors.
> +        * Pre-HSW bspec tells us to only consider the horizontal
> +        * downscaling factor here. We ignore that and just consider
> +        * both for simplicity.
> +        */
> +       pixel_rate = crtc_state->pixel_rate;
> +
> +       i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
> +
> +       /* two pixels per clock with double wide pipe */
> +       if (crtc_state->double_wide)
> +               den *= 2;
> +
> +       return DIV_ROUND_UP(pixel_rate * num, den);
> +}
> +
> +static void i9xx_update_plane(struct intel_plane *plane,
> +                             const struct intel_crtc_state *crtc_state,
> +                             const struct intel_plane_state *plane_state)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +       u32 linear_offset;
> +       int x = plane_state->color_plane[0].x;
> +       int y = plane_state->color_plane[0].y;
> +       int crtc_x = plane_state->uapi.dst.x1;
> +       int crtc_y = plane_state->uapi.dst.y1;
> +       int crtc_w = drm_rect_width(&plane_state->uapi.dst);
> +       int crtc_h = drm_rect_height(&plane_state->uapi.dst);
> +       unsigned long irqflags;
> +       u32 dspaddr_offset;
> +       u32 dspcntr;
> +
> +       dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
> +
> +       linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
> +
> +       if (INTEL_GEN(dev_priv) >= 4)
> +               dspaddr_offset = plane_state->color_plane[0].offset;
> +       else
> +               dspaddr_offset = linear_offset;
> +
> +       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> +       intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
> +                         plane_state->color_plane[0].stride);
> +
> +       if (INTEL_GEN(dev_priv) < 4) {
> +               /*
> +                * PLANE_A doesn't actually have a full window
> +                * generator but let's assume we still need to
> +                * program whatever is there.
> +                */
> +               intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
> +                                 (crtc_y << 16) | crtc_x);
> +               intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
> +                                 ((crtc_h - 1) << 16) | (crtc_w - 1));
> +       } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
> +               intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
> +                                 (crtc_y << 16) | crtc_x);
> +               intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
> +                                 ((crtc_h - 1) << 16) | (crtc_w - 1));
> +               intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
> +       }
> +
> +       if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
> +               intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
> +                                 (y << 16) | x);
> +       } else if (INTEL_GEN(dev_priv) >= 4) {
> +               intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
> +                                 linear_offset);
> +               intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
> +                                 (y << 16) | x);
> +       }
> +
> +       /*
> +        * The control register self-arms if the plane was previously
> +        * disabled. Try to make the plane enable atomic by writing
> +        * the control register just before the surface register.
> +        */
> +       intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> +       if (INTEL_GEN(dev_priv) >= 4)
> +               intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
> +                                 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> +       else
> +               intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
> +                                 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> +
> +       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static void i9xx_disable_plane(struct intel_plane *plane,
> +                              const struct intel_crtc_state *crtc_state)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +       unsigned long irqflags;
> +       u32 dspcntr;
> +
> +       /*
> +        * DSPCNTR pipe gamma enable on g4x+ and pipe csc
> +        * enable on ilk+ affect the pipe bottom color as
> +        * well, so we must configure them even if the plane
> +        * is disabled.
> +        *
> +        * On pre-g4x there is no way to gamma correct the
> +        * pipe bottom color but we'll keep on doing this
> +        * anyway so that the crtc state readout works correctly.
> +        */
> +       dspcntr = i9xx_plane_ctl_crtc(crtc_state);
> +
> +       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> +
> +       intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> +       if (INTEL_GEN(dev_priv) >= 4)
> +               intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
> +       else
> +               intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
> +
> +       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> +}
> +
> +static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
> +                                   enum pipe *pipe)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +       enum intel_display_power_domain power_domain;
> +       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +       intel_wakeref_t wakeref;
> +       bool ret;
> +       u32 val;
> +
> +       /*
> +        * Not 100% correct for planes that can move between pipes,
> +        * but that's only the case for gen2-4 which don't have any
> +        * display power wells.
> +        */
> +       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> +       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +       if (!wakeref)
> +               return false;
> +
> +       val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
> +
> +       ret = val & DISPLAY_PLANE_ENABLE;
> +
> +       if (INTEL_GEN(dev_priv) >= 5)
> +               *pipe = plane->pipe;
> +       else
> +               *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
> +                       DISPPLANE_SEL_PIPE_SHIFT;
> +
> +       intel_display_power_put(dev_priv, power_domain, wakeref);
> +
> +       return ret;
> +}
> +
> +unsigned int
> +i9xx_plane_max_stride(struct intel_plane *plane,
> +                     u32 pixel_format, u64 modifier,
> +                     unsigned int rotation)
> +{
> +       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> +
> +       if (!HAS_GMCH(dev_priv)) {
> +               return 32*1024;
> +       } else if (INTEL_GEN(dev_priv) >= 4) {
> +               if (modifier == I915_FORMAT_MOD_X_TILED)
> +                       return 16*1024;
> +               else
> +                       return 32*1024;
> +       } else if (INTEL_GEN(dev_priv) >= 3) {
> +               if (modifier == I915_FORMAT_MOD_X_TILED)
> +                       return 8*1024;
> +               else
> +                       return 16*1024;
> +       } else {
> +               if (plane->i9xx_plane == PLANE_C)
> +                       return 4*1024;
> +               else
> +                       return 8*1024;
> +       }
> +}
> +
> +static const struct drm_plane_funcs i965_plane_funcs = {
> +       .update_plane = drm_atomic_helper_update_plane,
> +       .disable_plane = drm_atomic_helper_disable_plane,
> +       .destroy = intel_plane_destroy,
> +       .atomic_duplicate_state = intel_plane_duplicate_state,
> +       .atomic_destroy_state = intel_plane_destroy_state,
> +       .format_mod_supported = i965_plane_format_mod_supported,
> +};
> +
> +static const struct drm_plane_funcs i8xx_plane_funcs = {
> +       .update_plane = drm_atomic_helper_update_plane,
> +       .disable_plane = drm_atomic_helper_disable_plane,
> +       .destroy = intel_plane_destroy,
> +       .atomic_duplicate_state = intel_plane_duplicate_state,
> +       .atomic_destroy_state = intel_plane_destroy_state,
> +       .format_mod_supported = i8xx_plane_format_mod_supported,
> +};
> +
> +static struct intel_plane *
> +intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> +{
> +       struct intel_plane *plane;
> +       const struct drm_plane_funcs *plane_funcs;
> +       unsigned int supported_rotations;
> +       const u32 *formats;
> +       int num_formats;
> +       int ret, zpos;
> +
> +       if (INTEL_GEN(dev_priv) >= 9)
> +               return skl_universal_plane_create(dev_priv, pipe,
> +                                                 PLANE_PRIMARY);
> +
> +       plane = intel_plane_alloc();
> +       if (IS_ERR(plane))
> +               return plane;
> +
> +       plane->pipe = pipe;
> +       /*
> +        * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
> +        * port is hooked to pipe B. Hence we want plane A feeding pipe B.
> +        */
> +       if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
> +           INTEL_NUM_PIPES(dev_priv) == 2)
> +               plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
> +       else
> +               plane->i9xx_plane = (enum i9xx_plane_id) pipe;
> +       plane->id = PLANE_PRIMARY;
> +       plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
> +
> +       plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
> +       if (plane->has_fbc) {
> +               struct intel_fbc *fbc = &dev_priv->fbc;
> +
> +               fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
> +       }
> +
> +       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +               formats = vlv_primary_formats;
> +               num_formats = ARRAY_SIZE(vlv_primary_formats);
> +       } else if (INTEL_GEN(dev_priv) >= 4) {
> +               /*
> +                * WaFP16GammaEnabling:ivb
> +                * "Workaround : When using the 64-bit format, the plane
> +                *  output on each color channel has one quarter amplitude.
> +                *  It can be brought up to full amplitude by using pipe
> +                *  gamma correction or pipe color space conversion to
> +                *  multiply the plane output by four."
> +                *
> +                * There is no dedicated plane gamma for the primary plane,
> +                * and using the pipe gamma/csc could conflict with other
> +                * planes, so we choose not to expose fp16 on IVB primary
> +                * planes. HSW primary planes no longer have this problem.
> +                */
> +               if (IS_IVYBRIDGE(dev_priv)) {
> +                       formats = ivb_primary_formats;
> +                       num_formats = ARRAY_SIZE(ivb_primary_formats);
> +               } else {
> +                       formats = i965_primary_formats;
> +                       num_formats = ARRAY_SIZE(i965_primary_formats);
> +               }
> +       } else {
> +               formats = i8xx_primary_formats;
> +               num_formats = ARRAY_SIZE(i8xx_primary_formats);
> +       }
> +
> +       if (INTEL_GEN(dev_priv) >= 4)
> +               plane_funcs = &i965_plane_funcs;
> +       else
> +               plane_funcs = &i8xx_plane_funcs;
> +
> +       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +               plane->min_cdclk = vlv_plane_min_cdclk;
> +       else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> +               plane->min_cdclk = hsw_plane_min_cdclk;
> +       else if (IS_IVYBRIDGE(dev_priv))
> +               plane->min_cdclk = ivb_plane_min_cdclk;
> +       else
> +               plane->min_cdclk = i9xx_plane_min_cdclk;
> +
> +       plane->max_stride = i9xx_plane_max_stride;
> +       plane->update_plane = i9xx_update_plane;
> +       plane->disable_plane = i9xx_disable_plane;
> +       plane->get_hw_state = i9xx_plane_get_hw_state;
> +       plane->check_plane = i9xx_plane_check;
> +
> +       if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> +               ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> +                                              0, plane_funcs,
> +                                              formats, num_formats,
> +                                              i9xx_format_modifiers,
> +                                              DRM_PLANE_TYPE_PRIMARY,
> +                                              "primary %c", pipe_name(pipe));
> +       else
> +               ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> +                                              0, plane_funcs,
> +                                              formats, num_formats,
> +                                              i9xx_format_modifiers,
> +                                              DRM_PLANE_TYPE_PRIMARY,
> +                                              "plane %c",
> +                                              plane_name(plane->i9xx_plane));
> +       if (ret)
> +               goto fail;
> +
> +       if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> +               supported_rotations =
> +                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
> +                       DRM_MODE_REFLECT_X;
> +       } else if (INTEL_GEN(dev_priv) >= 4) {
> +               supported_rotations =
> +                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
> +       } else {
> +               supported_rotations = DRM_MODE_ROTATE_0;
> +       }
> +
> +       if (INTEL_GEN(dev_priv) >= 4)
> +               drm_plane_create_rotation_property(&plane->base,
> +                                                  DRM_MODE_ROTATE_0,
> +                                                  supported_rotations);
> +
> +       zpos = 0;
> +       drm_plane_create_zpos_immutable_property(&plane->base, zpos);
> +
> +       drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
> +
> +       return plane;
> +
> +fail:
> +       intel_plane_free(plane);
> +
> +       return ERR_PTR(ret);
> +}
> +
> +static struct intel_crtc *intel_crtc_alloc(void)
> +{
> +       struct intel_crtc_state *crtc_state;
> +       struct intel_crtc *crtc;
> +
> +       crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
> +       if (!crtc)
> +               return ERR_PTR(-ENOMEM);
> +
> +       crtc_state = intel_crtc_state_alloc(crtc);
> +       if (!crtc_state) {
> +               kfree(crtc);
> +               return ERR_PTR(-ENOMEM);
> +       }
> +
> +       crtc->base.state = &crtc_state->uapi;
> +       crtc->config = crtc_state;
> +
> +       return crtc;
> +}
> +
> +static void intel_crtc_free(struct intel_crtc *crtc)
> +{
> +       intel_crtc_destroy_state(&crtc->base, crtc->base.state);
> +       kfree(crtc);
> +}
> +
> +static void intel_crtc_destroy(struct drm_crtc *crtc)
> +{
> +       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +
> +       drm_crtc_cleanup(crtc);
> +       kfree(intel_crtc);
> +}
> +
> +static int intel_crtc_late_register(struct drm_crtc *crtc)
> +{
> +       intel_crtc_debugfs_add(crtc);
> +       return 0;
> +}
> +
> +#define INTEL_CRTC_FUNCS \
> +       .gamma_set = drm_atomic_helper_legacy_gamma_set, \
> +       .set_config = drm_atomic_helper_set_config, \
> +       .destroy = intel_crtc_destroy, \
> +       .page_flip = drm_atomic_helper_page_flip, \
> +       .atomic_duplicate_state = intel_crtc_duplicate_state, \
> +       .atomic_destroy_state = intel_crtc_destroy_state, \
> +       .set_crc_source = intel_crtc_set_crc_source, \
> +       .verify_crc_source = intel_crtc_verify_crc_source, \
> +       .get_crc_sources = intel_crtc_get_crc_sources, \
> +       .late_register = intel_crtc_late_register
> +
> +static const struct drm_crtc_funcs bdw_crtc_funcs = {
> +       INTEL_CRTC_FUNCS,
> +
> +       .get_vblank_counter = g4x_get_vblank_counter,
> +       .enable_vblank = bdw_enable_vblank,
> +       .disable_vblank = bdw_disable_vblank,
> +       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs ilk_crtc_funcs = {
> +       INTEL_CRTC_FUNCS,
> +
> +       .get_vblank_counter = g4x_get_vblank_counter,
> +       .enable_vblank = ilk_enable_vblank,
> +       .disable_vblank = ilk_disable_vblank,
> +       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs g4x_crtc_funcs = {
> +       INTEL_CRTC_FUNCS,
> +
> +       .get_vblank_counter = g4x_get_vblank_counter,
> +       .enable_vblank = i965_enable_vblank,
> +       .disable_vblank = i965_disable_vblank,
> +       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i965_crtc_funcs = {
> +       INTEL_CRTC_FUNCS,
> +
> +       .get_vblank_counter = i915_get_vblank_counter,
> +       .enable_vblank = i965_enable_vblank,
> +       .disable_vblank = i965_disable_vblank,
> +       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i915gm_crtc_funcs = {
> +       INTEL_CRTC_FUNCS,
> +
> +       .get_vblank_counter = i915_get_vblank_counter,
> +       .enable_vblank = i915gm_enable_vblank,
> +       .disable_vblank = i915gm_disable_vblank,
> +       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i915_crtc_funcs = {
> +       INTEL_CRTC_FUNCS,
> +
> +       .get_vblank_counter = i915_get_vblank_counter,
> +       .enable_vblank = i8xx_enable_vblank,
> +       .disable_vblank = i8xx_disable_vblank,
> +       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +static const struct drm_crtc_funcs i8xx_crtc_funcs = {
> +       INTEL_CRTC_FUNCS,
> +
> +       /* no hw vblank counter */
> +       .enable_vblank = i8xx_enable_vblank,
> +       .disable_vblank = i8xx_disable_vblank,
> +       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> +};
> +
> +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
> +{
> +       struct intel_plane *primary, *cursor;
> +       const struct drm_crtc_funcs *funcs;
> +       struct intel_crtc *crtc;
> +       int sprite, ret;
> +
> +       crtc = intel_crtc_alloc();
> +       if (IS_ERR(crtc))
> +               return PTR_ERR(crtc);
> +
> +       crtc->pipe = pipe;
> +       crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
> +
> +       primary = intel_primary_plane_create(dev_priv, pipe);
> +       if (IS_ERR(primary)) {
> +               ret = PTR_ERR(primary);
> +               goto fail;
> +       }
> +       crtc->plane_ids_mask |= BIT(primary->id);
> +
> +       for_each_sprite(dev_priv, pipe, sprite) {
> +               struct intel_plane *plane;
> +
> +               plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
> +               if (IS_ERR(plane)) {
> +                       ret = PTR_ERR(plane);
> +                       goto fail;
> +               }
> +               crtc->plane_ids_mask |= BIT(plane->id);
> +       }
> +
> +       cursor = intel_cursor_plane_create(dev_priv, pipe);
> +       if (IS_ERR(cursor)) {
> +               ret = PTR_ERR(cursor);
> +               goto fail;
> +       }
> +       crtc->plane_ids_mask |= BIT(cursor->id);
> +
> +       if (HAS_GMCH(dev_priv)) {
> +               if (IS_CHERRYVIEW(dev_priv) ||
> +                   IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
> +                       funcs = &g4x_crtc_funcs;
> +               else if (IS_GEN(dev_priv, 4))
> +                       funcs = &i965_crtc_funcs;
> +               else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
> +                       funcs = &i915gm_crtc_funcs;
> +               else if (IS_GEN(dev_priv, 3))
> +                       funcs = &i915_crtc_funcs;
> +               else
> +                       funcs = &i8xx_crtc_funcs;
> +       } else {
> +               if (INTEL_GEN(dev_priv) >= 8)
> +                       funcs = &bdw_crtc_funcs;
> +               else
> +                       funcs = &ilk_crtc_funcs;
> +       }
> +
> +       ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
> +                                       &primary->base, &cursor->base,
> +                                       funcs, "pipe %c", pipe_name(pipe));
> +       if (ret)
> +               goto fail;
> +
> +       BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
> +              dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
> +       dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
> +
> +       if (INTEL_GEN(dev_priv) < 9) {
> +               enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
> +
> +               BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
> +                      dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
> +               dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
> +       }
> +
> +       if (INTEL_GEN(dev_priv) >= 10)
> +               drm_crtc_create_scaling_filter_property(&crtc->base,
> +                                               BIT(DRM_SCALING_FILTER_DEFAULT) |
> +                                               BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
> +
> +       intel_color_init(crtc);
> +
> +       intel_crtc_crc_init(crtc);
> +
> +       drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
> +
> +       return 0;
> +
> +fail:
> +       intel_crtc_free(crtc);
> +
> +       return ret;
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 0a3b97889248..c6f30e4ec51e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -87,56 +87,6 @@
>  #include "intel_tc.h"
>  #include "intel_vga.h"
>
> -/* Primary plane formats for gen <= 3 */
> -static const u32 i8xx_primary_formats[] = {
> -       DRM_FORMAT_C8,
> -       DRM_FORMAT_XRGB1555,
> -       DRM_FORMAT_RGB565,
> -       DRM_FORMAT_XRGB8888,
> -};
> -
> -/* Primary plane formats for ivb (no fp16 due to hw issue) */
> -static const u32 ivb_primary_formats[] = {
> -       DRM_FORMAT_C8,
> -       DRM_FORMAT_RGB565,
> -       DRM_FORMAT_XRGB8888,
> -       DRM_FORMAT_XBGR8888,
> -       DRM_FORMAT_XRGB2101010,
> -       DRM_FORMAT_XBGR2101010,
> -};
> -
> -/* Primary plane formats for gen >= 4, except ivb */
> -static const u32 i965_primary_formats[] = {
> -       DRM_FORMAT_C8,
> -       DRM_FORMAT_RGB565,
> -       DRM_FORMAT_XRGB8888,
> -       DRM_FORMAT_XBGR8888,
> -       DRM_FORMAT_XRGB2101010,
> -       DRM_FORMAT_XBGR2101010,
> -       DRM_FORMAT_XBGR16161616F,
> -};
> -
> -/* Primary plane formats for vlv/chv */
> -static const u32 vlv_primary_formats[] = {
> -       DRM_FORMAT_C8,
> -       DRM_FORMAT_RGB565,
> -       DRM_FORMAT_XRGB8888,
> -       DRM_FORMAT_XBGR8888,
> -       DRM_FORMAT_ARGB8888,
> -       DRM_FORMAT_ABGR8888,
> -       DRM_FORMAT_XRGB2101010,
> -       DRM_FORMAT_XBGR2101010,
> -       DRM_FORMAT_ARGB2101010,
> -       DRM_FORMAT_ABGR2101010,
> -       DRM_FORMAT_XBGR16161616F,
> -};
> -
> -static const u64 i9xx_format_modifiers[] = {
> -       I915_FORMAT_MOD_X_TILED,
> -       DRM_FORMAT_MOD_LINEAR,
> -       DRM_FORMAT_MOD_INVALID
> -};
> -
>  static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
>                                 struct intel_crtc_state *pipe_config);
>  static void ilk_pch_clock_get(struct intel_crtc *crtc,
> @@ -162,7 +112,6 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state);
>  static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
>  static void intel_modeset_setup_hw_state(struct drm_device *dev,
>                                          struct drm_modeset_acquire_ctx *ctx);
> -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
>
>  struct intel_limit {
>         struct {
> @@ -1306,12 +1255,6 @@ static void assert_planes_disabled(struct intel_crtc *crtc)
>                 assert_plane_disabled(plane);
>  }
>
> -static void assert_vblank_disabled(struct drm_crtc *crtc)
> -{
> -       if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
> -               drm_crtc_vblank_put(crtc);
> -}
> -
>  void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
>                                     enum pipe pipe)
>  {
> @@ -1796,55 +1739,6 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
>                 return crtc->pipe;
>  }
>
> -static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
> -{
> -       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -       u32 mode_flags = crtc->mode_flags;
> -
> -       /*
> -        * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
> -        * have updated at the beginning of TE, if we want to use
> -        * the hw counter, then we would find it updated in only
> -        * the next TE, hence switching to sw counter.
> -        */
> -       if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
> -               return 0;
> -
> -       /*
> -        * On i965gm the hardware frame counter reads
> -        * zero when the TV encoder is enabled :(
> -        */
> -       if (IS_I965GM(dev_priv) &&
> -           (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
> -               return 0;
> -
> -       if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> -               return 0xffffffff; /* full 32 bit counter */
> -       else if (INTEL_GEN(dev_priv) >= 3)
> -               return 0xffffff; /* only 24 bits of frame count */
> -       else
> -               return 0; /* Gen2 doesn't have a hardware frame counter */
> -}
> -
> -void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
> -{
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -
> -       assert_vblank_disabled(&crtc->base);
> -       drm_crtc_set_max_vblank_count(&crtc->base,
> -                                     intel_crtc_max_vblank_count(crtc_state));
> -       drm_crtc_vblank_on(&crtc->base);
> -}
> -
> -void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
> -{
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -
> -       drm_crtc_vblank_off(&crtc->base);
> -       assert_vblank_disabled(&crtc->base);
> -}
> -
>  void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
>  {
>         struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
> @@ -4057,171 +3951,6 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
>         return 0;
>  }
>
> -static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
> -                            const struct intel_plane_state *plane_state,
> -                            unsigned int *num, unsigned int *den)
> -{
> -       const struct drm_framebuffer *fb = plane_state->hw.fb;
> -       unsigned int cpp = fb->format->cpp[0];
> -
> -       /*
> -        * g4x bspec says 64bpp pixel rate can't exceed 80%
> -        * of cdclk when the sprite plane is enabled on the
> -        * same pipe. ilk/snb bspec says 64bpp pixel rate is
> -        * never allowed to exceed 80% of cdclk. Let's just go
> -        * with the ilk/snb limit always.
> -        */
> -       if (cpp == 8) {
> -               *num = 10;
> -               *den = 8;
> -       } else {
> -               *num = 1;
> -               *den = 1;
> -       }
> -}
> -
> -static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
> -                               const struct intel_plane_state *plane_state)
> -{
> -       unsigned int pixel_rate;
> -       unsigned int num, den;
> -
> -       /*
> -        * Note that crtc_state->pixel_rate accounts for both
> -        * horizontal and vertical panel fitter downscaling factors.
> -        * Pre-HSW bspec tells us to only consider the horizontal
> -        * downscaling factor here. We ignore that and just consider
> -        * both for simplicity.
> -        */
> -       pixel_rate = crtc_state->pixel_rate;
> -
> -       i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
> -
> -       /* two pixels per clock with double wide pipe */
> -       if (crtc_state->double_wide)
> -               den *= 2;
> -
> -       return DIV_ROUND_UP(pixel_rate * num, den);
> -}
> -
> -unsigned int
> -i9xx_plane_max_stride(struct intel_plane *plane,
> -                     u32 pixel_format, u64 modifier,
> -                     unsigned int rotation)
> -{
> -       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -
> -       if (!HAS_GMCH(dev_priv)) {
> -               return 32*1024;
> -       } else if (INTEL_GEN(dev_priv) >= 4) {
> -               if (modifier == I915_FORMAT_MOD_X_TILED)
> -                       return 16*1024;
> -               else
> -                       return 32*1024;
> -       } else if (INTEL_GEN(dev_priv) >= 3) {
> -               if (modifier == I915_FORMAT_MOD_X_TILED)
> -                       return 8*1024;
> -               else
> -                       return 16*1024;
> -       } else {
> -               if (plane->i9xx_plane == PLANE_C)
> -                       return 4*1024;
> -               else
> -                       return 8*1024;
> -       }
> -}
> -
> -static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
> -{
> -       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> -       u32 dspcntr = 0;
> -
> -       if (crtc_state->gamma_enable)
> -               dspcntr |= DISPPLANE_GAMMA_ENABLE;
> -
> -       if (crtc_state->csc_enable)
> -               dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
> -
> -       if (INTEL_GEN(dev_priv) < 5)
> -               dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
> -
> -       return dspcntr;
> -}
> -
> -static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
> -                         const struct intel_plane_state *plane_state)
> -{
> -       struct drm_i915_private *dev_priv =
> -               to_i915(plane_state->uapi.plane->dev);
> -       const struct drm_framebuffer *fb = plane_state->hw.fb;
> -       unsigned int rotation = plane_state->hw.rotation;
> -       u32 dspcntr;
> -
> -       dspcntr = DISPLAY_PLANE_ENABLE;
> -
> -       if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
> -           IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
> -               dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> -
> -       switch (fb->format->format) {
> -       case DRM_FORMAT_C8:
> -               dspcntr |= DISPPLANE_8BPP;
> -               break;
> -       case DRM_FORMAT_XRGB1555:
> -               dspcntr |= DISPPLANE_BGRX555;
> -               break;
> -       case DRM_FORMAT_ARGB1555:
> -               dspcntr |= DISPPLANE_BGRA555;
> -               break;
> -       case DRM_FORMAT_RGB565:
> -               dspcntr |= DISPPLANE_BGRX565;
> -               break;
> -       case DRM_FORMAT_XRGB8888:
> -               dspcntr |= DISPPLANE_BGRX888;
> -               break;
> -       case DRM_FORMAT_XBGR8888:
> -               dspcntr |= DISPPLANE_RGBX888;
> -               break;
> -       case DRM_FORMAT_ARGB8888:
> -               dspcntr |= DISPPLANE_BGRA888;
> -               break;
> -       case DRM_FORMAT_ABGR8888:
> -               dspcntr |= DISPPLANE_RGBA888;
> -               break;
> -       case DRM_FORMAT_XRGB2101010:
> -               dspcntr |= DISPPLANE_BGRX101010;
> -               break;
> -       case DRM_FORMAT_XBGR2101010:
> -               dspcntr |= DISPPLANE_RGBX101010;
> -               break;
> -       case DRM_FORMAT_ARGB2101010:
> -               dspcntr |= DISPPLANE_BGRA101010;
> -               break;
> -       case DRM_FORMAT_ABGR2101010:
> -               dspcntr |= DISPPLANE_RGBA101010;
> -               break;
> -       case DRM_FORMAT_XBGR16161616F:
> -               dspcntr |= DISPPLANE_RGBX161616;
> -               break;
> -       default:
> -               MISSING_CASE(fb->format->format);
> -               return 0;
> -       }
> -
> -       if (INTEL_GEN(dev_priv) >= 4 &&
> -           fb->modifier == I915_FORMAT_MOD_X_TILED)
> -               dspcntr |= DISPPLANE_TILED;
> -
> -       if (rotation & DRM_MODE_ROTATE_180)
> -               dspcntr |= DISPPLANE_ROTATE_180;
> -
> -       if (rotation & DRM_MODE_REFLECT_X)
> -               dspcntr |= DISPPLANE_MIRROR;
> -
> -       return dspcntr;
> -}
> -
>  int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
>  {
>         struct drm_i915_private *dev_priv =
> @@ -4282,197 +4011,6 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
>         return 0;
>  }
>
> -static bool i9xx_plane_has_windowing(struct intel_plane *plane)
> -{
> -       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -
> -       if (IS_CHERRYVIEW(dev_priv))
> -               return i9xx_plane == PLANE_B;
> -       else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> -               return false;
> -       else if (IS_GEN(dev_priv, 4))
> -               return i9xx_plane == PLANE_C;
> -       else
> -               return i9xx_plane == PLANE_B ||
> -                       i9xx_plane == PLANE_C;
> -}
> -
> -static int
> -i9xx_plane_check(struct intel_crtc_state *crtc_state,
> -                struct intel_plane_state *plane_state)
> -{
> -       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
> -       int ret;
> -
> -       ret = chv_plane_check_rotation(plane_state);
> -       if (ret)
> -               return ret;
> -
> -       ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
> -                                               DRM_PLANE_HELPER_NO_SCALING,
> -                                               DRM_PLANE_HELPER_NO_SCALING,
> -                                               i9xx_plane_has_windowing(plane));
> -       if (ret)
> -               return ret;
> -
> -       ret = i9xx_check_plane_surface(plane_state);
> -       if (ret)
> -               return ret;
> -
> -       if (!plane_state->uapi.visible)
> -               return 0;
> -
> -       ret = intel_plane_check_src_coordinates(plane_state);
> -       if (ret)
> -               return ret;
> -
> -       plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
> -
> -       return 0;
> -}
> -
> -static void i9xx_update_plane(struct intel_plane *plane,
> -                             const struct intel_crtc_state *crtc_state,
> -                             const struct intel_plane_state *plane_state)
> -{
> -       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -       u32 linear_offset;
> -       int x = plane_state->color_plane[0].x;
> -       int y = plane_state->color_plane[0].y;
> -       int crtc_x = plane_state->uapi.dst.x1;
> -       int crtc_y = plane_state->uapi.dst.y1;
> -       int crtc_w = drm_rect_width(&plane_state->uapi.dst);
> -       int crtc_h = drm_rect_height(&plane_state->uapi.dst);
> -       unsigned long irqflags;
> -       u32 dspaddr_offset;
> -       u32 dspcntr;
> -
> -       dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
> -
> -       linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
> -
> -       if (INTEL_GEN(dev_priv) >= 4)
> -               dspaddr_offset = plane_state->color_plane[0].offset;
> -       else
> -               dspaddr_offset = linear_offset;
> -
> -       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> -       intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
> -                         plane_state->color_plane[0].stride);
> -
> -       if (INTEL_GEN(dev_priv) < 4) {
> -               /*
> -                * PLANE_A doesn't actually have a full window
> -                * generator but let's assume we still need to
> -                * program whatever is there.
> -                */
> -               intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
> -                                 (crtc_y << 16) | crtc_x);
> -               intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
> -                                 ((crtc_h - 1) << 16) | (crtc_w - 1));
> -       } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
> -               intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
> -                                 (crtc_y << 16) | crtc_x);
> -               intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
> -                                 ((crtc_h - 1) << 16) | (crtc_w - 1));
> -               intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
> -       }
> -
> -       if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
> -               intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
> -                                 (y << 16) | x);
> -       } else if (INTEL_GEN(dev_priv) >= 4) {
> -               intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
> -                                 linear_offset);
> -               intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
> -                                 (y << 16) | x);
> -       }
> -
> -       /*
> -        * The control register self-arms if the plane was previously
> -        * disabled. Try to make the plane enable atomic by writing
> -        * the control register just before the surface register.
> -        */
> -       intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> -       if (INTEL_GEN(dev_priv) >= 4)
> -               intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
> -                                 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> -       else
> -               intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
> -                                 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
> -
> -       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static void i9xx_disable_plane(struct intel_plane *plane,
> -                              const struct intel_crtc_state *crtc_state)
> -{
> -       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -       unsigned long irqflags;
> -       u32 dspcntr;
> -
> -       /*
> -        * DSPCNTR pipe gamma enable on g4x+ and pipe csc
> -        * enable on ilk+ affect the pipe bottom color as
> -        * well, so we must configure them even if the plane
> -        * is disabled.
> -        *
> -        * On pre-g4x there is no way to gamma correct the
> -        * pipe bottom color but we'll keep on doing this
> -        * anyway so that the crtc state readout works correctly.
> -        */
> -       dspcntr = i9xx_plane_ctl_crtc(crtc_state);
> -
> -       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
> -
> -       intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
> -       if (INTEL_GEN(dev_priv) >= 4)
> -               intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
> -       else
> -               intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
> -
> -       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
> -}
> -
> -static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
> -                                   enum pipe *pipe)
> -{
> -       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> -       enum intel_display_power_domain power_domain;
> -       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> -       intel_wakeref_t wakeref;
> -       bool ret;
> -       u32 val;
> -
> -       /*
> -        * Not 100% correct for planes that can move between pipes,
> -        * but that's only the case for gen2-4 which don't have any
> -        * display power wells.
> -        */
> -       power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -       wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> -       if (!wakeref)
> -               return false;
> -
> -       val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
> -
> -       ret = val & DISPLAY_PLANE_ENABLE;
> -
> -       if (INTEL_GEN(dev_priv) >= 5)
> -               *pipe = plane->pipe;
> -       else
> -               *pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
> -                       DISPPLANE_SEL_PIPE_SHIFT;
> -
> -       intel_display_power_put(dev_priv, power_domain, wakeref);
> -
> -       return ret;
> -}
> -
>  static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
>  {
>         struct drm_device *dev = intel_crtc->base.dev;
> @@ -11919,33 +11457,6 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc,
>                                          &pipe_config->fdi_m_n);
>  }
>
> -static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> -                                  struct intel_crtc *crtc)
> -{
> -       memset(crtc_state, 0, sizeof(*crtc_state));
> -
> -       __drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
> -
> -       crtc_state->cpu_transcoder = INVALID_TRANSCODER;
> -       crtc_state->master_transcoder = INVALID_TRANSCODER;
> -       crtc_state->hsw_workaround_pipe = INVALID_PIPE;
> -       crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
> -       crtc_state->scaler_state.scaler_id = -1;
> -       crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
> -}
> -
> -static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
> -{
> -       struct intel_crtc_state *crtc_state;
> -
> -       crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
> -
> -       if (crtc_state)
> -               intel_crtc_state_reset(crtc_state, crtc);
> -
> -       return crtc_state;
> -}
> -
>  /* Returns the currently programmed mode of the given encoder. */
>  struct drm_display_mode *
>  intel_encoder_current_mode(struct intel_encoder *encoder)
> @@ -11986,14 +11497,6 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
>         return mode;
>  }
>
> -static void intel_crtc_destroy(struct drm_crtc *crtc)
> -{
> -       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -
> -       drm_crtc_cleanup(crtc);
> -       kfree(intel_crtc);
> -}
> -
>  /**
>   * intel_wm_need_update - Check whether watermarks need updating
>   * @cur: current plane state
> @@ -15197,17 +14700,6 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
>         return 0;
>  }
>
> -u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->base.dev;
> -       struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
> -
> -       if (!vblank->max_vblank_count)
> -               return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
> -
> -       return crtc->base.funcs->get_vblank_counter(&crtc->base);
> -}
> -
>  void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
>                                   struct intel_crtc_state *crtc_state)
>  {
> @@ -16260,336 +15752,6 @@ void intel_plane_destroy(struct drm_plane *plane)
>         kfree(to_intel_plane(plane));
>  }
>
> -static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
> -                                           u32 format, u64 modifier)
> -{
> -       switch (modifier) {
> -       case DRM_FORMAT_MOD_LINEAR:
> -       case I915_FORMAT_MOD_X_TILED:
> -               break;
> -       default:
> -               return false;
> -       }
> -
> -       switch (format) {
> -       case DRM_FORMAT_C8:
> -       case DRM_FORMAT_RGB565:
> -       case DRM_FORMAT_XRGB1555:
> -       case DRM_FORMAT_XRGB8888:
> -               return modifier == DRM_FORMAT_MOD_LINEAR ||
> -                       modifier == I915_FORMAT_MOD_X_TILED;
> -       default:
> -               return false;
> -       }
> -}
> -
> -static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
> -                                           u32 format, u64 modifier)
> -{
> -       switch (modifier) {
> -       case DRM_FORMAT_MOD_LINEAR:
> -       case I915_FORMAT_MOD_X_TILED:
> -               break;
> -       default:
> -               return false;
> -       }
> -
> -       switch (format) {
> -       case DRM_FORMAT_C8:
> -       case DRM_FORMAT_RGB565:
> -       case DRM_FORMAT_XRGB8888:
> -       case DRM_FORMAT_XBGR8888:
> -       case DRM_FORMAT_ARGB8888:
> -       case DRM_FORMAT_ABGR8888:
> -       case DRM_FORMAT_XRGB2101010:
> -       case DRM_FORMAT_XBGR2101010:
> -       case DRM_FORMAT_ARGB2101010:
> -       case DRM_FORMAT_ABGR2101010:
> -       case DRM_FORMAT_XBGR16161616F:
> -               return modifier == DRM_FORMAT_MOD_LINEAR ||
> -                       modifier == I915_FORMAT_MOD_X_TILED;
> -       default:
> -               return false;
> -       }
> -}
> -
> -static const struct drm_plane_funcs i965_plane_funcs = {
> -       .update_plane = drm_atomic_helper_update_plane,
> -       .disable_plane = drm_atomic_helper_disable_plane,
> -       .destroy = intel_plane_destroy,
> -       .atomic_duplicate_state = intel_plane_duplicate_state,
> -       .atomic_destroy_state = intel_plane_destroy_state,
> -       .format_mod_supported = i965_plane_format_mod_supported,
> -};
> -
> -static const struct drm_plane_funcs i8xx_plane_funcs = {
> -       .update_plane = drm_atomic_helper_update_plane,
> -       .disable_plane = drm_atomic_helper_disable_plane,
> -       .destroy = intel_plane_destroy,
> -       .atomic_duplicate_state = intel_plane_duplicate_state,
> -       .atomic_destroy_state = intel_plane_destroy_state,
> -       .format_mod_supported = i8xx_plane_format_mod_supported,
> -};
> -
> -static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
> -                              enum i9xx_plane_id i9xx_plane)
> -{
> -       if (!HAS_FBC(dev_priv))
> -               return false;
> -
> -       if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> -               return i9xx_plane == PLANE_A; /* tied to pipe A */
> -       else if (IS_IVYBRIDGE(dev_priv))
> -               return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
> -                       i9xx_plane == PLANE_C;
> -       else if (INTEL_GEN(dev_priv) >= 4)
> -               return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
> -       else
> -               return i9xx_plane == PLANE_A;
> -}
> -
> -static struct intel_plane *
> -intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
> -{
> -       struct intel_plane *plane;
> -       const struct drm_plane_funcs *plane_funcs;
> -       unsigned int supported_rotations;
> -       const u32 *formats;
> -       int num_formats;
> -       int ret, zpos;
> -
> -       if (INTEL_GEN(dev_priv) >= 9)
> -               return skl_universal_plane_create(dev_priv, pipe,
> -                                                 PLANE_PRIMARY);
> -
> -       plane = intel_plane_alloc();
> -       if (IS_ERR(plane))
> -               return plane;
> -
> -       plane->pipe = pipe;
> -       /*
> -        * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
> -        * port is hooked to pipe B. Hence we want plane A feeding pipe B.
> -        */
> -       if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
> -           INTEL_NUM_PIPES(dev_priv) == 2)
> -               plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
> -       else
> -               plane->i9xx_plane = (enum i9xx_plane_id) pipe;
> -       plane->id = PLANE_PRIMARY;
> -       plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
> -
> -       plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
> -       if (plane->has_fbc) {
> -               struct intel_fbc *fbc = &dev_priv->fbc;
> -
> -               fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
> -       }
> -
> -       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -               formats = vlv_primary_formats;
> -               num_formats = ARRAY_SIZE(vlv_primary_formats);
> -       } else if (INTEL_GEN(dev_priv) >= 4) {
> -               /*
> -                * WaFP16GammaEnabling:ivb
> -                * "Workaround : When using the 64-bit format, the plane
> -                *  output on each color channel has one quarter amplitude.
> -                *  It can be brought up to full amplitude by using pipe
> -                *  gamma correction or pipe color space conversion to
> -                *  multiply the plane output by four."
> -                *
> -                * There is no dedicated plane gamma for the primary plane,
> -                * and using the pipe gamma/csc could conflict with other
> -                * planes, so we choose not to expose fp16 on IVB primary
> -                * planes. HSW primary planes no longer have this problem.
> -                */
> -               if (IS_IVYBRIDGE(dev_priv)) {
> -                       formats = ivb_primary_formats;
> -                       num_formats = ARRAY_SIZE(ivb_primary_formats);
> -               } else {
> -                       formats = i965_primary_formats;
> -                       num_formats = ARRAY_SIZE(i965_primary_formats);
> -               }
> -       } else {
> -               formats = i8xx_primary_formats;
> -               num_formats = ARRAY_SIZE(i8xx_primary_formats);
> -       }
> -
> -       if (INTEL_GEN(dev_priv) >= 4)
> -               plane_funcs = &i965_plane_funcs;
> -       else
> -               plane_funcs = &i8xx_plane_funcs;
> -
> -       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -               plane->min_cdclk = vlv_plane_min_cdclk;
> -       else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> -               plane->min_cdclk = hsw_plane_min_cdclk;
> -       else if (IS_IVYBRIDGE(dev_priv))
> -               plane->min_cdclk = ivb_plane_min_cdclk;
> -       else
> -               plane->min_cdclk = i9xx_plane_min_cdclk;
> -
> -       plane->max_stride = i9xx_plane_max_stride;
> -       plane->update_plane = i9xx_update_plane;
> -       plane->disable_plane = i9xx_disable_plane;
> -       plane->get_hw_state = i9xx_plane_get_hw_state;
> -       plane->check_plane = i9xx_plane_check;
> -
> -       if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
> -               ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> -                                              0, plane_funcs,
> -                                              formats, num_formats,
> -                                              i9xx_format_modifiers,
> -                                              DRM_PLANE_TYPE_PRIMARY,
> -                                              "primary %c", pipe_name(pipe));
> -       else
> -               ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
> -                                              0, plane_funcs,
> -                                              formats, num_formats,
> -                                              i9xx_format_modifiers,
> -                                              DRM_PLANE_TYPE_PRIMARY,
> -                                              "plane %c",
> -                                              plane_name(plane->i9xx_plane));
> -       if (ret)
> -               goto fail;
> -
> -       if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
> -               supported_rotations =
> -                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
> -                       DRM_MODE_REFLECT_X;
> -       } else if (INTEL_GEN(dev_priv) >= 4) {
> -               supported_rotations =
> -                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
> -       } else {
> -               supported_rotations = DRM_MODE_ROTATE_0;
> -       }
> -
> -       if (INTEL_GEN(dev_priv) >= 4)
> -               drm_plane_create_rotation_property(&plane->base,
> -                                                  DRM_MODE_ROTATE_0,
> -                                                  supported_rotations);
> -
> -       zpos = 0;
> -       drm_plane_create_zpos_immutable_property(&plane->base, zpos);
> -
> -       drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
> -
> -       return plane;
> -
> -fail:
> -       intel_plane_free(plane);
> -
> -       return ERR_PTR(ret);
> -}
> -
> -static int intel_crtc_late_register(struct drm_crtc *crtc)
> -{
> -       intel_crtc_debugfs_add(crtc);
> -       return 0;
> -}
> -
> -#define INTEL_CRTC_FUNCS \
> -       .gamma_set = drm_atomic_helper_legacy_gamma_set, \
> -       .set_config = drm_atomic_helper_set_config, \
> -       .destroy = intel_crtc_destroy, \
> -       .page_flip = drm_atomic_helper_page_flip, \
> -       .atomic_duplicate_state = intel_crtc_duplicate_state, \
> -       .atomic_destroy_state = intel_crtc_destroy_state, \
> -       .set_crc_source = intel_crtc_set_crc_source, \
> -       .verify_crc_source = intel_crtc_verify_crc_source, \
> -       .get_crc_sources = intel_crtc_get_crc_sources, \
> -       .late_register = intel_crtc_late_register
> -
> -static const struct drm_crtc_funcs bdw_crtc_funcs = {
> -       INTEL_CRTC_FUNCS,
> -
> -       .get_vblank_counter = g4x_get_vblank_counter,
> -       .enable_vblank = bdw_enable_vblank,
> -       .disable_vblank = bdw_disable_vblank,
> -       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs ilk_crtc_funcs = {
> -       INTEL_CRTC_FUNCS,
> -
> -       .get_vblank_counter = g4x_get_vblank_counter,
> -       .enable_vblank = ilk_enable_vblank,
> -       .disable_vblank = ilk_disable_vblank,
> -       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs g4x_crtc_funcs = {
> -       INTEL_CRTC_FUNCS,
> -
> -       .get_vblank_counter = g4x_get_vblank_counter,
> -       .enable_vblank = i965_enable_vblank,
> -       .disable_vblank = i965_disable_vblank,
> -       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i965_crtc_funcs = {
> -       INTEL_CRTC_FUNCS,
> -
> -       .get_vblank_counter = i915_get_vblank_counter,
> -       .enable_vblank = i965_enable_vblank,
> -       .disable_vblank = i965_disable_vblank,
> -       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i915gm_crtc_funcs = {
> -       INTEL_CRTC_FUNCS,
> -
> -       .get_vblank_counter = i915_get_vblank_counter,
> -       .enable_vblank = i915gm_enable_vblank,
> -       .disable_vblank = i915gm_disable_vblank,
> -       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i915_crtc_funcs = {
> -       INTEL_CRTC_FUNCS,
> -
> -       .get_vblank_counter = i915_get_vblank_counter,
> -       .enable_vblank = i8xx_enable_vblank,
> -       .disable_vblank = i8xx_disable_vblank,
> -       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static const struct drm_crtc_funcs i8xx_crtc_funcs = {
> -       INTEL_CRTC_FUNCS,
> -
> -       /* no hw vblank counter */
> -       .enable_vblank = i8xx_enable_vblank,
> -       .disable_vblank = i8xx_disable_vblank,
> -       .get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
> -};
> -
> -static struct intel_crtc *intel_crtc_alloc(void)
> -{
> -       struct intel_crtc_state *crtc_state;
> -       struct intel_crtc *crtc;
> -
> -       crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
> -       if (!crtc)
> -               return ERR_PTR(-ENOMEM);
> -
> -       crtc_state = intel_crtc_state_alloc(crtc);
> -       if (!crtc_state) {
> -               kfree(crtc);
> -               return ERR_PTR(-ENOMEM);
> -       }
> -
> -       crtc->base.state = &crtc_state->uapi;
> -       crtc->config = crtc_state;
> -
> -       return crtc;
> -}
> -
> -static void intel_crtc_free(struct intel_crtc *crtc)
> -{
> -       intel_crtc_destroy_state(&crtc->base, crtc->base.state);
> -       kfree(crtc);
> -}
> -
>  static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
>  {
>         struct intel_plane *plane;
> @@ -16602,100 +15764,6 @@ static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
>         }
>  }
>
> -static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
> -{
> -       struct intel_plane *primary, *cursor;
> -       const struct drm_crtc_funcs *funcs;
> -       struct intel_crtc *crtc;
> -       int sprite, ret;
> -
> -       crtc = intel_crtc_alloc();
> -       if (IS_ERR(crtc))
> -               return PTR_ERR(crtc);
> -
> -       crtc->pipe = pipe;
> -       crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
> -
> -       primary = intel_primary_plane_create(dev_priv, pipe);
> -       if (IS_ERR(primary)) {
> -               ret = PTR_ERR(primary);
> -               goto fail;
> -       }
> -       crtc->plane_ids_mask |= BIT(primary->id);
> -
> -       for_each_sprite(dev_priv, pipe, sprite) {
> -               struct intel_plane *plane;
> -
> -               plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
> -               if (IS_ERR(plane)) {
> -                       ret = PTR_ERR(plane);
> -                       goto fail;
> -               }
> -               crtc->plane_ids_mask |= BIT(plane->id);
> -       }
> -
> -       cursor = intel_cursor_plane_create(dev_priv, pipe);
> -       if (IS_ERR(cursor)) {
> -               ret = PTR_ERR(cursor);
> -               goto fail;
> -       }
> -       crtc->plane_ids_mask |= BIT(cursor->id);
> -
> -       if (HAS_GMCH(dev_priv)) {
> -               if (IS_CHERRYVIEW(dev_priv) ||
> -                   IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
> -                       funcs = &g4x_crtc_funcs;
> -               else if (IS_GEN(dev_priv, 4))
> -                       funcs = &i965_crtc_funcs;
> -               else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
> -                       funcs = &i915gm_crtc_funcs;
> -               else if (IS_GEN(dev_priv, 3))
> -                       funcs = &i915_crtc_funcs;
> -               else
> -                       funcs = &i8xx_crtc_funcs;
> -       } else {
> -               if (INTEL_GEN(dev_priv) >= 8)
> -                       funcs = &bdw_crtc_funcs;
> -               else
> -                       funcs = &ilk_crtc_funcs;
> -       }
> -
> -       ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
> -                                       &primary->base, &cursor->base,
> -                                       funcs, "pipe %c", pipe_name(pipe));
> -       if (ret)
> -               goto fail;
> -
> -       BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
> -              dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
> -       dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
> -
> -       if (INTEL_GEN(dev_priv) < 9) {
> -               enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
> -
> -               BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
> -                      dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
> -               dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
> -       }
> -
> -       if (INTEL_GEN(dev_priv) >= 10)
> -               drm_crtc_create_scaling_filter_property(&crtc->base,
> -                                               BIT(DRM_SCALING_FILTER_DEFAULT) |
> -                                               BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
> -
> -       intel_color_init(crtc);
> -
> -       intel_crtc_crc_init(crtc);
> -
> -       drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
> -
> -       return 0;
> -
> -fail:
> -       intel_crtc_free(crtc);
> -
> -       return ret;
> -}
>
>  int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
>                                       struct drm_file *file)
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index f0a5bf69656f..0eba91d18e96 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -659,6 +659,13 @@ struct intel_plane *
>  intel_cursor_plane_create(struct drm_i915_private *dev_priv,
>                           enum pipe pipe);
>
> +/* crtc */
> +u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
> +int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
> +struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
> +void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
> +                           struct intel_crtc *crtc);
> +
>  /* modesetting */
>  void intel_modeset_init_hw(struct drm_i915_private *i915);
>  int intel_modeset_init_noirq(struct drm_i915_private *i915);
> --
> 2.27.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 98a35b939052..ffec257702af 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -196,6 +196,7 @@  i915-y += \
 	display/intel_color.o \
 	display/intel_combo_phy.o \
 	display/intel_connector.o \
+	display/intel_crtc.o \
 	display/intel_csr.o \
 	display/intel_cursor.o \
 	display/intel_display.o \
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
new file mode 100644
index 000000000000..75a79f18cee2
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -0,0 +1,951 @@ 
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_plane_helper.h>
+
+#include "intel_atomic.h"
+#include "intel_atomic_plane.h"
+#include "intel_color.h"
+#include "intel_display_debugfs.h"
+#include "intel_display_types.h"
+#include "intel_pipe_crc.h"
+#include "intel_sprite.h"
+
+/* Primary plane formats for gen <= 3 */
+static const u32 i8xx_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+};
+
+/* Primary plane formats for ivb (no fp16 due to hw issue) */
+static const u32 ivb_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+};
+
+/* Primary plane formats for gen >= 4, except ivb */
+static const u32 i965_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_XBGR16161616F,
+};
+
+/* Primary plane formats for vlv/chv */
+static const u32 vlv_primary_formats[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XRGB2101010,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ARGB2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_XBGR16161616F,
+};
+
+static const u64 i9xx_format_modifiers[] = {
+	I915_FORMAT_MOD_X_TILED,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
+static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
+					    u32 format, u64 modifier)
+{
+	switch (modifier) {
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+		break;
+	default:
+		return false;
+	}
+
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XRGB8888:
+		return modifier == DRM_FORMAT_MOD_LINEAR ||
+			modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
+					    u32 format, u64 modifier)
+{
+	switch (modifier) {
+	case DRM_FORMAT_MOD_LINEAR:
+	case I915_FORMAT_MOD_X_TILED:
+		break;
+	default:
+		return false;
+	}
+
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_XBGR16161616F:
+		return modifier == DRM_FORMAT_MOD_LINEAR ||
+			modifier == I915_FORMAT_MOD_X_TILED;
+	default:
+		return false;
+	}
+}
+
+static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
+			       enum i9xx_plane_id i9xx_plane)
+{
+	if (!HAS_FBC(dev_priv))
+		return false;
+
+	if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
+		return i9xx_plane == PLANE_A; /* tied to pipe A */
+	else if (IS_IVYBRIDGE(dev_priv))
+		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
+			i9xx_plane == PLANE_C;
+	else if (INTEL_GEN(dev_priv) >= 4)
+		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
+	else
+		return i9xx_plane == PLANE_A;
+}
+
+static void assert_vblank_disabled(struct drm_crtc *crtc)
+{
+	if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
+		drm_crtc_vblank_put(crtc);
+}
+
+u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
+
+	if (!vblank->max_vblank_count)
+		return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
+
+	return crtc->base.funcs->get_vblank_counter(&crtc->base);
+}
+
+u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	u32 mode_flags = crtc->mode_flags;
+
+	/*
+	 * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
+	 * have updated at the beginning of TE, if we want to use
+	 * the hw counter, then we would find it updated in only
+	 * the next TE, hence switching to sw counter.
+	 */
+	if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
+		return 0;
+
+	/*
+	 * On i965gm the hardware frame counter reads
+	 * zero when the TV encoder is enabled :(
+	 */
+	if (IS_I965GM(dev_priv) &&
+	    (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
+		return 0;
+
+	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		return 0xffffffff; /* full 32 bit counter */
+	else if (INTEL_GEN(dev_priv) >= 3)
+		return 0xffffff; /* only 24 bits of frame count */
+	else
+		return 0; /* Gen2 doesn't have a hardware frame counter */
+}
+
+void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	assert_vblank_disabled(&crtc->base);
+	drm_crtc_set_max_vblank_count(&crtc->base,
+				      intel_crtc_max_vblank_count(crtc_state));
+	drm_crtc_vblank_on(&crtc->base);
+}
+
+void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	drm_crtc_vblank_off(&crtc->base);
+	assert_vblank_disabled(&crtc->base);
+}
+
+struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
+{
+	struct intel_crtc_state *crtc_state;
+
+	crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
+
+	if (crtc_state)
+		intel_crtc_state_reset(crtc_state, crtc);
+
+	return crtc_state;
+}
+
+void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
+			    struct intel_crtc *crtc)
+{
+	memset(crtc_state, 0, sizeof(*crtc_state));
+
+	__drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
+
+	crtc_state->cpu_transcoder = INVALID_TRANSCODER;
+	crtc_state->master_transcoder = INVALID_TRANSCODER;
+	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
+	crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
+	crtc_state->scaler_state.scaler_id = -1;
+	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
+}
+
+static bool i9xx_plane_has_windowing(struct intel_plane *plane)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+
+	if (IS_CHERRYVIEW(dev_priv))
+		return i9xx_plane == PLANE_B;
+	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		return false;
+	else if (IS_GEN(dev_priv, 4))
+		return i9xx_plane == PLANE_C;
+	else
+		return i9xx_plane == PLANE_B ||
+			i9xx_plane == PLANE_C;
+}
+
+static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
+			  const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(plane_state->uapi.plane->dev);
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	unsigned int rotation = plane_state->hw.rotation;
+	u32 dspcntr;
+
+	dspcntr = DISPLAY_PLANE_ENABLE;
+
+	if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
+	    IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
+		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
+
+	switch (fb->format->format) {
+	case DRM_FORMAT_C8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case DRM_FORMAT_XRGB1555:
+		dspcntr |= DISPPLANE_BGRX555;
+		break;
+	case DRM_FORMAT_ARGB1555:
+		dspcntr |= DISPPLANE_BGRA555;
+		break;
+	case DRM_FORMAT_RGB565:
+		dspcntr |= DISPPLANE_BGRX565;
+		break;
+	case DRM_FORMAT_XRGB8888:
+		dspcntr |= DISPPLANE_BGRX888;
+		break;
+	case DRM_FORMAT_XBGR8888:
+		dspcntr |= DISPPLANE_RGBX888;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		dspcntr |= DISPPLANE_BGRA888;
+		break;
+	case DRM_FORMAT_ABGR8888:
+		dspcntr |= DISPPLANE_RGBA888;
+		break;
+	case DRM_FORMAT_XRGB2101010:
+		dspcntr |= DISPPLANE_BGRX101010;
+		break;
+	case DRM_FORMAT_XBGR2101010:
+		dspcntr |= DISPPLANE_RGBX101010;
+		break;
+	case DRM_FORMAT_ARGB2101010:
+		dspcntr |= DISPPLANE_BGRA101010;
+		break;
+	case DRM_FORMAT_ABGR2101010:
+		dspcntr |= DISPPLANE_RGBA101010;
+		break;
+	case DRM_FORMAT_XBGR16161616F:
+		dspcntr |= DISPPLANE_RGBX161616;
+		break;
+	default:
+		MISSING_CASE(fb->format->format);
+		return 0;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 4 &&
+	    fb->modifier == I915_FORMAT_MOD_X_TILED)
+		dspcntr |= DISPPLANE_TILED;
+
+	if (rotation & DRM_MODE_ROTATE_180)
+		dspcntr |= DISPPLANE_ROTATE_180;
+
+	if (rotation & DRM_MODE_REFLECT_X)
+		dspcntr |= DISPPLANE_MIRROR;
+
+	return dspcntr;
+}
+
+static int
+i9xx_plane_check(struct intel_crtc_state *crtc_state,
+		 struct intel_plane_state *plane_state)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+	int ret;
+
+	ret = chv_plane_check_rotation(plane_state);
+	if (ret)
+		return ret;
+
+	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
+						DRM_PLANE_HELPER_NO_SCALING,
+						DRM_PLANE_HELPER_NO_SCALING,
+						i9xx_plane_has_windowing(plane));
+	if (ret)
+		return ret;
+
+	ret = i9xx_check_plane_surface(plane_state);
+	if (ret)
+		return ret;
+
+	if (!plane_state->uapi.visible)
+		return 0;
+
+	ret = intel_plane_check_src_coordinates(plane_state);
+	if (ret)
+		return ret;
+
+	plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
+
+	return 0;
+}
+
+static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
+{
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	u32 dspcntr = 0;
+
+	if (crtc_state->gamma_enable)
+		dspcntr |= DISPPLANE_GAMMA_ENABLE;
+
+	if (crtc_state->csc_enable)
+		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
+
+	if (INTEL_GEN(dev_priv) < 5)
+		dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
+
+	return dspcntr;
+}
+
+static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
+			     const struct intel_plane_state *plane_state,
+			     unsigned int *num, unsigned int *den)
+{
+	const struct drm_framebuffer *fb = plane_state->hw.fb;
+	unsigned int cpp = fb->format->cpp[0];
+
+	/*
+	 * g4x bspec says 64bpp pixel rate can't exceed 80%
+	 * of cdclk when the sprite plane is enabled on the
+	 * same pipe. ilk/snb bspec says 64bpp pixel rate is
+	 * never allowed to exceed 80% of cdclk. Let's just go
+	 * with the ilk/snb limit always.
+	 */
+	if (cpp == 8) {
+		*num = 10;
+		*den = 8;
+	} else {
+		*num = 1;
+		*den = 1;
+	}
+}
+
+static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
+				const struct intel_plane_state *plane_state)
+{
+	unsigned int pixel_rate;
+	unsigned int num, den;
+
+	/*
+	 * Note that crtc_state->pixel_rate accounts for both
+	 * horizontal and vertical panel fitter downscaling factors.
+	 * Pre-HSW bspec tells us to only consider the horizontal
+	 * downscaling factor here. We ignore that and just consider
+	 * both for simplicity.
+	 */
+	pixel_rate = crtc_state->pixel_rate;
+
+	i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
+
+	/* two pixels per clock with double wide pipe */
+	if (crtc_state->double_wide)
+		den *= 2;
+
+	return DIV_ROUND_UP(pixel_rate * num, den);
+}
+
+static void i9xx_update_plane(struct intel_plane *plane,
+			      const struct intel_crtc_state *crtc_state,
+			      const struct intel_plane_state *plane_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+	u32 linear_offset;
+	int x = plane_state->color_plane[0].x;
+	int y = plane_state->color_plane[0].y;
+	int crtc_x = plane_state->uapi.dst.x1;
+	int crtc_y = plane_state->uapi.dst.y1;
+	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
+	int crtc_h = drm_rect_height(&plane_state->uapi.dst);
+	unsigned long irqflags;
+	u32 dspaddr_offset;
+	u32 dspcntr;
+
+	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
+
+	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		dspaddr_offset = plane_state->color_plane[0].offset;
+	else
+		dspaddr_offset = linear_offset;
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
+			  plane_state->color_plane[0].stride);
+
+	if (INTEL_GEN(dev_priv) < 4) {
+		/*
+		 * PLANE_A doesn't actually have a full window
+		 * generator but let's assume we still need to
+		 * program whatever is there.
+		 */
+		intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
+				  (crtc_y << 16) | crtc_x);
+		intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
+				  ((crtc_h - 1) << 16) | (crtc_w - 1));
+	} else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
+		intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
+				  (crtc_y << 16) | crtc_x);
+		intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
+				  ((crtc_h - 1) << 16) | (crtc_w - 1));
+		intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
+	}
+
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
+		intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
+				  (y << 16) | x);
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
+				  linear_offset);
+		intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
+				  (y << 16) | x);
+	}
+
+	/*
+	 * The control register self-arms if the plane was previously
+	 * disabled. Try to make the plane enable atomic by writing
+	 * the control register just before the surface register.
+	 */
+	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
+	if (INTEL_GEN(dev_priv) >= 4)
+		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
+				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
+	else
+		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
+				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static void i9xx_disable_plane(struct intel_plane *plane,
+			       const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+	unsigned long irqflags;
+	u32 dspcntr;
+
+	/*
+	 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
+	 * enable on ilk+ affect the pipe bottom color as
+	 * well, so we must configure them even if the plane
+	 * is disabled.
+	 *
+	 * On pre-g4x there is no way to gamma correct the
+	 * pipe bottom color but we'll keep on doing this
+	 * anyway so that the crtc state readout works correctly.
+	 */
+	dspcntr = i9xx_plane_ctl_crtc(crtc_state);
+
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
+	if (INTEL_GEN(dev_priv) >= 4)
+		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
+	else
+		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
+				    enum pipe *pipe)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+	enum intel_display_power_domain power_domain;
+	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+	intel_wakeref_t wakeref;
+	bool ret;
+	u32 val;
+
+	/*
+	 * Not 100% correct for planes that can move between pipes,
+	 * but that's only the case for gen2-4 which don't have any
+	 * display power wells.
+	 */
+	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
+		return false;
+
+	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
+
+	ret = val & DISPLAY_PLANE_ENABLE;
+
+	if (INTEL_GEN(dev_priv) >= 5)
+		*pipe = plane->pipe;
+	else
+		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
+			DISPPLANE_SEL_PIPE_SHIFT;
+
+	intel_display_power_put(dev_priv, power_domain, wakeref);
+
+	return ret;
+}
+
+unsigned int
+i9xx_plane_max_stride(struct intel_plane *plane,
+		      u32 pixel_format, u64 modifier,
+		      unsigned int rotation)
+{
+	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+
+	if (!HAS_GMCH(dev_priv)) {
+		return 32*1024;
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		if (modifier == I915_FORMAT_MOD_X_TILED)
+			return 16*1024;
+		else
+			return 32*1024;
+	} else if (INTEL_GEN(dev_priv) >= 3) {
+		if (modifier == I915_FORMAT_MOD_X_TILED)
+			return 8*1024;
+		else
+			return 16*1024;
+	} else {
+		if (plane->i9xx_plane == PLANE_C)
+			return 4*1024;
+		else
+			return 8*1024;
+	}
+}
+
+static const struct drm_plane_funcs i965_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = intel_plane_destroy,
+	.atomic_duplicate_state = intel_plane_duplicate_state,
+	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = i965_plane_format_mod_supported,
+};
+
+static const struct drm_plane_funcs i8xx_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = intel_plane_destroy,
+	.atomic_duplicate_state = intel_plane_duplicate_state,
+	.atomic_destroy_state = intel_plane_destroy_state,
+	.format_mod_supported = i8xx_plane_format_mod_supported,
+};
+
+static struct intel_plane *
+intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	struct intel_plane *plane;
+	const struct drm_plane_funcs *plane_funcs;
+	unsigned int supported_rotations;
+	const u32 *formats;
+	int num_formats;
+	int ret, zpos;
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		return skl_universal_plane_create(dev_priv, pipe,
+						  PLANE_PRIMARY);
+
+	plane = intel_plane_alloc();
+	if (IS_ERR(plane))
+		return plane;
+
+	plane->pipe = pipe;
+	/*
+	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
+	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
+	 */
+	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
+	    INTEL_NUM_PIPES(dev_priv) == 2)
+		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
+	else
+		plane->i9xx_plane = (enum i9xx_plane_id) pipe;
+	plane->id = PLANE_PRIMARY;
+	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
+
+	plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
+	if (plane->has_fbc) {
+		struct intel_fbc *fbc = &dev_priv->fbc;
+
+		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
+	}
+
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		formats = vlv_primary_formats;
+		num_formats = ARRAY_SIZE(vlv_primary_formats);
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		/*
+		 * WaFP16GammaEnabling:ivb
+		 * "Workaround : When using the 64-bit format, the plane
+		 *  output on each color channel has one quarter amplitude.
+		 *  It can be brought up to full amplitude by using pipe
+		 *  gamma correction or pipe color space conversion to
+		 *  multiply the plane output by four."
+		 *
+		 * There is no dedicated plane gamma for the primary plane,
+		 * and using the pipe gamma/csc could conflict with other
+		 * planes, so we choose not to expose fp16 on IVB primary
+		 * planes. HSW primary planes no longer have this problem.
+		 */
+		if (IS_IVYBRIDGE(dev_priv)) {
+			formats = ivb_primary_formats;
+			num_formats = ARRAY_SIZE(ivb_primary_formats);
+		} else {
+			formats = i965_primary_formats;
+			num_formats = ARRAY_SIZE(i965_primary_formats);
+		}
+	} else {
+		formats = i8xx_primary_formats;
+		num_formats = ARRAY_SIZE(i8xx_primary_formats);
+	}
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		plane_funcs = &i965_plane_funcs;
+	else
+		plane_funcs = &i8xx_plane_funcs;
+
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		plane->min_cdclk = vlv_plane_min_cdclk;
+	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
+		plane->min_cdclk = hsw_plane_min_cdclk;
+	else if (IS_IVYBRIDGE(dev_priv))
+		plane->min_cdclk = ivb_plane_min_cdclk;
+	else
+		plane->min_cdclk = i9xx_plane_min_cdclk;
+
+	plane->max_stride = i9xx_plane_max_stride;
+	plane->update_plane = i9xx_update_plane;
+	plane->disable_plane = i9xx_disable_plane;
+	plane->get_hw_state = i9xx_plane_get_hw_state;
+	plane->check_plane = i9xx_plane_check;
+
+	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
+					       0, plane_funcs,
+					       formats, num_formats,
+					       i9xx_format_modifiers,
+					       DRM_PLANE_TYPE_PRIMARY,
+					       "primary %c", pipe_name(pipe));
+	else
+		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
+					       0, plane_funcs,
+					       formats, num_formats,
+					       i9xx_format_modifiers,
+					       DRM_PLANE_TYPE_PRIMARY,
+					       "plane %c",
+					       plane_name(plane->i9xx_plane));
+	if (ret)
+		goto fail;
+
+	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+		supported_rotations =
+			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
+			DRM_MODE_REFLECT_X;
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		supported_rotations =
+			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
+	} else {
+		supported_rotations = DRM_MODE_ROTATE_0;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		drm_plane_create_rotation_property(&plane->base,
+						   DRM_MODE_ROTATE_0,
+						   supported_rotations);
+
+	zpos = 0;
+	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
+
+	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+
+	return plane;
+
+fail:
+	intel_plane_free(plane);
+
+	return ERR_PTR(ret);
+}
+
+static struct intel_crtc *intel_crtc_alloc(void)
+{
+	struct intel_crtc_state *crtc_state;
+	struct intel_crtc *crtc;
+
+	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
+	if (!crtc)
+		return ERR_PTR(-ENOMEM);
+
+	crtc_state = intel_crtc_state_alloc(crtc);
+	if (!crtc_state) {
+		kfree(crtc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	crtc->base.state = &crtc_state->uapi;
+	crtc->config = crtc_state;
+
+	return crtc;
+}
+
+static void intel_crtc_free(struct intel_crtc *crtc)
+{
+	intel_crtc_destroy_state(&crtc->base, crtc->base.state);
+	kfree(crtc);
+}
+
+static void intel_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+	drm_crtc_cleanup(crtc);
+	kfree(intel_crtc);
+}
+
+static int intel_crtc_late_register(struct drm_crtc *crtc)
+{
+	intel_crtc_debugfs_add(crtc);
+	return 0;
+}
+
+#define INTEL_CRTC_FUNCS \
+	.gamma_set = drm_atomic_helper_legacy_gamma_set, \
+	.set_config = drm_atomic_helper_set_config, \
+	.destroy = intel_crtc_destroy, \
+	.page_flip = drm_atomic_helper_page_flip, \
+	.atomic_duplicate_state = intel_crtc_duplicate_state, \
+	.atomic_destroy_state = intel_crtc_destroy_state, \
+	.set_crc_source = intel_crtc_set_crc_source, \
+	.verify_crc_source = intel_crtc_verify_crc_source, \
+	.get_crc_sources = intel_crtc_get_crc_sources, \
+	.late_register = intel_crtc_late_register
+
+static const struct drm_crtc_funcs bdw_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = g4x_get_vblank_counter,
+	.enable_vblank = bdw_enable_vblank,
+	.disable_vblank = bdw_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs ilk_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = g4x_get_vblank_counter,
+	.enable_vblank = ilk_enable_vblank,
+	.disable_vblank = ilk_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs g4x_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = g4x_get_vblank_counter,
+	.enable_vblank = i965_enable_vblank,
+	.disable_vblank = i965_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i965_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = i915_get_vblank_counter,
+	.enable_vblank = i965_enable_vblank,
+	.disable_vblank = i965_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i915gm_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = i915_get_vblank_counter,
+	.enable_vblank = i915gm_enable_vblank,
+	.disable_vblank = i915gm_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i915_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	.get_vblank_counter = i915_get_vblank_counter,
+	.enable_vblank = i8xx_enable_vblank,
+	.disable_vblank = i8xx_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+static const struct drm_crtc_funcs i8xx_crtc_funcs = {
+	INTEL_CRTC_FUNCS,
+
+	/* no hw vblank counter */
+	.enable_vblank = i8xx_enable_vblank,
+	.disable_vblank = i8xx_disable_vblank,
+	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
+};
+
+int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	struct intel_plane *primary, *cursor;
+	const struct drm_crtc_funcs *funcs;
+	struct intel_crtc *crtc;
+	int sprite, ret;
+
+	crtc = intel_crtc_alloc();
+	if (IS_ERR(crtc))
+		return PTR_ERR(crtc);
+
+	crtc->pipe = pipe;
+	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
+
+	primary = intel_primary_plane_create(dev_priv, pipe);
+	if (IS_ERR(primary)) {
+		ret = PTR_ERR(primary);
+		goto fail;
+	}
+	crtc->plane_ids_mask |= BIT(primary->id);
+
+	for_each_sprite(dev_priv, pipe, sprite) {
+		struct intel_plane *plane;
+
+		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
+		if (IS_ERR(plane)) {
+			ret = PTR_ERR(plane);
+			goto fail;
+		}
+		crtc->plane_ids_mask |= BIT(plane->id);
+	}
+
+	cursor = intel_cursor_plane_create(dev_priv, pipe);
+	if (IS_ERR(cursor)) {
+		ret = PTR_ERR(cursor);
+		goto fail;
+	}
+	crtc->plane_ids_mask |= BIT(cursor->id);
+
+	if (HAS_GMCH(dev_priv)) {
+		if (IS_CHERRYVIEW(dev_priv) ||
+		    IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
+			funcs = &g4x_crtc_funcs;
+		else if (IS_GEN(dev_priv, 4))
+			funcs = &i965_crtc_funcs;
+		else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
+			funcs = &i915gm_crtc_funcs;
+		else if (IS_GEN(dev_priv, 3))
+			funcs = &i915_crtc_funcs;
+		else
+			funcs = &i8xx_crtc_funcs;
+	} else {
+		if (INTEL_GEN(dev_priv) >= 8)
+			funcs = &bdw_crtc_funcs;
+		else
+			funcs = &ilk_crtc_funcs;
+	}
+
+	ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
+					&primary->base, &cursor->base,
+					funcs, "pipe %c", pipe_name(pipe));
+	if (ret)
+		goto fail;
+
+	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
+	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
+	dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
+
+	if (INTEL_GEN(dev_priv) < 9) {
+		enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
+
+		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
+		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
+		dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 10)
+		drm_crtc_create_scaling_filter_property(&crtc->base,
+						BIT(DRM_SCALING_FILTER_DEFAULT) |
+						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
+
+	intel_color_init(crtc);
+
+	intel_crtc_crc_init(crtc);
+
+	drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
+
+	return 0;
+
+fail:
+	intel_crtc_free(crtc);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 0a3b97889248..c6f30e4ec51e 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -87,56 +87,6 @@ 
 #include "intel_tc.h"
 #include "intel_vga.h"
 
-/* Primary plane formats for gen <= 3 */
-static const u32 i8xx_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_XRGB1555,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-};
-
-/* Primary plane formats for ivb (no fp16 due to hw issue) */
-static const u32 ivb_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-};
-
-/* Primary plane formats for gen >= 4, except ivb */
-static const u32 i965_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_XBGR16161616F,
-};
-
-/* Primary plane formats for vlv/chv */
-static const u32 vlv_primary_formats[] = {
-	DRM_FORMAT_C8,
-	DRM_FORMAT_RGB565,
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_XBGR8888,
-	DRM_FORMAT_ARGB8888,
-	DRM_FORMAT_ABGR8888,
-	DRM_FORMAT_XRGB2101010,
-	DRM_FORMAT_XBGR2101010,
-	DRM_FORMAT_ARGB2101010,
-	DRM_FORMAT_ABGR2101010,
-	DRM_FORMAT_XBGR16161616F,
-};
-
-static const u64 i9xx_format_modifiers[] = {
-	I915_FORMAT_MOD_X_TILED,
-	DRM_FORMAT_MOD_LINEAR,
-	DRM_FORMAT_MOD_INVALID
-};
-
 static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
 				struct intel_crtc_state *pipe_config);
 static void ilk_pch_clock_get(struct intel_crtc *crtc,
@@ -162,7 +112,6 @@  static void skl_pfit_enable(const struct intel_crtc_state *crtc_state);
 static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
 static void intel_modeset_setup_hw_state(struct drm_device *dev,
 					 struct drm_modeset_acquire_ctx *ctx);
-static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
 
 struct intel_limit {
 	struct {
@@ -1306,12 +1255,6 @@  static void assert_planes_disabled(struct intel_crtc *crtc)
 		assert_plane_disabled(plane);
 }
 
-static void assert_vblank_disabled(struct drm_crtc *crtc)
-{
-	if (I915_STATE_WARN_ON(drm_crtc_vblank_get(crtc) == 0))
-		drm_crtc_vblank_put(crtc);
-}
-
 void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
 				    enum pipe pipe)
 {
@@ -1796,55 +1739,6 @@  enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
 		return crtc->pipe;
 }
 
-static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	u32 mode_flags = crtc->mode_flags;
-
-	/*
-	 * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
-	 * have updated at the beginning of TE, if we want to use
-	 * the hw counter, then we would find it updated in only
-	 * the next TE, hence switching to sw counter.
-	 */
-	if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
-		return 0;
-
-	/*
-	 * On i965gm the hardware frame counter reads
-	 * zero when the TV encoder is enabled :(
-	 */
-	if (IS_I965GM(dev_priv) &&
-	    (crtc_state->output_types & BIT(INTEL_OUTPUT_TVOUT)))
-		return 0;
-
-	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-		return 0xffffffff; /* full 32 bit counter */
-	else if (INTEL_GEN(dev_priv) >= 3)
-		return 0xffffff; /* only 24 bits of frame count */
-	else
-		return 0; /* Gen2 doesn't have a hardware frame counter */
-}
-
-void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-	assert_vblank_disabled(&crtc->base);
-	drm_crtc_set_max_vblank_count(&crtc->base,
-				      intel_crtc_max_vblank_count(crtc_state));
-	drm_crtc_vblank_on(&crtc->base);
-}
-
-void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-	drm_crtc_vblank_off(&crtc->base);
-	assert_vblank_disabled(&crtc->base);
-}
-
 void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
@@ -4057,171 +3951,6 @@  int skl_check_plane_surface(struct intel_plane_state *plane_state)
 	return 0;
 }
 
-static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
-			     const struct intel_plane_state *plane_state,
-			     unsigned int *num, unsigned int *den)
-{
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	unsigned int cpp = fb->format->cpp[0];
-
-	/*
-	 * g4x bspec says 64bpp pixel rate can't exceed 80%
-	 * of cdclk when the sprite plane is enabled on the
-	 * same pipe. ilk/snb bspec says 64bpp pixel rate is
-	 * never allowed to exceed 80% of cdclk. Let's just go
-	 * with the ilk/snb limit always.
-	 */
-	if (cpp == 8) {
-		*num = 10;
-		*den = 8;
-	} else {
-		*num = 1;
-		*den = 1;
-	}
-}
-
-static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
-				const struct intel_plane_state *plane_state)
-{
-	unsigned int pixel_rate;
-	unsigned int num, den;
-
-	/*
-	 * Note that crtc_state->pixel_rate accounts for both
-	 * horizontal and vertical panel fitter downscaling factors.
-	 * Pre-HSW bspec tells us to only consider the horizontal
-	 * downscaling factor here. We ignore that and just consider
-	 * both for simplicity.
-	 */
-	pixel_rate = crtc_state->pixel_rate;
-
-	i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
-
-	/* two pixels per clock with double wide pipe */
-	if (crtc_state->double_wide)
-		den *= 2;
-
-	return DIV_ROUND_UP(pixel_rate * num, den);
-}
-
-unsigned int
-i9xx_plane_max_stride(struct intel_plane *plane,
-		      u32 pixel_format, u64 modifier,
-		      unsigned int rotation)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-
-	if (!HAS_GMCH(dev_priv)) {
-		return 32*1024;
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		if (modifier == I915_FORMAT_MOD_X_TILED)
-			return 16*1024;
-		else
-			return 32*1024;
-	} else if (INTEL_GEN(dev_priv) >= 3) {
-		if (modifier == I915_FORMAT_MOD_X_TILED)
-			return 8*1024;
-		else
-			return 16*1024;
-	} else {
-		if (plane->i9xx_plane == PLANE_C)
-			return 4*1024;
-		else
-			return 8*1024;
-	}
-}
-
-static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
-{
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-	u32 dspcntr = 0;
-
-	if (crtc_state->gamma_enable)
-		dspcntr |= DISPPLANE_GAMMA_ENABLE;
-
-	if (crtc_state->csc_enable)
-		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
-
-	if (INTEL_GEN(dev_priv) < 5)
-		dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
-
-	return dspcntr;
-}
-
-static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
-			  const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv =
-		to_i915(plane_state->uapi.plane->dev);
-	const struct drm_framebuffer *fb = plane_state->hw.fb;
-	unsigned int rotation = plane_state->hw.rotation;
-	u32 dspcntr;
-
-	dspcntr = DISPLAY_PLANE_ENABLE;
-
-	if (IS_G4X(dev_priv) || IS_GEN(dev_priv, 5) ||
-	    IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
-		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
-
-	switch (fb->format->format) {
-	case DRM_FORMAT_C8:
-		dspcntr |= DISPPLANE_8BPP;
-		break;
-	case DRM_FORMAT_XRGB1555:
-		dspcntr |= DISPPLANE_BGRX555;
-		break;
-	case DRM_FORMAT_ARGB1555:
-		dspcntr |= DISPPLANE_BGRA555;
-		break;
-	case DRM_FORMAT_RGB565:
-		dspcntr |= DISPPLANE_BGRX565;
-		break;
-	case DRM_FORMAT_XRGB8888:
-		dspcntr |= DISPPLANE_BGRX888;
-		break;
-	case DRM_FORMAT_XBGR8888:
-		dspcntr |= DISPPLANE_RGBX888;
-		break;
-	case DRM_FORMAT_ARGB8888:
-		dspcntr |= DISPPLANE_BGRA888;
-		break;
-	case DRM_FORMAT_ABGR8888:
-		dspcntr |= DISPPLANE_RGBA888;
-		break;
-	case DRM_FORMAT_XRGB2101010:
-		dspcntr |= DISPPLANE_BGRX101010;
-		break;
-	case DRM_FORMAT_XBGR2101010:
-		dspcntr |= DISPPLANE_RGBX101010;
-		break;
-	case DRM_FORMAT_ARGB2101010:
-		dspcntr |= DISPPLANE_BGRA101010;
-		break;
-	case DRM_FORMAT_ABGR2101010:
-		dspcntr |= DISPPLANE_RGBA101010;
-		break;
-	case DRM_FORMAT_XBGR16161616F:
-		dspcntr |= DISPPLANE_RGBX161616;
-		break;
-	default:
-		MISSING_CASE(fb->format->format);
-		return 0;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 4 &&
-	    fb->modifier == I915_FORMAT_MOD_X_TILED)
-		dspcntr |= DISPPLANE_TILED;
-
-	if (rotation & DRM_MODE_ROTATE_180)
-		dspcntr |= DISPPLANE_ROTATE_180;
-
-	if (rotation & DRM_MODE_REFLECT_X)
-		dspcntr |= DISPPLANE_MIRROR;
-
-	return dspcntr;
-}
-
 int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 {
 	struct drm_i915_private *dev_priv =
@@ -4282,197 +4011,6 @@  int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 	return 0;
 }
 
-static bool i9xx_plane_has_windowing(struct intel_plane *plane)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-
-	if (IS_CHERRYVIEW(dev_priv))
-		return i9xx_plane == PLANE_B;
-	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-		return false;
-	else if (IS_GEN(dev_priv, 4))
-		return i9xx_plane == PLANE_C;
-	else
-		return i9xx_plane == PLANE_B ||
-			i9xx_plane == PLANE_C;
-}
-
-static int
-i9xx_plane_check(struct intel_crtc_state *crtc_state,
-		 struct intel_plane_state *plane_state)
-{
-	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
-	int ret;
-
-	ret = chv_plane_check_rotation(plane_state);
-	if (ret)
-		return ret;
-
-	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
-						DRM_PLANE_HELPER_NO_SCALING,
-						DRM_PLANE_HELPER_NO_SCALING,
-						i9xx_plane_has_windowing(plane));
-	if (ret)
-		return ret;
-
-	ret = i9xx_check_plane_surface(plane_state);
-	if (ret)
-		return ret;
-
-	if (!plane_state->uapi.visible)
-		return 0;
-
-	ret = intel_plane_check_src_coordinates(plane_state);
-	if (ret)
-		return ret;
-
-	plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
-
-	return 0;
-}
-
-static void i9xx_update_plane(struct intel_plane *plane,
-			      const struct intel_crtc_state *crtc_state,
-			      const struct intel_plane_state *plane_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-	u32 linear_offset;
-	int x = plane_state->color_plane[0].x;
-	int y = plane_state->color_plane[0].y;
-	int crtc_x = plane_state->uapi.dst.x1;
-	int crtc_y = plane_state->uapi.dst.y1;
-	int crtc_w = drm_rect_width(&plane_state->uapi.dst);
-	int crtc_h = drm_rect_height(&plane_state->uapi.dst);
-	unsigned long irqflags;
-	u32 dspaddr_offset;
-	u32 dspcntr;
-
-	dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
-
-	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
-
-	if (INTEL_GEN(dev_priv) >= 4)
-		dspaddr_offset = plane_state->color_plane[0].offset;
-	else
-		dspaddr_offset = linear_offset;
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane),
-			  plane_state->color_plane[0].stride);
-
-	if (INTEL_GEN(dev_priv) < 4) {
-		/*
-		 * PLANE_A doesn't actually have a full window
-		 * generator but let's assume we still need to
-		 * program whatever is there.
-		 */
-		intel_de_write_fw(dev_priv, DSPPOS(i9xx_plane),
-				  (crtc_y << 16) | crtc_x);
-		intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane),
-				  ((crtc_h - 1) << 16) | (crtc_w - 1));
-	} else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
-		intel_de_write_fw(dev_priv, PRIMPOS(i9xx_plane),
-				  (crtc_y << 16) | crtc_x);
-		intel_de_write_fw(dev_priv, PRIMSIZE(i9xx_plane),
-				  ((crtc_h - 1) << 16) | (crtc_w - 1));
-		intel_de_write_fw(dev_priv, PRIMCNSTALPHA(i9xx_plane), 0);
-	}
-
-	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
-		intel_de_write_fw(dev_priv, DSPOFFSET(i9xx_plane),
-				  (y << 16) | x);
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		intel_de_write_fw(dev_priv, DSPLINOFF(i9xx_plane),
-				  linear_offset);
-		intel_de_write_fw(dev_priv, DSPTILEOFF(i9xx_plane),
-				  (y << 16) | x);
-	}
-
-	/*
-	 * The control register self-arms if the plane was previously
-	 * disabled. Try to make the plane enable atomic by writing
-	 * the control register just before the surface register.
-	 */
-	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
-	if (INTEL_GEN(dev_priv) >= 4)
-		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane),
-				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
-	else
-		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane),
-				  intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static void i9xx_disable_plane(struct intel_plane *plane,
-			       const struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-	unsigned long irqflags;
-	u32 dspcntr;
-
-	/*
-	 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
-	 * enable on ilk+ affect the pipe bottom color as
-	 * well, so we must configure them even if the plane
-	 * is disabled.
-	 *
-	 * On pre-g4x there is no way to gamma correct the
-	 * pipe bottom color but we'll keep on doing this
-	 * anyway so that the crtc state readout works correctly.
-	 */
-	dspcntr = i9xx_plane_ctl_crtc(crtc_state);
-
-	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
-
-	intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr);
-	if (INTEL_GEN(dev_priv) >= 4)
-		intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0);
-	else
-		intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0);
-
-	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
-}
-
-static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
-				    enum pipe *pipe)
-{
-	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-	enum intel_display_power_domain power_domain;
-	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
-	intel_wakeref_t wakeref;
-	bool ret;
-	u32 val;
-
-	/*
-	 * Not 100% correct for planes that can move between pipes,
-	 * but that's only the case for gen2-4 which don't have any
-	 * display power wells.
-	 */
-	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
-	if (!wakeref)
-		return false;
-
-	val = intel_de_read(dev_priv, DSPCNTR(i9xx_plane));
-
-	ret = val & DISPLAY_PLANE_ENABLE;
-
-	if (INTEL_GEN(dev_priv) >= 5)
-		*pipe = plane->pipe;
-	else
-		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
-			DISPPLANE_SEL_PIPE_SHIFT;
-
-	intel_display_power_put(dev_priv, power_domain, wakeref);
-
-	return ret;
-}
-
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
 {
 	struct drm_device *dev = intel_crtc->base.dev;
@@ -11919,33 +11457,6 @@  static void ilk_pch_clock_get(struct intel_crtc *crtc,
 					 &pipe_config->fdi_m_n);
 }
 
-static void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
-				   struct intel_crtc *crtc)
-{
-	memset(crtc_state, 0, sizeof(*crtc_state));
-
-	__drm_atomic_helper_crtc_state_reset(&crtc_state->uapi, &crtc->base);
-
-	crtc_state->cpu_transcoder = INVALID_TRANSCODER;
-	crtc_state->master_transcoder = INVALID_TRANSCODER;
-	crtc_state->hsw_workaround_pipe = INVALID_PIPE;
-	crtc_state->output_format = INTEL_OUTPUT_FORMAT_INVALID;
-	crtc_state->scaler_state.scaler_id = -1;
-	crtc_state->mst_master_transcoder = INVALID_TRANSCODER;
-}
-
-static struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
-{
-	struct intel_crtc_state *crtc_state;
-
-	crtc_state = kmalloc(sizeof(*crtc_state), GFP_KERNEL);
-
-	if (crtc_state)
-		intel_crtc_state_reset(crtc_state, crtc);
-
-	return crtc_state;
-}
-
 /* Returns the currently programmed mode of the given encoder. */
 struct drm_display_mode *
 intel_encoder_current_mode(struct intel_encoder *encoder)
@@ -11986,14 +11497,6 @@  intel_encoder_current_mode(struct intel_encoder *encoder)
 	return mode;
 }
 
-static void intel_crtc_destroy(struct drm_crtc *crtc)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	drm_crtc_cleanup(crtc);
-	kfree(intel_crtc);
-}
-
 /**
  * intel_wm_need_update - Check whether watermarks need updating
  * @cur: current plane state
@@ -15197,17 +14700,6 @@  static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
 	return 0;
 }
 
-u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)];
-
-	if (!vblank->max_vblank_count)
-		return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
-
-	return crtc->base.funcs->get_vblank_counter(&crtc->base);
-}
-
 void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
 				  struct intel_crtc_state *crtc_state)
 {
@@ -16260,336 +15752,6 @@  void intel_plane_destroy(struct drm_plane *plane)
 	kfree(to_intel_plane(plane));
 }
 
-static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
-					    u32 format, u64 modifier)
-{
-	switch (modifier) {
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-		break;
-	default:
-		return false;
-	}
-
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_XRGB1555:
-	case DRM_FORMAT_XRGB8888:
-		return modifier == DRM_FORMAT_MOD_LINEAR ||
-			modifier == I915_FORMAT_MOD_X_TILED;
-	default:
-		return false;
-	}
-}
-
-static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
-					    u32 format, u64 modifier)
-{
-	switch (modifier) {
-	case DRM_FORMAT_MOD_LINEAR:
-	case I915_FORMAT_MOD_X_TILED:
-		break;
-	default:
-		return false;
-	}
-
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_XBGR16161616F:
-		return modifier == DRM_FORMAT_MOD_LINEAR ||
-			modifier == I915_FORMAT_MOD_X_TILED;
-	default:
-		return false;
-	}
-}
-
-static const struct drm_plane_funcs i965_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = intel_plane_destroy,
-	.atomic_duplicate_state = intel_plane_duplicate_state,
-	.atomic_destroy_state = intel_plane_destroy_state,
-	.format_mod_supported = i965_plane_format_mod_supported,
-};
-
-static const struct drm_plane_funcs i8xx_plane_funcs = {
-	.update_plane = drm_atomic_helper_update_plane,
-	.disable_plane = drm_atomic_helper_disable_plane,
-	.destroy = intel_plane_destroy,
-	.atomic_duplicate_state = intel_plane_duplicate_state,
-	.atomic_destroy_state = intel_plane_destroy_state,
-	.format_mod_supported = i8xx_plane_format_mod_supported,
-};
-
-static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
-			       enum i9xx_plane_id i9xx_plane)
-{
-	if (!HAS_FBC(dev_priv))
-		return false;
-
-	if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
-		return i9xx_plane == PLANE_A; /* tied to pipe A */
-	else if (IS_IVYBRIDGE(dev_priv))
-		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
-			i9xx_plane == PLANE_C;
-	else if (INTEL_GEN(dev_priv) >= 4)
-		return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
-	else
-		return i9xx_plane == PLANE_A;
-}
-
-static struct intel_plane *
-intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
-	struct intel_plane *plane;
-	const struct drm_plane_funcs *plane_funcs;
-	unsigned int supported_rotations;
-	const u32 *formats;
-	int num_formats;
-	int ret, zpos;
-
-	if (INTEL_GEN(dev_priv) >= 9)
-		return skl_universal_plane_create(dev_priv, pipe,
-						  PLANE_PRIMARY);
-
-	plane = intel_plane_alloc();
-	if (IS_ERR(plane))
-		return plane;
-
-	plane->pipe = pipe;
-	/*
-	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
-	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
-	 */
-	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4 &&
-	    INTEL_NUM_PIPES(dev_priv) == 2)
-		plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
-	else
-		plane->i9xx_plane = (enum i9xx_plane_id) pipe;
-	plane->id = PLANE_PRIMARY;
-	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
-
-	plane->has_fbc = i9xx_plane_has_fbc(dev_priv, plane->i9xx_plane);
-	if (plane->has_fbc) {
-		struct intel_fbc *fbc = &dev_priv->fbc;
-
-		fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
-	}
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		formats = vlv_primary_formats;
-		num_formats = ARRAY_SIZE(vlv_primary_formats);
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		/*
-		 * WaFP16GammaEnabling:ivb
-		 * "Workaround : When using the 64-bit format, the plane
-		 *  output on each color channel has one quarter amplitude.
-		 *  It can be brought up to full amplitude by using pipe
-		 *  gamma correction or pipe color space conversion to
-		 *  multiply the plane output by four."
-		 *
-		 * There is no dedicated plane gamma for the primary plane,
-		 * and using the pipe gamma/csc could conflict with other
-		 * planes, so we choose not to expose fp16 on IVB primary
-		 * planes. HSW primary planes no longer have this problem.
-		 */
-		if (IS_IVYBRIDGE(dev_priv)) {
-			formats = ivb_primary_formats;
-			num_formats = ARRAY_SIZE(ivb_primary_formats);
-		} else {
-			formats = i965_primary_formats;
-			num_formats = ARRAY_SIZE(i965_primary_formats);
-		}
-	} else {
-		formats = i8xx_primary_formats;
-		num_formats = ARRAY_SIZE(i8xx_primary_formats);
-	}
-
-	if (INTEL_GEN(dev_priv) >= 4)
-		plane_funcs = &i965_plane_funcs;
-	else
-		plane_funcs = &i8xx_plane_funcs;
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		plane->min_cdclk = vlv_plane_min_cdclk;
-	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
-		plane->min_cdclk = hsw_plane_min_cdclk;
-	else if (IS_IVYBRIDGE(dev_priv))
-		plane->min_cdclk = ivb_plane_min_cdclk;
-	else
-		plane->min_cdclk = i9xx_plane_min_cdclk;
-
-	plane->max_stride = i9xx_plane_max_stride;
-	plane->update_plane = i9xx_update_plane;
-	plane->disable_plane = i9xx_disable_plane;
-	plane->get_hw_state = i9xx_plane_get_hw_state;
-	plane->check_plane = i9xx_plane_check;
-
-	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
-		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
-					       0, plane_funcs,
-					       formats, num_formats,
-					       i9xx_format_modifiers,
-					       DRM_PLANE_TYPE_PRIMARY,
-					       "primary %c", pipe_name(pipe));
-	else
-		ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
-					       0, plane_funcs,
-					       formats, num_formats,
-					       i9xx_format_modifiers,
-					       DRM_PLANE_TYPE_PRIMARY,
-					       "plane %c",
-					       plane_name(plane->i9xx_plane));
-	if (ret)
-		goto fail;
-
-	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
-		supported_rotations =
-			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
-			DRM_MODE_REFLECT_X;
-	} else if (INTEL_GEN(dev_priv) >= 4) {
-		supported_rotations =
-			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
-	} else {
-		supported_rotations = DRM_MODE_ROTATE_0;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 4)
-		drm_plane_create_rotation_property(&plane->base,
-						   DRM_MODE_ROTATE_0,
-						   supported_rotations);
-
-	zpos = 0;
-	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
-
-	drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
-
-	return plane;
-
-fail:
-	intel_plane_free(plane);
-
-	return ERR_PTR(ret);
-}
-
-static int intel_crtc_late_register(struct drm_crtc *crtc)
-{
-	intel_crtc_debugfs_add(crtc);
-	return 0;
-}
-
-#define INTEL_CRTC_FUNCS \
-	.gamma_set = drm_atomic_helper_legacy_gamma_set, \
-	.set_config = drm_atomic_helper_set_config, \
-	.destroy = intel_crtc_destroy, \
-	.page_flip = drm_atomic_helper_page_flip, \
-	.atomic_duplicate_state = intel_crtc_duplicate_state, \
-	.atomic_destroy_state = intel_crtc_destroy_state, \
-	.set_crc_source = intel_crtc_set_crc_source, \
-	.verify_crc_source = intel_crtc_verify_crc_source, \
-	.get_crc_sources = intel_crtc_get_crc_sources, \
-	.late_register = intel_crtc_late_register
-
-static const struct drm_crtc_funcs bdw_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = g4x_get_vblank_counter,
-	.enable_vblank = bdw_enable_vblank,
-	.disable_vblank = bdw_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs ilk_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = g4x_get_vblank_counter,
-	.enable_vblank = ilk_enable_vblank,
-	.disable_vblank = ilk_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs g4x_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = g4x_get_vblank_counter,
-	.enable_vblank = i965_enable_vblank,
-	.disable_vblank = i965_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i965_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = i915_get_vblank_counter,
-	.enable_vblank = i965_enable_vblank,
-	.disable_vblank = i965_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i915gm_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = i915_get_vblank_counter,
-	.enable_vblank = i915gm_enable_vblank,
-	.disable_vblank = i915gm_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i915_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	.get_vblank_counter = i915_get_vblank_counter,
-	.enable_vblank = i8xx_enable_vblank,
-	.disable_vblank = i8xx_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static const struct drm_crtc_funcs i8xx_crtc_funcs = {
-	INTEL_CRTC_FUNCS,
-
-	/* no hw vblank counter */
-	.enable_vblank = i8xx_enable_vblank,
-	.disable_vblank = i8xx_disable_vblank,
-	.get_vblank_timestamp = intel_crtc_get_vblank_timestamp,
-};
-
-static struct intel_crtc *intel_crtc_alloc(void)
-{
-	struct intel_crtc_state *crtc_state;
-	struct intel_crtc *crtc;
-
-	crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
-	if (!crtc)
-		return ERR_PTR(-ENOMEM);
-
-	crtc_state = intel_crtc_state_alloc(crtc);
-	if (!crtc_state) {
-		kfree(crtc);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	crtc->base.state = &crtc_state->uapi;
-	crtc->config = crtc_state;
-
-	return crtc;
-}
-
-static void intel_crtc_free(struct intel_crtc *crtc)
-{
-	intel_crtc_destroy_state(&crtc->base, crtc->base.state);
-	kfree(crtc);
-}
-
 static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
 {
 	struct intel_plane *plane;
@@ -16602,100 +15764,6 @@  static void intel_plane_possible_crtcs_init(struct drm_i915_private *dev_priv)
 	}
 }
 
-static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
-{
-	struct intel_plane *primary, *cursor;
-	const struct drm_crtc_funcs *funcs;
-	struct intel_crtc *crtc;
-	int sprite, ret;
-
-	crtc = intel_crtc_alloc();
-	if (IS_ERR(crtc))
-		return PTR_ERR(crtc);
-
-	crtc->pipe = pipe;
-	crtc->num_scalers = RUNTIME_INFO(dev_priv)->num_scalers[pipe];
-
-	primary = intel_primary_plane_create(dev_priv, pipe);
-	if (IS_ERR(primary)) {
-		ret = PTR_ERR(primary);
-		goto fail;
-	}
-	crtc->plane_ids_mask |= BIT(primary->id);
-
-	for_each_sprite(dev_priv, pipe, sprite) {
-		struct intel_plane *plane;
-
-		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
-		if (IS_ERR(plane)) {
-			ret = PTR_ERR(plane);
-			goto fail;
-		}
-		crtc->plane_ids_mask |= BIT(plane->id);
-	}
-
-	cursor = intel_cursor_plane_create(dev_priv, pipe);
-	if (IS_ERR(cursor)) {
-		ret = PTR_ERR(cursor);
-		goto fail;
-	}
-	crtc->plane_ids_mask |= BIT(cursor->id);
-
-	if (HAS_GMCH(dev_priv)) {
-		if (IS_CHERRYVIEW(dev_priv) ||
-		    IS_VALLEYVIEW(dev_priv) || IS_G4X(dev_priv))
-			funcs = &g4x_crtc_funcs;
-		else if (IS_GEN(dev_priv, 4))
-			funcs = &i965_crtc_funcs;
-		else if (IS_I945GM(dev_priv) || IS_I915GM(dev_priv))
-			funcs = &i915gm_crtc_funcs;
-		else if (IS_GEN(dev_priv, 3))
-			funcs = &i915_crtc_funcs;
-		else
-			funcs = &i8xx_crtc_funcs;
-	} else {
-		if (INTEL_GEN(dev_priv) >= 8)
-			funcs = &bdw_crtc_funcs;
-		else
-			funcs = &ilk_crtc_funcs;
-	}
-
-	ret = drm_crtc_init_with_planes(&dev_priv->drm, &crtc->base,
-					&primary->base, &cursor->base,
-					funcs, "pipe %c", pipe_name(pipe));
-	if (ret)
-		goto fail;
-
-	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->pipe_to_crtc_mapping) ||
-	       dev_priv->pipe_to_crtc_mapping[pipe] != NULL);
-	dev_priv->pipe_to_crtc_mapping[pipe] = crtc;
-
-	if (INTEL_GEN(dev_priv) < 9) {
-		enum i9xx_plane_id i9xx_plane = primary->i9xx_plane;
-
-		BUG_ON(i9xx_plane >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
-		       dev_priv->plane_to_crtc_mapping[i9xx_plane] != NULL);
-		dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 10)
-		drm_crtc_create_scaling_filter_property(&crtc->base,
-						BIT(DRM_SCALING_FILTER_DEFAULT) |
-						BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
-
-	intel_color_init(crtc);
-
-	intel_crtc_crc_init(crtc);
-
-	drm_WARN_ON(&dev_priv->drm, drm_crtc_index(&crtc->base) != crtc->pipe);
-
-	return 0;
-
-fail:
-	intel_crtc_free(crtc);
-
-	return ret;
-}
 
 int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
 				      struct drm_file *file)
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index f0a5bf69656f..0eba91d18e96 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -659,6 +659,13 @@  struct intel_plane *
 intel_cursor_plane_create(struct drm_i915_private *dev_priv,
 			  enum pipe pipe);
 
+/* crtc */
+u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state);
+int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe);
+struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc);
+void intel_crtc_state_reset(struct intel_crtc_state *crtc_state,
+			    struct intel_crtc *crtc);
+
 /* modesetting */
 void intel_modeset_init_hw(struct drm_i915_private *i915);
 int intel_modeset_init_noirq(struct drm_i915_private *i915);