]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/gpu/drm/i915/display/intel_display.c
drm/i915: Avoid calling i915_gem_object_unbind holding object lock
[linux.git] / drivers / gpu / drm / i915 / display / intel_display.c
index dfff6f4357b85a7307db60298d3f5b441011fe94..37760a3814020ce490e698454e3d97a8b53627a5 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/module.h>
 #include <linux/dma-resv.h>
 #include <linux/slab.h>
-#include <linux/vgaarb.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -56,6 +55,8 @@
 #include "display/intel_tv.h"
 #include "display/intel_vdsc.h"
 
+#include "gt/intel_rps.h"
+
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "intel_acpi.h"
@@ -65,6 +66,7 @@
 #include "intel_cdclk.h"
 #include "intel_color.h"
 #include "intel_display_types.h"
+#include "intel_dp_link_training.h"
 #include "intel_fbc.h"
 #include "intel_fbdev.h"
 #include "intel_fifo_underrun.h"
 #include "intel_sideband.h"
 #include "intel_sprite.h"
 #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_RGB565,
        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 */
+/* Primary plane formats for gen >= 4, except ivb */
 static const u32 i965_primary_formats[] = {
        DRM_FORMAT_C8,
        DRM_FORMAT_RGB565,
@@ -96,6 +109,22 @@ static const u32 i965_primary_formats[] = {
        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[] = {
@@ -135,8 +164,6 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
 static void chv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
-static void intel_begin_crtc_commit(struct intel_atomic_state *, struct intel_crtc *);
-static void intel_finish_crtc_commit(struct intel_atomic_state *, struct intel_crtc *);
 static void intel_crtc_init_scalers(struct intel_crtc *crtc,
                                    struct intel_crtc_state *crtc_state);
 static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state);
@@ -144,7 +171,6 @@ static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state)
 static void ironlake_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 void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
 
 struct intel_limit {
        struct {
@@ -490,7 +516,7 @@ static const struct intel_limit intel_limits_bxt = {
 
 /* WA Display #0827: Gen9:all */
 static void
-skl_wa_827(struct drm_i915_private *dev_priv, int pipe, bool enable)
+skl_wa_827(struct drm_i915_private *dev_priv, enum pipe pipe, bool enable)
 {
        if (enable)
                I915_WRITE(CLKGATE_DIS_PSL(pipe),
@@ -518,7 +544,27 @@ icl_wa_scalerclkgating(struct drm_i915_private *dev_priv, enum pipe pipe,
 static bool
 needs_modeset(const struct intel_crtc_state *state)
 {
-       return drm_atomic_crtc_needs_modeset(&state->base);
+       return drm_atomic_crtc_needs_modeset(&state->uapi);
+}
+
+bool
+is_trans_port_sync_mode(const struct intel_crtc_state *crtc_state)
+{
+       return (crtc_state->master_transcoder != INVALID_TRANSCODER ||
+               crtc_state->sync_mode_slaves_mask);
+}
+
+static bool
+is_trans_port_sync_master(const struct intel_crtc_state *crtc_state)
+{
+       return (crtc_state->master_transcoder == INVALID_TRANSCODER &&
+               crtc_state->sync_mode_slaves_mask);
+}
+
+static bool
+is_trans_port_sync_slave(const struct intel_crtc_state *crtc_state)
+{
+       return crtc_state->master_transcoder != INVALID_TRANSCODER;
 }
 
 /*
@@ -632,7 +678,7 @@ i9xx_select_p2_div(const struct intel_limit *limit,
                   const struct intel_crtc_state *crtc_state,
                   int target)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 
        if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
                /*
@@ -668,7 +714,7 @@ i9xx_find_best_dpll(const struct intel_limit *limit,
                    int target, int refclk, struct dpll *match_clock,
                    struct dpll *best_clock)
 {
-       struct drm_device *dev = crtc_state->base.crtc->dev;
+       struct drm_device *dev = crtc_state->uapi.crtc->dev;
        struct dpll clock;
        int err = target;
 
@@ -726,7 +772,7 @@ pnv_find_best_dpll(const struct intel_limit *limit,
                   int target, int refclk, struct dpll *match_clock,
                   struct dpll *best_clock)
 {
-       struct drm_device *dev = crtc_state->base.crtc->dev;
+       struct drm_device *dev = crtc_state->uapi.crtc->dev;
        struct dpll clock;
        int err = target;
 
@@ -782,7 +828,7 @@ g4x_find_best_dpll(const struct intel_limit *limit,
                   int target, int refclk, struct dpll *match_clock,
                   struct dpll *best_clock)
 {
-       struct drm_device *dev = crtc_state->base.crtc->dev;
+       struct drm_device *dev = crtc_state->uapi.crtc->dev;
        struct dpll clock;
        int max_n;
        bool found = false;
@@ -876,7 +922,7 @@ vlv_find_best_dpll(const struct intel_limit *limit,
                   int target, int refclk, struct dpll *match_clock,
                   struct dpll *best_clock)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_device *dev = crtc->base.dev;
        struct dpll clock;
        unsigned int bestppm = 1000000;
@@ -936,7 +982,7 @@ chv_find_best_dpll(const struct intel_limit *limit,
                   int target, int refclk, struct dpll *match_clock,
                   struct dpll *best_clock)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_device *dev = crtc->base.dev;
        unsigned int best_error_ppm;
        struct dpll clock;
@@ -1015,7 +1061,7 @@ bool intel_crtc_active(struct intel_crtc *crtc)
         * for atomic.
         */
        return crtc->active && crtc->base.primary->state->fb &&
-               crtc->config->base.adjusted_mode.crtc_clock;
+               crtc->config->hw.adjusted_mode.crtc_clock;
 }
 
 enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
@@ -1069,7 +1115,7 @@ static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc)
 static void
 intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        if (INTEL_GEN(dev_priv) >= 4) {
@@ -1528,7 +1574,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc,
 
 static void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
 
@@ -1612,14 +1658,14 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
 
        if (intel_de_wait_for_register(dev_priv, dpll_reg,
                                       port_mask, expected_mask, 1000))
-               WARN(1, "timed out waiting for port %c ready: got 0x%x, expected 0x%x\n",
-                    port_name(dport->base.port),
+               WARN(1, "timed out waiting for [ENCODER:%d:%s] port ready: got 0x%x, expected 0x%x\n",
+                    dport->base.base.base.id, dport->base.base.name,
                     I915_READ(dpll_reg) & port_mask, expected_mask);
 }
 
 static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
@@ -1633,11 +1679,16 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
        assert_fdi_rx_enabled(dev_priv, pipe);
 
        if (HAS_PCH_CPT(dev_priv)) {
-               /* Workaround: Set the timing override bit before enabling the
-                * pch transcoder. */
                reg = TRANS_CHICKEN2(pipe);
                val = I915_READ(reg);
+               /*
+                * Workaround: Set the timing override bit
+                * before enabling the pch transcoder.
+                */
                val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+               /* Configure frame start delay to match the CPU */
+               val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
+               val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
                I915_WRITE(reg, val);
        }
 
@@ -1646,6 +1697,10 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
        pipeconf_val = I915_READ(PIPECONF(pipe));
 
        if (HAS_PCH_IBX(dev_priv)) {
+               /* Configure frame start delay to match the CPU */
+               val &= ~TRANS_FRAME_START_DELAY_MASK;
+               val |= TRANS_FRAME_START_DELAY(0);
+
                /*
                 * Make the BPC in transcoder be consistent with
                 * that in pipeconf reg. For HDMI we must use 8bpc
@@ -1683,9 +1738,12 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
        assert_fdi_rx_enabled(dev_priv, PIPE_A);
 
-       /* Workaround: set timing override bit. */
        val = I915_READ(TRANS_CHICKEN2(PIPE_A));
+       /* Workaround: set timing override bit. */
        val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
+       /* Configure frame start delay to match the CPU */
+       val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
+       val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
        I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
 
        val = TRANS_ENABLE;
@@ -1763,7 +1821,7 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
 
 static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 
        /*
         * On i965gm the hardware frame counter reads
@@ -1783,16 +1841,23 @@ static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state
 
 static void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       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);
 }
 
+static void intel_crtc_vblank_off(struct intel_crtc *crtc)
+{
+       drm_crtc_vblank_off(&crtc->base);
+       assert_vblank_disabled(&crtc->base);
+}
+
 static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
        enum pipe pipe = crtc->pipe;
@@ -1850,7 +1915,7 @@ static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
 
 static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
        enum pipe pipe = crtc->pipe;
@@ -2057,7 +2122,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
 
 static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 
        return INTEL_GEN(dev_priv) < 4 ||
@@ -2079,7 +2144,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
        unsigned int pinctl;
        u32 alignment;
 
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+       if (WARN_ON(!i915_gem_object_is_framebuffer(obj)))
+               return ERR_PTR(-EINVAL);
 
        alignment = intel_surf_alignment(fb, 0);
 
@@ -2099,19 +2165,18 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
         * pin/unpin/fence and not more.
         */
        wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
-       i915_gem_object_lock(obj);
 
        atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
 
-       pinctl = 0;
-
-       /* Valleyview is definitely limited to scanning out the first
+       /*
+        * Valleyview is definitely limited to scanning out the first
         * 512MiB. Lets presume this behaviour was inherited from the
         * g4x display engine and that all earlier gen are similarly
         * limited. Testing suggests that it is a little more
         * complicated than this. For example, Cherryview appears quite
         * happy to scanout from anywhere within its global aperture.
         */
+       pinctl = 0;
        if (HAS_GMCH(dev_priv))
                pinctl |= PIN_MAPPABLE;
 
@@ -2123,7 +2188,8 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
        if (uses_fence && i915_vma_is_map_and_fenceable(vma)) {
                int ret;
 
-               /* Install a fence for tiled scan-out. Pre-i965 always needs a
+               /*
+                * Install a fence for tiled scan-out. Pre-i965 always needs a
                 * fence, whereas 965+ only requires a fence if using
                 * framebuffer compression.  For simplicity, we always, when
                 * possible, install a fence as the cost is not that onerous.
@@ -2153,16 +2219,12 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
        i915_vma_get(vma);
 err:
        atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
-
-       i915_gem_object_unlock(obj);
        intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
        return vma;
 }
 
 void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags)
 {
-       lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
-
        i915_gem_object_lock(vma->obj);
        if (flags & PLANE_HAS_FENCE)
                i915_vma_unpin_fence(vma);
@@ -2191,7 +2253,7 @@ u32 intel_fb_xy_to_linear(int x, int y,
                          const struct intel_plane_state *state,
                          int color_plane)
 {
-       const struct drm_framebuffer *fb = state->base.fb;
+       const struct drm_framebuffer *fb = state->hw.fb;
        unsigned int cpp = fb->format->cpp[color_plane];
        unsigned int pitch = state->color_plane[color_plane].stride;
 
@@ -2292,8 +2354,8 @@ static u32 intel_plane_adjust_aligned_offset(int *x, int *y,
                                             int color_plane,
                                             u32 old_offset, u32 new_offset)
 {
-       return intel_adjust_aligned_offset(x, y, state->base.fb, color_plane,
-                                          state->base.rotation,
+       return intel_adjust_aligned_offset(x, y, state->hw.fb, color_plane,
+                                          state->hw.rotation,
                                           state->color_plane[color_plane].stride,
                                           old_offset, new_offset);
 }
@@ -2367,10 +2429,10 @@ static u32 intel_plane_compute_aligned_offset(int *x, int *y,
                                              const struct intel_plane_state *state,
                                              int color_plane)
 {
-       struct intel_plane *intel_plane = to_intel_plane(state->base.plane);
+       struct intel_plane *intel_plane = to_intel_plane(state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
-       const struct drm_framebuffer *fb = state->base.fb;
-       unsigned int rotation = state->base.rotation;
+       const struct drm_framebuffer *fb = state->hw.fb;
+       unsigned int rotation = state->hw.rotation;
        int pitch = state->color_plane[color_plane].stride;
        u32 alignment;
 
@@ -2504,6 +2566,9 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
         * the highest stride limits of them all.
         */
        crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
+       if (!crtc)
+               return 0;
+
        plane = to_intel_plane(crtc->base.primary);
 
        return plane->max_stride(plane, pixel_format, modifier,
@@ -2555,9 +2620,9 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
 
 bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        int i;
 
        /* We don't want to deal with remapping with cursors */
@@ -2595,16 +2660,16 @@ bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
 
 static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       unsigned int rotation = plane_state->hw.rotation;
        u32 stride, max_stride;
 
        /*
         * No remapping for invisible planes since we don't have
         * an actual source viewport to remap.
         */
-       if (!plane_state->base.visible)
+       if (!plane_state->uapi.visible)
                return false;
 
        if (!intel_plane_can_remap(plane_state))
@@ -2736,10 +2801,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
                                size++;
 
                        /* rotate the x/y offsets to match the GTT view */
-                       r.x1 = x;
-                       r.y1 = y;
-                       r.x2 = x + width;
-                       r.y2 = y + height;
+                       drm_rect_init(&r, x, y, width, height);
                        drm_rect_rotate(&r,
                                        rot_info->plane[i].width * tile_width,
                                        rot_info->plane[i].height * tile_height,
@@ -2790,11 +2852,11 @@ static void
 intel_plane_remap_gtt(struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv =
-               to_i915(plane_state->base.plane->dev);
-       struct drm_framebuffer *fb = plane_state->base.fb;
+               to_i915(plane_state->uapi.plane->dev);
+       struct drm_framebuffer *fb = plane_state->hw.fb;
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct intel_rotation_info *info = &plane_state->view.rotated;
-       unsigned int rotation = plane_state->base.rotation;
+       unsigned int rotation = plane_state->hw.rotation;
        int i, num_planes = fb->format->num_planes;
        unsigned int tile_size = intel_tile_size(dev_priv);
        unsigned int src_x, src_y;
@@ -2805,20 +2867,20 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)
        plane_state->view.type = drm_rotation_90_or_270(rotation) ?
                I915_GGTT_VIEW_ROTATED : I915_GGTT_VIEW_REMAPPED;
 
-       src_x = plane_state->base.src.x1 >> 16;
-       src_y = plane_state->base.src.y1 >> 16;
-       src_w = drm_rect_width(&plane_state->base.src) >> 16;
-       src_h = drm_rect_height(&plane_state->base.src) >> 16;
+       src_x = plane_state->uapi.src.x1 >> 16;
+       src_y = plane_state->uapi.src.y1 >> 16;
+       src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+       src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 
        WARN_ON(is_ccs_modifier(fb->modifier));
 
        /* Make src coordinates relative to the viewport */
-       drm_rect_translate(&plane_state->base.src,
+       drm_rect_translate(&plane_state->uapi.src,
                           -(src_x << 16), -(src_y << 16));
 
        /* Rotate src coordinates to match rotated GTT view */
        if (drm_rotation_90_or_270(rotation))
-               drm_rect_rotate(&plane_state->base.src,
+               drm_rect_rotate(&plane_state->uapi.src,
                                src_w << 16, src_h << 16,
                                DRM_MODE_ROTATE_270);
 
@@ -2861,10 +2923,7 @@ intel_plane_remap_gtt(struct intel_plane_state *plane_state)
                        struct drm_rect r;
 
                        /* rotate the x/y offsets to match the GTT view */
-                       r.x1 = x;
-                       r.y1 = y;
-                       r.x2 = x + width;
-                       r.y2 = y + height;
+                       drm_rect_init(&r, x, y, width, height);
                        drm_rect_rotate(&r,
                                        info->plane[i].width * tile_width,
                                        info->plane[i].height * tile_height,
@@ -2903,8 +2962,8 @@ static int
 intel_plane_compute_gtt(struct intel_plane_state *plane_state)
 {
        const struct intel_framebuffer *fb =
-               to_intel_framebuffer(plane_state->base.fb);
-       unsigned int rotation = plane_state->base.rotation;
+               to_intel_framebuffer(plane_state->hw.fb);
+       unsigned int rotation = plane_state->hw.rotation;
        int i, num_planes;
 
        if (!fb)
@@ -2941,7 +3000,7 @@ intel_plane_compute_gtt(struct intel_plane_state *plane_state)
 
        /* Rotate src coordinates to match rotated GTT view */
        if (drm_rotation_90_or_270(rotation))
-               drm_rect_rotate(&plane_state->base.src,
+               drm_rect_rotate(&plane_state->uapi.src,
                                fb->base.width << 16, fb->base.height << 16,
                                DRM_MODE_ROTATE_270);
 
@@ -2953,6 +3012,8 @@ static int i9xx_format_to_fourcc(int format)
        switch (format) {
        case DISPPLANE_8BPP:
                return DRM_FORMAT_C8;
+       case DISPPLANE_BGRA555:
+               return DRM_FORMAT_ARGB1555;
        case DISPPLANE_BGRX555:
                return DRM_FORMAT_XRGB1555;
        case DISPPLANE_BGRX565:
@@ -2962,10 +3023,20 @@ static int i9xx_format_to_fourcc(int format)
                return DRM_FORMAT_XRGB8888;
        case DISPPLANE_RGBX888:
                return DRM_FORMAT_XBGR8888;
+       case DISPPLANE_BGRA888:
+               return DRM_FORMAT_ARGB8888;
+       case DISPPLANE_RGBA888:
+               return DRM_FORMAT_ABGR8888;
        case DISPPLANE_BGRX101010:
                return DRM_FORMAT_XRGB2101010;
        case DISPPLANE_RGBX101010:
                return DRM_FORMAT_XBGR2101010;
+       case DISPPLANE_BGRA101010:
+               return DRM_FORMAT_ARGB2101010;
+       case DISPPLANE_RGBA101010:
+               return DRM_FORMAT_ABGR2101010;
+       case DISPPLANE_RGBX161616:
+               return DRM_FORMAT_XBGR16161616F;
        }
 }
 
@@ -3008,10 +3079,17 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
                                return DRM_FORMAT_XRGB8888;
                }
        case PLANE_CTL_FORMAT_XRGB_2101010:
-               if (rgb_order)
-                       return DRM_FORMAT_XBGR2101010;
-               else
-                       return DRM_FORMAT_XRGB2101010;
+               if (rgb_order) {
+                       if (alpha)
+                               return DRM_FORMAT_ABGR2101010;
+                       else
+                               return DRM_FORMAT_XBGR2101010;
+               } else {
+                       if (alpha)
+                               return DRM_FORMAT_ARGB2101010;
+                       else
+                               return DRM_FORMAT_XRGB2101010;
+               }
        case PLANE_CTL_FORMAT_XRGB_16161616F:
                if (rgb_order) {
                        if (alpha)
@@ -3063,13 +3141,11 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
                return false;
        }
 
-       mutex_lock(&dev->struct_mutex);
        obj = i915_gem_object_create_stolen_for_preallocated(dev_priv,
                                                             base_aligned,
                                                             base_aligned,
                                                             size_aligned);
-       mutex_unlock(&dev->struct_mutex);
-       if (!obj)
+       if (IS_ERR(obj))
                return false;
 
        switch (plane_config->tiling) {
@@ -3109,19 +3185,19 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state,
                        struct intel_plane_state *plane_state,
                        bool visible)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
 
-       plane_state->base.visible = visible;
+       plane_state->uapi.visible = visible;
 
        if (visible)
-               crtc_state->base.plane_mask |= drm_plane_mask(&plane->base);
+               crtc_state->uapi.plane_mask |= drm_plane_mask(&plane->base);
        else
-               crtc_state->base.plane_mask &= ~drm_plane_mask(&plane->base);
+               crtc_state->uapi.plane_mask &= ~drm_plane_mask(&plane->base);
 }
 
 static void fixup_active_planes(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
        struct drm_plane *plane;
 
        /*
@@ -3132,13 +3208,14 @@ static void fixup_active_planes(struct intel_crtc_state *crtc_state)
        crtc_state->active_planes = 0;
 
        drm_for_each_plane_mask(plane, &dev_priv->drm,
-                               crtc_state->base.plane_mask)
+                               crtc_state->uapi.plane_mask)
                crtc_state->active_planes |= BIT(to_intel_plane(plane)->id);
 }
 
 static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
                                         struct intel_plane *plane)
 {
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct intel_crtc_state *crtc_state =
                to_intel_crtc_state(crtc->base.state);
        struct intel_plane_state *plane_state =
@@ -3151,9 +3228,30 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
        intel_set_plane_visible(crtc_state, plane_state, false);
        fixup_active_planes(crtc_state);
        crtc_state->data_rate[plane->id] = 0;
+       crtc_state->min_cdclk[plane->id] = 0;
 
        if (plane->id == PLANE_PRIMARY)
-               intel_pre_disable_primary_noatomic(&crtc->base);
+               hsw_disable_ips(crtc_state);
+
+       /*
+        * Vblank time updates from the shadow to live plane control register
+        * are blocked if the memory self-refresh mode is active at that
+        * moment. So to make sure the plane gets truly disabled, disable
+        * first the self-refresh mode. The self-refresh enable bit in turn
+        * will be checked/applied by the HW only at the next frame start
+        * event which is after the vblank start event, so we need to have a
+        * wait-for-vblank between disabling the plane and the pipe.
+        */
+       if (HAS_GMCH(dev_priv) &&
+           intel_set_memory_cxsr(dev_priv, false))
+               intel_wait_for_vblank(dev_priv, crtc->pipe);
+
+       /*
+        * Gen2 reports pipe underruns whenever all planes are disabled.
+        * So disable underrun reporting before all the planes get disabled.
+        */
+       if (IS_GEN(dev_priv, 2) && !crtc_state->active_planes)
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
 
        intel_disable_plane(plane, crtc_state);
 }
@@ -3206,7 +3304,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
                        continue;
 
                if (intel_plane_ggtt_offset(state) == plane_config->base) {
-                       fb = state->base.fb;
+                       fb = state->hw.fb;
                        drm_framebuffer_get(fb);
                        goto valid_fb;
                }
@@ -3224,19 +3322,17 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        return;
 
 valid_fb:
-       intel_state->base.rotation = plane_config->rotation;
+       intel_state->hw.rotation = plane_config->rotation;
        intel_fill_fb_ggtt_view(&intel_state->view, fb,
-                               intel_state->base.rotation);
+                               intel_state->hw.rotation);
        intel_state->color_plane[0].stride =
-               intel_fb_pitch(fb, 0, intel_state->base.rotation);
+               intel_fb_pitch(fb, 0, intel_state->hw.rotation);
 
-       mutex_lock(&dev->struct_mutex);
        intel_state->vma =
                intel_pin_and_fence_fb_obj(fb,
                                           &intel_state->view,
                                           intel_plane_uses_fence(intel_state),
                                           &intel_state->flags);
-       mutex_unlock(&dev->struct_mutex);
        if (IS_ERR(intel_state->vma)) {
                DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
                          intel_crtc->pipe, PTR_ERR(intel_state->vma));
@@ -3258,14 +3354,15 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        plane_state->crtc_w = fb->width;
        plane_state->crtc_h = fb->height;
 
-       intel_state->base.src = drm_plane_state_src(plane_state);
-       intel_state->base.dst = drm_plane_state_dest(plane_state);
+       intel_state->uapi.src = drm_plane_state_src(plane_state);
+       intel_state->uapi.dst = drm_plane_state_dest(plane_state);
 
        if (plane_config->tiling)
                dev_priv->preserve_bios_swizzle = true;
 
        plane_state->fb = fb;
        plane_state->crtc = &intel_crtc->base;
+       intel_plane_copy_uapi_to_hw_state(intel_state, intel_state);
 
        atomic_or(to_intel_plane(primary)->frontbuffer_bit,
                  &to_intel_frontbuffer(fb)->bits);
@@ -3344,10 +3441,20 @@ static int icl_max_plane_width(const struct drm_framebuffer *fb,
        return 5120;
 }
 
+static int skl_max_plane_height(void)
+{
+       return 4096;
+}
+
+static int icl_max_plane_height(void)
+{
+       return 4320;
+}
+
 static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
                                           int main_x, int main_y, u32 main_offset)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        int hsub = fb->format->hsub;
        int vsub = fb->format->vsub;
        int aux_x = plane_state->color_plane[1].x;
@@ -3384,15 +3491,15 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state
 
 static int skl_check_main_surface(struct intel_plane_state *plane_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
-       int x = plane_state->base.src.x1 >> 16;
-       int y = plane_state->base.src.y1 >> 16;
-       int w = drm_rect_width(&plane_state->base.src) >> 16;
-       int h = drm_rect_height(&plane_state->base.src) >> 16;
+       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;
+       int x = plane_state->uapi.src.x1 >> 16;
+       int y = plane_state->uapi.src.y1 >> 16;
+       int w = drm_rect_width(&plane_state->uapi.src) >> 16;
+       int h = drm_rect_height(&plane_state->uapi.src) >> 16;
        int max_width;
-       int max_height = 4096;
+       int max_height;
        u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset;
 
        if (INTEL_GEN(dev_priv) >= 11)
@@ -3402,6 +3509,11 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
        else
                max_width = skl_max_plane_width(fb, 0, rotation);
 
+       if (INTEL_GEN(dev_priv) >= 11)
+               max_height = icl_max_plane_height();
+       else
+               max_height = skl_max_plane_height();
+
        if (w > max_width || h > max_height) {
                DRM_DEBUG_KMS("requested Y/RGB source size %dx%d too big (limit %dx%d)\n",
                              w, h, max_width, max_height);
@@ -3468,23 +3580,22 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
         * Put the final coordinates back so that the src
         * coordinate checks will see the right values.
         */
-       drm_rect_translate(&plane_state->base.src,
-                          (x << 16) - plane_state->base.src.x1,
-                          (y << 16) - plane_state->base.src.y1);
+       drm_rect_translate_to(&plane_state->uapi.src,
+                             x << 16, y << 16);
 
        return 0;
 }
 
 static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       unsigned int rotation = plane_state->hw.rotation;
        int max_width = skl_max_plane_width(fb, 1, rotation);
        int max_height = 4096;
-       int x = plane_state->base.src.x1 >> 17;
-       int y = plane_state->base.src.y1 >> 17;
-       int w = drm_rect_width(&plane_state->base.src) >> 17;
-       int h = drm_rect_height(&plane_state->base.src) >> 17;
+       int x = plane_state->uapi.src.x1 >> 17;
+       int y = plane_state->uapi.src.y1 >> 17;
+       int w = drm_rect_width(&plane_state->uapi.src) >> 17;
+       int h = drm_rect_height(&plane_state->uapi.src) >> 17;
        u32 offset;
 
        intel_add_fb_offsets(&x, &y, plane_state, 1);
@@ -3506,9 +3617,9 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
 
 static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       int src_x = plane_state->base.src.x1 >> 16;
-       int src_y = plane_state->base.src.y1 >> 16;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       int src_x = plane_state->uapi.src.x1 >> 16;
+       int src_y = plane_state->uapi.src.y1 >> 16;
        int hsub = fb->format->hsub;
        int vsub = fb->format->vsub;
        int x = src_x / hsub;
@@ -3527,21 +3638,21 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
 
 int skl_check_plane_surface(struct intel_plane_state *plane_state)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        int ret;
 
        ret = intel_plane_compute_gtt(plane_state);
        if (ret)
                return ret;
 
-       if (!plane_state->base.visible)
+       if (!plane_state->uapi.visible)
                return 0;
 
        /*
         * Handle the AUX surface first since
         * the main surface setup depends on it.
         */
-       if (is_planar_yuv_format(fb->format->format)) {
+       if (drm_format_info_is_yuv_semiplanar(fb->format)) {
                ret = skl_check_nv12_aux_surface(plane_state);
                if (ret)
                        return ret;
@@ -3562,6 +3673,53 @@ 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,
@@ -3591,7 +3749,7 @@ i9xx_plane_max_stride(struct intel_plane *plane,
 
 static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       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;
 
@@ -3611,9 +3769,9 @@ 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->base.plane->dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
+               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;
@@ -3629,6 +3787,9 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
        case DRM_FORMAT_XRGB1555:
                dspcntr |= DISPPLANE_BGRX555;
                break;
+       case DRM_FORMAT_ARGB1555:
+               dspcntr |= DISPPLANE_BGRA555;
+               break;
        case DRM_FORMAT_RGB565:
                dspcntr |= DISPPLANE_BGRX565;
                break;
@@ -3638,12 +3799,27 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
        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;
@@ -3665,8 +3841,9 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
 int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv =
-               to_i915(plane_state->base.plane->dev);
-       int src_x, src_y;
+               to_i915(plane_state->uapi.plane->dev);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       int src_x, src_y, src_w;
        u32 offset;
        int ret;
 
@@ -3674,11 +3851,16 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
        if (ret)
                return ret;
 
-       if (!plane_state->base.visible)
+       if (!plane_state->uapi.visible)
                return 0;
 
-       src_x = plane_state->base.src.x1 >> 16;
-       src_y = plane_state->base.src.y1 >> 16;
+       src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+       src_x = plane_state->uapi.src.x1 >> 16;
+       src_y = plane_state->uapi.src.y1 >> 16;
+
+       /* Undocumented hardware limit on i965/g4x/vlv/chv */
+       if (HAS_GMCH(dev_priv) && fb->format->cpp[0] == 8 && src_w > 2048)
+               return -EINVAL;
 
        intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
 
@@ -3692,15 +3874,14 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
         * Put the final coordinates back so that the src
         * coordinate checks will see the right values.
         */
-       drm_rect_translate(&plane_state->base.src,
-                          (src_x << 16) - plane_state->base.src.x1,
-                          (src_y << 16) - plane_state->base.src.y1);
+       drm_rect_translate_to(&plane_state->uapi.src,
+                             src_x << 16, src_y << 16);
 
        /* HSW/BDW do this automagically in hardware */
        if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
-               unsigned int rotation = plane_state->base.rotation;
-               int src_w = drm_rect_width(&plane_state->base.src) >> 16;
-               int src_h = drm_rect_height(&plane_state->base.src) >> 16;
+               unsigned int rotation = plane_state->hw.rotation;
+               int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+               int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
 
                if (rotation & DRM_MODE_ROTATE_180) {
                        src_x += src_w - 1;
@@ -3737,15 +3918,15 @@ 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->base.plane);
+       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 = drm_atomic_helper_check_plane_state(&plane_state->base,
-                                                 &crtc_state->base,
+       ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
+                                                 &crtc_state->uapi,
                                                  DRM_PLANE_HELPER_NO_SCALING,
                                                  DRM_PLANE_HELPER_NO_SCALING,
                                                  i9xx_plane_has_windowing(plane),
@@ -3757,7 +3938,7 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
-       if (!plane_state->base.visible)
+       if (!plane_state->uapi.visible)
                return 0;
 
        ret = intel_plane_check_src_coordinates(plane_state);
@@ -3778,10 +3959,10 @@ static void i9xx_update_plane(struct intel_plane *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->base.dst.x1;
-       int crtc_y = plane_state->base.dst.y1;
-       int crtc_w = drm_rect_width(&plane_state->base.dst);
-       int crtc_h = drm_rect_height(&plane_state->base.dst);
+       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;
@@ -3921,7 +4102,7 @@ static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
  */
 static void skl_detach_scalers(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
        const struct intel_crtc_scaler_state *scaler_state =
                &crtc_state->scaler_state;
        int i;
@@ -3951,8 +4132,8 @@ static unsigned int skl_plane_stride_mult(const struct drm_framebuffer *fb,
 u32 skl_plane_stride(const struct intel_plane_state *plane_state,
                     int color_plane)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       unsigned int rotation = plane_state->hw.rotation;
        u32 stride = plane_state->color_plane[color_plane].stride;
 
        if (color_plane >= fb->format->num_planes)
@@ -3975,8 +4156,10 @@ static u32 skl_plane_ctl_format(u32 pixel_format)
        case DRM_FORMAT_ARGB8888:
                return PLANE_CTL_FORMAT_XRGB_8888;
        case DRM_FORMAT_XBGR2101010:
+       case DRM_FORMAT_ABGR2101010:
                return PLANE_CTL_FORMAT_XRGB_2101010 | PLANE_CTL_ORDER_RGBX;
        case DRM_FORMAT_XRGB2101010:
+       case DRM_FORMAT_ARGB2101010:
                return PLANE_CTL_FORMAT_XRGB_2101010;
        case DRM_FORMAT_XBGR16161616F:
        case DRM_FORMAT_ABGR16161616F:
@@ -4021,10 +4204,10 @@ static u32 skl_plane_ctl_format(u32 pixel_format)
 
 static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
 {
-       if (!plane_state->base.fb->format->has_alpha)
+       if (!plane_state->hw.fb->format->has_alpha)
                return PLANE_CTL_ALPHA_DISABLE;
 
-       switch (plane_state->base.pixel_blend_mode) {
+       switch (plane_state->hw.pixel_blend_mode) {
        case DRM_MODE_BLEND_PIXEL_NONE:
                return PLANE_CTL_ALPHA_DISABLE;
        case DRM_MODE_BLEND_PREMULTI:
@@ -4032,17 +4215,17 @@ static u32 skl_plane_ctl_alpha(const struct intel_plane_state *plane_state)
        case DRM_MODE_BLEND_COVERAGE:
                return PLANE_CTL_ALPHA_HW_PREMULTIPLY;
        default:
-               MISSING_CASE(plane_state->base.pixel_blend_mode);
+               MISSING_CASE(plane_state->hw.pixel_blend_mode);
                return PLANE_CTL_ALPHA_DISABLE;
        }
 }
 
 static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state)
 {
-       if (!plane_state->base.fb->format->has_alpha)
+       if (!plane_state->hw.fb->format->has_alpha)
                return PLANE_COLOR_ALPHA_DISABLE;
 
-       switch (plane_state->base.pixel_blend_mode) {
+       switch (plane_state->hw.pixel_blend_mode) {
        case DRM_MODE_BLEND_PIXEL_NONE:
                return PLANE_COLOR_ALPHA_DISABLE;
        case DRM_MODE_BLEND_PREMULTI:
@@ -4050,7 +4233,7 @@ static u32 glk_plane_color_ctl_alpha(const struct intel_plane_state *plane_state
        case DRM_MODE_BLEND_COVERAGE:
                return PLANE_COLOR_ALPHA_HW_PREMULTIPLY;
        default:
-               MISSING_CASE(plane_state->base.pixel_blend_mode);
+               MISSING_CASE(plane_state->hw.pixel_blend_mode);
                return PLANE_COLOR_ALPHA_DISABLE;
        }
 }
@@ -4116,7 +4299,7 @@ static u32 cnl_plane_ctl_flip(unsigned int reflect)
 
 u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
        u32 plane_ctl = 0;
 
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
@@ -4135,9 +4318,9 @@ u32 skl_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->base.plane->dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
+               to_i915(plane_state->uapi.plane->dev);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       unsigned int rotation = plane_state->hw.rotation;
        const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
        u32 plane_ctl;
 
@@ -4147,10 +4330,10 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
                plane_ctl |= skl_plane_ctl_alpha(plane_state);
                plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
 
-               if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
+               if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
                        plane_ctl |= PLANE_CTL_YUV_TO_RGB_CSC_FORMAT_BT709;
 
-               if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
+               if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
                        plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
        }
 
@@ -4172,7 +4355,7 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
 
 u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
        u32 plane_color_ctl = 0;
 
        if (INTEL_GEN(dev_priv) >= 11)
@@ -4191,21 +4374,21 @@ u32 glk_plane_color_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->base.plane->dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+               to_i915(plane_state->uapi.plane->dev);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        u32 plane_color_ctl = 0;
 
        plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
        plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
 
        if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
-               if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
+               if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
                        plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
                else
                        plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB709;
 
-               if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
+               if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
                        plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
        } else if (fb->format->is_yuv) {
                plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE;
@@ -4224,7 +4407,7 @@ __intel_display_resume(struct drm_device *dev,
        int i, ret;
 
        intel_modeset_setup_hw_state(dev, ctx);
-       i915_redisable_vga(to_i915(dev));
+       intel_vga_redisable(to_i915(dev));
 
        if (!state)
                return 0;
@@ -4256,7 +4439,7 @@ __intel_display_resume(struct drm_device *dev,
 static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
 {
        return (INTEL_INFO(dev_priv)->gpu_reset_clobbers_display &&
-               intel_has_gpu_reset(dev_priv));
+               intel_has_gpu_reset(&dev_priv->gt));
 }
 
 void intel_prepare_reset(struct drm_i915_private *dev_priv)
@@ -4343,7 +4526,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                 * so need a full re-initialization.
                 */
                intel_pps_unlock_regs_wa(dev_priv);
-               intel_modeset_init_hw(dev);
+               intel_modeset_init_hw(dev_priv);
                intel_init_clock_gating(dev_priv);
 
                spin_lock_irq(&dev_priv->irq_lock);
@@ -4391,50 +4574,60 @@ static void icl_set_pipe_chicken(struct intel_crtc *crtc)
        I915_WRITE(PIPE_CHICKEN(pipe), tmp);
 }
 
-static void intel_update_pipe_config(const struct intel_crtc_state *old_crtc_state,
-                                    const struct intel_crtc_state *new_crtc_state)
+static void icl_enable_trans_port_sync(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
-       /* drm_atomic_helper_update_legacy_modeset_state might not be called. */
-       crtc->base.mode = new_crtc_state->base.mode;
+       u32 trans_ddi_func_ctl2_val;
+       u8 master_select;
 
        /*
-        * Update pipe size and adjust fitter if needed: the reason for this is
-        * that in compute_mode_changes we check the native mode (not the pfit
-        * mode) to see if we can flip rather than do a full mode set. In the
-        * fastboot case, we'll flip, but if we don't update the pipesrc and
-        * pfit state, we'll end up with a big fb scanned out into the wrong
-        * sized surface.
+        * Configure the master select and enable Transcoder Port Sync for
+        * Slave CRTCs transcoder.
         */
+       if (crtc_state->master_transcoder == INVALID_TRANSCODER)
+               return;
 
-       I915_WRITE(PIPESRC(crtc->pipe),
-                  ((new_crtc_state->pipe_src_w - 1) << 16) |
-                  (new_crtc_state->pipe_src_h - 1));
+       if (crtc_state->master_transcoder == TRANSCODER_EDP)
+               master_select = 0;
+       else
+               master_select = crtc_state->master_transcoder + 1;
 
-       /* on skylake this is done by detaching scalers */
-       if (INTEL_GEN(dev_priv) >= 9) {
-               skl_detach_scalers(new_crtc_state);
+       /* Set the master select bits for Tranascoder Port Sync */
+       trans_ddi_func_ctl2_val = (PORT_SYNC_MODE_MASTER_SELECT(master_select) &
+                                  PORT_SYNC_MODE_MASTER_SELECT_MASK) <<
+               PORT_SYNC_MODE_MASTER_SELECT_SHIFT;
+       /* Enable Transcoder Port Sync */
+       trans_ddi_func_ctl2_val |= PORT_SYNC_MODE_ENABLE;
 
-               if (new_crtc_state->pch_pfit.enabled)
-                       skylake_pfit_enable(new_crtc_state);
-       } else if (HAS_PCH_SPLIT(dev_priv)) {
-               if (new_crtc_state->pch_pfit.enabled)
-                       ironlake_pfit_enable(new_crtc_state);
-               else if (old_crtc_state->pch_pfit.enabled)
-                       ironlake_pfit_disable(old_crtc_state);
-       }
+       I915_WRITE(TRANS_DDI_FUNC_CTL2(crtc_state->cpu_transcoder),
+                  trans_ddi_func_ctl2_val);
+}
 
-       if (INTEL_GEN(dev_priv) >= 11)
-               icl_set_pipe_chicken(crtc);
+static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       i915_reg_t reg;
+       u32 trans_ddi_func_ctl2_val;
+
+       if (old_crtc_state->master_transcoder == INVALID_TRANSCODER)
+               return;
+
+       DRM_DEBUG_KMS("Disabling Transcoder Port Sync on Slave Transcoder %s\n",
+                     transcoder_name(old_crtc_state->cpu_transcoder));
+
+       reg = TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder);
+       trans_ddi_func_ctl2_val = ~(PORT_SYNC_MODE_ENABLE |
+                                   PORT_SYNC_MODE_MASTER_SELECT_MASK);
+       I915_WRITE(reg, trans_ddi_func_ctl2_val);
 }
 
 static void intel_fdi_normal_train(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = crtc->pipe;
+       enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
        u32 temp;
 
@@ -4477,7 +4670,7 @@ static void ironlake_fdi_link_train(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = crtc->pipe;
+       enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
        u32 temp, tries;
 
@@ -4578,7 +4771,7 @@ static void gen6_fdi_link_train(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = crtc->pipe;
+       enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
        u32 temp, i, retry;
 
@@ -4711,7 +4904,7 @@ static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = crtc->pipe;
+       enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
        u32 temp, i, j;
 
@@ -4827,9 +5020,9 @@ static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,
 
 static void ironlake_fdi_pll_enable(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
-       int pipe = intel_crtc->pipe;
+       enum pipe pipe = intel_crtc->pipe;
        i915_reg_t reg;
        u32 temp;
 
@@ -4866,7 +5059,7 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
 {
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = intel_crtc->pipe;
+       enum pipe pipe = intel_crtc->pipe;
        i915_reg_t reg;
        u32 temp;
 
@@ -4892,12 +5085,10 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
        udelay(100);
 }
 
-static void ironlake_fdi_disable(struct drm_crtc *crtc)
+static void ironlake_fdi_disable(struct intel_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
        u32 temp;
 
@@ -4988,9 +5179,9 @@ void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
 /* Program iCLKIP clock to the desired frequency */
 static void lpt_program_iclkip(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       int clock = crtc_state->base.adjusted_mode.crtc_clock;
+       int clock = crtc_state->hw.adjusted_mode.crtc_clock;
        u32 divsel, phaseinc, auxdiv, phasedir = 0;
        u32 temp;
 
@@ -5104,7 +5295,7 @@ int lpt_get_iclkip(struct drm_i915_private *dev_priv)
 static void ironlake_pch_transcoder_set_timings(const struct intel_crtc_state *crtc_state,
                                                enum pipe pch_transcoder)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
@@ -5147,7 +5338,7 @@ static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool e
 
 static void ivybridge_update_fdi_bc_bifurcation(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        switch (crtc->pipe) {
@@ -5177,7 +5368,7 @@ static struct intel_encoder *
 intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
                           const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        const struct drm_connector_state *connector_state;
        const struct drm_connector *connector;
        struct intel_encoder *encoder = NULL;
@@ -5209,10 +5400,10 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state,
 static void ironlake_pch_enable(const struct intel_atomic_state *state,
                                const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = crtc->pipe;
+       enum pipe pipe = crtc->pipe;
        u32 temp;
 
        assert_pch_transcoder_disabled(dev_priv, pipe);
@@ -5263,7 +5454,7 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state,
        if (HAS_PCH_CPT(dev_priv) &&
            intel_crtc_has_dp_encoder(crtc_state)) {
                const struct drm_display_mode *adjusted_mode =
-                       &crtc_state->base.adjusted_mode;
+                       &crtc_state->hw.adjusted_mode;
                u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
                i915_reg_t reg = TRANS_DP_CTL(pipe);
                enum port port;
@@ -5293,7 +5484,7 @@ static void ironlake_pch_enable(const struct intel_atomic_state *state,
 static void lpt_pch_enable(const struct intel_atomic_state *state,
                           const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
@@ -5307,9 +5498,9 @@ static void lpt_pch_enable(const struct intel_atomic_state *state,
        lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
 }
 
-static void cpt_verify_modeset(struct drm_device *dev, int pipe)
+static void cpt_verify_modeset(struct drm_i915_private *dev_priv,
+                              enum pipe pipe)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
        i915_reg_t dslreg = PIPEDSL(pipe);
        u32 temp;
 
@@ -5410,10 +5601,10 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
        struct intel_crtc_scaler_state *scaler_state =
                &crtc_state->scaler_state;
        struct intel_crtc *intel_crtc =
-               to_intel_crtc(crtc_state->base.crtc);
+               to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
        const struct drm_display_mode *adjusted_mode =
-               &crtc_state->base.adjusted_mode;
+               &crtc_state->hw.adjusted_mode;
 
        /*
         * Src coordinates are already rotated by 270 degrees for
@@ -5429,7 +5620,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
         * Once NV12 is enabled, handle it here while allocating scaler
         * for NV12.
         */
-       if (INTEL_GEN(dev_priv) >= 9 && crtc_state->base.enable &&
+       if (INTEL_GEN(dev_priv) >= 9 && crtc_state->hw.enable &&
            need_scaler && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
                DRM_DEBUG_KMS("Pipe/Plane scaling not supported with IF-ID mode\n");
                return -EINVAL;
@@ -5459,7 +5650,7 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
                return 0;
        }
 
-       if (format && is_planar_yuv_format(format->format) &&
+       if (format && drm_format_info_is_yuv_semiplanar(format) &&
            (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) {
                DRM_DEBUG_KMS("Planar YUV: src dimensions not met\n");
                return -EINVAL;
@@ -5501,13 +5692,13 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
  */
 int skl_update_scaler_crtc(struct intel_crtc_state *state)
 {
-       const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
+       const struct drm_display_mode *adjusted_mode = &state->hw.adjusted_mode;
        bool need_scaler = false;
 
        if (state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
                need_scaler = true;
 
-       return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
+       return skl_update_scaler(state, !state->hw.active, SKL_CRTC_INDEX,
                                 &state->scaler_state.scaler_id,
                                 state->pipe_src_w, state->pipe_src_h,
                                 adjusted_mode->crtc_hdisplay,
@@ -5527,25 +5718,25 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
                                   struct intel_plane_state *plane_state)
 {
        struct intel_plane *intel_plane =
-               to_intel_plane(plane_state->base.plane);
+               to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
-       struct drm_framebuffer *fb = plane_state->base.fb;
+       struct drm_framebuffer *fb = plane_state->hw.fb;
        int ret;
-       bool force_detach = !fb || !plane_state->base.visible;
+       bool force_detach = !fb || !plane_state->uapi.visible;
        bool need_scaler = false;
 
        /* Pre-gen11 and SDR planes always need a scaler for planar formats. */
        if (!icl_is_hdr_plane(dev_priv, intel_plane->id) &&
-           fb && is_planar_yuv_format(fb->format->format))
+           fb && drm_format_info_is_yuv_semiplanar(fb->format))
                need_scaler = true;
 
        ret = skl_update_scaler(crtc_state, force_detach,
                                drm_plane_index(&intel_plane->base),
                                &plane_state->scaler_id,
-                               drm_rect_width(&plane_state->base.src) >> 16,
-                               drm_rect_height(&plane_state->base.src) >> 16,
-                               drm_rect_width(&plane_state->base.dst),
-                               drm_rect_height(&plane_state->base.dst),
+                               drm_rect_width(&plane_state->uapi.src) >> 16,
+                               drm_rect_height(&plane_state->uapi.src) >> 16,
+                               drm_rect_width(&plane_state->uapi.dst),
+                               drm_rect_height(&plane_state->uapi.dst),
                                fb ? fb->format : NULL, need_scaler);
 
        if (ret || plane_state->scaler_id < 0)
@@ -5568,10 +5759,8 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
        case DRM_FORMAT_ARGB8888:
        case DRM_FORMAT_XRGB2101010:
        case DRM_FORMAT_XBGR2101010:
-       case DRM_FORMAT_XBGR16161616F:
-       case DRM_FORMAT_ABGR16161616F:
-       case DRM_FORMAT_XRGB16161616F:
-       case DRM_FORMAT_ARGB16161616F:
+       case DRM_FORMAT_ARGB2101010:
+       case DRM_FORMAT_ABGR2101010:
        case DRM_FORMAT_YUYV:
        case DRM_FORMAT_YVYU:
        case DRM_FORMAT_UYVY:
@@ -5587,6 +5776,13 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
        case DRM_FORMAT_XVYU12_16161616:
        case DRM_FORMAT_XVYU16161616:
                break;
+       case DRM_FORMAT_XBGR16161616F:
+       case DRM_FORMAT_ABGR16161616F:
+       case DRM_FORMAT_XRGB16161616F:
+       case DRM_FORMAT_ARGB16161616F:
+               if (INTEL_GEN(dev_priv) >= 11)
+                       break;
+               /* fall through */
        default:
                DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n",
                              intel_plane->base.base.id, intel_plane->base.name,
@@ -5607,7 +5803,7 @@ static void skylake_scaler_disable(struct intel_crtc *crtc)
 
 static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
        const struct intel_crtc_scaler_state *scaler_state =
@@ -5644,9 +5840,9 @@ static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state)
 
 static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       int pipe = crtc->pipe;
+       enum pipe pipe = crtc->pipe;
 
        if (crtc_state->pch_pfit.enabled) {
                /* Force use of hard-coded filter coefficients
@@ -5665,7 +5861,7 @@ static void ironlake_pfit_enable(const struct intel_crtc_state *crtc_state)
 
 void hsw_enable_ips(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
@@ -5701,7 +5897,7 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state)
 
 void hsw_disable_ips(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
@@ -5728,90 +5924,18 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state)
 
 static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
 {
-       if (intel_crtc->overlay) {
-               struct drm_device *dev = intel_crtc->base.dev;
-
-               mutex_lock(&dev->struct_mutex);
+       if (intel_crtc->overlay)
                (void) intel_overlay_switch_off(intel_crtc->overlay);
-               mutex_unlock(&dev->struct_mutex);
-       }
 
        /* Let userspace switch the overlay on again. In most cases userspace
         * has to recompute where to put it anyway.
         */
 }
 
-/**
- * intel_post_enable_primary - Perform operations after enabling primary plane
- * @crtc: the CRTC whose primary plane was just enabled
- * @new_crtc_state: the enabling state
- *
- * Performs potentially sleeping operations that must be done after the primary
- * plane is enabled, such as updating FBC and IPS.  Note that this may be
- * called due to an explicit primary plane update, or due to an implicit
- * re-enable that is caused when a sprite plane is updated to no longer
- * completely hide the primary plane.
- */
-static void
-intel_post_enable_primary(struct drm_crtc *crtc,
-                         const struct intel_crtc_state *new_crtc_state)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-
-       /*
-        * Gen2 reports pipe underruns whenever all planes are disabled.
-        * So don't enable underrun reporting before at least some planes
-        * are enabled.
-        * FIXME: Need to fix the logic to work when we turn off all planes
-        * but leave the pipe running.
-        */
-       if (IS_GEN(dev_priv, 2))
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
-       /* Underruns don't always raise interrupts, so check manually. */
-       intel_check_cpu_fifo_underruns(dev_priv);
-       intel_check_pch_fifo_underruns(dev_priv);
-}
-
-/* FIXME get rid of this and use pre_plane_update */
-static void
-intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-
-       /*
-        * Gen2 reports pipe underruns whenever all planes are disabled.
-        * So disable underrun reporting before all the planes get disabled.
-        */
-       if (IS_GEN(dev_priv, 2))
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-
-       hsw_disable_ips(to_intel_crtc_state(crtc->state));
-
-       /*
-        * Vblank time updates from the shadow to live plane control register
-        * are blocked if the memory self-refresh mode is active at that
-        * moment. So to make sure the plane gets truly disabled, disable
-        * first the self-refresh mode. The self-refresh enable bit in turn
-        * will be checked/applied by the HW only at the next frame start
-        * event which is after the vblank start event, so we need to have a
-        * wait-for-vblank between disabling the plane and the pipe.
-        */
-       if (HAS_GMCH(dev_priv) &&
-           intel_set_memory_cxsr(dev_priv, false))
-               intel_wait_for_vblank(dev_priv, pipe);
-}
-
 static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_state,
                                       const struct intel_crtc_state *new_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        if (!old_crtc_state->ips_enabled)
@@ -5827,7 +5951,7 @@ static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_s
         * Disable IPS before we program the LUT.
         */
        if (IS_HASWELL(dev_priv) &&
-           (new_crtc_state->base.color_mgmt_changed ||
+           (new_crtc_state->uapi.color_mgmt_changed ||
             new_crtc_state->update_pipe) &&
            new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
                return true;
@@ -5838,7 +5962,7 @@ static bool hsw_pre_update_disable_ips(const struct intel_crtc_state *old_crtc_s
 static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_state,
                                       const struct intel_crtc_state *new_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        if (!new_crtc_state->ips_enabled)
@@ -5854,7 +5978,7 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s
         * Re-enable IPS after the LUT has been programmed.
         */
        if (IS_HASWELL(dev_priv) &&
-           (new_crtc_state->base.color_mgmt_changed ||
+           (new_crtc_state->uapi.color_mgmt_changed ||
             new_crtc_state->update_pipe) &&
            new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
                return true;
@@ -5864,15 +5988,16 @@ static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_s
         * forcibly enable IPS on the first fastset.
         */
        if (new_crtc_state->update_pipe &&
-           old_crtc_state->base.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED)
+           old_crtc_state->hw.adjusted_mode.private_flags & I915_MODE_FLAG_INHERITED)
                return true;
 
        return !old_crtc_state->ips_enabled;
 }
 
-static bool needs_nv12_wa(struct drm_i915_private *dev_priv,
-                         const struct intel_crtc_state *crtc_state)
+static bool needs_nv12_wa(const struct intel_crtc_state *crtc_state)
 {
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+
        if (!crtc_state->nv12_planes)
                return false;
 
@@ -5883,9 +6008,10 @@ static bool needs_nv12_wa(struct drm_i915_private *dev_priv,
        return false;
 }
 
-static bool needs_scalerclk_wa(struct drm_i915_private *dev_priv,
-                              const struct intel_crtc_state *crtc_state)
+static bool needs_scalerclk_wa(const struct intel_crtc_state *crtc_state)
 {
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+
        /* Wa_2006604312:icl */
        if (crtc_state->scaler_state.scaler_users > 0 && IS_ICELAKE(dev_priv))
                return true;
@@ -5893,89 +6019,81 @@ static bool needs_scalerclk_wa(struct drm_i915_private *dev_priv,
        return false;
 }
 
-static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
+static bool planes_enabling(const struct intel_crtc_state *old_crtc_state,
+                           const struct intel_crtc_state *new_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct drm_atomic_state *state = old_crtc_state->base.state;
-       struct intel_crtc_state *pipe_config =
-               intel_atomic_get_new_crtc_state(to_intel_atomic_state(state),
-                                               crtc);
-       struct drm_plane *primary = crtc->base.primary;
-       struct drm_plane_state *old_primary_state =
-               drm_atomic_get_old_plane_state(state, primary);
+       return (!old_crtc_state->active_planes || needs_modeset(new_crtc_state)) &&
+               new_crtc_state->active_planes;
+}
 
-       intel_frontbuffer_flip(to_i915(crtc->base.dev), pipe_config->fb_bits);
+static bool planes_disabling(const struct intel_crtc_state *old_crtc_state,
+                            const struct intel_crtc_state *new_crtc_state)
+{
+       return old_crtc_state->active_planes &&
+               (!new_crtc_state->active_planes || needs_modeset(new_crtc_state));
+}
 
-       if (pipe_config->update_wm_post && pipe_config->base.active)
-               intel_update_watermarks(crtc);
+static void intel_post_plane_update(struct intel_atomic_state *state,
+                                   struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_plane *primary = to_intel_plane(crtc->base.primary);
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       const struct intel_plane_state *new_primary_state =
+               intel_atomic_get_new_plane_state(state, primary);
+       enum pipe pipe = crtc->pipe;
+
+       intel_frontbuffer_flip(dev_priv, new_crtc_state->fb_bits);
 
-       if (hsw_post_update_enable_ips(old_crtc_state, pipe_config))
-               hsw_enable_ips(pipe_config);
+       if (new_crtc_state->update_wm_post && new_crtc_state->hw.active)
+               intel_update_watermarks(crtc);
 
-       if (old_primary_state) {
-               struct drm_plane_state *new_primary_state =
-                       drm_atomic_get_new_plane_state(state, primary);
+       if (hsw_post_update_enable_ips(old_crtc_state, new_crtc_state))
+               hsw_enable_ips(new_crtc_state);
 
+       if (new_primary_state)
                intel_fbc_post_update(crtc);
 
-               if (new_primary_state->visible &&
-                   (needs_modeset(pipe_config) ||
-                    !old_primary_state->visible))
-                       intel_post_enable_primary(&crtc->base, pipe_config);
-       }
-
-       if (needs_nv12_wa(dev_priv, old_crtc_state) &&
-           !needs_nv12_wa(dev_priv, pipe_config))
-               skl_wa_827(dev_priv, crtc->pipe, false);
+       if (needs_nv12_wa(old_crtc_state) &&
+           !needs_nv12_wa(new_crtc_state))
+               skl_wa_827(dev_priv, pipe, false);
 
-       if (needs_scalerclk_wa(dev_priv, old_crtc_state) &&
-           !needs_scalerclk_wa(dev_priv, pipe_config))
-               icl_wa_scalerclkgating(dev_priv, crtc->pipe, false);
+       if (needs_scalerclk_wa(old_crtc_state) &&
+           !needs_scalerclk_wa(new_crtc_state))
+               icl_wa_scalerclkgating(dev_priv, pipe, false);
 }
 
-static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
-                                  struct intel_crtc_state *pipe_config)
+static void intel_pre_plane_update(struct intel_atomic_state *state,
+                                  struct intel_crtc *crtc)
 {
-       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct drm_atomic_state *state = old_crtc_state->base.state;
-       struct drm_plane *primary = crtc->base.primary;
-       struct drm_plane_state *old_primary_state =
-               drm_atomic_get_old_plane_state(state, primary);
-       bool modeset = needs_modeset(pipe_config);
-       struct intel_atomic_state *intel_state =
-               to_intel_atomic_state(state);
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_plane *primary = to_intel_plane(crtc->base.primary);
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       const struct intel_plane_state *new_primary_state =
+               intel_atomic_get_new_plane_state(state, primary);
+       enum pipe pipe = crtc->pipe;
 
-       if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config))
+       if (hsw_pre_update_disable_ips(old_crtc_state, new_crtc_state))
                hsw_disable_ips(old_crtc_state);
 
-       if (old_primary_state) {
-               struct intel_plane_state *new_primary_state =
-                       intel_atomic_get_new_plane_state(intel_state,
-                                                        to_intel_plane(primary));
-
-               intel_fbc_pre_update(crtc, pipe_config, new_primary_state);
-               /*
-                * Gen2 reports pipe underruns whenever all planes are disabled.
-                * So disable underrun reporting before all the planes get disabled.
-                */
-               if (IS_GEN(dev_priv, 2) && old_primary_state->visible &&
-                   (modeset || !new_primary_state->base.visible))
-                       intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
-       }
+       if (new_primary_state)
+               intel_fbc_pre_update(crtc, new_crtc_state, new_primary_state);
 
        /* Display WA 827 */
-       if (!needs_nv12_wa(dev_priv, old_crtc_state) &&
-           needs_nv12_wa(dev_priv, pipe_config))
-               skl_wa_827(dev_priv, crtc->pipe, true);
+       if (!needs_nv12_wa(old_crtc_state) &&
+           needs_nv12_wa(new_crtc_state))
+               skl_wa_827(dev_priv, pipe, true);
 
        /* Wa_2006604312:icl */
-       if (!needs_scalerclk_wa(dev_priv, old_crtc_state) &&
-           needs_scalerclk_wa(dev_priv, pipe_config))
-               icl_wa_scalerclkgating(dev_priv, crtc->pipe, true);
+       if (!needs_scalerclk_wa(old_crtc_state) &&
+           needs_scalerclk_wa(new_crtc_state))
+               icl_wa_scalerclkgating(dev_priv, pipe, true);
 
        /*
         * Vblank time updates from the shadow to live plane control register
@@ -5986,9 +6104,9 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
         * event which is after the vblank start event, so we need to have a
         * wait-for-vblank between disabling the plane and the pipe.
         */
-       if (HAS_GMCH(dev_priv) && old_crtc_state->base.active &&
-           pipe_config->disable_cxsr && intel_set_memory_cxsr(dev_priv, false))
-               intel_wait_for_vblank(dev_priv, crtc->pipe);
+       if (HAS_GMCH(dev_priv) && old_crtc_state->hw.active &&
+           new_crtc_state->disable_cxsr && intel_set_memory_cxsr(dev_priv, false))
+               intel_wait_for_vblank(dev_priv, pipe);
 
        /*
         * IVB workaround: must disable low power watermarks for at least
@@ -5997,36 +6115,45 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
         *
         * WaCxSRDisabledForSpriteScaling:ivb
         */
-       if (pipe_config->disable_lp_wm && ilk_disable_lp_wm(dev) &&
-           old_crtc_state->base.active)
-               intel_wait_for_vblank(dev_priv, crtc->pipe);
+       if (old_crtc_state->hw.active &&
+           new_crtc_state->disable_lp_wm && ilk_disable_lp_wm(dev_priv))
+               intel_wait_for_vblank(dev_priv, pipe);
 
        /*
-        * If we're doing a modeset, we're done.  No need to do any pre-vblank
-        * watermark programming here.
+        * If we're doing a modeset we don't need to do any
+        * pre-vblank watermark programming here.
         */
-       if (needs_modeset(pipe_config))
-               return;
+       if (!needs_modeset(new_crtc_state)) {
+               /*
+                * For platforms that support atomic watermarks, program the
+                * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these
+                * will be the intermediate values that are safe for both pre- and
+                * post- vblank; when vblank happens, the 'active' values will be set
+                * to the final 'target' values and we'll do this again to get the
+                * optimal watermarks.  For gen9+ platforms, the values we program here
+                * will be the final target values which will get automatically latched
+                * at vblank time; no further programming will be necessary.
+                *
+                * If a platform hasn't been transitioned to atomic watermarks yet,
+                * we'll continue to update watermarks the old way, if flags tell
+                * us to.
+                */
+               if (dev_priv->display.initial_watermarks)
+                       dev_priv->display.initial_watermarks(state, crtc);
+               else if (new_crtc_state->update_wm_pre)
+                       intel_update_watermarks(crtc);
+       }
 
        /*
-        * For platforms that support atomic watermarks, program the
-        * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these
-        * will be the intermediate values that are safe for both pre- and
-        * post- vblank; when vblank happens, the 'active' values will be set
-        * to the final 'target' values and we'll do this again to get the
-        * optimal watermarks.  For gen9+ platforms, the values we program here
-        * will be the final target values which will get automatically latched
-        * at vblank time; no further programming will be necessary.
+        * Gen2 reports pipe underruns whenever all planes are disabled.
+        * So disable underrun reporting before all the planes get disabled.
         *
-        * If a platform hasn't been transitioned to atomic watermarks yet,
-        * we'll continue to update watermarks the old way, if flags tell
-        * us to.
+        * We do this after .initial_watermarks() so that we have a
+        * chance of catching underruns with the intermediate watermarks
+        * vs. the old plane configuration.
         */
-       if (dev_priv->display.initial_watermarks != NULL)
-               dev_priv->display.initial_watermarks(intel_state,
-                                                    pipe_config);
-       else if (pipe_config->update_wm_pre)
-               intel_update_watermarks(crtc);
+       if (IS_GEN(dev_priv, 2) && planes_disabling(old_crtc_state, new_crtc_state))
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 }
 
 static void intel_crtc_disable_planes(struct intel_atomic_state *state,
@@ -6050,7 +6177,7 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state,
 
                intel_disable_plane(plane, new_crtc_state);
 
-               if (old_plane_state->base.visible)
+               if (old_plane_state->uapi.visible)
                        fb_bits |= plane->frontbuffer_bit;
        }
 
@@ -6149,11 +6276,12 @@ static void intel_encoders_update_complete(struct intel_atomic_state *state)
        }
 }
 
-static void intel_encoders_pre_pll_enable(struct intel_crtc *crtc,
-                                         struct intel_crtc_state *crtc_state,
-                                         struct intel_atomic_state *state)
+static void intel_encoders_pre_pll_enable(struct intel_atomic_state *state,
+                                         struct intel_crtc *crtc)
 {
-       struct drm_connector_state *conn_state;
+       const struct intel_crtc_state *crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       const struct drm_connector_state *conn_state;
        struct drm_connector *conn;
        int i;
 
@@ -6169,11 +6297,12 @@ static void intel_encoders_pre_pll_enable(struct intel_crtc *crtc,
        }
 }
 
-static void intel_encoders_pre_enable(struct intel_crtc *crtc,
-                                     struct intel_crtc_state *crtc_state,
-                                     struct intel_atomic_state *state)
+static void intel_encoders_pre_enable(struct intel_atomic_state *state,
+                                     struct intel_crtc *crtc)
 {
-       struct drm_connector_state *conn_state;
+       const struct intel_crtc_state *crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       const struct drm_connector_state *conn_state;
        struct drm_connector *conn;
        int i;
 
@@ -6189,11 +6318,12 @@ static void intel_encoders_pre_enable(struct intel_crtc *crtc,
        }
 }
 
-static void intel_encoders_enable(struct intel_crtc *crtc,
-                                 struct intel_crtc_state *crtc_state,
-                                 struct intel_atomic_state *state)
+static void intel_encoders_enable(struct intel_atomic_state *state,
+                                 struct intel_crtc *crtc)
 {
-       struct drm_connector_state *conn_state;
+       const struct intel_crtc_state *crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       const struct drm_connector_state *conn_state;
        struct drm_connector *conn;
        int i;
 
@@ -6210,11 +6340,12 @@ static void intel_encoders_enable(struct intel_crtc *crtc,
        }
 }
 
-static void intel_encoders_disable(struct intel_crtc *crtc,
-                                  struct intel_crtc_state *old_crtc_state,
-                                  struct intel_atomic_state *state)
+static void intel_encoders_disable(struct intel_atomic_state *state,
+                                  struct intel_crtc *crtc)
 {
-       struct drm_connector_state *old_conn_state;
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct drm_connector_state *old_conn_state;
        struct drm_connector *conn;
        int i;
 
@@ -6231,11 +6362,12 @@ static void intel_encoders_disable(struct intel_crtc *crtc,
        }
 }
 
-static void intel_encoders_post_disable(struct intel_crtc *crtc,
-                                       struct intel_crtc_state *old_crtc_state,
-                                       struct intel_atomic_state *state)
+static void intel_encoders_post_disable(struct intel_atomic_state *state,
+                                       struct intel_crtc *crtc)
 {
-       struct drm_connector_state *old_conn_state;
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct drm_connector_state *old_conn_state;
        struct drm_connector *conn;
        int i;
 
@@ -6251,11 +6383,12 @@ static void intel_encoders_post_disable(struct intel_crtc *crtc,
        }
 }
 
-static void intel_encoders_post_pll_disable(struct intel_crtc *crtc,
-                                           struct intel_crtc_state *old_crtc_state,
-                                           struct intel_atomic_state *state)
+static void intel_encoders_post_pll_disable(struct intel_atomic_state *state,
+                                           struct intel_crtc *crtc)
 {
-       struct drm_connector_state *old_conn_state;
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       const struct drm_connector_state *old_conn_state;
        struct drm_connector *conn;
        int i;
 
@@ -6271,11 +6404,12 @@ static void intel_encoders_post_pll_disable(struct intel_crtc *crtc,
        }
 }
 
-static void intel_encoders_update_pipe(struct intel_crtc *crtc,
-                                      struct intel_crtc_state *crtc_state,
-                                      struct intel_atomic_state *state)
+static void intel_encoders_update_pipe(struct intel_atomic_state *state,
+                                      struct intel_crtc *crtc)
 {
-       struct drm_connector_state *conn_state;
+       const struct intel_crtc_state *crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       const struct drm_connector_state *conn_state;
        struct drm_connector *conn;
        int i;
 
@@ -6293,22 +6427,21 @@ static void intel_encoders_update_pipe(struct intel_crtc *crtc,
 
 static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct intel_plane *plane = to_intel_plane(crtc->base.primary);
 
        plane->disable_plane(plane, crtc_state);
 }
 
-static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
-                                struct intel_atomic_state *state)
+static void ironlake_crtc_enable(struct intel_atomic_state *state,
+                                struct intel_crtc *crtc)
 {
-       struct drm_crtc *crtc = pipe_config->base.crtc;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
 
-       if (WARN_ON(intel_crtc->active))
+       if (WARN_ON(crtc->active))
                return;
 
        /*
@@ -6324,61 +6457,59 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
        intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
        intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
 
-       if (pipe_config->has_pch_encoder)
-               intel_prepare_shared_dpll(pipe_config);
+       if (new_crtc_state->has_pch_encoder)
+               intel_prepare_shared_dpll(new_crtc_state);
 
-       if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(pipe_config, M1_N1);
+       if (intel_crtc_has_dp_encoder(new_crtc_state))
+               intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(pipe_config);
-       intel_set_pipe_src_size(pipe_config);
+       intel_set_pipe_timings(new_crtc_state);
+       intel_set_pipe_src_size(new_crtc_state);
 
-       if (pipe_config->has_pch_encoder) {
-               intel_cpu_transcoder_set_m_n(pipe_config,
-                                            &pipe_config->fdi_m_n, NULL);
-       }
+       if (new_crtc_state->has_pch_encoder)
+               intel_cpu_transcoder_set_m_n(new_crtc_state,
+                                            &new_crtc_state->fdi_m_n, NULL);
 
-       ironlake_set_pipeconf(pipe_config);
+       ironlake_set_pipeconf(new_crtc_state);
 
-       intel_crtc->active = true;
+       crtc->active = true;
 
-       intel_encoders_pre_enable(intel_crtc, pipe_config, state);
+       intel_encoders_pre_enable(state, crtc);
 
-       if (pipe_config->has_pch_encoder) {
+       if (new_crtc_state->has_pch_encoder) {
                /* Note: FDI PLL enabling _must_ be done before we enable the
                 * cpu pipes, hence this is separate from all the other fdi/pch
                 * enabling. */
-               ironlake_fdi_pll_enable(pipe_config);
+               ironlake_fdi_pll_enable(new_crtc_state);
        } else {
                assert_fdi_tx_disabled(dev_priv, pipe);
                assert_fdi_rx_disabled(dev_priv, pipe);
        }
 
-       ironlake_pfit_enable(pipe_config);
+       ironlake_pfit_enable(new_crtc_state);
 
        /*
         * On ILK+ LUT must be loaded before the pipe is running but with
         * clocks enabled
         */
-       intel_color_load_luts(pipe_config);
-       intel_color_commit(pipe_config);
+       intel_color_load_luts(new_crtc_state);
+       intel_color_commit(new_crtc_state);
        /* update DSPCNTR to configure gamma for pipe bottom color */
-       intel_disable_primary_plane(pipe_config);
+       intel_disable_primary_plane(new_crtc_state);
 
-       if (dev_priv->display.initial_watermarks != NULL)
-               dev_priv->display.initial_watermarks(state, pipe_config);
-       intel_enable_pipe(pipe_config);
+       if (dev_priv->display.initial_watermarks)
+               dev_priv->display.initial_watermarks(state, crtc);
+       intel_enable_pipe(new_crtc_state);
 
-       if (pipe_config->has_pch_encoder)
-               ironlake_pch_enable(state, pipe_config);
+       if (new_crtc_state->has_pch_encoder)
+               ironlake_pch_enable(state, new_crtc_state);
 
-       assert_vblank_disabled(crtc);
-       intel_crtc_vblank_on(pipe_config);
+       intel_crtc_vblank_on(new_crtc_state);
 
-       intel_encoders_enable(intel_crtc, pipe_config, state);
+       intel_encoders_enable(state, crtc);
 
        if (HAS_PCH_CPT(dev_priv))
-               cpt_verify_modeset(dev, intel_crtc->pipe);
+               cpt_verify_modeset(dev_priv, pipe);
 
        /*
         * Must wait for vblank to avoid spurious PCH FIFO underruns.
@@ -6386,7 +6517,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
         * some interlaced HDMI modes. Let's do the double wait always
         * in case there are more corner cases we don't know about.
         */
-       if (pipe_config->has_pch_encoder) {
+       if (new_crtc_state->has_pch_encoder) {
                intel_wait_for_vblank(dev_priv, pipe);
                intel_wait_for_vblank(dev_priv, pipe);
        }
@@ -6433,101 +6564,112 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
        I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);
 }
 
-static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
-                               struct intel_atomic_state *state)
+static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_crtc *crtc = pipe_config->base.crtc;
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe, hsw_workaround_pipe;
-       enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       i915_reg_t reg = CHICKEN_TRANS(crtc_state->cpu_transcoder);
+       u32 val;
+
+       val = I915_READ(reg);
+       val &= ~HSW_FRAME_START_DELAY_MASK;
+       val |= HSW_FRAME_START_DELAY(0);
+       I915_WRITE(reg, val);
+}
+
+static void haswell_crtc_enable(struct intel_atomic_state *state,
+                               struct intel_crtc *crtc)
+{
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe, hsw_workaround_pipe;
+       enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
        bool psl_clkgate_wa;
 
-       if (WARN_ON(intel_crtc->active))
+       if (WARN_ON(crtc->active))
                return;
 
-       intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state);
+       intel_encoders_pre_pll_enable(state, crtc);
 
-       if (pipe_config->shared_dpll)
-               intel_enable_shared_dpll(pipe_config);
+       if (new_crtc_state->shared_dpll)
+               intel_enable_shared_dpll(new_crtc_state);
 
-       intel_encoders_pre_enable(intel_crtc, pipe_config, state);
+       intel_encoders_pre_enable(state, crtc);
 
-       if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(pipe_config, M1_N1);
+       if (intel_crtc_has_dp_encoder(new_crtc_state))
+               intel_dp_set_m_n(new_crtc_state, M1_N1);
 
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_set_pipe_timings(pipe_config);
+               intel_set_pipe_timings(new_crtc_state);
 
-       intel_set_pipe_src_size(pipe_config);
+       if (INTEL_GEN(dev_priv) >= 11)
+               icl_enable_trans_port_sync(new_crtc_state);
+
+       intel_set_pipe_src_size(new_crtc_state);
 
        if (cpu_transcoder != TRANSCODER_EDP &&
-           !transcoder_is_dsi(cpu_transcoder)) {
+           !transcoder_is_dsi(cpu_transcoder))
                I915_WRITE(PIPE_MULT(cpu_transcoder),
-                          pipe_config->pixel_multiplier - 1);
-       }
+                          new_crtc_state->pixel_multiplier - 1);
 
-       if (pipe_config->has_pch_encoder) {
-               intel_cpu_transcoder_set_m_n(pipe_config,
-                                            &pipe_config->fdi_m_n, NULL);
-       }
+       if (new_crtc_state->has_pch_encoder)
+               intel_cpu_transcoder_set_m_n(new_crtc_state,
+                                            &new_crtc_state->fdi_m_n, NULL);
 
-       if (!transcoder_is_dsi(cpu_transcoder))
-               haswell_set_pipeconf(pipe_config);
+       if (!transcoder_is_dsi(cpu_transcoder)) {
+               hsw_set_frame_start_delay(new_crtc_state);
+               haswell_set_pipeconf(new_crtc_state);
+       }
 
        if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
-               bdw_set_pipemisc(pipe_config);
+               bdw_set_pipemisc(new_crtc_state);
 
-       intel_crtc->active = true;
+       crtc->active = true;
 
        /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */
        psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
-                        pipe_config->pch_pfit.enabled;
+               new_crtc_state->pch_pfit.enabled;
        if (psl_clkgate_wa)
                glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true);
 
        if (INTEL_GEN(dev_priv) >= 9)
-               skylake_pfit_enable(pipe_config);
+               skylake_pfit_enable(new_crtc_state);
        else
-               ironlake_pfit_enable(pipe_config);
+               ironlake_pfit_enable(new_crtc_state);
 
        /*
         * On ILK+ LUT must be loaded before the pipe is running but with
         * clocks enabled
         */
-       intel_color_load_luts(pipe_config);
-       intel_color_commit(pipe_config);
+       intel_color_load_luts(new_crtc_state);
+       intel_color_commit(new_crtc_state);
        /* update DSPCNTR to configure gamma/csc for pipe bottom color */
        if (INTEL_GEN(dev_priv) < 9)
-               intel_disable_primary_plane(pipe_config);
+               intel_disable_primary_plane(new_crtc_state);
 
        if (INTEL_GEN(dev_priv) >= 11)
-               icl_set_pipe_chicken(intel_crtc);
+               icl_set_pipe_chicken(crtc);
 
-       intel_ddi_set_pipe_settings(pipe_config);
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_ddi_enable_transcoder_func(pipe_config);
+               intel_ddi_enable_transcoder_func(new_crtc_state);
 
-       if (dev_priv->display.initial_watermarks != NULL)
-               dev_priv->display.initial_watermarks(state, pipe_config);
+       if (dev_priv->display.initial_watermarks)
+               dev_priv->display.initial_watermarks(state, crtc);
 
        if (INTEL_GEN(dev_priv) >= 11)
-               icl_pipe_mbus_enable(intel_crtc);
+               icl_pipe_mbus_enable(crtc);
 
        /* XXX: Do the pipe assertions at the right place for BXT DSI. */
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_enable_pipe(pipe_config);
-
-       if (pipe_config->has_pch_encoder)
-               lpt_pch_enable(state, pipe_config);
+               intel_enable_pipe(new_crtc_state);
 
-       if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST))
-               intel_ddi_set_vc_payload_alloc(pipe_config, true);
+       if (new_crtc_state->has_pch_encoder)
+               lpt_pch_enable(state, new_crtc_state);
 
-       assert_vblank_disabled(crtc);
-       intel_crtc_vblank_on(pipe_config);
+       intel_crtc_vblank_on(new_crtc_state);
 
-       intel_encoders_enable(intel_crtc, pipe_config, state);
+       intel_encoders_enable(state, crtc);
 
        if (psl_clkgate_wa) {
                intel_wait_for_vblank(dev_priv, pipe);
@@ -6536,7 +6678,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 
        /* If we change the relative order between pipe/planes enabling, we need
         * to change the workaround. */
-       hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
+       hsw_workaround_pipe = new_crtc_state->hsw_workaround_pipe;
        if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) {
                intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);
                intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);
@@ -6545,7 +6687,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 
 static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
 
@@ -6558,14 +6700,13 @@ static void ironlake_pfit_disable(const struct intel_crtc_state *old_crtc_state)
        }
 }
 
-static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,
-                                 struct intel_atomic_state *state)
+static void ironlake_crtc_disable(struct intel_atomic_state *state,
+                                 struct intel_crtc *crtc)
 {
-       struct drm_crtc *crtc = old_crtc_state->base.crtc;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
 
        /*
         * Sometimes spurious CPU pipe underruns happen when the
@@ -6575,10 +6716,9 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,
        intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
        intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
 
-       intel_encoders_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_disable(state, crtc);
 
-       drm_crtc_vblank_off(crtc);
-       assert_vblank_disabled(crtc);
+       intel_crtc_vblank_off(crtc);
 
        intel_disable_pipe(old_crtc_state);
 
@@ -6587,7 +6727,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,
        if (old_crtc_state->has_pch_encoder)
                ironlake_fdi_disable(crtc);
 
-       intel_encoders_post_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_post_disable(state, crtc);
 
        if (old_crtc_state->has_pch_encoder) {
                ironlake_disable_pch_transcoder(dev_priv, pipe);
@@ -6610,32 +6750,31 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,
                        I915_WRITE(PCH_DPLL_SEL, temp);
                }
 
-               ironlake_fdi_pll_disable(intel_crtc);
+               ironlake_fdi_pll_disable(crtc);
        }
 
        intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
        intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
 }
 
-static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
-                                struct intel_atomic_state *state)
+static void haswell_crtc_disable(struct intel_atomic_state *state,
+                                struct intel_crtc *crtc)
 {
-       struct drm_crtc *crtc = old_crtc_state->base.crtc;
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       const struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
 
-       intel_encoders_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_disable(state, crtc);
 
-       drm_crtc_vblank_off(crtc);
-       assert_vblank_disabled(crtc);
+       intel_crtc_vblank_off(crtc);
 
        /* XXX: Do the pipe assertions at the right place for BXT DSI. */
        if (!transcoder_is_dsi(cpu_transcoder))
                intel_disable_pipe(old_crtc_state);
 
-       if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST))
-               intel_ddi_set_vc_payload_alloc(old_crtc_state, false);
+       if (INTEL_GEN(dev_priv) >= 11)
+               icl_disable_transcoder_port_sync(old_crtc_state);
 
        if (!transcoder_is_dsi(cpu_transcoder))
                intel_ddi_disable_transcoder_func(old_crtc_state);
@@ -6643,18 +6782,18 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
        intel_dsc_disable(old_crtc_state);
 
        if (INTEL_GEN(dev_priv) >= 9)
-               skylake_scaler_disable(intel_crtc);
+               skylake_scaler_disable(crtc);
        else
                ironlake_pfit_disable(old_crtc_state);
 
-       intel_encoders_post_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_post_disable(state, crtc);
 
-       intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_post_pll_disable(state, crtc);
 }
 
 static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        if (!crtc_state->gmch_pfit.control)
@@ -6734,6 +6873,8 @@ enum intel_display_power_domain intel_port_to_power_domain(enum port port)
                return POWER_DOMAIN_PORT_DDI_E_LANES;
        case PORT_F:
                return POWER_DOMAIN_PORT_DDI_F_LANES;
+       case PORT_G:
+               return POWER_DOMAIN_PORT_DDI_G_LANES;
        default:
                MISSING_CASE(port);
                return POWER_DOMAIN_PORT_OTHER;
@@ -6750,16 +6891,18 @@ intel_aux_power_domain(struct intel_digital_port *dig_port)
            dig_port->tc_mode == TC_PORT_TBT_ALT) {
                switch (dig_port->aux_ch) {
                case AUX_CH_C:
-                       return POWER_DOMAIN_AUX_TBT1;
+                       return POWER_DOMAIN_AUX_C_TBT;
                case AUX_CH_D:
-                       return POWER_DOMAIN_AUX_TBT2;
+                       return POWER_DOMAIN_AUX_D_TBT;
                case AUX_CH_E:
-                       return POWER_DOMAIN_AUX_TBT3;
+                       return POWER_DOMAIN_AUX_E_TBT;
                case AUX_CH_F:
-                       return POWER_DOMAIN_AUX_TBT4;
+                       return POWER_DOMAIN_AUX_F_TBT;
+               case AUX_CH_G:
+                       return POWER_DOMAIN_AUX_G_TBT;
                default:
                        MISSING_CASE(dig_port->aux_ch);
-                       return POWER_DOMAIN_AUX_TBT1;
+                       return POWER_DOMAIN_AUX_C_TBT;
                }
        }
 
@@ -6776,6 +6919,8 @@ intel_aux_power_domain(struct intel_digital_port *dig_port)
                return POWER_DOMAIN_AUX_E;
        case AUX_CH_F:
                return POWER_DOMAIN_AUX_F;
+       case AUX_CH_G:
+               return POWER_DOMAIN_AUX_G;
        default:
                MISSING_CASE(dig_port->aux_ch);
                return POWER_DOMAIN_AUX_A;
@@ -6784,14 +6929,14 @@ intel_aux_power_domain(struct intel_digital_port *dig_port)
 
 static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct drm_encoder *encoder;
        enum pipe pipe = crtc->pipe;
        u64 mask;
        enum transcoder transcoder = crtc_state->cpu_transcoder;
 
-       if (!crtc_state->base.active)
+       if (!crtc_state->hw.active)
                return 0;
 
        mask = BIT_ULL(POWER_DOMAIN_PIPE(pipe));
@@ -6801,7 +6946,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)
                mask |= BIT_ULL(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
 
        drm_for_each_encoder_mask(encoder, &dev_priv->drm,
-                                 crtc_state->base.encoder_mask) {
+                                 crtc_state->uapi.encoder_mask) {
                struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
 
                mask |= BIT_ULL(intel_encoder->power_domain);
@@ -6819,7 +6964,7 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state)
 static u64
 modeset_get_crtc_power_domains(struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum intel_display_power_domain domain;
        u64 domains, new_domains, old_domains;
@@ -6845,126 +6990,121 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
                intel_display_power_put_unchecked(dev_priv, domain);
 }
 
-static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
-                                  struct intel_atomic_state *state)
+static void valleyview_crtc_enable(struct intel_atomic_state *state,
+                                  struct intel_crtc *crtc)
 {
-       struct drm_crtc *crtc = pipe_config->base.crtc;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
 
-       if (WARN_ON(intel_crtc->active))
+       if (WARN_ON(crtc->active))
                return;
 
-       if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(pipe_config, M1_N1);
+       if (intel_crtc_has_dp_encoder(new_crtc_state))
+               intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(pipe_config);
-       intel_set_pipe_src_size(pipe_config);
+       intel_set_pipe_timings(new_crtc_state);
+       intel_set_pipe_src_size(new_crtc_state);
 
        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
                I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
                I915_WRITE(CHV_CANVAS(pipe), 0);
        }
 
-       i9xx_set_pipeconf(pipe_config);
+       i9xx_set_pipeconf(new_crtc_state);
 
-       intel_crtc->active = true;
+       crtc->active = true;
 
        intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
-       intel_encoders_pre_pll_enable(intel_crtc, pipe_config, state);
+       intel_encoders_pre_pll_enable(state, crtc);
 
        if (IS_CHERRYVIEW(dev_priv)) {
-               chv_prepare_pll(intel_crtc, pipe_config);
-               chv_enable_pll(intel_crtc, pipe_config);
+               chv_prepare_pll(crtc, new_crtc_state);
+               chv_enable_pll(crtc, new_crtc_state);
        } else {
-               vlv_prepare_pll(intel_crtc, pipe_config);
-               vlv_enable_pll(intel_crtc, pipe_config);
+               vlv_prepare_pll(crtc, new_crtc_state);
+               vlv_enable_pll(crtc, new_crtc_state);
        }
 
-       intel_encoders_pre_enable(intel_crtc, pipe_config, state);
+       intel_encoders_pre_enable(state, crtc);
 
-       i9xx_pfit_enable(pipe_config);
+       i9xx_pfit_enable(new_crtc_state);
 
-       intel_color_load_luts(pipe_config);
-       intel_color_commit(pipe_config);
+       intel_color_load_luts(new_crtc_state);
+       intel_color_commit(new_crtc_state);
        /* update DSPCNTR to configure gamma for pipe bottom color */
-       intel_disable_primary_plane(pipe_config);
+       intel_disable_primary_plane(new_crtc_state);
 
-       dev_priv->display.initial_watermarks(state, pipe_config);
-       intel_enable_pipe(pipe_config);
+       dev_priv->display.initial_watermarks(state, crtc);
+       intel_enable_pipe(new_crtc_state);
 
-       assert_vblank_disabled(crtc);
-       intel_crtc_vblank_on(pipe_config);
+       intel_crtc_vblank_on(new_crtc_state);
 
-       intel_encoders_enable(intel_crtc, pipe_config, state);
+       intel_encoders_enable(state, crtc);
 }
 
 static void i9xx_set_pll_dividers(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        I915_WRITE(FP0(crtc->pipe), crtc_state->dpll_hw_state.fp0);
        I915_WRITE(FP1(crtc->pipe), crtc_state->dpll_hw_state.fp1);
 }
 
-static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
-                            struct intel_atomic_state *state)
+static void i9xx_crtc_enable(struct intel_atomic_state *state,
+                            struct intel_crtc *crtc)
 {
-       struct drm_crtc *crtc = pipe_config->base.crtc;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       enum pipe pipe = intel_crtc->pipe;
+       const struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
 
-       if (WARN_ON(intel_crtc->active))
+       if (WARN_ON(crtc->active))
                return;
 
-       i9xx_set_pll_dividers(pipe_config);
+       i9xx_set_pll_dividers(new_crtc_state);
 
-       if (intel_crtc_has_dp_encoder(pipe_config))
-               intel_dp_set_m_n(pipe_config, M1_N1);
+       if (intel_crtc_has_dp_encoder(new_crtc_state))
+               intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(pipe_config);
-       intel_set_pipe_src_size(pipe_config);
+       intel_set_pipe_timings(new_crtc_state);
+       intel_set_pipe_src_size(new_crtc_state);
 
-       i9xx_set_pipeconf(pipe_config);
+       i9xx_set_pipeconf(new_crtc_state);
 
-       intel_crtc->active = true;
+       crtc->active = true;
 
        if (!IS_GEN(dev_priv, 2))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
-       intel_encoders_pre_enable(intel_crtc, pipe_config, state);
+       intel_encoders_pre_enable(state, crtc);
 
-       i9xx_enable_pll(intel_crtc, pipe_config);
+       i9xx_enable_pll(crtc, new_crtc_state);
 
-       i9xx_pfit_enable(pipe_config);
+       i9xx_pfit_enable(new_crtc_state);
 
-       intel_color_load_luts(pipe_config);
-       intel_color_commit(pipe_config);
+       intel_color_load_luts(new_crtc_state);
+       intel_color_commit(new_crtc_state);
        /* update DSPCNTR to configure gamma for pipe bottom color */
-       intel_disable_primary_plane(pipe_config);
+       intel_disable_primary_plane(new_crtc_state);
 
-       if (dev_priv->display.initial_watermarks != NULL)
-               dev_priv->display.initial_watermarks(state,
-                                                    pipe_config);
+       if (dev_priv->display.initial_watermarks)
+               dev_priv->display.initial_watermarks(state, crtc);
        else
-               intel_update_watermarks(intel_crtc);
-       intel_enable_pipe(pipe_config);
+               intel_update_watermarks(crtc);
+       intel_enable_pipe(new_crtc_state);
 
-       assert_vblank_disabled(crtc);
-       intel_crtc_vblank_on(pipe_config);
+       intel_crtc_vblank_on(new_crtc_state);
 
-       intel_encoders_enable(intel_crtc, pipe_config, state);
+       intel_encoders_enable(state, crtc);
 }
 
 static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        if (!old_crtc_state->gmch_pfit.control)
@@ -6977,14 +7117,13 @@ static void i9xx_pfit_disable(const struct intel_crtc_state *old_crtc_state)
        I915_WRITE(PFIT_CONTROL, 0);
 }
 
-static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
-                             struct intel_atomic_state *state)
+static void i9xx_crtc_disable(struct intel_atomic_state *state,
+                             struct intel_crtc *crtc)
 {
-       struct drm_crtc *crtc = old_crtc_state->base.crtc;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
+       struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
 
        /*
         * On gen2 planes are double buffered but the pipe isn't, so we must
@@ -6993,16 +7132,15 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
        if (IS_GEN(dev_priv, 2))
                intel_wait_for_vblank(dev_priv, pipe);
 
-       intel_encoders_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_disable(state, crtc);
 
-       drm_crtc_vblank_off(crtc);
-       assert_vblank_disabled(crtc);
+       intel_crtc_vblank_off(crtc);
 
        intel_disable_pipe(old_crtc_state);
 
        i9xx_pfit_disable(old_crtc_state);
 
-       intel_encoders_post_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_post_disable(state, crtc);
 
        if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DSI)) {
                if (IS_CHERRYVIEW(dev_priv))
@@ -7013,92 +7151,97 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
                        i9xx_disable_pll(old_crtc_state);
        }
 
-       intel_encoders_post_pll_disable(intel_crtc, old_crtc_state, state);
+       intel_encoders_post_pll_disable(state, crtc);
 
        if (!IS_GEN(dev_priv, 2))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
        if (!dev_priv->display.initial_watermarks)
-               intel_update_watermarks(intel_crtc);
+               intel_update_watermarks(crtc);
 
        /* clock the pipe down to 640x480@60 to potentially save power */
        if (IS_I830(dev_priv))
                i830_enable_pipe(dev_priv, pipe);
 }
 
-static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
+static void intel_crtc_disable_noatomic(struct intel_crtc *crtc,
                                        struct drm_modeset_acquire_ctx *ctx)
 {
        struct intel_encoder *encoder;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct intel_bw_state *bw_state =
                to_intel_bw_state(dev_priv->bw_obj.state);
+       struct intel_crtc_state *crtc_state =
+               to_intel_crtc_state(crtc->base.state);
        enum intel_display_power_domain domain;
        struct intel_plane *plane;
-       u64 domains;
        struct drm_atomic_state *state;
-       struct intel_crtc_state *crtc_state;
+       struct intel_crtc_state *temp_crtc_state;
+       enum pipe pipe = crtc->pipe;
+       u64 domains;
        int ret;
 
-       if (!intel_crtc->active)
+       if (!crtc_state->hw.active)
                return;
 
-       for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc, plane) {
+       for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
                const struct intel_plane_state *plane_state =
                        to_intel_plane_state(plane->base.state);
 
-               if (plane_state->base.visible)
-                       intel_plane_disable_noatomic(intel_crtc, plane);
+               if (plane_state->uapi.visible)
+                       intel_plane_disable_noatomic(crtc, plane);
        }
 
-       state = drm_atomic_state_alloc(crtc->dev);
+       state = drm_atomic_state_alloc(&dev_priv->drm);
        if (!state) {
                DRM_DEBUG_KMS("failed to disable [CRTC:%d:%s], out of memory",
-                             crtc->base.id, crtc->name);
+                             crtc->base.base.id, crtc->base.name);
                return;
        }
 
        state->acquire_ctx = ctx;
 
        /* Everything's already locked, -EDEADLK can't happen. */
-       crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
-       ret = drm_atomic_add_affected_connectors(state, crtc);
+       temp_crtc_state = intel_atomic_get_crtc_state(state, crtc);
+       ret = drm_atomic_add_affected_connectors(state, &crtc->base);
 
-       WARN_ON(IS_ERR(crtc_state) || ret);
+       WARN_ON(IS_ERR(temp_crtc_state) || ret);
 
-       dev_priv->display.crtc_disable(crtc_state, to_intel_atomic_state(state));
+       dev_priv->display.crtc_disable(to_intel_atomic_state(state), crtc);
 
        drm_atomic_state_put(state);
 
        DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
-                     crtc->base.id, crtc->name);
+                     crtc->base.base.id, crtc->base.name);
+
+       crtc->active = false;
+       crtc->base.enabled = false;
 
-       WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0);
-       crtc->state->active = false;
-       intel_crtc->active = false;
-       crtc->enabled = false;
-       crtc->state->connector_mask = 0;
-       crtc->state->encoder_mask = 0;
+       WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, NULL) < 0);
+       crtc_state->uapi.active = false;
+       crtc_state->uapi.connector_mask = 0;
+       crtc_state->uapi.encoder_mask = 0;
+       intel_crtc_free_hw_state(crtc_state);
+       memset(&crtc_state->hw, 0, sizeof(crtc_state->hw));
 
-       for_each_encoder_on_crtc(crtc->dev, crtc, encoder)
+       for_each_encoder_on_crtc(&dev_priv->drm, &crtc->base, encoder)
                encoder->base.crtc = NULL;
 
-       intel_fbc_disable(intel_crtc);
-       intel_update_watermarks(intel_crtc);
-       intel_disable_shared_dpll(to_intel_crtc_state(crtc->state));
+       intel_fbc_disable(crtc);
+       intel_update_watermarks(crtc);
+       intel_disable_shared_dpll(crtc_state);
 
-       domains = intel_crtc->enabled_power_domains;
+       domains = crtc->enabled_power_domains;
        for_each_power_domain(domain, domains)
                intel_display_power_put_unchecked(dev_priv, domain);
-       intel_crtc->enabled_power_domains = 0;
+       crtc->enabled_power_domains = 0;
 
-       dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
-       dev_priv->min_cdclk[intel_crtc->pipe] = 0;
-       dev_priv->min_voltage_level[intel_crtc->pipe] = 0;
+       dev_priv->active_pipes &= ~BIT(pipe);
+       dev_priv->min_cdclk[pipe] = 0;
+       dev_priv->min_voltage_level[pipe] = 0;
 
-       bw_state->data_rate[intel_crtc->pipe] = 0;
-       bw_state->num_active_planes[intel_crtc->pipe] = 0;
+       bw_state->data_rate[pipe] = 0;
+       bw_state->num_active_planes[pipe] = 0;
 }
 
 /*
@@ -7148,8 +7291,8 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
                if (!crtc_state)
                        return;
 
-               I915_STATE_WARN(!crtc_state->base.active,
-                     "connector is active, but attached crtc isn't\n");
+               I915_STATE_WARN(!crtc_state->hw.active,
+                               "connector is active, but attached crtc isn't\n");
 
                if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)
                        return;
@@ -7160,8 +7303,8 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
                I915_STATE_WARN(conn_state->crtc != encoder->base.crtc,
                        "attached encoder crtc differs from connector crtc\n");
        } else {
-               I915_STATE_WARN(crtc_state && crtc_state->base.active,
-                       "attached crtc is active, but connector isn't\n");
+               I915_STATE_WARN(crtc_state && crtc_state->hw.active,
+                               "attached crtc is active, but connector isn't\n");
                I915_STATE_WARN(!crtc_state && conn_state->best_encoder,
                        "best encoder set without crtc!\n");
        }
@@ -7169,7 +7312,7 @@ static void intel_connector_verify_state(struct intel_crtc_state *crtc_state,
 
 static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
 {
-       if (crtc_state->base.enable && crtc_state->has_pch_encoder)
+       if (crtc_state->hw.enable && crtc_state->has_pch_encoder)
                return crtc_state->fdi_lanes;
 
        return 0;
@@ -7179,7 +7322,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
                                     struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct drm_atomic_state *state = pipe_config->base.state;
+       struct drm_atomic_state *state = pipe_config->uapi.state;
        struct intel_crtc *other_crtc;
        struct intel_crtc_state *other_crtc_state;
 
@@ -7201,7 +7344,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
                }
        }
 
-       if (INTEL_INFO(dev_priv)->num_pipes == 2)
+       if (INTEL_NUM_PIPES(dev_priv) == 2)
                return 0;
 
        /* Ivybridge 3 pipe is really complicated */
@@ -7252,7 +7395,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
                                       struct intel_crtc_state *pipe_config)
 {
        struct drm_device *dev = intel_crtc->base.dev;
-       const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+       const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
        int lane, link_bw, fdi_dotclock, ret;
        bool needs_recompute = false;
 
@@ -7298,7 +7441,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
 
 bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        /* IPS only exists on ULT machines and is tied to pipe A. */
@@ -7328,9 +7471,9 @@ bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
 static bool hsw_compute_ips_config(struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv =
-               to_i915(crtc_state->base.crtc->dev);
+               to_i915(crtc_state->uapi.crtc->dev);
        struct intel_atomic_state *intel_state =
-               to_intel_atomic_state(crtc_state->base.state);
+               to_intel_atomic_state(crtc_state->uapi.state);
 
        if (!hsw_crtc_state_ips_capable(crtc_state))
                return false;
@@ -7369,7 +7512,7 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
 {
        u32 pixel_rate;
 
-       pixel_rate = pipe_config->base.adjusted_mode.crtc_clock;
+       pixel_rate = pipe_config->hw.adjusted_mode.crtc_clock;
 
        /*
         * We only use IF-ID interlacing. If we ever use
@@ -7402,12 +7545,12 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
 
 static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 
        if (HAS_GMCH(dev_priv))
                /* FIXME calculate proper pipe pixel rate for GMCH pfit */
                crtc_state->pixel_rate =
-                       crtc_state->base.adjusted_mode.crtc_clock;
+                       crtc_state->hw.adjusted_mode.crtc_clock;
        else
                crtc_state->pixel_rate =
                        ilk_pipe_pixel_rate(crtc_state);
@@ -7417,7 +7560,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
                                     struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+       const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
        int clock_limit = dev_priv->max_dotclk_freq;
 
        if (INTEL_GEN(dev_priv) < 4) {
@@ -7443,7 +7586,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 
        if ((pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
             pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) &&
-            pipe_config->base.ctm) {
+            pipe_config->hw.ctm) {
                /*
                 * There is only one pipe CSC unit per pipe, and we need that
                 * for output conversion from RGB->YCBCR. So if CTM is already
@@ -7539,6 +7682,27 @@ intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
                    constant_n);
 }
 
+static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)
+{
+       /*
+        * There may be no VBT; and if the BIOS enabled SSC we can
+        * just keep using it to avoid unnecessary flicker.  Whereas if the
+        * BIOS isn't using it, don't assume it will work even if the VBT
+        * indicates as much.
+        */
+       if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
+               bool bios_lvds_use_ssc = I915_READ(PCH_DREF_CONTROL) &
+                       DREF_SSC1_ENABLE;
+
+               if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) {
+                       DRM_DEBUG_KMS("SSC %s by BIOS, overriding VBT which says %s\n",
+                                     enableddisabled(bios_lvds_use_ssc),
+                                     enableddisabled(dev_priv->vbt.lvds_use_ssc));
+                       dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc;
+               }
+       }
+}
+
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 {
        if (i915_modparams.panel_use_ssc >= 0)
@@ -7616,7 +7780,7 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
 static void intel_pch_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
                                         const struct intel_link_m_n *m_n)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
 
@@ -7643,7 +7807,7 @@ static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_sta
                                         const struct intel_link_m_n *m_n,
                                         const struct intel_link_m_n *m2_n2)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
        enum transcoder transcoder = crtc_state->cpu_transcoder;
@@ -7956,7 +8120,7 @@ int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
        if (!pipe_config)
                return -ENOMEM;
 
-       pipe_config->base.crtc = &crtc->base;
+       pipe_config->uapi.crtc = &crtc->base;
        pipe_config->pixel_multiplier = 1;
        pipe_config->dpll = *dpll;
 
@@ -8116,11 +8280,11 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,
 
 static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-       const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
+       const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;
        u32 crtc_vtotal, crtc_vblank_end;
        int vsyncshift = 0;
 
@@ -8178,7 +8342,7 @@ static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state)
 
 static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
 
@@ -8190,6 +8354,21 @@ static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state)
                   (crtc_state->pipe_src_h - 1));
 }
 
+static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+
+       if (IS_GEN(dev_priv, 2))
+               return false;
+
+       if (INTEL_GEN(dev_priv) >= 9 ||
+           IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
+               return I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK_HSW;
+       else
+               return I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK;
+}
+
 static void intel_get_pipe_timings(struct intel_crtc *crtc,
                                   struct intel_crtc_state *pipe_config)
 {
@@ -8199,39 +8378,39 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
        u32 tmp;
 
        tmp = I915_READ(HTOTAL(cpu_transcoder));
-       pipe_config->base.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1;
-       pipe_config->base.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1;
 
        if (!transcoder_is_dsi(cpu_transcoder)) {
                tmp = I915_READ(HBLANK(cpu_transcoder));
-               pipe_config->base.adjusted_mode.crtc_hblank_start =
+               pipe_config->hw.adjusted_mode.crtc_hblank_start =
                                                        (tmp & 0xffff) + 1;
-               pipe_config->base.adjusted_mode.crtc_hblank_end =
+               pipe_config->hw.adjusted_mode.crtc_hblank_end =
                                                ((tmp >> 16) & 0xffff) + 1;
        }
        tmp = I915_READ(HSYNC(cpu_transcoder));
-       pipe_config->base.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1;
-       pipe_config->base.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1;
 
        tmp = I915_READ(VTOTAL(cpu_transcoder));
-       pipe_config->base.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1;
-       pipe_config->base.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1;
 
        if (!transcoder_is_dsi(cpu_transcoder)) {
                tmp = I915_READ(VBLANK(cpu_transcoder));
-               pipe_config->base.adjusted_mode.crtc_vblank_start =
+               pipe_config->hw.adjusted_mode.crtc_vblank_start =
                                                        (tmp & 0xffff) + 1;
-               pipe_config->base.adjusted_mode.crtc_vblank_end =
+               pipe_config->hw.adjusted_mode.crtc_vblank_end =
                                                ((tmp >> 16) & 0xffff) + 1;
        }
        tmp = I915_READ(VSYNC(cpu_transcoder));
-       pipe_config->base.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1;
-       pipe_config->base.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1;
+       pipe_config->hw.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1;
 
-       if (I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK) {
-               pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE;
-               pipe_config->base.adjusted_mode.crtc_vtotal += 1;
-               pipe_config->base.adjusted_mode.crtc_vblank_end += 1;
+       if (intel_pipe_is_interlaced(pipe_config)) {
+               pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_INTERLACE;
+               pipe_config->hw.adjusted_mode.crtc_vtotal += 1;
+               pipe_config->hw.adjusted_mode.crtc_vblank_end += 1;
        }
 }
 
@@ -8246,27 +8425,27 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc,
        pipe_config->pipe_src_h = (tmp & 0xffff) + 1;
        pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1;
 
-       pipe_config->base.mode.vdisplay = pipe_config->pipe_src_h;
-       pipe_config->base.mode.hdisplay = pipe_config->pipe_src_w;
+       pipe_config->hw.mode.vdisplay = pipe_config->pipe_src_h;
+       pipe_config->hw.mode.hdisplay = pipe_config->pipe_src_w;
 }
 
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
                                 struct intel_crtc_state *pipe_config)
 {
-       mode->hdisplay = pipe_config->base.adjusted_mode.crtc_hdisplay;
-       mode->htotal = pipe_config->base.adjusted_mode.crtc_htotal;
-       mode->hsync_start = pipe_config->base.adjusted_mode.crtc_hsync_start;
-       mode->hsync_end = pipe_config->base.adjusted_mode.crtc_hsync_end;
+       mode->hdisplay = pipe_config->hw.adjusted_mode.crtc_hdisplay;
+       mode->htotal = pipe_config->hw.adjusted_mode.crtc_htotal;
+       mode->hsync_start = pipe_config->hw.adjusted_mode.crtc_hsync_start;
+       mode->hsync_end = pipe_config->hw.adjusted_mode.crtc_hsync_end;
 
-       mode->vdisplay = pipe_config->base.adjusted_mode.crtc_vdisplay;
-       mode->vtotal = pipe_config->base.adjusted_mode.crtc_vtotal;
-       mode->vsync_start = pipe_config->base.adjusted_mode.crtc_vsync_start;
-       mode->vsync_end = pipe_config->base.adjusted_mode.crtc_vsync_end;
+       mode->vdisplay = pipe_config->hw.adjusted_mode.crtc_vdisplay;
+       mode->vtotal = pipe_config->hw.adjusted_mode.crtc_vtotal;
+       mode->vsync_start = pipe_config->hw.adjusted_mode.crtc_vsync_start;
+       mode->vsync_end = pipe_config->hw.adjusted_mode.crtc_vsync_end;
 
-       mode->flags = pipe_config->base.adjusted_mode.flags;
+       mode->flags = pipe_config->hw.adjusted_mode.flags;
        mode->type = DRM_MODE_TYPE_DRIVER;
 
-       mode->clock = pipe_config->base.adjusted_mode.crtc_clock;
+       mode->clock = pipe_config->hw.adjusted_mode.crtc_clock;
 
        mode->hsync = drm_mode_hsync(mode);
        mode->vrefresh = drm_mode_vrefresh(mode);
@@ -8275,7 +8454,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 
 static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 pipeconf;
 
@@ -8312,7 +8491,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
                }
        }
 
-       if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
+       if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
                if (INTEL_GEN(dev_priv) < 4 ||
                    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
                        pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
@@ -8328,6 +8507,8 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
 
        pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 
+       pipeconf |= PIPECONF_FRAME_START_DELAY(0);
+
        I915_WRITE(PIPECONF(crtc->pipe), pipeconf);
        POSTING_READ(PIPECONF(crtc->pipe));
 }
@@ -8560,7 +8741,7 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = pipe_config->cpu_transcoder;
+       enum pipe pipe = crtc->pipe;
        struct dpll clock;
        u32 mdiv;
        int refclk = 100000;
@@ -8670,7 +8851,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = pipe_config->cpu_transcoder;
+       enum pipe pipe = crtc->pipe;
        enum dpio_channel port = vlv_pipe_to_channel(pipe);
        struct dpll clock;
        u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3;
@@ -8699,52 +8880,29 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
        pipe_config->port_clock = chv_calc_dpll_params(refclk, &clock);
 }
 
-static void intel_get_crtc_ycbcr_config(struct intel_crtc *crtc,
-                                       struct intel_crtc_state *pipe_config)
+static enum intel_output_format
+bdw_get_pipemisc_output_format(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       enum intel_output_format output = INTEL_OUTPUT_FORMAT_RGB;
-
-       pipe_config->lspcon_downsampling = false;
+       u32 tmp;
 
-       if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) {
-               u32 tmp = I915_READ(PIPEMISC(crtc->pipe));
+       tmp = I915_READ(PIPEMISC(crtc->pipe));
 
-               if (tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV) {
-                       bool ycbcr420_enabled = tmp & PIPEMISC_YUV420_ENABLE;
-                       bool blend = tmp & PIPEMISC_YUV420_MODE_FULL_BLEND;
+       if (tmp & PIPEMISC_YUV420_ENABLE) {
+               /* We support 4:2:0 in full blend mode only */
+               WARN_ON((tmp & PIPEMISC_YUV420_MODE_FULL_BLEND) == 0);
 
-                       if (ycbcr420_enabled) {
-                               /* We support 4:2:0 in full blend mode only */
-                               if (!blend)
-                                       output = INTEL_OUTPUT_FORMAT_INVALID;
-                               else if (!(IS_GEMINILAKE(dev_priv) ||
-                                          INTEL_GEN(dev_priv) >= 10))
-                                       output = INTEL_OUTPUT_FORMAT_INVALID;
-                               else
-                                       output = INTEL_OUTPUT_FORMAT_YCBCR420;
-                       } else {
-                               /*
-                                * Currently there is no interface defined to
-                                * check user preference between RGB/YCBCR444
-                                * or YCBCR420. So the only possible case for
-                                * YCBCR444 usage is driving YCBCR420 output
-                                * with LSPCON, when pipe is configured for
-                                * YCBCR444 output and LSPCON takes care of
-                                * downsampling it.
-                                */
-                               pipe_config->lspcon_downsampling = true;
-                               output = INTEL_OUTPUT_FORMAT_YCBCR444;
-                       }
-               }
+               return INTEL_OUTPUT_FORMAT_YCBCR420;
+       } else if (tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV) {
+               return INTEL_OUTPUT_FORMAT_YCBCR444;
+       } else {
+               return INTEL_OUTPUT_FORMAT_RGB;
        }
-
-       pipe_config->output_format = output;
 }
 
 static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct intel_plane *plane = to_intel_plane(crtc->base.primary);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
@@ -8777,6 +8935,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = NULL;
+       pipe_config->master_transcoder = INVALID_TRANSCODER;
 
        ret = false;
 
@@ -8867,7 +9026,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
         * but in case the pipe is enabled w/o any ports we need a sane
         * default.
         */
-       pipe_config->base.adjusted_mode.crtc_clock =
+       pipe_config->hw.adjusted_mode.crtc_clock =
                pipe_config->port_clock / pipe_config->pixel_multiplier;
 
        ret = true;
@@ -9383,7 +9542,7 @@ void intel_init_pch_refclk(struct drm_i915_private *dev_priv)
 
 static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
        u32 val;
@@ -9411,23 +9570,35 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)
        if (crtc_state->dither)
                val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
 
-       if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+       if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                val |= PIPECONF_INTERLACED_ILK;
        else
                val |= PIPECONF_PROGRESSIVE;
 
+       /*
+        * This would end up with an odd purple hue over
+        * the entire display. Make sure we don't do it.
+        */
+       WARN_ON(crtc_state->limited_color_range &&
+               crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
+
        if (crtc_state->limited_color_range)
                val |= PIPECONF_COLOR_RANGE_SELECT;
 
+       if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
+               val |= PIPECONF_OUTPUT_COLORSPACE_YUV709;
+
        val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
 
+       val |= PIPECONF_FRAME_START_DELAY(0);
+
        I915_WRITE(PIPECONF(pipe), val);
        POSTING_READ(PIPECONF(pipe));
 }
 
 static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        u32 val = 0;
@@ -9435,18 +9606,22 @@ static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state)
        if (IS_HASWELL(dev_priv) && crtc_state->dither)
                val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
 
-       if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
+       if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
                val |= PIPECONF_INTERLACED_ILK;
        else
                val |= PIPECONF_PROGRESSIVE;
 
+       if (IS_HASWELL(dev_priv) &&
+           crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
+               val |= PIPECONF_OUTPUT_COLORSPACE_YUV_HSW;
+
        I915_WRITE(PIPECONF(cpu_transcoder), val);
        POSTING_READ(PIPECONF(cpu_transcoder));
 }
 
 static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 val = 0;
 
@@ -9590,7 +9765,7 @@ static void ironlake_compute_dpll(struct intel_crtc *crtc,
         * clear if it''s a win or loss power wise. No point in doing
         * this on ILK at all since it has a fixed DPLL<->pipe mapping.
         */
-       if (INTEL_INFO(dev_priv)->num_pipes == 3 &&
+       if (INTEL_NUM_PIPES(dev_priv) == 3 &&
            intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG))
                dpll |= DPLL_SDVO_HIGH_SPEED;
 
@@ -9632,7 +9807,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct intel_atomic_state *state =
-               to_intel_atomic_state(crtc_state->base.state);
+               to_intel_atomic_state(crtc_state->uapi.state);
        const struct intel_limit *limit;
        int refclk = 120000;
 
@@ -9889,8 +10064,8 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
        offset = I915_READ(PLANE_OFFSET(pipe, plane_id));
 
        val = I915_READ(PLANE_SIZE(pipe, plane_id));
-       fb->height = ((val >> 16) & 0xfff) + 1;
-       fb->width = ((val >> 0) & 0x1fff) + 1;
+       fb->height = ((val >> 16) & 0xffff) + 1;
+       fb->width = ((val >> 0) & 0xffff) + 1;
 
        val = I915_READ(PLANE_STRIDE(pipe, plane_id));
        stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
@@ -9951,9 +10126,9 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        if (!wakeref)
                return false;
 
-       pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = NULL;
+       pipe_config->master_transcoder = INVALID_TRANSCODER;
 
        ret = false;
        tmp = I915_READ(PIPECONF(crtc->pipe));
@@ -9980,6 +10155,16 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        if (tmp & PIPECONF_COLOR_RANGE_SELECT)
                pipe_config->limited_color_range = true;
 
+       switch (tmp & PIPECONF_OUTPUT_COLORSPACE_MASK) {
+       case PIPECONF_OUTPUT_COLORSPACE_YUV601:
+       case PIPECONF_OUTPUT_COLORSPACE_YUV709:
+               pipe_config->output_format = INTEL_OUTPUT_FORMAT_YCBCR444;
+               break;
+       default:
+               pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
+               break;
+       }
+
        pipe_config->gamma_mode = (tmp & PIPECONF_GAMMA_MODE_MASK_ILK) >>
                PIPECONF_GAMMA_MODE_SHIFT;
 
@@ -10048,7 +10233,7 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct intel_atomic_state *state =
-               to_intel_atomic_state(crtc_state->base.state);
+               to_intel_atomic_state(crtc_state->uapi.state);
 
        if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
            INTEL_GEN(dev_priv) >= 11) {
@@ -10349,16 +10534,21 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
                                       struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
        struct intel_shared_dpll *pll;
        enum port port;
        u32 tmp;
 
-       tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
-
-       if (INTEL_GEN(dev_priv) >= 12)
-               port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp);
-       else
-               port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp);
+       if (transcoder_is_dsi(cpu_transcoder)) {
+               port = (cpu_transcoder == TRANSCODER_DSI_A) ?
+                                               PORT_A : PORT_B;
+       } else {
+               tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+               if (INTEL_GEN(dev_priv) >= 12)
+                       port = TGL_TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp);
+               else
+                       port = TRANS_DDI_FUNC_CTL_VAL_TO_PORT(tmp);
+       }
 
        if (INTEL_GEN(dev_priv) >= 11)
                icelake_get_ddi_pll(dev_priv, port, pipe_config);
@@ -10394,6 +10584,59 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
        }
 }
 
+static enum transcoder transcoder_master_readout(struct drm_i915_private *dev_priv,
+                                                enum transcoder cpu_transcoder)
+{
+       u32 trans_port_sync, master_select;
+
+       trans_port_sync = I915_READ(TRANS_DDI_FUNC_CTL2(cpu_transcoder));
+
+       if ((trans_port_sync & PORT_SYNC_MODE_ENABLE) == 0)
+               return INVALID_TRANSCODER;
+
+       master_select = trans_port_sync &
+                       PORT_SYNC_MODE_MASTER_SELECT_MASK;
+       if (master_select == 0)
+               return TRANSCODER_EDP;
+       else
+               return master_select - 1;
+}
+
+static void icelake_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+       u32 transcoders;
+       enum transcoder cpu_transcoder;
+
+       crtc_state->master_transcoder = transcoder_master_readout(dev_priv,
+                                                                 crtc_state->cpu_transcoder);
+
+       transcoders = BIT(TRANSCODER_A) |
+               BIT(TRANSCODER_B) |
+               BIT(TRANSCODER_C) |
+               BIT(TRANSCODER_D);
+       for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) {
+               enum intel_display_power_domain power_domain;
+               intel_wakeref_t trans_wakeref;
+
+               power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+               trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
+                                                                  power_domain);
+
+               if (!trans_wakeref)
+                       continue;
+
+               if (transcoder_master_readout(dev_priv, cpu_transcoder) ==
+                   crtc_state->cpu_transcoder)
+                       crtc_state->sync_mode_slaves_mask |= BIT(cpu_transcoder);
+
+               intel_display_power_put(dev_priv, power_domain, trans_wakeref);
+       }
+
+       WARN_ON(crtc_state->master_transcoder != INVALID_TRANSCODER &&
+               crtc_state->sync_mode_slaves_mask);
+}
+
 static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                                    struct intel_crtc_state *pipe_config)
 {
@@ -10405,6 +10648,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
        intel_crtc_init_scalers(crtc, pipe_config);
 
+       pipe_config->master_transcoder = INVALID_TRANSCODER;
+
        power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
        wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
        if (!wf)
@@ -10435,7 +10680,30 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        }
 
        intel_get_pipe_src_size(crtc, pipe_config);
-       intel_get_crtc_ycbcr_config(crtc, pipe_config);
+
+       if (IS_HASWELL(dev_priv)) {
+               u32 tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
+
+               if (tmp & PIPECONF_OUTPUT_COLORSPACE_YUV_HSW)
+                       pipe_config->output_format = INTEL_OUTPUT_FORMAT_YCBCR444;
+               else
+                       pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
+       } else {
+               pipe_config->output_format =
+                       bdw_get_pipemisc_output_format(crtc);
+
+               /*
+                * Currently there is no interface defined to
+                * check user preference between RGB/YCBCR444
+                * or YCBCR420. So the only possible case for
+                * YCBCR444 usage is driving YCBCR420 output
+                * with LSPCON, when pipe is configured for
+                * YCBCR444 output and LSPCON takes care of
+                * downsampling it.
+                */
+               pipe_config->lspcon_downsampling =
+                       pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444;
+       }
 
        pipe_config->gamma_mode = I915_READ(GAMMA_MODE(crtc->pipe));
 
@@ -10490,6 +10758,10 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->pixel_multiplier = 1;
        }
 
+       if (INTEL_GEN(dev_priv) >= 11 &&
+           !transcoder_is_dsi(pipe_config->cpu_transcoder))
+               icelake_get_trans_port_sync_config(pipe_config);
+
 out:
        for_each_power_domain(power_domain, power_domain_mask)
                intel_display_power_put(dev_priv,
@@ -10501,8 +10773,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv =
-               to_i915(plane_state->base.plane->dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+               to_i915(plane_state->uapi.plane->dev);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        u32 base;
 
@@ -10511,21 +10783,13 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
        else
                base = intel_plane_ggtt_offset(plane_state);
 
-       base += plane_state->color_plane[0].offset;
-
-       /* ILK+ do this automagically */
-       if (HAS_GMCH(dev_priv) &&
-           plane_state->base.rotation & DRM_MODE_ROTATE_180)
-               base += (plane_state->base.crtc_h *
-                        plane_state->base.crtc_w - 1) * fb->format->cpp[0];
-
-       return base;
+       return base + plane_state->color_plane[0].offset;
 }
 
 static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
 {
-       int x = plane_state->base.crtc_x;
-       int y = plane_state->base.crtc_y;
+       int x = plane_state->uapi.dst.x1;
+       int y = plane_state->uapi.dst.y1;
        u32 pos = 0;
 
        if (x < 0) {
@@ -10546,9 +10810,9 @@ static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
 static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
 {
        const struct drm_mode_config *config =
-               &plane_state->base.plane->dev->mode_config;
-       int width = plane_state->base.crtc_w;
-       int height = plane_state->base.crtc_h;
+               &plane_state->uapi.plane->dev->mode_config;
+       int width = drm_rect_width(&plane_state->uapi.dst);
+       int height = drm_rect_height(&plane_state->uapi.dst);
 
        return width > 0 && width <= config->cursor_width &&
                height > 0 && height <= config->cursor_height;
@@ -10556,6 +10820,9 @@ static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
 
 static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
 {
+       struct drm_i915_private *dev_priv =
+               to_i915(plane_state->uapi.plane->dev);
+       unsigned int rotation = plane_state->hw.rotation;
        int src_x, src_y;
        u32 offset;
        int ret;
@@ -10564,11 +10831,11 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
        if (ret)
                return ret;
 
-       if (!plane_state->base.visible)
+       if (!plane_state->uapi.visible)
                return 0;
 
-       src_x = plane_state->base.src_x >> 16;
-       src_y = plane_state->base.src_y >> 16;
+       src_x = plane_state->uapi.src.x1 >> 16;
+       src_y = plane_state->uapi.src.y1 >> 16;
 
        intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
        offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
@@ -10579,7 +10846,25 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
                return -EINVAL;
        }
 
+       /*
+        * Put the final coordinates back so that the src
+        * coordinate checks will see the right values.
+        */
+       drm_rect_translate_to(&plane_state->uapi.src,
+                             src_x << 16, src_y << 16);
+
+       /* ILK+ do this automagically in hardware */
+       if (HAS_GMCH(dev_priv) && rotation & DRM_MODE_ROTATE_180) {
+               const struct drm_framebuffer *fb = plane_state->hw.fb;
+               int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
+               int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
+
+               offset += (src_h * src_w - 1) * fb->format->cpp[0];
+       }
+
        plane_state->color_plane[0].offset = offset;
+       plane_state->color_plane[0].x = src_x;
+       plane_state->color_plane[0].y = src_y;
 
        return 0;
 }
@@ -10587,7 +10872,7 @@ static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
 static int intel_check_cursor(struct intel_crtc_state *crtc_state,
                              struct intel_plane_state *plane_state)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        int ret;
 
        if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
@@ -10595,19 +10880,23 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
                return -EINVAL;
        }
 
-       ret = drm_atomic_helper_check_plane_state(&plane_state->base,
-                                                 &crtc_state->base,
+       ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
+                                                 &crtc_state->uapi,
                                                  DRM_PLANE_HELPER_NO_SCALING,
                                                  DRM_PLANE_HELPER_NO_SCALING,
                                                  true, true);
        if (ret)
                return ret;
 
+       /* Use the unclipped src/dst rectangles, which we program to hw */
+       plane_state->uapi.src = drm_plane_state_src(&plane_state->uapi);
+       plane_state->uapi.dst = drm_plane_state_dest(&plane_state->uapi);
+
        ret = intel_cursor_check_surface(plane_state);
        if (ret)
                return ret;
 
-       if (!plane_state->base.visible)
+       if (!plane_state->uapi.visible)
                return 0;
 
        ret = intel_plane_check_src_coordinates(plane_state);
@@ -10645,7 +10934,7 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
 
 static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
 {
-       int width = plane_state->base.crtc_w;
+       int width = drm_rect_width(&plane_state->uapi.dst);
 
        /*
         * 845g/865g are only limited by the width of their cursors,
@@ -10657,7 +10946,7 @@ static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
 static int i845_check_cursor(struct intel_crtc_state *crtc_state,
                             struct intel_plane_state *plane_state)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        int ret;
 
        ret = intel_check_cursor(crtc_state, plane_state);
@@ -10671,12 +10960,12 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
        /* Check for which cursor types we support */
        if (!i845_cursor_size_ok(plane_state)) {
                DRM_DEBUG("Cursor dimension %dx%d not supported\n",
-                         plane_state->base.crtc_w,
-                         plane_state->base.crtc_h);
+                         drm_rect_width(&plane_state->uapi.dst),
+                         drm_rect_height(&plane_state->uapi.dst));
                return -EINVAL;
        }
 
-       WARN_ON(plane_state->base.visible &&
+       WARN_ON(plane_state->uapi.visible &&
                plane_state->color_plane[0].stride != fb->pitches[0]);
 
        switch (fb->pitches[0]) {
@@ -10704,9 +10993,9 @@ static void i845_update_cursor(struct intel_plane *plane,
        u32 cntl = 0, base = 0, pos = 0, size = 0;
        unsigned long irqflags;
 
-       if (plane_state && plane_state->base.visible) {
-               unsigned int width = plane_state->base.crtc_w;
-               unsigned int height = plane_state->base.crtc_h;
+       if (plane_state && plane_state->uapi.visible) {
+               unsigned int width = drm_rect_width(&plane_state->uapi.dst);
+               unsigned int height = drm_rect_height(&plane_state->uapi.dst);
 
                cntl = plane_state->ctl |
                        i845_cursor_ctl_crtc(crtc_state);
@@ -10779,7 +11068,7 @@ i9xx_cursor_max_stride(struct intel_plane *plane,
 
 static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 cntl = 0;
 
@@ -10802,13 +11091,13 @@ static u32 i9xx_cursor_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->base.plane->dev);
+               to_i915(plane_state->uapi.plane->dev);
        u32 cntl = 0;
 
        if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv))
                cntl |= MCURSOR_TRICKLE_FEED_DISABLE;
 
-       switch (plane_state->base.crtc_w) {
+       switch (drm_rect_width(&plane_state->uapi.dst)) {
        case 64:
                cntl |= MCURSOR_MODE_64_ARGB_AX;
                break;
@@ -10819,11 +11108,11 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
                cntl |= MCURSOR_MODE_256_ARGB_AX;
                break;
        default:
-               MISSING_CASE(plane_state->base.crtc_w);
+               MISSING_CASE(drm_rect_width(&plane_state->uapi.dst));
                return 0;
        }
 
-       if (plane_state->base.rotation & DRM_MODE_ROTATE_180)
+       if (plane_state->hw.rotation & DRM_MODE_ROTATE_180)
                cntl |= MCURSOR_ROTATE_180;
 
        return cntl;
@@ -10832,9 +11121,9 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
 static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv =
-               to_i915(plane_state->base.plane->dev);
-       int width = plane_state->base.crtc_w;
-       int height = plane_state->base.crtc_h;
+               to_i915(plane_state->uapi.plane->dev);
+       int width = drm_rect_width(&plane_state->uapi.dst);
+       int height = drm_rect_height(&plane_state->uapi.dst);
 
        if (!intel_cursor_size_ok(plane_state))
                return false;
@@ -10856,7 +11145,7 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
         * cursors.
         */
        if (HAS_CUR_FBC(dev_priv) &&
-           plane_state->base.rotation & DRM_MODE_ROTATE_0) {
+           plane_state->hw.rotation & DRM_MODE_ROTATE_0) {
                if (height < 8 || height > width)
                        return false;
        } else {
@@ -10870,9 +11159,9 @@ static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
 static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
                             struct intel_plane_state *plane_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        enum pipe pipe = plane->pipe;
        int ret;
 
@@ -10887,17 +11176,19 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
        /* Check for which cursor types we support */
        if (!i9xx_cursor_size_ok(plane_state)) {
                DRM_DEBUG("Cursor dimension %dx%d not supported\n",
-                         plane_state->base.crtc_w,
-                         plane_state->base.crtc_h);
+                         drm_rect_width(&plane_state->uapi.dst),
+                         drm_rect_height(&plane_state->uapi.dst));
                return -EINVAL;
        }
 
-       WARN_ON(plane_state->base.visible &&
+       WARN_ON(plane_state->uapi.visible &&
                plane_state->color_plane[0].stride != fb->pitches[0]);
 
-       if (fb->pitches[0] != plane_state->base.crtc_w * fb->format->cpp[0]) {
+       if (fb->pitches[0] !=
+           drm_rect_width(&plane_state->uapi.dst) * fb->format->cpp[0]) {
                DRM_DEBUG_KMS("Invalid cursor stride (%u) (cursor width %d)\n",
-                             fb->pitches[0], plane_state->base.crtc_w);
+                             fb->pitches[0],
+                             drm_rect_width(&plane_state->uapi.dst));
                return -EINVAL;
        }
 
@@ -10912,7 +11203,7 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
         * Refuse the put the cursor into that compromised position.
         */
        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
-           plane_state->base.visible && plane_state->base.crtc_x < 0) {
+           plane_state->uapi.visible && plane_state->uapi.dst.x1 < 0) {
                DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
                return -EINVAL;
        }
@@ -10931,12 +11222,15 @@ static void i9xx_update_cursor(struct intel_plane *plane,
        u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
        unsigned long irqflags;
 
-       if (plane_state && plane_state->base.visible) {
+       if (plane_state && plane_state->uapi.visible) {
+               unsigned width = drm_rect_width(&plane_state->uapi.dst);
+               unsigned height = drm_rect_height(&plane_state->uapi.dst);
+
                cntl = plane_state->ctl |
                        i9xx_cursor_ctl_crtc(crtc_state);
 
-               if (plane_state->base.crtc_h != plane_state->base.crtc_w)
-                       fbc_ctl = CUR_FBC_CTL_EN | (plane_state->base.crtc_h - 1);
+               if (width != height)
+                       fbc_ctl = CUR_FBC_CTL_EN | (height - 1);
 
                base = intel_cursor_base(plane_state);
                pos = intel_cursor_position(plane_state);
@@ -11081,7 +11375,6 @@ static int intel_modeset_disable_planes(struct drm_atomic_state *state,
 }
 
 int intel_get_load_detect_pipe(struct drm_connector *connector,
-                              const struct drm_display_mode *mode,
                               struct intel_load_detect_pipe *old,
                               struct drm_modeset_acquire_ctx *ctx)
 {
@@ -11186,12 +11479,10 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
                goto fail;
        }
 
-       crtc_state->base.active = crtc_state->base.enable = true;
-
-       if (!mode)
-               mode = &load_detect_mode;
+       crtc_state->uapi.active = true;
 
-       ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, mode);
+       ret = drm_atomic_set_mode_for_crtc(&crtc_state->uapi,
+                                          &load_detect_mode);
        if (ret)
                goto fail;
 
@@ -11283,7 +11574,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       int pipe = pipe_config->cpu_transcoder;
+       enum pipe pipe = crtc->pipe;
        u32 dpll = pipe_config->dpll_hw_state.dpll;
        u32 fp;
        struct dpll clock;
@@ -11399,7 +11690,7 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
         * we may need some idea for the dotclock anyway.
         * Calculate one based on the FDI configuration.
         */
-       pipe_config->base.adjusted_mode.crtc_clock =
+       pipe_config->hw.adjusted_mode.crtc_clock =
                intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),
                                         &pipe_config->fdi_m_n);
 }
@@ -11429,7 +11720,7 @@ intel_encoder_current_mode(struct intel_encoder *encoder)
                return NULL;
        }
 
-       crtc_state->base.crtc = &crtc->base;
+       crtc_state->uapi.crtc = &crtc->base;
 
        if (!dev_priv->display.get_pipe_config(crtc, crtc_state)) {
                kfree(crtc_state);
@@ -11468,18 +11759,18 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur,
                                 struct intel_plane_state *new)
 {
        /* Update watermarks on tiling or size changes. */
-       if (new->base.visible != cur->base.visible)
+       if (new->uapi.visible != cur->uapi.visible)
                return true;
 
-       if (!cur->base.fb || !new->base.fb)
+       if (!cur->hw.fb || !new->hw.fb)
                return false;
 
-       if (cur->base.fb->modifier != new->base.fb->modifier ||
-           cur->base.rotation != new->base.rotation ||
-           drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) ||
-           drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) ||
-           drm_rect_width(&new->base.dst) != drm_rect_width(&cur->base.dst) ||
-           drm_rect_height(&new->base.dst) != drm_rect_height(&cur->base.dst))
+       if (cur->hw.fb->modifier != new->hw.fb->modifier ||
+           cur->hw.rotation != new->hw.rotation ||
+           drm_rect_width(&new->uapi.src) != drm_rect_width(&cur->uapi.src) ||
+           drm_rect_height(&new->uapi.src) != drm_rect_height(&cur->uapi.src) ||
+           drm_rect_width(&new->uapi.dst) != drm_rect_width(&cur->uapi.dst) ||
+           drm_rect_height(&new->uapi.dst) != drm_rect_height(&cur->uapi.dst))
                return true;
 
        return false;
@@ -11487,10 +11778,10 @@ static bool intel_wm_need_update(const struct intel_plane_state *cur,
 
 static bool needs_scaling(const struct intel_plane_state *state)
 {
-       int src_w = drm_rect_width(&state->base.src) >> 16;
-       int src_h = drm_rect_height(&state->base.src) >> 16;
-       int dst_w = drm_rect_width(&state->base.dst);
-       int dst_h = drm_rect_height(&state->base.dst);
+       int src_w = drm_rect_width(&state->uapi.src) >> 16;
+       int src_h = drm_rect_height(&state->uapi.src) >> 16;
+       int dst_w = drm_rect_width(&state->uapi.dst);
+       int dst_h = drm_rect_height(&state->uapi.dst);
 
        return (src_w != dst_w || src_h != dst_h);
 }
@@ -11500,14 +11791,13 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat
                                    const struct intel_plane_state *old_plane_state,
                                    struct intel_plane_state *plane_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        bool mode_changed = needs_modeset(crtc_state);
-       bool was_crtc_enabled = old_crtc_state->base.active;
-       bool is_crtc_enabled = crtc_state->base.active;
+       bool was_crtc_enabled = old_crtc_state->hw.active;
+       bool is_crtc_enabled = crtc_state->hw.active;
        bool turn_off, turn_on, visible, was_visible;
-       struct drm_framebuffer *fb = plane_state->base.fb;
        int ret;
 
        if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_CURSOR) {
@@ -11516,8 +11806,8 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat
                        return ret;
        }
 
-       was_visible = old_plane_state->base.visible;
-       visible = plane_state->base.visible;
+       was_visible = old_plane_state->uapi.visible;
+       visible = plane_state->uapi.visible;
 
        if (!was_crtc_enabled && WARN_ON(was_visible))
                was_visible = false;
@@ -11533,26 +11823,20 @@ int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_stat
         * only combine the results from all planes in the current place?
         */
        if (!is_crtc_enabled) {
-               plane_state->base.visible = visible = false;
+               plane_state->uapi.visible = visible = false;
                crtc_state->active_planes &= ~BIT(plane->id);
                crtc_state->data_rate[plane->id] = 0;
+               crtc_state->min_cdclk[plane->id] = 0;
        }
 
        if (!was_visible && !visible)
                return 0;
 
-       if (fb != old_plane_state->base.fb)
-               crtc_state->fb_changed = true;
-
        turn_off = was_visible && (!visible || mode_changed);
        turn_on = visible && (!was_visible || mode_changed);
 
-       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
+       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] with [PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
                         crtc->base.base.id, crtc->base.name,
-                        plane->base.base.id, plane->base.name,
-                        fb ? fb->base.id : -1);
-
-       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
                         plane->base.base.id, plane->base.name,
                         was_visible, visible,
                         turn_off, turn_on, mode_changed);
@@ -11662,7 +11946,7 @@ static int icl_add_linked_planes(struct intel_atomic_state *state)
        int i;
 
        for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
-               linked = plane_state->linked_plane;
+               linked = plane_state->planar_linked_plane;
 
                if (!linked)
                        continue;
@@ -11671,8 +11955,8 @@ static int icl_add_linked_planes(struct intel_atomic_state *state)
                if (IS_ERR(linked_plane_state))
                        return PTR_ERR(linked_plane_state);
 
-               WARN_ON(linked_plane_state->linked_plane != plane);
-               WARN_ON(linked_plane_state->slave == plane_state->slave);
+               WARN_ON(linked_plane_state->planar_linked_plane != plane);
+               WARN_ON(linked_plane_state->planar_slave == plane_state->planar_slave);
        }
 
        return 0;
@@ -11680,9 +11964,9 @@ static int icl_add_linked_planes(struct intel_atomic_state *state)
 
 static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->base.state);
+       struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
        struct intel_plane *plane, *linked;
        struct intel_plane_state *plane_state;
        int i;
@@ -11695,16 +11979,16 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
         * in the crtc_state->active_planes mask.
         */
        for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
-               if (plane->pipe != crtc->pipe || !plane_state->linked_plane)
+               if (plane->pipe != crtc->pipe || !plane_state->planar_linked_plane)
                        continue;
 
-               plane_state->linked_plane = NULL;
-               if (plane_state->slave && !plane_state->base.visible) {
+               plane_state->planar_linked_plane = NULL;
+               if (plane_state->planar_slave && !plane_state->uapi.visible) {
                        crtc_state->active_planes &= ~BIT(plane->id);
                        crtc_state->update_planes |= BIT(plane->id);
                }
 
-               plane_state->slave = false;
+               plane_state->planar_slave = false;
        }
 
        if (!crtc_state->nv12_planes)
@@ -11738,13 +12022,31 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
                        return -EINVAL;
                }
 
-               plane_state->linked_plane = linked;
+               plane_state->planar_linked_plane = linked;
 
-               linked_state->slave = true;
-               linked_state->linked_plane = plane;
+               linked_state->planar_slave = true;
+               linked_state->planar_linked_plane = plane;
                crtc_state->active_planes |= BIT(linked->id);
                crtc_state->update_planes |= BIT(linked->id);
                DRM_DEBUG_KMS("Using %s as Y plane for %s\n", linked->base.name, plane->base.name);
+
+               /* Copy parameters to slave plane */
+               linked_state->ctl = plane_state->ctl | PLANE_CTL_YUV420_Y_PLANE;
+               linked_state->color_ctl = plane_state->color_ctl;
+               linked_state->color_plane[0] = plane_state->color_plane[0];
+
+               intel_plane_copy_uapi_to_hw_state(linked_state, plane_state);
+               linked_state->uapi.src = plane_state->uapi.src;
+               linked_state->uapi.dst = plane_state->uapi.dst;
+
+               if (icl_is_hdr_plane(dev_priv, plane->id)) {
+                       if (linked->id == PLANE_SPRITE5)
+                               plane_state->cus_ctl |= PLANE_CUS_PLANE_7;
+                       else if (linked->id == PLANE_SPRITE4)
+                               plane_state->cus_ctl |= PLANE_CUS_PLANE_6;
+                       else
+                               MISSING_CASE(linked->id);
+               }
        }
 
        return 0;
@@ -11752,55 +12054,138 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
 
 static bool c8_planes_changed(const struct intel_crtc_state *new_crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
        struct intel_atomic_state *state =
-               to_intel_atomic_state(new_crtc_state->base.state);
+               to_intel_atomic_state(new_crtc_state->uapi.state);
        const struct intel_crtc_state *old_crtc_state =
                intel_atomic_get_old_crtc_state(state, crtc);
 
        return !old_crtc_state->c8_planes != !new_crtc_state->c8_planes;
 }
 
-static int intel_crtc_atomic_check(struct drm_crtc *crtc,
-                                  struct drm_crtc_state *crtc_state)
+static int icl_add_sync_mode_crtcs(struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_crtc_state *pipe_config =
-               to_intel_crtc_state(crtc_state);
-       int ret;
-       bool mode_changed = needs_modeset(pipe_config);
-
-       if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv) &&
-           mode_changed && !crtc_state->active)
-               pipe_config->update_wm_post = true;
+       struct drm_crtc *crtc = crtc_state->uapi.crtc;
+       struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+       struct drm_connector *master_connector, *connector;
+       struct drm_connector_state *connector_state;
+       struct drm_connector_list_iter conn_iter;
+       struct drm_crtc *master_crtc = NULL;
+       struct drm_crtc_state *master_crtc_state;
+       struct intel_crtc_state *master_pipe_config;
+       int i, tile_group_id;
 
-       if (mode_changed && crtc_state->enable &&
-           dev_priv->display.crtc_compute_clock &&
-           !WARN_ON(pipe_config->shared_dpll)) {
-               ret = dev_priv->display.crtc_compute_clock(intel_crtc,
-                                                          pipe_config);
-               if (ret)
-                       return ret;
-       }
+       if (INTEL_GEN(dev_priv) < 11)
+               return 0;
 
        /*
-        * May need to update pipe gamma enable bits
-        * when C8 planes are getting enabled/disabled.
+        * In case of tiled displays there could be one or more slaves but there is
+        * only one master. Lets make the CRTC used by the connector corresponding
+        * to the last horizonal and last vertical tile a master/genlock CRTC.
+        * All the other CRTCs corresponding to other tiles of the same Tile group
+        * are the slave CRTCs and hold a pointer to their genlock CRTC.
         */
-       if (c8_planes_changed(pipe_config))
-               crtc_state->color_mgmt_changed = true;
-
-       if (mode_changed || pipe_config->update_pipe ||
-           crtc_state->color_mgmt_changed) {
-               ret = intel_color_check(pipe_config);
-               if (ret)
-                       return ret;
-       }
+       for_each_new_connector_in_state(&state->base, connector, connector_state, i) {
+               if (connector_state->crtc != crtc)
+                       continue;
+               if (!connector->has_tile)
+                       continue;
+               if (crtc_state->hw.mode.hdisplay != connector->tile_h_size ||
+                   crtc_state->hw.mode.vdisplay != connector->tile_v_size)
+                       return 0;
+               if (connector->tile_h_loc == connector->num_h_tile - 1 &&
+                   connector->tile_v_loc == connector->num_v_tile - 1)
+                       continue;
+               crtc_state->sync_mode_slaves_mask = 0;
+               tile_group_id = connector->tile_group->id;
+               drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
+               drm_for_each_connector_iter(master_connector, &conn_iter) {
+                       struct drm_connector_state *master_conn_state = NULL;
+
+                       if (!master_connector->has_tile)
+                               continue;
+                       if (master_connector->tile_h_loc != master_connector->num_h_tile - 1 ||
+                           master_connector->tile_v_loc != master_connector->num_v_tile - 1)
+                               continue;
+                       if (master_connector->tile_group->id != tile_group_id)
+                               continue;
+
+                       master_conn_state = drm_atomic_get_connector_state(&state->base,
+                                                                          master_connector);
+                       if (IS_ERR(master_conn_state)) {
+                               drm_connector_list_iter_end(&conn_iter);
+                               return PTR_ERR(master_conn_state);
+                       }
+                       if (master_conn_state->crtc) {
+                               master_crtc = master_conn_state->crtc;
+                               break;
+                       }
+               }
+               drm_connector_list_iter_end(&conn_iter);
+
+               if (!master_crtc) {
+                       DRM_DEBUG_KMS("Could not find Master CRTC for Slave CRTC %d\n",
+                                     connector_state->crtc->base.id);
+                       return -EINVAL;
+               }
+
+               master_crtc_state = drm_atomic_get_crtc_state(&state->base,
+                                                             master_crtc);
+               if (IS_ERR(master_crtc_state))
+                       return PTR_ERR(master_crtc_state);
+
+               master_pipe_config = to_intel_crtc_state(master_crtc_state);
+               crtc_state->master_transcoder = master_pipe_config->cpu_transcoder;
+               master_pipe_config->sync_mode_slaves_mask |=
+                       BIT(crtc_state->cpu_transcoder);
+               DRM_DEBUG_KMS("Master Transcoder = %s added for Slave CRTC = %d, slave transcoder bitmask = %d\n",
+                             transcoder_name(crtc_state->master_transcoder),
+                             crtc_state->uapi.crtc->base.id,
+                             master_pipe_config->sync_mode_slaves_mask);
+       }
+
+       return 0;
+}
+
+static int intel_crtc_atomic_check(struct intel_atomic_state *state,
+                                  struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_crtc_state *crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       bool mode_changed = needs_modeset(crtc_state);
+       int ret;
+
+       if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv) &&
+           mode_changed && !crtc_state->hw.active)
+               crtc_state->update_wm_post = true;
+
+       if (mode_changed && crtc_state->hw.enable &&
+           dev_priv->display.crtc_compute_clock &&
+           !WARN_ON(crtc_state->shared_dpll)) {
+               ret = dev_priv->display.crtc_compute_clock(crtc, crtc_state);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * May need to update pipe gamma enable bits
+        * when C8 planes are getting enabled/disabled.
+        */
+       if (c8_planes_changed(crtc_state))
+               crtc_state->uapi.color_mgmt_changed = true;
+
+       if (mode_changed || crtc_state->update_pipe ||
+           crtc_state->uapi.color_mgmt_changed) {
+               ret = intel_color_check(crtc_state);
+               if (ret)
+                       return ret;
+       }
 
        ret = 0;
        if (dev_priv->display.compute_pipe_wm) {
-               ret = dev_priv->display.compute_pipe_wm(pipe_config);
+               ret = dev_priv->display.compute_pipe_wm(crtc_state);
                if (ret) {
                        DRM_DEBUG_KMS("Target pipe watermarks are invalid\n");
                        return ret;
@@ -11816,7 +12201,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
                 * old state and the new state.  We can program these
                 * immediately.
                 */
-               ret = dev_priv->display.compute_intermediate_wm(pipe_config);
+               ret = dev_priv->display.compute_intermediate_wm(crtc_state);
                if (ret) {
                        DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
                        return ret;
@@ -11824,29 +12209,19 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
        }
 
        if (INTEL_GEN(dev_priv) >= 9) {
-               if (mode_changed || pipe_config->update_pipe)
-                       ret = skl_update_scaler_crtc(pipe_config);
-
+               if (mode_changed || crtc_state->update_pipe)
+                       ret = skl_update_scaler_crtc(crtc_state);
                if (!ret)
-                       ret = icl_check_nv12_planes(pipe_config);
-               if (!ret)
-                       ret = skl_check_pipe_max_pixel_rate(intel_crtc,
-                                                           pipe_config);
-               if (!ret)
-                       ret = intel_atomic_setup_scalers(dev_priv, intel_crtc,
-                                                        pipe_config);
+                       ret = intel_atomic_setup_scalers(dev_priv, crtc,
+                                                        crtc_state);
        }
 
        if (HAS_IPS(dev_priv))
-               pipe_config->ips_enabled = hsw_compute_ips_config(pipe_config);
+               crtc_state->ips_enabled = hsw_compute_ips_config(crtc_state);
 
        return ret;
 }
 
-static const struct drm_crtc_helper_funcs intel_helper_funcs = {
-       .atomic_check = intel_crtc_atomic_check,
-};
-
 static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
 {
        struct intel_connector *connector;
@@ -11915,7 +12290,7 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
                          struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       struct drm_atomic_state *state = pipe_config->base.state;
+       struct drm_atomic_state *state = pipe_config->uapi.state;
        struct drm_connector *connector;
        struct drm_connector_state *connector_state;
        int bpp, i;
@@ -12040,14 +12415,14 @@ static const char *output_formats(enum intel_output_format format)
 
 static void intel_dump_plane_state(const struct intel_plane_state *plane_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+       const struct drm_framebuffer *fb = plane_state->hw.fb;
        struct drm_format_name_buf format_name;
 
        if (!fb) {
                DRM_DEBUG_KMS("[PLANE:%d:%s] fb: [NOFB], visible: %s\n",
                              plane->base.base.id, plane->base.name,
-                             yesno(plane_state->base.visible));
+                             yesno(plane_state->uapi.visible));
                return;
        }
 
@@ -12055,20 +12430,20 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state)
                      plane->base.base.id, plane->base.name,
                      fb->base.id, fb->width, fb->height,
                      drm_get_format_name(fb->format->format, &format_name),
-                     yesno(plane_state->base.visible));
+                     yesno(plane_state->uapi.visible));
        DRM_DEBUG_KMS("\trotation: 0x%x, scaler: %d\n",
-                     plane_state->base.rotation, plane_state->scaler_id);
-       if (plane_state->base.visible)
+                     plane_state->hw.rotation, plane_state->scaler_id);
+       if (plane_state->uapi.visible)
                DRM_DEBUG_KMS("\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n",
-                             DRM_RECT_FP_ARG(&plane_state->base.src),
-                             DRM_RECT_ARG(&plane_state->base.dst));
+                             DRM_RECT_FP_ARG(&plane_state->uapi.src),
+                             DRM_RECT_ARG(&plane_state->uapi.dst));
 }
 
 static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                                   struct intel_atomic_state *state,
                                   const char *context)
 {
-       struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct intel_plane_state *plane_state;
        struct intel_plane *plane;
@@ -12077,14 +12452,14 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
 
        DRM_DEBUG_KMS("[CRTC:%d:%s] enable: %s %s\n",
                      crtc->base.base.id, crtc->base.name,
-                     yesno(pipe_config->base.enable), context);
+                     yesno(pipe_config->hw.enable), context);
 
-       if (!pipe_config->base.enable)
+       if (!pipe_config->hw.enable)
                goto dump_planes;
 
        snprintf_output_types(buf, sizeof(buf), pipe_config->output_types);
        DRM_DEBUG_KMS("active: %s, output_types: %s (0x%x), output format: %s\n",
-                     yesno(pipe_config->base.active),
+                     yesno(pipe_config->hw.active),
                      buf, pipe_config->output_types,
                      output_formats(pipe_config->output_format));
 
@@ -12124,10 +12499,10 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                intel_dump_infoframe(dev_priv, &pipe_config->infoframes.hdmi);
 
        DRM_DEBUG_KMS("requested mode:\n");
-       drm_mode_debug_printmodeline(&pipe_config->base.mode);
+       drm_mode_debug_printmodeline(&pipe_config->hw.mode);
        DRM_DEBUG_KMS("adjusted mode:\n");
-       drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode);
-       intel_dump_crtc_timings(&pipe_config->base.adjusted_mode);
+       drm_mode_debug_printmodeline(&pipe_config->hw.adjusted_mode);
+       intel_dump_crtc_timings(&pipe_config->hw.adjusted_mode);
        DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d, pixel rate %d\n",
                      pipe_config->port_clock,
                      pipe_config->pipe_src_w, pipe_config->pipe_src_h,
@@ -12156,6 +12531,15 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
 
        intel_dpll_dump_hw_state(dev_priv, &pipe_config->dpll_hw_state);
 
+       if (IS_CHERRYVIEW(dev_priv))
+               DRM_DEBUG_KMS("cgm_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n",
+                             pipe_config->cgm_mode, pipe_config->gamma_mode,
+                             pipe_config->gamma_enable, pipe_config->csc_enable);
+       else
+               DRM_DEBUG_KMS("csc_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n",
+                             pipe_config->csc_mode, pipe_config->gamma_mode,
+                             pipe_config->gamma_enable, pipe_config->csc_enable);
+
 dump_planes:
        if (!state)
                return;
@@ -12175,6 +12559,12 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state)
        unsigned int used_mst_ports = 0;
        bool ret = true;
 
+       /*
+        * We're going to peek into connector->state,
+        * hence connection_mutex must be held.
+        */
+       drm_modeset_lock_assert_held(&dev->mode_config.connection_mutex);
+
        /*
         * Walk the connector list instead of the encoder
         * list to detect the problem on ddi platforms
@@ -12232,22 +12622,59 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state)
        return ret;
 }
 
+static void
+intel_crtc_copy_uapi_to_hw_state_nomodeset(struct intel_crtc_state *crtc_state)
+{
+       intel_crtc_copy_color_blobs(crtc_state);
+}
+
+static void
+intel_crtc_copy_uapi_to_hw_state(struct intel_crtc_state *crtc_state)
+{
+       crtc_state->hw.enable = crtc_state->uapi.enable;
+       crtc_state->hw.active = crtc_state->uapi.active;
+       crtc_state->hw.mode = crtc_state->uapi.mode;
+       crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode;
+       intel_crtc_copy_uapi_to_hw_state_nomodeset(crtc_state);
+}
+
+static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state)
+{
+       crtc_state->uapi.enable = crtc_state->hw.enable;
+       crtc_state->uapi.active = crtc_state->hw.active;
+       WARN_ON(drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0);
+
+       crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
+
+       /* copy color blobs to uapi */
+       drm_property_replace_blob(&crtc_state->uapi.degamma_lut,
+                                 crtc_state->hw.degamma_lut);
+       drm_property_replace_blob(&crtc_state->uapi.gamma_lut,
+                                 crtc_state->hw.gamma_lut);
+       drm_property_replace_blob(&crtc_state->uapi.ctm,
+                                 crtc_state->hw.ctm);
+}
+
 static int
-clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
+intel_crtc_prepare_cleared_state(struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv =
-               to_i915(crtc_state->base.crtc->dev);
+               to_i915(crtc_state->uapi.crtc->dev);
        struct intel_crtc_state *saved_state;
 
        saved_state = kzalloc(sizeof(*saved_state), GFP_KERNEL);
        if (!saved_state)
                return -ENOMEM;
 
+       /* free the old crtc_state->hw members */
+       intel_crtc_free_hw_state(crtc_state);
+
        /* FIXME: before the switch to atomic started, a new pipe_config was
         * kzalloc'd. Code that depends on any field being zero should be
         * fixed, so that the crtc_state can be safely duplicated. For now,
         * only fields that are know to not cause problems are preserved. */
 
+       saved_state->uapi = crtc_state->uapi;
        saved_state->scaler_state = crtc_state->scaler_state;
        saved_state->shared_dpll = crtc_state->shared_dpll;
        saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
@@ -12257,21 +12684,27 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
        if (IS_G4X(dev_priv) ||
            IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                saved_state->wm = crtc_state->wm;
+       /*
+        * Save the slave bitmask which gets filled for master crtc state during
+        * slave atomic check call.
+        */
+       if (is_trans_port_sync_master(crtc_state))
+               saved_state->sync_mode_slaves_mask =
+                       crtc_state->sync_mode_slaves_mask;
 
-       /* Keep base drm_crtc_state intact, only clear our extended struct */
-       BUILD_BUG_ON(offsetof(struct intel_crtc_state, base));
-       memcpy(&crtc_state->base + 1, &saved_state->base + 1,
-              sizeof(*crtc_state) - sizeof(crtc_state->base));
-
+       memcpy(crtc_state, saved_state, sizeof(*crtc_state));
        kfree(saved_state);
+
+       intel_crtc_copy_uapi_to_hw_state(crtc_state);
+
        return 0;
 }
 
 static int
 intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
 {
-       struct drm_crtc *crtc = pipe_config->base.crtc;
-       struct drm_atomic_state *state = pipe_config->base.state;
+       struct drm_crtc *crtc = pipe_config->uapi.crtc;
+       struct drm_atomic_state *state = pipe_config->uapi.state;
        struct intel_encoder *encoder;
        struct drm_connector *connector;
        struct drm_connector_state *connector_state;
@@ -12279,10 +12712,6 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
        int i;
        bool retry = true;
 
-       ret = clear_intel_crtc_state(pipe_config);
-       if (ret)
-               return ret;
-
        pipe_config->cpu_transcoder =
                (enum transcoder) to_intel_crtc(crtc)->pipe;
 
@@ -12291,13 +12720,13 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
         * positive or negative polarity is requested, treat this as meaning
         * negative polarity.
         */
-       if (!(pipe_config->base.adjusted_mode.flags &
+       if (!(pipe_config->hw.adjusted_mode.flags &
              (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC)))
-               pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC;
+               pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NHSYNC;
 
-       if (!(pipe_config->base.adjusted_mode.flags &
+       if (!(pipe_config->hw.adjusted_mode.flags &
              (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)))
-               pipe_config->base.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC;
+               pipe_config->hw.adjusted_mode.flags |= DRM_MODE_FLAG_NVSYNC;
 
        ret = compute_baseline_pipe_bpp(to_intel_crtc(crtc),
                                        pipe_config);
@@ -12314,7 +12743,7 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
         * computation to clearly distinguish it from the adjusted mode, which
         * can be changed by the connectors in the below retry loop.
         */
-       drm_mode_get_hv_timing(&pipe_config->base.mode,
+       drm_mode_get_hv_timing(&pipe_config->hw.mode,
                               &pipe_config->pipe_src_w,
                               &pipe_config->pipe_src_h);
 
@@ -12347,9 +12776,18 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
        pipe_config->pixel_multiplier = 1;
 
        /* Fill in default crtc timings, allow encoders to overwrite them. */
-       drm_mode_set_crtcinfo(&pipe_config->base.adjusted_mode,
+       drm_mode_set_crtcinfo(&pipe_config->hw.adjusted_mode,
                              CRTC_STEREO_DOUBLE);
 
+       /* Set the crtc_state defaults for trans_port_sync */
+       pipe_config->master_transcoder = INVALID_TRANSCODER;
+       ret = icl_add_sync_mode_crtcs(pipe_config);
+       if (ret) {
+               DRM_DEBUG_KMS("Cannot assign Sync Mode CRTCs: %d\n",
+                             ret);
+               return ret;
+       }
+
        /* Pass our mode to the connectors and the CRTC to give them a chance to
         * adjust it according to limitations or connector properties, and also
         * a chance to reject the mode entirely.
@@ -12372,7 +12810,7 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
        /* Set default port clock if not overwritten by the encoder. Needs to be
         * done afterwards in case the encoder adjusts the mode. */
        if (!pipe_config->port_clock)
-               pipe_config->port_clock = pipe_config->base.adjusted_mode.crtc_clock
+               pipe_config->port_clock = pipe_config->hw.adjusted_mode.crtc_clock
                        * pipe_config->pixel_multiplier;
 
        ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config);
@@ -12401,6 +12839,12 @@ intel_modeset_pipe_config(struct intel_crtc_state *pipe_config)
        DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n",
                      base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
 
+       /*
+        * Make drm_calc_timestamping_constants in
+        * drm_atomic_helper_update_legacy_modeset_state() happy
+        */
+       pipe_config->uapi.adjusted_mode = pipe_config->hw.adjusted_mode;
+
        return 0;
 }
 
@@ -12482,22 +12926,23 @@ pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv,
                if ((drm_debug & DRM_UT_KMS) == 0)
                        return;
 
-               drm_dbg(DRM_UT_KMS, "fastset mismatch in %s infoframe", name);
-               drm_dbg(DRM_UT_KMS, "expected:");
+               DRM_DEBUG_KMS("fastset mismatch in %s infoframe\n", name);
+               DRM_DEBUG_KMS("expected:\n");
                hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, a);
-               drm_dbg(DRM_UT_KMS, "found");
+               DRM_DEBUG_KMS("found:\n");
                hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, b);
        } else {
-               drm_err("mismatch in %s infoframe", name);
-               drm_err("expected:");
+               DRM_ERROR("mismatch in %s infoframe\n", name);
+               DRM_ERROR("expected:\n");
                hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, a);
-               drm_err("found");
+               DRM_ERROR("found:\n");
                hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, b);
        }
 }
 
-static void __printf(3, 4)
-pipe_config_mismatch(bool fastset, const char *name, const char *format, ...)
+static void __printf(4, 5)
+pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc,
+                    const char *name, const char *format, ...)
 {
        struct va_format vaf;
        va_list args;
@@ -12507,9 +12952,11 @@ pipe_config_mismatch(bool fastset, const char *name, const char *format, ...)
        vaf.va = &args;
 
        if (fastset)
-               drm_dbg(DRM_UT_KMS, "fastset mismatch in %s %pV", name, &vaf);
+               DRM_DEBUG_KMS("[CRTC:%d:%s] fastset mismatch in %s %pV\n",
+                             crtc->base.base.id, crtc->base.name, name, &vaf);
        else
-               drm_err("mismatch in %s %pV", name, &vaf);
+               DRM_ERROR("[CRTC:%d:%s] mismatch in %s %pV\n",
+                         crtc->base.base.id, crtc->base.name, name, &vaf);
 
        va_end(args);
 }
@@ -12536,11 +12983,13 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
                          const struct intel_crtc_state *pipe_config,
                          bool fastset)
 {
-       struct drm_i915_private *dev_priv = to_i915(current_config->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev);
+       struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
        bool ret = true;
+       u32 bp_gamma = 0;
        bool fixup_inherited = fastset &&
-               (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) &&
-               !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED);
+               (current_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED) &&
+               !(pipe_config->hw.mode.private_flags & I915_MODE_FLAG_INHERITED);
 
        if (fixup_inherited && !fastboot_enabled(dev_priv)) {
                DRM_DEBUG_KMS("initial modeset and fastboot not set\n");
@@ -12549,8 +12998,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
 #define PIPE_CONF_CHECK_X(name) do { \
        if (current_config->name != pipe_config->name) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
-                                    "(expected 0x%08x, found 0x%08x)\n", \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
+                                    "(expected 0x%08x, found 0x%08x)", \
                                     current_config->name, \
                                     pipe_config->name); \
                ret = false; \
@@ -12559,8 +13008,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
 #define PIPE_CONF_CHECK_I(name) do { \
        if (current_config->name != pipe_config->name) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
-                                    "(expected %i, found %i)\n", \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
+                                    "(expected %i, found %i)", \
                                     current_config->name, \
                                     pipe_config->name); \
                ret = false; \
@@ -12569,8 +13018,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
 #define PIPE_CONF_CHECK_BOOL(name) do { \
        if (current_config->name != pipe_config->name) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
-                                    "(expected %s, found %s)\n", \
+               pipe_config_mismatch(fastset, crtc,  __stringify(name), \
+                                    "(expected %s, found %s)", \
                                     yesno(current_config->name), \
                                     yesno(pipe_config->name)); \
                ret = false; \
@@ -12586,8 +13035,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        if (!fixup_inherited || (!current_config->name && !pipe_config->name)) { \
                PIPE_CONF_CHECK_BOOL(name); \
        } else { \
-               pipe_config_mismatch(fastset, __stringify(name), \
-                                    "unable to verify whether state matches exactly, forcing modeset (expected %s, found %s)\n", \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
+                                    "unable to verify whether state matches exactly, forcing modeset (expected %s, found %s)", \
                                     yesno(current_config->name), \
                                     yesno(pipe_config->name)); \
                ret = false; \
@@ -12596,8 +13045,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
 #define PIPE_CONF_CHECK_P(name) do { \
        if (current_config->name != pipe_config->name) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
-                                    "(expected %p, found %p)\n", \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
+                                    "(expected %p, found %p)", \
                                     current_config->name, \
                                     pipe_config->name); \
                ret = false; \
@@ -12608,9 +13057,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        if (!intel_compare_link_m_n(&current_config->name, \
                                    &pipe_config->name,\
                                    !fastset)) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
                                     "(expected tu %i gmch %i/%i link %i/%i, " \
-                                    "found tu %i, gmch %i/%i link %i/%i)\n", \
+                                    "found tu %i, gmch %i/%i link %i/%i)", \
                                     current_config->name.tu, \
                                     current_config->name.gmch_m, \
                                     current_config->name.gmch_n, \
@@ -12635,10 +13084,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
                                    &pipe_config->name, !fastset) && \
            !intel_compare_link_m_n(&current_config->alt_name, \
                                    &pipe_config->name, !fastset)) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
                                     "(expected tu %i gmch %i/%i link %i/%i, " \
                                     "or tu %i gmch %i/%i link %i/%i, " \
-                                    "found tu %i, gmch %i/%i link %i/%i)\n", \
+                                    "found tu %i, gmch %i/%i link %i/%i)", \
                                     current_config->name.tu, \
                                     current_config->name.gmch_m, \
                                     current_config->name.gmch_n, \
@@ -12660,8 +13109,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
 #define PIPE_CONF_CHECK_FLAGS(name, mask) do { \
        if ((current_config->name ^ pipe_config->name) & (mask)) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
-                                    "(%x) (expected %i, found %i)\n", \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
+                                    "(%x) (expected %i, found %i)", \
                                     (mask), \
                                     current_config->name & (mask), \
                                     pipe_config->name & (mask)); \
@@ -12671,8 +13120,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
 #define PIPE_CONF_CHECK_CLOCK_FUZZY(name) do { \
        if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) { \
-               pipe_config_mismatch(fastset, __stringify(name), \
-                                    "(expected %i, found %i)\n", \
+               pipe_config_mismatch(fastset, crtc, __stringify(name), \
+                                    "(expected %i, found %i)", \
                                     current_config->name, \
                                     pipe_config->name); \
                ret = false; \
@@ -12689,6 +13138,24 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        } \
 } while (0)
 
+#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \
+       if (current_config->name1 != pipe_config->name1) { \
+               pipe_config_mismatch(fastset, crtc, __stringify(name1), \
+                               "(expected %i, found %i, won't compare lut values)", \
+                               current_config->name1, \
+                               pipe_config->name1); \
+               ret = false;\
+       } else { \
+               if (!intel_color_lut_equal(current_config->name2, \
+                                       pipe_config->name2, pipe_config->name1, \
+                                       bit_precision)) { \
+                       pipe_config_mismatch(fastset, crtc, __stringify(name2), \
+                                       "hw_state doesn't match sw_state"); \
+                       ret = false; \
+               } \
+       } \
+} while (0)
+
 #define PIPE_CONF_QUIRK(quirk) \
        ((current_config->quirks | pipe_config->quirks) & (quirk))
 
@@ -12711,22 +13178,23 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
        PIPE_CONF_CHECK_X(output_types);
 
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_end);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_start);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hsync_end);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hdisplay);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_htotal);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_start);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hblank_end);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_start);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_hsync_end);
 
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vdisplay);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vtotal);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_start);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vblank_end);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_start);
-       PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vdisplay);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vtotal);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_start);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vblank_end);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_start);
+       PIPE_CONF_CHECK_I(hw.adjusted_mode.crtc_vsync_end);
 
        PIPE_CONF_CHECK_I(pixel_multiplier);
        PIPE_CONF_CHECK_I(output_format);
+       PIPE_CONF_CHECK_I(dc3co_exitline);
        PIPE_CONF_CHECK_BOOL(has_hdmi_sink);
        if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) ||
            IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
@@ -12735,20 +13203,21 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        PIPE_CONF_CHECK_BOOL(hdmi_scrambling);
        PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio);
        PIPE_CONF_CHECK_BOOL(has_infoframe);
+       PIPE_CONF_CHECK_BOOL(fec_enable);
 
        PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio);
 
-       PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
+       PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
                              DRM_MODE_FLAG_INTERLACE);
 
        if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS)) {
-               PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
+               PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
                                      DRM_MODE_FLAG_PHSYNC);
-               PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
+               PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
                                      DRM_MODE_FLAG_NHSYNC);
-               PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
+               PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
                                      DRM_MODE_FLAG_PVSYNC);
-               PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
+               PIPE_CONF_CHECK_FLAGS(hw.adjusted_mode.flags,
                                      DRM_MODE_FLAG_NVSYNC);
        }
 
@@ -12784,6 +13253,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
                        PIPE_CONF_CHECK_X(csc_mode);
                PIPE_CONF_CHECK_BOOL(gamma_enable);
                PIPE_CONF_CHECK_BOOL(csc_enable);
+
+               bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);
+               if (bp_gamma)
+                       PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, hw.gamma_lut, bp_gamma);
+
        }
 
        PIPE_CONF_CHECK_BOOL(double_wide);
@@ -12827,7 +13301,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5)
                PIPE_CONF_CHECK_I(pipe_bpp);
 
-       PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock);
+       PIPE_CONF_CHECK_CLOCK_FUZZY(hw.adjusted_mode.crtc_clock);
        PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
 
        PIPE_CONF_CHECK_I(min_voltage_level);
@@ -12839,6 +13313,9 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
        PIPE_CONF_CHECK_INFOFRAME(hdmi);
        PIPE_CONF_CHECK_INFOFRAME(drm);
 
+       PIPE_CONF_CHECK_I(sync_mode_slaves_mask);
+       PIPE_CONF_CHECK_I(master_transcoder);
+
 #undef PIPE_CONF_CHECK_X
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_BOOL
@@ -12846,6 +13323,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 #undef PIPE_CONF_CHECK_P
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_CHECK_CLOCK_FUZZY
+#undef PIPE_CONF_CHECK_COLOR_LUT
 #undef PIPE_CONF_QUIRK
 
        return ret;
@@ -12857,7 +13335,7 @@ static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv,
        if (pipe_config->has_pch_encoder) {
                int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),
                                                            &pipe_config->fdi_m_n);
-               int dotclock = pipe_config->base.adjusted_mode.crtc_clock;
+               int dotclock = pipe_config->hw.adjusted_mode.crtc_clock;
 
                /*
                 * FDI already provided one idea for the dotclock.
@@ -12885,7 +13363,7 @@ static void verify_wm_state(struct intel_crtc *crtc,
        const enum pipe pipe = crtc->pipe;
        int plane, level, max_level = ilk_wm_max_level(dev_priv);
 
-       if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->base.active)
+       if (INTEL_GEN(dev_priv) < 9 || !new_crtc_state->hw.active)
                return;
 
        hw = kzalloc(sizeof(*hw), GFP_KERNEL);
@@ -13094,12 +13572,14 @@ verify_crtc_state(struct intel_crtc *crtc,
        struct drm_atomic_state *state;
        bool active;
 
-       state = old_crtc_state->base.state;
-       __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->base);
+       state = old_crtc_state->uapi.state;
+       __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi);
+       intel_crtc_free_hw_state(old_crtc_state);
+
        pipe_config = old_crtc_state;
        memset(pipe_config, 0, sizeof(*pipe_config));
-       pipe_config->base.crtc = &crtc->base;
-       pipe_config->base.state = state;
+       pipe_config->uapi.crtc = &crtc->base;
+       pipe_config->uapi.state = state;
 
        DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.base.id, crtc->base.name);
 
@@ -13107,23 +13587,26 @@ verify_crtc_state(struct intel_crtc *crtc,
 
        /* we keep both pipes enabled on 830 */
        if (IS_I830(dev_priv))
-               active = new_crtc_state->base.active;
+               active = new_crtc_state->hw.active;
 
-       I915_STATE_WARN(new_crtc_state->base.active != active,
-            "crtc active state doesn't match with hw state "
-            "(expected %i, found %i)\n", new_crtc_state->base.active, active);
+       I915_STATE_WARN(new_crtc_state->hw.active != active,
+                       "crtc active state doesn't match with hw state "
+                       "(expected %i, found %i)\n",
+                       new_crtc_state->hw.active, active);
 
-       I915_STATE_WARN(crtc->active != new_crtc_state->base.active,
-            "transitional active state does not match atomic hw state "
-            "(expected %i, found %i)\n", new_crtc_state->base.active, crtc->active);
+       I915_STATE_WARN(crtc->active != new_crtc_state->hw.active,
+                       "transitional active state does not match atomic hw state "
+                       "(expected %i, found %i)\n",
+                       new_crtc_state->hw.active, crtc->active);
 
        for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
                enum pipe pipe;
 
                active = encoder->get_hw_state(encoder, &pipe);
-               I915_STATE_WARN(active != new_crtc_state->base.active,
-                       "[ENCODER:%i] active %i with crtc active %i\n",
-                       encoder->base.base.id, active, new_crtc_state->base.active);
+               I915_STATE_WARN(active != new_crtc_state->hw.active,
+                               "[ENCODER:%i] active %i with crtc active %i\n",
+                               encoder->base.base.id, active,
+                               new_crtc_state->hw.active);
 
                I915_STATE_WARN(active && crtc->pipe != pipe,
                                "Encoder connected to wrong pipe %c\n",
@@ -13135,7 +13618,7 @@ verify_crtc_state(struct intel_crtc *crtc,
 
        intel_crtc_compute_pixel_rate(pipe_config);
 
-       if (!new_crtc_state->base.active)
+       if (!new_crtc_state->hw.active)
                return;
 
        intel_pipe_config_sanity_check(dev_priv, pipe_config);
@@ -13157,8 +13640,8 @@ intel_verify_planes(struct intel_atomic_state *state)
 
        for_each_new_intel_plane_in_state(state, plane,
                                          plane_state, i)
-               assert_plane(plane, plane_state->slave ||
-                            plane_state->base.visible);
+               assert_plane(plane, plane_state->planar_slave ||
+                            plane_state->uapi.visible);
 }
 
 static void
@@ -13197,7 +13680,7 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
 
        crtc_mask = drm_crtc_mask(&crtc->base);
 
-       if (new_crtc_state->base.active)
+       if (new_crtc_state->hw.active)
                I915_STATE_WARN(!(pll->active_mask & crtc_mask),
                                "pll active mismatch (expected pipe %c in active mask 0x%02x)\n",
                                pipe_name(drm_crtc_index(&crtc->base)), pll->active_mask);
@@ -13273,10 +13756,15 @@ intel_modeset_verify_disabled(struct drm_i915_private *dev_priv,
        verify_disabled_dpll_state(dev_priv);
 }
 
-static void update_scanline_offset(const struct intel_crtc_state *crtc_state)
+static void
+intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       const struct drm_display_mode *adjusted_mode =
+               &crtc_state->hw.adjusted_mode;
+
+       drm_calc_timestamping_constants(&crtc->base, adjusted_mode);
 
        /*
         * The scanline counter increments at the leading edge of hsync.
@@ -13306,7 +13794,6 @@ static void update_scanline_offset(const struct intel_crtc_state *crtc_state)
         * answer that's slightly in the future.
         */
        if (IS_GEN(dev_priv, 2)) {
-               const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
                int vtotal;
 
                vtotal = adjusted_mode->crtc_vtotal;
@@ -13317,8 +13804,9 @@ static void update_scanline_offset(const struct intel_crtc_state *crtc_state)
        } else if (HAS_DDI(dev_priv) &&
                   intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
                crtc->scanline_offset = 2;
-       } else
+       } else {
                crtc->scanline_offset = 1;
+       }
 }
 
 static void intel_modeset_clear_plls(struct intel_atomic_state *state)
@@ -13356,7 +13844,7 @@ static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state)
 
        /* look at all crtc's that are going to be enabled in during modeset */
        for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-               if (!crtc_state->base.active ||
+               if (!crtc_state->hw.active ||
                    !needs_modeset(crtc_state))
                        continue;
 
@@ -13381,7 +13869,7 @@ static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state)
 
                crtc_state->hsw_workaround_pipe = INVALID_PIPE;
 
-               if (!crtc_state->base.active ||
+               if (!crtc_state->hw.active ||
                    needs_modeset(crtc_state))
                        continue;
 
@@ -13400,158 +13888,43 @@ static int haswell_mode_set_planes_workaround(struct intel_atomic_state *state)
        return 0;
 }
 
-static int intel_lock_all_pipes(struct intel_atomic_state *state)
-{
-       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       struct intel_crtc *crtc;
-
-       /* Add all pipes to the state */
-       for_each_intel_crtc(&dev_priv->drm, crtc) {
-               struct intel_crtc_state *crtc_state;
-
-               crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
-               if (IS_ERR(crtc_state))
-                       return PTR_ERR(crtc_state);
-       }
-
-       return 0;
-}
-
-static int intel_modeset_all_pipes(struct intel_atomic_state *state)
-{
-       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       struct intel_crtc *crtc;
-
-       /*
-        * Add all pipes to the state, and force
-        * a modeset on all the active ones.
-        */
-       for_each_intel_crtc(&dev_priv->drm, crtc) {
-               struct intel_crtc_state *crtc_state;
-               int ret;
-
-               crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
-               if (IS_ERR(crtc_state))
-                       return PTR_ERR(crtc_state);
-
-               if (!crtc_state->base.active || needs_modeset(crtc_state))
-                       continue;
-
-               crtc_state->base.mode_changed = true;
-
-               ret = drm_atomic_add_affected_connectors(&state->base,
-                                                        &crtc->base);
-               if (ret)
-                       return ret;
-
-               ret = drm_atomic_add_affected_planes(&state->base,
-                                                    &crtc->base);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
 static int intel_modeset_checks(struct intel_atomic_state *state)
 {
        struct drm_i915_private *dev_priv = to_i915(state->base.dev);
        struct intel_crtc_state *old_crtc_state, *new_crtc_state;
        struct intel_crtc *crtc;
-       int ret = 0, i;
-
-       if (!check_digital_port_conflicts(state)) {
-               DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
-               return -EINVAL;
-       }
+       int ret, i;
 
        /* keep the current setting */
        if (!state->cdclk.force_min_cdclk_changed)
                state->cdclk.force_min_cdclk = dev_priv->cdclk.force_min_cdclk;
 
        state->modeset = true;
-       state->active_crtcs = dev_priv->active_crtcs;
+       state->active_pipes = dev_priv->active_pipes;
        state->cdclk.logical = dev_priv->cdclk.logical;
        state->cdclk.actual = dev_priv->cdclk.actual;
-       state->cdclk.pipe = INVALID_PIPE;
 
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
                                            new_crtc_state, i) {
-               if (new_crtc_state->base.active)
-                       state->active_crtcs |= 1 << i;
+               if (new_crtc_state->hw.active)
+                       state->active_pipes |= BIT(crtc->pipe);
                else
-                       state->active_crtcs &= ~(1 << i);
+                       state->active_pipes &= ~BIT(crtc->pipe);
 
-               if (old_crtc_state->base.active != new_crtc_state->base.active)
-                       state->active_pipe_changes |= drm_crtc_mask(&crtc->base);
+               if (old_crtc_state->hw.active != new_crtc_state->hw.active)
+                       state->active_pipe_changes |= BIT(crtc->pipe);
        }
 
-       /*
-        * See if the config requires any additional preparation, e.g.
-        * to adjust global state with pipes off.  We need to do this
-        * here so we can get the modeset_pipe updated config for the new
-        * mode set on this crtc.  For other crtcs we need to use the
-        * adjusted_mode bits in the crtc directly.
-        */
-       if (dev_priv->display.modeset_calc_cdclk) {
-               enum pipe pipe;
-
-               ret = dev_priv->display.modeset_calc_cdclk(state);
-               if (ret < 0)
+       if (state->active_pipe_changes) {
+               ret = intel_atomic_lock_global_state(state);
+               if (ret)
                        return ret;
-
-               /*
-                * Writes to dev_priv->cdclk.logical must protected by
-                * holding all the crtc locks, even if we don't end up
-                * touching the hardware
-                */
-               if (intel_cdclk_changed(&dev_priv->cdclk.logical,
-                                       &state->cdclk.logical)) {
-                       ret = intel_lock_all_pipes(state);
-                       if (ret < 0)
-                               return ret;
-               }
-
-               if (is_power_of_2(state->active_crtcs)) {
-                       struct intel_crtc *crtc;
-                       struct intel_crtc_state *crtc_state;
-
-                       pipe = ilog2(state->active_crtcs);
-                       crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
-                       crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
-                       if (crtc_state && needs_modeset(crtc_state))
-                               pipe = INVALID_PIPE;
-               } else {
-                       pipe = INVALID_PIPE;
-               }
-
-               /* All pipes must be switched off while we change the cdclk. */
-               if (pipe != INVALID_PIPE &&
-                   intel_cdclk_needs_cd2x_update(dev_priv,
-                                                 &dev_priv->cdclk.actual,
-                                                 &state->cdclk.actual)) {
-                       ret = intel_lock_all_pipes(state);
-                       if (ret < 0)
-                               return ret;
-
-                       state->cdclk.pipe = pipe;
-               } else if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual,
-                                                    &state->cdclk.actual)) {
-                       ret = intel_modeset_all_pipes(state);
-                       if (ret < 0)
-                               return ret;
-
-                       state->cdclk.pipe = INVALID_PIPE;
-               }
-
-               DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n",
-                             state->cdclk.logical.cdclk,
-                             state->cdclk.actual.cdclk);
-               DRM_DEBUG_KMS("New voltage level calculated to be logical %u, actual %u\n",
-                             state->cdclk.logical.voltage_level,
-                             state->cdclk.actual.voltage_level);
        }
 
+       ret = intel_modeset_calc_cdclk(state);
+       if (ret)
+               return ret;
+
        intel_modeset_clear_plls(state);
 
        if (IS_HASWELL(dev_priv))
@@ -13583,7 +13956,7 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta
        if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true))
                return;
 
-       new_crtc_state->base.mode_changed = false;
+       new_crtc_state->uapi.mode_changed = false;
        new_crtc_state->update_pipe = true;
 
        /*
@@ -13600,6 +13973,114 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta
        new_crtc_state->has_drrs = old_crtc_state->has_drrs;
 }
 
+static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state,
+                                         struct intel_crtc *crtc,
+                                         u8 plane_ids_mask)
+{
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_plane *plane;
+
+       for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
+               struct intel_plane_state *plane_state;
+
+               if ((plane_ids_mask & BIT(plane->id)) == 0)
+                       continue;
+
+               plane_state = intel_atomic_get_plane_state(state, plane);
+               if (IS_ERR(plane_state))
+                       return PTR_ERR(plane_state);
+       }
+
+       return 0;
+}
+
+static bool active_planes_affects_min_cdclk(struct drm_i915_private *dev_priv)
+{
+       /* See {hsw,vlv,ivb}_plane_ratio() */
+       return IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv) ||
+               IS_CHERRYVIEW(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+               IS_IVYBRIDGE(dev_priv);
+}
+
+static int intel_atomic_check_planes(struct intel_atomic_state *state,
+                                    bool *need_modeset)
+{
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_crtc_state *old_crtc_state, *new_crtc_state;
+       struct intel_plane_state *plane_state;
+       struct intel_plane *plane;
+       struct intel_crtc *crtc;
+       int i, ret;
+
+       ret = icl_add_linked_planes(state);
+       if (ret)
+               return ret;
+
+       for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
+               ret = intel_plane_atomic_check(state, plane);
+               if (ret) {
+                       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic driver check failed\n",
+                                        plane->base.base.id, plane->base.name);
+                       return ret;
+               }
+       }
+
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+                                           new_crtc_state, i) {
+               u8 old_active_planes, new_active_planes;
+
+               ret = icl_check_nv12_planes(new_crtc_state);
+               if (ret)
+                       return ret;
+
+               /*
+                * On some platforms the number of active planes affects
+                * the planes' minimum cdclk calculation. Add such planes
+                * to the state before we compute the minimum cdclk.
+                */
+               if (!active_planes_affects_min_cdclk(dev_priv))
+                       continue;
+
+               old_active_planes = old_crtc_state->active_planes & ~BIT(PLANE_CURSOR);
+               new_active_planes = new_crtc_state->active_planes & ~BIT(PLANE_CURSOR);
+
+               if (hweight8(old_active_planes) == hweight8(new_active_planes))
+                       continue;
+
+               ret = intel_crtc_add_planes_to_state(state, crtc, new_active_planes);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * active_planes bitmask has been updated, and potentially
+        * affected planes are part of the state. We can now
+        * compute the minimum cdclk for each plane.
+        */
+       for_each_new_intel_plane_in_state(state, plane, plane_state, i)
+               *need_modeset |= intel_plane_calc_min_cdclk(state, plane);
+
+       return 0;
+}
+
+static int intel_atomic_check_crtcs(struct intel_atomic_state *state)
+{
+       struct intel_crtc_state *crtc_state;
+       struct intel_crtc *crtc;
+       int i;
+
+       for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
+               int ret = intel_crtc_atomic_check(state, crtc);
+               if (ret) {
+                       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic driver check failed\n",
+                                        crtc->base.base.id, crtc->base.name);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -13613,14 +14094,14 @@ static int intel_atomic_check(struct drm_device *dev,
        struct intel_crtc_state *old_crtc_state, *new_crtc_state;
        struct intel_crtc *crtc;
        int ret, i;
-       bool any_ms = state->cdclk.force_min_cdclk_changed;
+       bool any_ms = false;
 
        /* Catch I915_MODE_FLAG_INHERITED */
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
                                            new_crtc_state, i) {
-               if (new_crtc_state->base.mode.private_flags !=
-                   old_crtc_state->base.mode.private_flags)
-                       new_crtc_state->base.mode_changed = true;
+               if (new_crtc_state->hw.mode.private_flags !=
+                   old_crtc_state->hw.mode.private_flags)
+                       new_crtc_state->uapi.mode_changed = true;
        }
 
        ret = drm_atomic_helper_check_modeset(dev, &state->base);
@@ -13629,15 +14110,25 @@ static int intel_atomic_check(struct drm_device *dev,
 
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
                                            new_crtc_state, i) {
-               if (!needs_modeset(new_crtc_state))
+               if (!needs_modeset(new_crtc_state)) {
+                       /* Light copy */
+                       intel_crtc_copy_uapi_to_hw_state_nomodeset(new_crtc_state);
+
                        continue;
+               }
+
+               if (!new_crtc_state->uapi.enable) {
+                       intel_crtc_copy_uapi_to_hw_state(new_crtc_state);
 
-               if (!new_crtc_state->base.enable) {
                        any_ms = true;
                        continue;
                }
 
-               ret = intel_modeset_pipe_config(new_crtc_state);
+               ret = intel_crtc_prepare_cleared_state(new_crtc_state);
+               if (ret)
+                       goto fail;
+
+               ret = intel_modeset_pipe_config(new_crtc_state);
                if (ret)
                        goto fail;
 
@@ -13647,10 +14138,22 @@ static int intel_atomic_check(struct drm_device *dev,
                        any_ms = true;
        }
 
+       if (any_ms && !check_digital_port_conflicts(state)) {
+               DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
+               ret = EINVAL;
+               goto fail;
+       }
+
        ret = drm_dp_mst_atomic_check(&state->base);
        if (ret)
                goto fail;
 
+       any_ms |= state->cdclk.force_min_cdclk_changed;
+
+       ret = intel_atomic_check_planes(state, &any_ms);
+       if (ret)
+               goto fail;
+
        if (any_ms) {
                ret = intel_modeset_checks(state);
                if (ret)
@@ -13659,11 +14162,7 @@ static int intel_atomic_check(struct drm_device *dev,
                state->cdclk.logical = dev_priv->cdclk.logical;
        }
 
-       ret = icl_add_linked_planes(state);
-       if (ret)
-               goto fail;
-
-       ret = drm_atomic_helper_check_planes(dev, &state->base);
+       ret = intel_atomic_check_crtcs(state);
        if (ret)
                goto fail;
 
@@ -13721,29 +14220,114 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
        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)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+       if (!IS_GEN(dev_priv, 2) || crtc_state->active_planes)
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
+
+       if (crtc_state->has_pch_encoder) {
+               enum pipe pch_transcoder =
+                       intel_crtc_pch_transcoder(crtc);
+
+               intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true);
+       }
+}
+
+static void intel_pipe_fastset(const struct intel_crtc_state *old_crtc_state,
+                              const struct intel_crtc_state *new_crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+       /*
+        * Update pipe size and adjust fitter if needed: the reason for this is
+        * that in compute_mode_changes we check the native mode (not the pfit
+        * mode) to see if we can flip rather than do a full mode set. In the
+        * fastboot case, we'll flip, but if we don't update the pipesrc and
+        * pfit state, we'll end up with a big fb scanned out into the wrong
+        * sized surface.
+        */
+       intel_set_pipe_src_size(new_crtc_state);
+
+       /* on skylake this is done by detaching scalers */
+       if (INTEL_GEN(dev_priv) >= 9) {
+               skl_detach_scalers(new_crtc_state);
+
+               if (new_crtc_state->pch_pfit.enabled)
+                       skylake_pfit_enable(new_crtc_state);
+       } else if (HAS_PCH_SPLIT(dev_priv)) {
+               if (new_crtc_state->pch_pfit.enabled)
+                       ironlake_pfit_enable(new_crtc_state);
+               else if (old_crtc_state->pch_pfit.enabled)
+                       ironlake_pfit_disable(old_crtc_state);
+       }
+
+       if (INTEL_GEN(dev_priv) >= 11)
+               icl_set_pipe_chicken(crtc);
+}
+
+static void commit_pipe_config(struct intel_atomic_state *state,
+                              struct intel_crtc_state *old_crtc_state,
+                              struct intel_crtc_state *new_crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       bool modeset = needs_modeset(new_crtc_state);
+
+       /*
+        * During modesets pipe configuration was programmed as the
+        * CRTC was enabled.
+        */
+       if (!modeset) {
+               if (new_crtc_state->uapi.color_mgmt_changed ||
+                   new_crtc_state->update_pipe)
+                       intel_color_commit(new_crtc_state);
+
+               if (INTEL_GEN(dev_priv) >= 9)
+                       skl_detach_scalers(new_crtc_state);
+
+               if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
+                       bdw_set_pipemisc(new_crtc_state);
+
+               if (new_crtc_state->update_pipe)
+                       intel_pipe_fastset(old_crtc_state, new_crtc_state);
+       }
+
+       if (dev_priv->display.atomic_update_watermarks)
+               dev_priv->display.atomic_update_watermarks(state, crtc);
+}
+
 static void intel_update_crtc(struct intel_crtc *crtc,
                              struct intel_atomic_state *state,
                              struct intel_crtc_state *old_crtc_state,
                              struct intel_crtc_state *new_crtc_state)
 {
-       struct drm_device *dev = state->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
        bool modeset = needs_modeset(new_crtc_state);
        struct intel_plane_state *new_plane_state =
                intel_atomic_get_new_plane_state(state,
                                                 to_intel_plane(crtc->base.primary));
 
        if (modeset) {
-               update_scanline_offset(new_crtc_state);
-               dev_priv->display.crtc_enable(new_crtc_state, state);
+               intel_crtc_update_active_timings(new_crtc_state);
+
+               dev_priv->display.crtc_enable(state, crtc);
 
                /* vblanks work again, re-enable pipe CRC. */
                intel_crtc_enable_pipe_crc(crtc);
        } else {
-               intel_pre_plane_update(old_crtc_state, new_crtc_state);
+               if (new_crtc_state->preload_luts &&
+                   (new_crtc_state->uapi.color_mgmt_changed ||
+                    new_crtc_state->update_pipe))
+                       intel_color_load_luts(new_crtc_state);
+
+               intel_pre_plane_update(state, crtc);
 
                if (new_crtc_state->update_pipe)
-                       intel_encoders_update_pipe(crtc, new_crtc_state, state);
+                       intel_encoders_update_pipe(state, crtc);
        }
 
        if (new_crtc_state->update_pipe && !new_crtc_state->enable_fbc)
@@ -13751,24 +14335,120 @@ static void intel_update_crtc(struct intel_crtc *crtc,
        else if (new_plane_state)
                intel_fbc_enable(crtc, new_crtc_state, new_plane_state);
 
-       intel_begin_crtc_commit(state, crtc);
+       /* Perform vblank evasion around commit operation */
+       intel_pipe_update_start(new_crtc_state);
+
+       commit_pipe_config(state, old_crtc_state, new_crtc_state);
 
        if (INTEL_GEN(dev_priv) >= 9)
                skl_update_planes_on_crtc(state, crtc);
        else
                i9xx_update_planes_on_crtc(state, crtc);
 
-       intel_finish_crtc_commit(state, crtc);
+       intel_pipe_update_end(new_crtc_state);
+
+       /*
+        * We usually enable FIFO underrun interrupts as part of the
+        * CRTC enable sequence during modesets.  But when we inherit a
+        * valid pipe configuration from the BIOS we need to take care
+        * of enabling them on the CRTC's first fastset.
+        */
+       if (new_crtc_state->update_pipe && !modeset &&
+           old_crtc_state->hw.mode.private_flags & I915_MODE_FLAG_INHERITED)
+               intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);
+}
+
+static struct intel_crtc *intel_get_slave_crtc(const struct intel_crtc_state *new_crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(new_crtc_state->uapi.crtc->dev);
+       enum transcoder slave_transcoder;
+
+       WARN_ON(!is_power_of_2(new_crtc_state->sync_mode_slaves_mask));
+
+       slave_transcoder = ffs(new_crtc_state->sync_mode_slaves_mask) - 1;
+       return intel_get_crtc_for_pipe(dev_priv,
+                                      (enum pipe)slave_transcoder);
+}
+
+static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
+                                         struct intel_crtc_state *old_crtc_state,
+                                         struct intel_crtc_state *new_crtc_state,
+                                         struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+
+       intel_crtc_disable_planes(state, crtc);
+
+       /*
+        * We need to disable pipe CRC before disabling the pipe,
+        * or we race against vblank off.
+        */
+       intel_crtc_disable_pipe_crc(crtc);
+
+       dev_priv->display.crtc_disable(state, crtc);
+       crtc->active = false;
+       intel_fbc_disable(crtc);
+       intel_disable_shared_dpll(old_crtc_state);
+
+       /* FIXME unify this for all platforms */
+       if (!new_crtc_state->hw.active &&
+           !HAS_GMCH(dev_priv) &&
+           dev_priv->display.initial_watermarks)
+               dev_priv->display.initial_watermarks(state, crtc);
+}
+
+static void intel_commit_modeset_disables(struct intel_atomic_state *state)
+{
+       struct intel_crtc_state *new_crtc_state, *old_crtc_state;
+       struct intel_crtc *crtc;
+       u32 handled = 0;
+       int i;
+
+       /* Only disable port sync slaves */
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+                                           new_crtc_state, i) {
+               if (!needs_modeset(new_crtc_state))
+                       continue;
+
+               if (!old_crtc_state->hw.active)
+                       continue;
+
+               /* In case of Transcoder port Sync master slave CRTCs can be
+                * assigned in any order and we need to make sure that
+                * slave CRTCs are disabled first and then master CRTC since
+                * Slave vblanks are masked till Master Vblanks.
+                */
+               if (!is_trans_port_sync_slave(old_crtc_state))
+                       continue;
+
+               intel_pre_plane_update(state, crtc);
+               intel_old_crtc_state_disables(state, old_crtc_state,
+                                             new_crtc_state, crtc);
+               handled |= BIT(crtc->pipe);
+       }
+
+       /* Disable everything else left on */
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+                                           new_crtc_state, i) {
+               if (!needs_modeset(new_crtc_state) ||
+                   (handled & BIT(crtc->pipe)))
+                       continue;
+
+               intel_pre_plane_update(state, crtc);
+               if (old_crtc_state->hw.active)
+                       intel_old_crtc_state_disables(state, old_crtc_state,
+                                                     new_crtc_state, crtc);
+       }
 }
 
-static void intel_update_crtcs(struct intel_atomic_state *state)
+static void intel_commit_modeset_enables(struct intel_atomic_state *state)
 {
        struct intel_crtc *crtc;
        struct intel_crtc_state *old_crtc_state, *new_crtc_state;
        int i;
 
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
-               if (!new_crtc_state->base.active)
+               if (!new_crtc_state->hw.active)
                        continue;
 
                intel_update_crtc(crtc, state, old_crtc_state,
@@ -13776,14 +14456,120 @@ static void intel_update_crtcs(struct intel_atomic_state *state)
        }
 }
 
-static void skl_update_crtcs(struct intel_atomic_state *state)
+static void intel_crtc_enable_trans_port_sync(struct intel_crtc *crtc,
+                                             struct intel_atomic_state *state,
+                                             struct intel_crtc_state *new_crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+
+       intel_crtc_update_active_timings(new_crtc_state);
+       dev_priv->display.crtc_enable(state, crtc);
+       intel_crtc_enable_pipe_crc(crtc);
+}
+
+static void intel_set_dp_tp_ctl_normal(struct intel_crtc *crtc,
+                                      struct intel_atomic_state *state)
+{
+       struct drm_connector *uninitialized_var(conn);
+       struct drm_connector_state *conn_state;
+       struct intel_dp *intel_dp;
+       int i;
+
+       for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
+               if (conn_state->crtc == &crtc->base)
+                       break;
+       }
+       intel_dp = enc_to_intel_dp(&intel_attached_encoder(conn)->base);
+       intel_dp_stop_link_train(intel_dp);
+}
+
+static void intel_post_crtc_enable_updates(struct intel_crtc *crtc,
+                                          struct intel_atomic_state *state)
+{
+       struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       struct intel_plane_state *new_plane_state =
+               intel_atomic_get_new_plane_state(state,
+                                                to_intel_plane(crtc->base.primary));
+       bool modeset = needs_modeset(new_crtc_state);
+
+       if (new_crtc_state->update_pipe && !new_crtc_state->enable_fbc)
+               intel_fbc_disable(crtc);
+       else if (new_plane_state)
+               intel_fbc_enable(crtc, new_crtc_state, new_plane_state);
+
+       /* Perform vblank evasion around commit operation */
+       intel_pipe_update_start(new_crtc_state);
+       commit_pipe_config(state, old_crtc_state, new_crtc_state);
+       skl_update_planes_on_crtc(state, crtc);
+       intel_pipe_update_end(new_crtc_state);
+
+       /*
+        * We usually enable FIFO underrun interrupts as part of the
+        * CRTC enable sequence during modesets.  But when we inherit a
+        * valid pipe configuration from the BIOS we need to take care
+        * of enabling them on the CRTC's first fastset.
+        */
+       if (new_crtc_state->update_pipe && !modeset &&
+           old_crtc_state->hw.mode.private_flags & I915_MODE_FLAG_INHERITED)
+               intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);
+}
+
+static void intel_update_trans_port_sync_crtcs(struct intel_crtc *crtc,
+                                              struct intel_atomic_state *state,
+                                              struct intel_crtc_state *old_crtc_state,
+                                              struct intel_crtc_state *new_crtc_state)
+{
+       struct intel_crtc *slave_crtc = intel_get_slave_crtc(new_crtc_state);
+       struct intel_crtc_state *new_slave_crtc_state =
+               intel_atomic_get_new_crtc_state(state, slave_crtc);
+       struct intel_crtc_state *old_slave_crtc_state =
+               intel_atomic_get_old_crtc_state(state, slave_crtc);
+
+       WARN_ON(!slave_crtc || !new_slave_crtc_state ||
+               !old_slave_crtc_state);
+
+       DRM_DEBUG_KMS("Updating Transcoder Port Sync Master CRTC = %d %s and Slave CRTC %d %s\n",
+                     crtc->base.base.id, crtc->base.name, slave_crtc->base.base.id,
+                     slave_crtc->base.name);
+
+       /* Enable seq for slave with with DP_TP_CTL left Idle until the
+        * master is ready
+        */
+       intel_crtc_enable_trans_port_sync(slave_crtc,
+                                         state,
+                                         new_slave_crtc_state);
+
+       /* Enable seq for master with with DP_TP_CTL left Idle */
+       intel_crtc_enable_trans_port_sync(crtc,
+                                         state,
+                                         new_crtc_state);
+
+       /* Set Slave's DP_TP_CTL to Normal */
+       intel_set_dp_tp_ctl_normal(slave_crtc,
+                                  state);
+
+       /* Set Master's DP_TP_CTL To Normal */
+       usleep_range(200, 400);
+       intel_set_dp_tp_ctl_normal(crtc,
+                                  state);
+
+       /* Now do the post crtc enable for all master and slaves */
+       intel_post_crtc_enable_updates(slave_crtc,
+                                      state);
+       intel_post_crtc_enable_updates(crtc,
+                                      state);
+}
+
+static void skl_commit_modeset_enables(struct intel_atomic_state *state)
 {
        struct drm_i915_private *dev_priv = to_i915(state->base.dev);
        struct intel_crtc *crtc;
        struct intel_crtc_state *old_crtc_state, *new_crtc_state;
        unsigned int updated = 0;
        bool progress;
-       enum pipe pipe;
        int i;
        u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
        u8 required_slices = state->wm_results.ddb.enabled_slices;
@@ -13791,7 +14577,7 @@ static void skl_update_crtcs(struct intel_atomic_state *state)
 
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i)
                /* ignore allocations for crtc's that have been turned off. */
-               if (new_crtc_state->base.active)
+               if (!needs_modeset(new_crtc_state) && new_crtc_state->hw.active)
                        entries[i] = old_crtc_state->wm.skl.ddb;
 
        /* If 2nd DBuf slice required, enable it here */
@@ -13808,20 +14594,19 @@ static void skl_update_crtcs(struct intel_atomic_state *state)
                progress = false;
 
                for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+                       enum pipe pipe = crtc->pipe;
                        bool vbl_wait = false;
-                       unsigned int cmask = drm_crtc_mask(&crtc->base);
-
-                       pipe = crtc->pipe;
+                       bool modeset = needs_modeset(new_crtc_state);
 
-                       if (updated & cmask || !new_crtc_state->base.active)
+                       if (updated & BIT(crtc->pipe) || !new_crtc_state->hw.active)
                                continue;
 
                        if (skl_ddb_allocation_overlaps(&new_crtc_state->wm.skl.ddb,
                                                        entries,
-                                                       INTEL_INFO(dev_priv)->num_pipes, i))
+                                                       INTEL_NUM_PIPES(dev_priv), i))
                                continue;
 
-                       updated |= cmask;
+                       updated |= BIT(pipe);
                        entries[i] = new_crtc_state->wm.skl.ddb;
 
                        /*
@@ -13832,12 +14617,22 @@ static void skl_update_crtcs(struct intel_atomic_state *state)
                         */
                        if (!skl_ddb_entry_equal(&new_crtc_state->wm.skl.ddb,
                                                 &old_crtc_state->wm.skl.ddb) &&
-                           !new_crtc_state->base.active_changed &&
+                           !modeset &&
                            state->wm_results.dirty_pipes != updated)
                                vbl_wait = true;
 
-                       intel_update_crtc(crtc, state, old_crtc_state,
-                                         new_crtc_state);
+                       if (modeset && is_trans_port_sync_mode(new_crtc_state)) {
+                               if (is_trans_port_sync_master(new_crtc_state))
+                                       intel_update_trans_port_sync_crtcs(crtc,
+                                                                          state,
+                                                                          old_crtc_state,
+                                                                          new_crtc_state);
+                               else
+                                       continue;
+                       } else {
+                               intel_update_crtc(crtc, state, old_crtc_state,
+                                                 new_crtc_state);
+                       }
 
                        if (vbl_wait)
                                intel_wait_for_vblank(dev_priv, pipe);
@@ -13926,49 +14721,18 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
        if (state->modeset)
                wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
 
-       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+                                           new_crtc_state, i) {
                if (needs_modeset(new_crtc_state) ||
                    new_crtc_state->update_pipe) {
 
                        put_domains[crtc->pipe] =
                                modeset_get_crtc_power_domains(new_crtc_state);
                }
-
-               if (!needs_modeset(new_crtc_state))
-                       continue;
-
-               intel_pre_plane_update(old_crtc_state, new_crtc_state);
-
-               if (old_crtc_state->base.active) {
-                       intel_crtc_disable_planes(state, crtc);
-
-                       /*
-                        * We need to disable pipe CRC before disabling the pipe,
-                        * or we race against vblank off.
-                        */
-                       intel_crtc_disable_pipe_crc(crtc);
-
-                       dev_priv->display.crtc_disable(old_crtc_state, state);
-                       crtc->active = false;
-                       intel_fbc_disable(crtc);
-                       intel_disable_shared_dpll(old_crtc_state);
-
-                       /*
-                        * Underruns don't always raise
-                        * interrupts, so check manually.
-                        */
-                       intel_check_cpu_fifo_underruns(dev_priv);
-                       intel_check_pch_fifo_underruns(dev_priv);
-
-                       /* FIXME unify this for all platforms */
-                       if (!new_crtc_state->base.active &&
-                           !HAS_GMCH(dev_priv) &&
-                           dev_priv->display.initial_watermarks)
-                               dev_priv->display.initial_watermarks(state,
-                                                                    new_crtc_state);
-               }
        }
 
+       intel_commit_modeset_disables(state);
+
        /* FIXME: Eventually get rid of our crtc->config pointer */
        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i)
                crtc->config = new_crtc_state;
@@ -13996,12 +14760,13 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
                bool modeset = needs_modeset(new_crtc_state);
 
                /* Complete events for now disable pipes here. */
-               if (modeset && !new_crtc_state->base.active && new_crtc_state->base.event) {
+               if (modeset && !new_crtc_state->hw.active && new_crtc_state->uapi.event) {
                        spin_lock_irq(&dev->event_lock);
-                       drm_crtc_send_vblank_event(&crtc->base, new_crtc_state->base.event);
+                       drm_crtc_send_vblank_event(&crtc->base,
+                                                  new_crtc_state->uapi.event);
                        spin_unlock_irq(&dev->event_lock);
 
-                       new_crtc_state->base.event = NULL;
+                       new_crtc_state->uapi.event = NULL;
                }
        }
 
@@ -14009,7 +14774,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
                intel_encoders_update_prepare(state);
 
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
-       dev_priv->display.update_crtcs(state);
+       dev_priv->display.commit_modeset_enables(state);
 
        if (state->modeset) {
                intel_encoders_update_complete(state);
@@ -14032,9 +14797,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
        drm_atomic_helper_wait_for_flip_done(dev, &state->base);
 
        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
-               if (new_crtc_state->base.active &&
+               if (new_crtc_state->hw.active &&
                    !needs_modeset(new_crtc_state) &&
-                   (new_crtc_state->base.color_mgmt_changed ||
+                   !new_crtc_state->preload_luts &&
+                   (new_crtc_state->uapi.color_mgmt_changed ||
                     new_crtc_state->update_pipe))
                        intel_color_load_luts(new_crtc_state);
        }
@@ -14046,14 +14812,25 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
         *
         * TODO: Move this (and other cleanup) to an async worker eventually.
         */
-       for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+                                           new_crtc_state, i) {
+               /*
+                * Gen2 reports pipe underruns whenever all planes are disabled.
+                * So re-enable underrun reporting after some planes get enabled.
+                *
+                * We do this before .optimize_watermarks() so that we have a
+                * chance of catching underruns with the intermediate watermarks
+                * vs. the new plane configuration.
+                */
+               if (IS_GEN(dev_priv, 2) && planes_enabling(old_crtc_state, new_crtc_state))
+                       intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
+
                if (dev_priv->display.optimize_watermarks)
-                       dev_priv->display.optimize_watermarks(state,
-                                                             new_crtc_state);
+                       dev_priv->display.optimize_watermarks(state, crtc);
        }
 
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
-               intel_post_plane_update(old_crtc_state);
+               intel_post_plane_update(state, crtc);
 
                if (put_domains[i])
                        modeset_put_power_domains(dev_priv, put_domains[i]);
@@ -14061,6 +14838,10 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
                intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state);
        }
 
+       /* Underruns don't always raise interrupts, so check manually */
+       intel_check_cpu_fifo_underruns(dev_priv);
+       intel_check_pch_fifo_underruns(dev_priv);
+
        if (state->modeset)
                intel_verify_planes(state);
 
@@ -14134,11 +14915,19 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state)
 
        for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
                                             new_plane_state, i)
-               intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->base.fb),
-                                       to_intel_frontbuffer(new_plane_state->base.fb),
+               intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
+                                       to_intel_frontbuffer(new_plane_state->hw.fb),
                                        plane->frontbuffer_bit);
 }
 
+static void assert_global_state_locked(struct drm_i915_private *dev_priv)
+{
+       struct intel_crtc *crtc;
+
+       for_each_intel_crtc(&dev_priv->drm, crtc)
+               drm_modeset_lock_assert_held(&crtc->base.mutex);
+}
+
 static int intel_atomic_commit(struct drm_device *dev,
                               struct drm_atomic_state *_state,
                               bool nonblock)
@@ -14204,12 +14993,14 @@ static int intel_atomic_commit(struct drm_device *dev,
        intel_shared_dpll_swap_state(state);
        intel_atomic_track_fbs(state);
 
-       if (state->modeset) {
+       if (state->global_state_changed) {
+               assert_global_state_locked(dev_priv);
+
                memcpy(dev_priv->min_cdclk, state->min_cdclk,
                       sizeof(state->min_cdclk));
                memcpy(dev_priv->min_voltage_level, state->min_voltage_level,
                       sizeof(state->min_voltage_level));
-               dev_priv->active_crtcs = state->active_crtcs;
+               dev_priv->active_pipes = state->active_pipes;
                dev_priv->cdclk.force_min_cdclk = state->cdclk.force_min_cdclk;
 
                intel_cdclk_swap_state(state);
@@ -14222,7 +15013,7 @@ static int intel_atomic_commit(struct drm_device *dev,
        if (nonblock && state->modeset) {
                queue_work(dev_priv->modeset_wq, &state->base.commit_work);
        } else if (nonblock) {
-               queue_work(system_unbound_wq, &state->base.commit_work);
+               queue_work(dev_priv->flip_wq, &state->base.commit_work);
        } else {
                if (state->modeset)
                        flush_workqueue(dev_priv->modeset_wq);
@@ -14251,7 +15042,7 @@ static int do_rps_boost(struct wait_queue_entry *_wait,
         * vblank without our intervention, so leave RPS alone.
         */
        if (!i915_request_started(rq))
-               gen6_rps_boost(rq);
+               intel_rps_boost(rq);
        i915_request_put(rq);
 
        drm_crtc_vblank_put(wait->crtc);
@@ -14292,9 +15083,9 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc,
 
 static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       struct drm_framebuffer *fb = plane_state->base.fb;
+       struct drm_framebuffer *fb = plane_state->hw.fb;
        struct i915_vma *vma;
 
        if (plane->id == PLANE_CURSOR &&
@@ -14332,7 +15123,7 @@ static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
 static void fb_obj_bump_render_priority(struct drm_i915_gem_object *obj)
 {
        struct i915_sched_attr attr = {
-               .priority = I915_PRIORITY_DISPLAY,
+               .priority = I915_USER_PRIORITY(I915_PRIORITY_DISPLAY),
        };
 
        i915_gem_object_wait_priority(obj, 0, &attr);
@@ -14341,25 +15132,25 @@ static void fb_obj_bump_render_priority(struct drm_i915_gem_object *obj)
 /**
  * intel_prepare_plane_fb - Prepare fb for usage on plane
  * @plane: drm plane to prepare for
- * @new_state: the plane state being prepared
+ * @_new_plane_state: the plane state being prepared
  *
  * Prepares a framebuffer for usage on a display plane.  Generally this
  * involves pinning the underlying object and updating the frontbuffer tracking
  * bits.  Some older platforms need special physical address handling for
  * cursor planes.
  *
- * Must be called with struct_mutex held.
- *
  * Returns 0 on success, negative error code on failure.
  */
 int
 intel_prepare_plane_fb(struct drm_plane *plane,
-                      struct drm_plane_state *new_state)
+                      struct drm_plane_state *_new_plane_state)
 {
+       struct intel_plane_state *new_plane_state =
+               to_intel_plane_state(_new_plane_state);
        struct intel_atomic_state *intel_state =
-               to_intel_atomic_state(new_state->state);
+               to_intel_atomic_state(new_plane_state->uapi.state);
        struct drm_i915_private *dev_priv = to_i915(plane->dev);
-       struct drm_framebuffer *fb = new_state->fb;
+       struct drm_framebuffer *fb = new_plane_state->hw.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
        int ret;
@@ -14390,9 +15181,9 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                }
        }
 
-       if (new_state->fence) { /* explicit fencing */
+       if (new_plane_state->uapi.fence) { /* explicit fencing */
                ret = i915_sw_fence_await_dma_fence(&intel_state->commit_ready,
-                                                   new_state->fence,
+                                                   new_plane_state->uapi.fence,
                                                    I915_FENCE_TIMEOUT,
                                                    GFP_KERNEL);
                if (ret < 0)
@@ -14406,15 +15197,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        if (ret)
                return ret;
 
-       ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
-       if (ret) {
-               i915_gem_object_unpin_pages(obj);
-               return ret;
-       }
-
-       ret = intel_plane_pin_fb(to_intel_plane_state(new_state));
+       ret = intel_plane_pin_fb(new_plane_state);
 
-       mutex_unlock(&dev_priv->drm.struct_mutex);
        i915_gem_object_unpin_pages(obj);
        if (ret)
                return ret;
@@ -14422,7 +15206,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        fb_obj_bump_render_priority(obj);
        intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB);
 
-       if (!new_state->fence) { /* implicit fencing */
+       if (!new_plane_state->uapi.fence) { /* implicit fencing */
                struct dma_fence *fence;
 
                ret = i915_sw_fence_await_reservation(&intel_state->commit_ready,
@@ -14434,11 +15218,13 @@ intel_prepare_plane_fb(struct drm_plane *plane,
 
                fence = dma_resv_get_excl_rcu(obj->base.resv);
                if (fence) {
-                       add_rps_boost_after_vblank(new_state->crtc, fence);
+                       add_rps_boost_after_vblank(new_plane_state->hw.crtc,
+                                                  fence);
                        dma_fence_put(fence);
                }
        } else {
-               add_rps_boost_after_vblank(new_state->crtc, new_state->fence);
+               add_rps_boost_after_vblank(new_plane_state->hw.crtc,
+                                          new_plane_state->uapi.fence);
        }
 
        /*
@@ -14450,7 +15236,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
         * maximum clocks following a vblank miss (see do_rps_boost()).
         */
        if (!intel_state->rps_interactive) {
-               intel_rps_mark_interactive(dev_priv, true);
+               intel_rps_mark_interactive(&dev_priv->gt.rps, true);
                intel_state->rps_interactive = true;
        }
 
@@ -14460,130 +15246,27 @@ intel_prepare_plane_fb(struct drm_plane *plane,
 /**
  * intel_cleanup_plane_fb - Cleans up an fb after plane use
  * @plane: drm plane to clean up for
- * @old_state: the state from the previous modeset
+ * @_old_plane_state: the state from the previous modeset
  *
  * Cleans up a framebuffer that has just been removed from a plane.
- *
- * Must be called with struct_mutex held.
  */
 void
 intel_cleanup_plane_fb(struct drm_plane *plane,
-                      struct drm_plane_state *old_state)
+                      struct drm_plane_state *_old_plane_state)
 {
+       struct intel_plane_state *old_plane_state =
+               to_intel_plane_state(_old_plane_state);
        struct intel_atomic_state *intel_state =
-               to_intel_atomic_state(old_state->state);
+               to_intel_atomic_state(old_plane_state->uapi.state);
        struct drm_i915_private *dev_priv = to_i915(plane->dev);
 
        if (intel_state->rps_interactive) {
-               intel_rps_mark_interactive(dev_priv, false);
-               intel_state->rps_interactive = false;
-       }
-
-       /* Should only be called after a successful intel_prepare_plane_fb()! */
-       mutex_lock(&dev_priv->drm.struct_mutex);
-       intel_plane_unpin_fb(to_intel_plane_state(old_state));
-       mutex_unlock(&dev_priv->drm.struct_mutex);
-}
-
-int
-skl_max_scale(const struct intel_crtc_state *crtc_state,
-             u32 pixel_format)
-{
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       int max_scale, mult;
-       int crtc_clock, max_dotclk, tmpclk1, tmpclk2;
-
-       if (!crtc_state->base.enable)
-               return DRM_PLANE_HELPER_NO_SCALING;
-
-       crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
-       max_dotclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk;
-
-       if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10)
-               max_dotclk *= 2;
-
-       if (WARN_ON_ONCE(!crtc_clock || max_dotclk < crtc_clock))
-               return DRM_PLANE_HELPER_NO_SCALING;
-
-       /*
-        * skl max scale is lower of:
-        *    close to 3 but not 3, -1 is for that purpose
-        *            or
-        *    cdclk/crtc_clock
-        */
-       mult = is_planar_yuv_format(pixel_format) ? 2 : 3;
-       tmpclk1 = (1 << 16) * mult - 1;
-       tmpclk2 = (1 << 8) * ((max_dotclk << 8) / crtc_clock);
-       max_scale = min(tmpclk1, tmpclk2);
-
-       return max_scale;
-}
-
-static void intel_begin_crtc_commit(struct intel_atomic_state *state,
-                                   struct intel_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       struct intel_crtc_state *old_crtc_state =
-               intel_atomic_get_old_crtc_state(state, crtc);
-       struct intel_crtc_state *new_crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
-       bool modeset = needs_modeset(new_crtc_state);
-
-       /* Perform vblank evasion around commit operation */
-       intel_pipe_update_start(new_crtc_state);
-
-       if (modeset)
-               goto out;
-
-       if (new_crtc_state->base.color_mgmt_changed ||
-           new_crtc_state->update_pipe)
-               intel_color_commit(new_crtc_state);
-
-       if (new_crtc_state->update_pipe)
-               intel_update_pipe_config(old_crtc_state, new_crtc_state);
-       else if (INTEL_GEN(dev_priv) >= 9)
-               skl_detach_scalers(new_crtc_state);
-
-       if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
-               bdw_set_pipemisc(new_crtc_state);
-
-out:
-       if (dev_priv->display.atomic_update_watermarks)
-               dev_priv->display.atomic_update_watermarks(state,
-                                                          new_crtc_state);
-}
-
-void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
-                                 struct intel_crtc_state *crtc_state)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
-       if (!IS_GEN(dev_priv, 2))
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
-
-       if (crtc_state->has_pch_encoder) {
-               enum pipe pch_transcoder =
-                       intel_crtc_pch_transcoder(crtc);
-
-               intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true);
-       }
-}
-
-static void intel_finish_crtc_commit(struct intel_atomic_state *state,
-                                    struct intel_crtc *crtc)
-{
-       struct intel_crtc_state *old_crtc_state =
-               intel_atomic_get_old_crtc_state(state, crtc);
-       struct intel_crtc_state *new_crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
-
-       intel_pipe_update_end(new_crtc_state);
+               intel_rps_mark_interactive(&dev_priv->gt.rps, false);
+               intel_state->rps_interactive = false;
+       }
 
-       if (new_crtc_state->update_pipe &&
-           !needs_modeset(new_crtc_state) &&
-           old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED)
-               intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);
+       /* Should only be called after a successful intel_prepare_plane_fb()! */
+       intel_plane_unpin_fb(old_plane_state);
 }
 
 /**
@@ -14638,8 +15321,13 @@ static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
        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:
@@ -14673,8 +15361,8 @@ static const struct drm_plane_funcs i8xx_plane_funcs = {
 };
 
 static int
-intel_legacy_cursor_update(struct drm_plane *plane,
-                          struct drm_crtc *crtc,
+intel_legacy_cursor_update(struct drm_plane *_plane,
+                          struct drm_crtc *_crtc,
                           struct drm_framebuffer *fb,
                           int crtc_x, int crtc_y,
                           unsigned int crtc_w, unsigned int crtc_h,
@@ -14682,11 +15370,13 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                           u32 src_w, u32 src_h,
                           struct drm_modeset_acquire_ctx *ctx)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct drm_plane_state *old_plane_state, *new_plane_state;
-       struct intel_plane *intel_plane = to_intel_plane(plane);
+       struct intel_plane *plane = to_intel_plane(_plane);
+       struct intel_crtc *crtc = to_intel_crtc(_crtc);
+       struct intel_plane_state *old_plane_state =
+               to_intel_plane_state(plane->base.state);
+       struct intel_plane_state *new_plane_state;
        struct intel_crtc_state *crtc_state =
-               to_intel_crtc_state(crtc->state);
+               to_intel_crtc_state(crtc->base.state);
        struct intel_crtc_state *new_crtc_state;
        int ret;
 
@@ -14694,18 +15384,17 @@ intel_legacy_cursor_update(struct drm_plane *plane,
         * When crtc is inactive or there is a modeset pending,
         * wait for it to complete in the slowpath
         */
-       if (!crtc_state->base.active || needs_modeset(crtc_state) ||
+       if (!crtc_state->hw.active || needs_modeset(crtc_state) ||
            crtc_state->update_pipe)
                goto slow;
 
-       old_plane_state = plane->state;
        /*
         * Don't do an async update if there is an outstanding commit modifying
         * the plane.  This prevents our async update's changes from getting
         * overridden by a previous synchronous update's state.
         */
-       if (old_plane_state->commit &&
-           !try_wait_for_completion(&old_plane_state->commit->hw_done))
+       if (old_plane_state->uapi.commit &&
+           !try_wait_for_completion(&old_plane_state->uapi.commit->hw_done))
                goto slow;
 
        /*
@@ -14713,56 +15402,52 @@ intel_legacy_cursor_update(struct drm_plane *plane,
         * take the slowpath. Only changing fb or position should be
         * in the fastpath.
         */
-       if (old_plane_state->crtc != crtc ||
-           old_plane_state->src_w != src_w ||
-           old_plane_state->src_h != src_h ||
-           old_plane_state->crtc_w != crtc_w ||
-           old_plane_state->crtc_h != crtc_h ||
-           !old_plane_state->fb != !fb)
+       if (old_plane_state->uapi.crtc != &crtc->base ||
+           old_plane_state->uapi.src_w != src_w ||
+           old_plane_state->uapi.src_h != src_h ||
+           old_plane_state->uapi.crtc_w != crtc_w ||
+           old_plane_state->uapi.crtc_h != crtc_h ||
+           !old_plane_state->uapi.fb != !fb)
                goto slow;
 
-       new_plane_state = intel_plane_duplicate_state(plane);
+       new_plane_state = to_intel_plane_state(intel_plane_duplicate_state(&plane->base));
        if (!new_plane_state)
                return -ENOMEM;
 
-       new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(crtc));
+       new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(&crtc->base));
        if (!new_crtc_state) {
                ret = -ENOMEM;
                goto out_free;
        }
 
-       drm_atomic_set_fb_for_plane(new_plane_state, fb);
+       drm_atomic_set_fb_for_plane(&new_plane_state->uapi, fb);
 
-       new_plane_state->src_x = src_x;
-       new_plane_state->src_y = src_y;
-       new_plane_state->src_w = src_w;
-       new_plane_state->src_h = src_h;
-       new_plane_state->crtc_x = crtc_x;
-       new_plane_state->crtc_y = crtc_y;
-       new_plane_state->crtc_w = crtc_w;
-       new_plane_state->crtc_h = crtc_h;
+       new_plane_state->uapi.src_x = src_x;
+       new_plane_state->uapi.src_y = src_y;
+       new_plane_state->uapi.src_w = src_w;
+       new_plane_state->uapi.src_h = src_h;
+       new_plane_state->uapi.crtc_x = crtc_x;
+       new_plane_state->uapi.crtc_y = crtc_y;
+       new_plane_state->uapi.crtc_w = crtc_w;
+       new_plane_state->uapi.crtc_h = crtc_h;
 
        ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
-                                                 to_intel_plane_state(old_plane_state),
-                                                 to_intel_plane_state(new_plane_state));
+                                                 old_plane_state, new_plane_state);
        if (ret)
                goto out_free;
 
-       ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
+       ret = intel_plane_pin_fb(new_plane_state);
        if (ret)
                goto out_free;
 
-       ret = intel_plane_pin_fb(to_intel_plane_state(new_plane_state));
-       if (ret)
-               goto out_unlock;
-
-       intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_FLIP);
-       intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->fb),
-                               to_intel_frontbuffer(fb),
-                               intel_plane->frontbuffer_bit);
+       intel_frontbuffer_flush(to_intel_frontbuffer(new_plane_state->hw.fb),
+                               ORIGIN_FLIP);
+       intel_frontbuffer_track(to_intel_frontbuffer(old_plane_state->hw.fb),
+                               to_intel_frontbuffer(new_plane_state->hw.fb),
+                               plane->frontbuffer_bit);
 
        /* Swap plane state */
-       plane->state = new_plane_state;
+       plane->base.state = &new_plane_state->uapi;
 
        /*
         * We cannot swap crtc_state as it may be in use by an atomic commit or
@@ -14776,27 +15461,24 @@ intel_legacy_cursor_update(struct drm_plane *plane,
         */
        crtc_state->active_planes = new_crtc_state->active_planes;
 
-       if (plane->state->visible)
-               intel_update_plane(intel_plane, crtc_state,
-                                  to_intel_plane_state(plane->state));
+       if (new_plane_state->uapi.visible)
+               intel_update_plane(plane, crtc_state, new_plane_state);
        else
-               intel_disable_plane(intel_plane, crtc_state);
+               intel_disable_plane(plane, crtc_state);
 
-       intel_plane_unpin_fb(to_intel_plane_state(old_plane_state));
+       intel_plane_unpin_fb(old_plane_state);
 
-out_unlock:
-       mutex_unlock(&dev_priv->drm.struct_mutex);
 out_free:
        if (new_crtc_state)
-               intel_crtc_destroy_state(crtc, &new_crtc_state->base);
+               intel_crtc_destroy_state(&crtc->base, &new_crtc_state->uapi);
        if (ret)
-               intel_plane_destroy_state(plane, new_plane_state);
+               intel_plane_destroy_state(&plane->base, &new_plane_state->uapi);
        else
-               intel_plane_destroy_state(plane, old_plane_state);
+               intel_plane_destroy_state(&plane->base, &old_plane_state->uapi);
        return ret;
 
 slow:
-       return drm_atomic_helper_update_plane(plane, crtc, fb,
+       return drm_atomic_helper_update_plane(&plane->base, &crtc->base, fb,
                                              crtc_x, crtc_y, crtc_w, crtc_h,
                                              src_x, src_y, src_w, src_h, ctx);
 }
@@ -14834,10 +15516,9 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
        const struct drm_plane_funcs *plane_funcs;
        unsigned int supported_rotations;
        unsigned int possible_crtcs;
-       const u64 *modifiers;
        const u32 *formats;
        int num_formats;
-       int ret;
+       int ret, zpos;
 
        if (INTEL_GEN(dev_priv) >= 9)
                return skl_universal_plane_create(dev_priv, pipe,
@@ -14866,44 +15547,69 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
        }
 
-       if (INTEL_GEN(dev_priv) >= 4) {
-               formats = i965_primary_formats;
-               num_formats = ARRAY_SIZE(i965_primary_formats);
-               modifiers = i9xx_format_modifiers;
-
-               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;
-
-               plane_funcs = &i965_plane_funcs;
+       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);
-               modifiers = i9xx_format_modifiers;
-
-               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) >= 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;
 
        possible_crtcs = BIT(pipe);
 
        if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
                ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
                                               possible_crtcs, plane_funcs,
-                                              formats, num_formats, modifiers,
+                                              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,
                                               possible_crtcs, plane_funcs,
-                                              formats, num_formats, modifiers,
+                                              formats, num_formats,
+                                              i9xx_format_modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
                                               "plane %c",
                                               plane_name(plane->i9xx_plane));
@@ -14926,6 +15632,9 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                                                   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;
@@ -14942,7 +15651,7 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
 {
        unsigned int possible_crtcs;
        struct intel_plane *cursor;
-       int ret;
+       int ret, zpos;
 
        cursor = intel_plane_alloc();
        if (IS_ERR(cursor))
@@ -14991,6 +15700,9 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
                                                   DRM_MODE_ROTATE_0 |
                                                   DRM_MODE_ROTATE_180);
 
+       zpos = RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1;
+       drm_plane_create_zpos_immutable_property(&cursor->base, zpos);
+
        drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
 
        return cursor;
@@ -15066,12 +15778,12 @@ static const struct drm_crtc_funcs i965_crtc_funcs = {
        .disable_vblank = i965_disable_vblank,
 };
 
-static const struct drm_crtc_funcs i945gm_crtc_funcs = {
+static const struct drm_crtc_funcs i915gm_crtc_funcs = {
        INTEL_CRTC_FUNCS,
 
        .get_vblank_counter = i915_get_vblank_counter,
-       .enable_vblank = i945gm_enable_vblank,
-       .disable_vblank = i945gm_disable_vblank,
+       .enable_vblank = i915gm_enable_vblank,
+       .disable_vblank = i915gm_disable_vblank,
 };
 
 static const struct drm_crtc_funcs i915_crtc_funcs = {
@@ -15108,7 +15820,7 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
                ret = -ENOMEM;
                goto fail;
        }
-       __drm_atomic_helper_crtc_reset(&intel_crtc->base, &crtc_state->base);
+       __drm_atomic_helper_crtc_reset(&intel_crtc->base, &crtc_state->uapi);
        intel_crtc->config = crtc_state;
 
        primary = intel_primary_plane_create(dev_priv, pipe);
@@ -15142,8 +15854,8 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
                        funcs = &g4x_crtc_funcs;
                else if (IS_GEN(dev_priv, 4))
                        funcs = &i965_crtc_funcs;
-               else if (IS_I945GM(dev_priv))
-                       funcs = &i945gm_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
@@ -15178,8 +15890,6 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
                dev_priv->plane_to_crtc_mapping[i9xx_plane] = intel_crtc;
        }
 
-       drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
-
        intel_color_init(intel_crtc);
 
        WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
@@ -15214,21 +15924,32 @@ int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
-static int intel_encoder_clones(struct intel_encoder *encoder)
+static u32 intel_encoder_possible_clones(struct intel_encoder *encoder)
 {
        struct drm_device *dev = encoder->base.dev;
        struct intel_encoder *source_encoder;
-       int index_mask = 0;
-       int entry = 0;
+       u32 possible_clones = 0;
 
        for_each_intel_encoder(dev, source_encoder) {
                if (encoders_cloneable(encoder, source_encoder))
-                       index_mask |= (1 << entry);
+                       possible_clones |= drm_encoder_mask(&source_encoder->base);
+       }
+
+       return possible_clones;
+}
+
+static u32 intel_encoder_possible_crtcs(struct intel_encoder *encoder)
+{
+       struct drm_device *dev = encoder->base.dev;
+       struct intel_crtc *crtc;
+       u32 possible_crtcs = 0;
 
-               entry++;
+       for_each_intel_crtc(dev, crtc) {
+               if (encoder->pipe_mask & BIT(crtc->pipe))
+                       possible_crtcs |= drm_crtc_mask(&crtc->base);
        }
 
-       return index_mask;
+       return possible_crtcs;
 }
 
 static bool ilk_has_edp_a(struct drm_i915_private *dev_priv)
@@ -15310,13 +16031,18 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 
        intel_pps_init(dev_priv);
 
-       if (!HAS_DISPLAY(dev_priv))
+       if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv))
                return;
 
        if (INTEL_GEN(dev_priv) >= 12) {
-               /* TODO: initialize TC ports as well */
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
+               intel_ddi_init(dev_priv, PORT_D);
+               intel_ddi_init(dev_priv, PORT_E);
+               intel_ddi_init(dev_priv, PORT_F);
+               intel_ddi_init(dev_priv, PORT_G);
+               intel_ddi_init(dev_priv, PORT_H);
+               intel_ddi_init(dev_priv, PORT_I);
                icl_dsi_init(dev_priv);
        } else if (IS_ELKHARTLAKE(dev_priv)) {
                intel_ddi_init(dev_priv, PORT_A);
@@ -15526,9 +16252,10 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
        intel_psr_init(dev_priv);
 
        for_each_intel_encoder(&dev_priv->drm, encoder) {
-               encoder->base.possible_crtcs = encoder->crtc_mask;
+               encoder->base.possible_crtcs =
+                       intel_encoder_possible_crtcs(encoder);
                encoder->base.possible_clones =
-                       intel_encoder_clones(encoder);
+                       intel_encoder_possible_clones(encoder);
        }
 
        intel_init_pch_refclk(dev_priv);
@@ -15783,8 +16510,14 @@ intel_mode_valid(struct drm_device *dev,
                           DRM_MODE_FLAG_CLKDIV2))
                return MODE_BAD;
 
-       if (INTEL_GEN(dev_priv) >= 9 ||
-           IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
+       /* Transcoder timing limits */
+       if (INTEL_GEN(dev_priv) >= 11) {
+               hdisplay_max = 16384;
+               vdisplay_max = 8192;
+               htotal_max = 16384;
+               vtotal_max = 8192;
+       } else if (INTEL_GEN(dev_priv) >= 9 ||
+                  IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
                hdisplay_max = 8192; /* FDI max 4096 handled elsewhere */
                vdisplay_max = 4096;
                htotal_max = 8192;
@@ -15813,6 +16546,56 @@ intel_mode_valid(struct drm_device *dev,
            mode->vtotal > vtotal_max)
                return MODE_V_ILLEGAL;
 
+       if (INTEL_GEN(dev_priv) >= 5) {
+               if (mode->hdisplay < 64 ||
+                   mode->htotal - mode->hdisplay < 32)
+                       return MODE_H_ILLEGAL;
+
+               if (mode->vtotal - mode->vdisplay < 5)
+                       return MODE_V_ILLEGAL;
+       } else {
+               if (mode->htotal - mode->hdisplay < 32)
+                       return MODE_H_ILLEGAL;
+
+               if (mode->vtotal - mode->vdisplay < 3)
+                       return MODE_V_ILLEGAL;
+       }
+
+       return MODE_OK;
+}
+
+enum drm_mode_status
+intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
+                               const struct drm_display_mode *mode)
+{
+       int plane_width_max, plane_height_max;
+
+       /*
+        * intel_mode_valid() should be
+        * sufficient on older platforms.
+        */
+       if (INTEL_GEN(dev_priv) < 9)
+               return MODE_OK;
+
+       /*
+        * Most people will probably want a fullscreen
+        * plane so let's not advertize modes that are
+        * too big for that.
+        */
+       if (INTEL_GEN(dev_priv) >= 11) {
+               plane_width_max = 5120;
+               plane_height_max = 4320;
+       } else {
+               plane_width_max = 5120;
+               plane_height_max = 4096;
+       }
+
+       if (mode->hdisplay > plane_width_max)
+               return MODE_H_ILLEGAL;
+
+       if (mode->vdisplay > plane_height_max)
+               return MODE_V_ILLEGAL;
+
        return MODE_OK;
 }
 
@@ -15916,47 +16699,17 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
        }
 
        if (INTEL_GEN(dev_priv) >= 9)
-               dev_priv->display.update_crtcs = skl_update_crtcs;
-       else
-               dev_priv->display.update_crtcs = intel_update_crtcs;
-}
-
-static i915_reg_t i915_vgacntrl_reg(struct drm_i915_private *dev_priv)
-{
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               return VLV_VGACNTRL;
-       else if (INTEL_GEN(dev_priv) >= 5)
-               return CPU_VGACNTRL;
+               dev_priv->display.commit_modeset_enables = skl_commit_modeset_enables;
        else
-               return VGACNTRL;
-}
-
-/* Disable the VGA plane that we never use */
-static void i915_disable_vga(struct drm_i915_private *dev_priv)
-{
-       struct pci_dev *pdev = dev_priv->drm.pdev;
-       u8 sr1;
-       i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv);
+               dev_priv->display.commit_modeset_enables = intel_commit_modeset_enables;
 
-       /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
-       vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
-       outb(SR01, VGA_SR_INDEX);
-       sr1 = inb(VGA_SR_DATA);
-       outb(sr1 | 1<<5, VGA_SR_DATA);
-       vga_put(pdev, VGA_RSRC_LEGACY_IO);
-       udelay(300);
-
-       I915_WRITE(vga_reg, VGA_DISP_DISABLE);
-       POSTING_READ(vga_reg);
 }
 
-void intel_modeset_init_hw(struct drm_device *dev)
+void intel_modeset_init_hw(struct drm_i915_private *i915)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
-
-       intel_update_cdclk(dev_priv);
-       intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
-       dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw;
+       intel_update_cdclk(i915);
+       intel_dump_cdclk_state(&i915->cdclk.hw, "Current CDCLK");
+       i915->cdclk.logical = i915->cdclk.actual = i915->cdclk.hw;
 }
 
 /*
@@ -16032,7 +16785,7 @@ static void sanitize_watermarks(struct drm_device *dev)
        /* Write calculated watermark values back */
        for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
                crtc_state->wm.need_postvbl_update = true;
-               dev_priv->display.optimize_watermarks(intel_state, crtc_state);
+               dev_priv->display.optimize_watermarks(intel_state, crtc);
 
                to_intel_crtc_state(crtc->base.state)->wm = crtc_state->wm;
        }
@@ -16064,8 +16817,7 @@ static int intel_initial_commit(struct drm_device *dev)
 {
        struct drm_atomic_state *state = NULL;
        struct drm_modeset_acquire_ctx ctx;
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *crtc_state;
+       struct intel_crtc *crtc;
        int ret = 0;
 
        state = drm_atomic_state_alloc(dev);
@@ -16077,15 +16829,17 @@ static int intel_initial_commit(struct drm_device *dev)
 retry:
        state->acquire_ctx = &ctx;
 
-       drm_for_each_crtc(crtc, dev) {
-               crtc_state = drm_atomic_get_crtc_state(state, crtc);
+       for_each_intel_crtc(dev, crtc) {
+               struct intel_crtc_state *crtc_state =
+                       intel_atomic_get_crtc_state(state, crtc);
+
                if (IS_ERR(crtc_state)) {
                        ret = PTR_ERR(crtc_state);
                        goto out;
                }
 
-               if (crtc_state->active) {
-                       ret = drm_atomic_add_affected_planes(state, crtc);
+               if (crtc_state->hw.active) {
+                       ret = drm_atomic_add_affected_planes(state, &crtc->base);
                        if (ret)
                                goto out;
 
@@ -16095,7 +16849,7 @@ static int intel_initial_commit(struct drm_device *dev)
                         * having a proper LUT loaded. Remove once we
                         * have readout for pipe gamma enable.
                         */
-                       crtc_state->color_mgmt_changed = true;
+                       crtc_state->uapi.color_mgmt_changed = true;
                }
        }
 
@@ -16116,114 +16870,111 @@ static int intel_initial_commit(struct drm_device *dev)
        return ret;
 }
 
-int intel_modeset_init(struct drm_device *dev)
+static void intel_mode_config_init(struct drm_i915_private *i915)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       enum pipe pipe;
-       struct intel_crtc *crtc;
-       int ret;
-
-       dev_priv->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0);
-
-       drm_mode_config_init(dev);
-
-       ret = intel_bw_init(dev_priv);
-       if (ret)
-               return ret;
-
-       dev->mode_config.min_width = 0;
-       dev->mode_config.min_height = 0;
-
-       dev->mode_config.preferred_depth = 24;
-       dev->mode_config.prefer_shadow = 1;
+       struct drm_mode_config *mode_config = &i915->drm.mode_config;
 
-       dev->mode_config.allow_fb_modifiers = true;
+       drm_mode_config_init(&i915->drm);
 
-       dev->mode_config.funcs = &intel_mode_funcs;
+       mode_config->min_width = 0;
+       mode_config->min_height = 0;
 
-       init_llist_head(&dev_priv->atomic_helper.free_list);
-       INIT_WORK(&dev_priv->atomic_helper.free_work,
-                 intel_atomic_helper_free_state_worker);
-
-       intel_init_quirks(dev_priv);
-
-       intel_fbc_init(dev_priv);
-
-       intel_init_pm(dev_priv);
+       mode_config->preferred_depth = 24;
+       mode_config->prefer_shadow = 1;
 
-       /*
-        * There may be no VBT; and if the BIOS enabled SSC we can
-        * just keep using it to avoid unnecessary flicker.  Whereas if the
-        * BIOS isn't using it, don't assume it will work even if the VBT
-        * indicates as much.
-        */
-       if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
-               bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
-                                           DREF_SSC1_ENABLE);
+       mode_config->allow_fb_modifiers = true;
 
-               if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) {
-                       DRM_DEBUG_KMS("SSC %sabled by BIOS, overriding VBT which says %sabled\n",
-                                    bios_lvds_use_ssc ? "en" : "dis",
-                                    dev_priv->vbt.lvds_use_ssc ? "en" : "dis");
-                       dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc;
-               }
-       }
+       mode_config->funcs = &intel_mode_funcs;
 
        /*
         * Maximum framebuffer dimensions, chosen to match
         * the maximum render engine surface size on gen4+.
         */
-       if (INTEL_GEN(dev_priv) >= 7) {
-               dev->mode_config.max_width = 16384;
-               dev->mode_config.max_height = 16384;
-       } else if (INTEL_GEN(dev_priv) >= 4) {
-               dev->mode_config.max_width = 8192;
-               dev->mode_config.max_height = 8192;
-       } else if (IS_GEN(dev_priv, 3)) {
-               dev->mode_config.max_width = 4096;
-               dev->mode_config.max_height = 4096;
+       if (INTEL_GEN(i915) >= 7) {
+               mode_config->max_width = 16384;
+               mode_config->max_height = 16384;
+       } else if (INTEL_GEN(i915) >= 4) {
+               mode_config->max_width = 8192;
+               mode_config->max_height = 8192;
+       } else if (IS_GEN(i915, 3)) {
+               mode_config->max_width = 4096;
+               mode_config->max_height = 4096;
        } else {
-               dev->mode_config.max_width = 2048;
-               dev->mode_config.max_height = 2048;
+               mode_config->max_width = 2048;
+               mode_config->max_height = 2048;
        }
 
-       if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
-               dev->mode_config.cursor_width = IS_I845G(dev_priv) ? 64 : 512;
-               dev->mode_config.cursor_height = 1023;
-       } else if (IS_GEN(dev_priv, 2)) {
-               dev->mode_config.cursor_width = 64;
-               dev->mode_config.cursor_height = 64;
+       if (IS_I845G(i915) || IS_I865G(i915)) {
+               mode_config->cursor_width = IS_I845G(i915) ? 64 : 512;
+               mode_config->cursor_height = 1023;
+       } else if (IS_GEN(i915, 2)) {
+               mode_config->cursor_width = 64;
+               mode_config->cursor_height = 64;
        } else {
-               dev->mode_config.cursor_width = 256;
-               dev->mode_config.cursor_height = 256;
+               mode_config->cursor_width = 256;
+               mode_config->cursor_height = 256;
        }
+}
 
-       DRM_DEBUG_KMS("%d display pipe%s available.\n",
-                     INTEL_INFO(dev_priv)->num_pipes,
-                     INTEL_INFO(dev_priv)->num_pipes > 1 ? "s" : "");
+int intel_modeset_init(struct drm_i915_private *i915)
+{
+       struct drm_device *dev = &i915->drm;
+       enum pipe pipe;
+       struct intel_crtc *crtc;
+       int ret;
 
-       for_each_pipe(dev_priv, pipe) {
-               ret = intel_crtc_init(dev_priv, pipe);
-               if (ret) {
-                       drm_mode_config_cleanup(dev);
-                       return ret;
+       i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0);
+       i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI |
+                                       WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
+
+       intel_mode_config_init(i915);
+
+       ret = intel_bw_init(i915);
+       if (ret)
+               return ret;
+
+       init_llist_head(&i915->atomic_helper.free_list);
+       INIT_WORK(&i915->atomic_helper.free_work,
+                 intel_atomic_helper_free_state_worker);
+
+       intel_init_quirks(i915);
+
+       intel_fbc_init(i915);
+
+       intel_init_pm(i915);
+
+       intel_panel_sanitize_ssc(i915);
+
+       intel_gmbus_setup(i915);
+
+       DRM_DEBUG_KMS("%d display pipe%s available.\n",
+                     INTEL_NUM_PIPES(i915),
+                     INTEL_NUM_PIPES(i915) > 1 ? "s" : "");
+
+       if (HAS_DISPLAY(i915) && INTEL_DISPLAY_ENABLED(i915)) {
+               for_each_pipe(i915, pipe) {
+                       ret = intel_crtc_init(i915, pipe);
+                       if (ret) {
+                               drm_mode_config_cleanup(dev);
+                               return ret;
+                       }
                }
        }
 
        intel_shared_dpll_init(dev);
-       intel_update_fdi_pll_freq(dev_priv);
+       intel_update_fdi_pll_freq(i915);
 
-       intel_update_czclk(dev_priv);
-       intel_modeset_init_hw(dev);
+       intel_update_czclk(i915);
+       intel_modeset_init_hw(i915);
 
-       intel_hdcp_component_init(dev_priv);
+       intel_hdcp_component_init(i915);
 
-       if (dev_priv->max_cdclk_freq == 0)
-               intel_update_max_cdclk(dev_priv);
+       if (i915->max_cdclk_freq == 0)
+               intel_update_max_cdclk(i915);
 
        /* Just disable it once at startup */
-       i915_disable_vga(dev_priv);
-       intel_setup_outputs(dev_priv);
+       intel_vga_disable(i915);
+       intel_setup_outputs(i915);
 
        drm_modeset_lock_all(dev);
        intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx);
@@ -16242,8 +16993,7 @@ int intel_modeset_init(struct drm_device *dev)
                 * can even allow for smooth boot transitions if the BIOS
                 * fb is large enough for the active pipe configuration.
                 */
-               dev_priv->display.get_initial_plane_config(crtc,
-                                                          &plane_config);
+               i915->display.get_initial_plane_config(crtc, &plane_config);
 
                /*
                 * If the fb is shared between multiple heads, we'll
@@ -16257,7 +17007,7 @@ int intel_modeset_init(struct drm_device *dev)
         * Note that we need to do this after reconstructing the BIOS fb's
         * since the watermark calculation done here will use pstate->fb.
         */
-       if (!HAS_GMCH(dev_priv))
+       if (!HAS_GMCH(i915))
                sanitize_watermarks(dev);
 
        /*
@@ -16422,31 +17172,76 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv,
                (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A);
 }
 
-static void intel_sanitize_crtc(struct intel_crtc *crtc,
-                               struct drm_modeset_acquire_ctx *ctx)
+static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
-       /* Clear any frame start delays used for debugging left by the BIOS */
-       if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) {
+       if (INTEL_GEN(dev_priv) >= 9 ||
+           IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
+               i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
+               u32 val;
+
+               if (transcoder_is_dsi(cpu_transcoder))
+                       return;
+
+               val = I915_READ(reg);
+               val &= ~HSW_FRAME_START_DELAY_MASK;
+               val |= HSW_FRAME_START_DELAY(0);
+               I915_WRITE(reg, val);
+       } else {
                i915_reg_t reg = PIPECONF(cpu_transcoder);
+               u32 val;
 
-               I915_WRITE(reg,
-                          I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+               val = I915_READ(reg);
+               val &= ~PIPECONF_FRAME_START_DELAY_MASK;
+               val |= PIPECONF_FRAME_START_DELAY(0);
+               I915_WRITE(reg, val);
+       }
+
+       if (!crtc_state->has_pch_encoder)
+               return;
+
+       if (HAS_PCH_IBX(dev_priv)) {
+               i915_reg_t reg = PCH_TRANSCONF(crtc->pipe);
+               u32 val;
+
+               val = I915_READ(reg);
+               val &= ~TRANS_FRAME_START_DELAY_MASK;
+               val |= TRANS_FRAME_START_DELAY(0);
+               I915_WRITE(reg, val);
+       } else {
+               enum pipe pch_transcoder = intel_crtc_pch_transcoder(crtc);
+               i915_reg_t reg = TRANS_CHICKEN2(pch_transcoder);
+               u32 val;
+
+               val = I915_READ(reg);
+               val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
+               val |= TRANS_CHICKEN2_FRAME_START_DELAY(0);
+               I915_WRITE(reg, val);
        }
+}
 
-       if (crtc_state->base.active) {
+static void intel_sanitize_crtc(struct intel_crtc *crtc,
+                               struct drm_modeset_acquire_ctx *ctx)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state);
+
+       if (crtc_state->hw.active) {
                struct intel_plane *plane;
 
+               /* Clear any frame start delays used for debugging left by the BIOS */
+               intel_sanitize_frame_start_delay(crtc_state);
+
                /* Disable everything but the primary plane */
                for_each_intel_plane_on_crtc(dev, crtc, plane) {
                        const struct intel_plane_state *plane_state =
                                to_intel_plane_state(plane->base.state);
 
-                       if (plane_state->base.visible &&
+                       if (plane_state->uapi.visible &&
                            plane->base.type != DRM_PLANE_TYPE_PRIMARY)
                                intel_plane_disable_noatomic(crtc, plane);
                }
@@ -16463,10 +17258,10 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
 
        /* Adjust the state of the output pipe according to whether we
         * have active connectors/encoders. */
-       if (crtc_state->base.active && !intel_crtc_has_encoders(crtc))
-               intel_crtc_disable_noatomic(&crtc->base, ctx);
+       if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc))
+               intel_crtc_disable_noatomic(crtc, ctx);
 
-       if (crtc_state->base.active || HAS_GMCH(dev_priv)) {
+       if (crtc_state->hw.active || HAS_GMCH(dev_priv)) {
                /*
                 * We start out with underrun reporting disabled to avoid races.
                 * For correct bookkeeping mark this on active crtcs.
@@ -16497,7 +17292,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
 
 static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 
        /*
         * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram
@@ -16510,7 +17305,7 @@ static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
         * road.
         */
        return IS_GEN(dev_priv, 6) &&
-               crtc_state->base.active &&
+               crtc_state->hw.active &&
                crtc_state->shared_dpll &&
                crtc_state->port_clock == 0;
 }
@@ -16527,7 +17322,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
         * encoder is active and trying to read from a pipe) and the
         * pipe itself being active. */
        bool has_active_crtc = crtc_state &&
-               crtc_state->base.active;
+               crtc_state->hw.active;
 
        if (crtc_state && has_bogus_dpll_config(crtc_state)) {
                DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n",
@@ -16582,39 +17377,6 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                icl_sanitize_encoder_pll_mapping(encoder);
 }
 
-void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
-{
-       i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv);
-
-       if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
-               DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
-               i915_disable_vga(dev_priv);
-       }
-}
-
-void i915_redisable_vga(struct drm_i915_private *dev_priv)
-{
-       intel_wakeref_t wakeref;
-
-       /*
-        * This function can be called both from intel_modeset_setup_hw_state or
-        * at a very early point in our resume sequence, where the power well
-        * structures are not yet restored. Since this function is at a very
-        * paranoid "someone might have enabled VGA while we were not looking"
-        * level, just check if the power well is enabled instead of trying to
-        * follow the "don't touch the power well if we don't need it" policy
-        * the rest of the driver uses.
-        */
-       wakeref = intel_display_power_get_if_enabled(dev_priv,
-                                                    POWER_DOMAIN_VGA);
-       if (!wakeref)
-               return;
-
-       i915_redisable_vga_power_on(dev_priv);
-
-       intel_display_power_put(dev_priv, POWER_DOMAIN_VGA, wakeref);
-}
-
 /* FIXME read out full plane state for all planes */
 static void readout_plane_state(struct drm_i915_private *dev_priv)
 {
@@ -16658,28 +17420,29 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
        struct drm_connector_list_iter conn_iter;
        int i;
 
-       dev_priv->active_crtcs = 0;
+       dev_priv->active_pipes = 0;
 
        for_each_intel_crtc(dev, crtc) {
                struct intel_crtc_state *crtc_state =
                        to_intel_crtc_state(crtc->base.state);
 
-               __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
+               __drm_atomic_helper_crtc_destroy_state(&crtc_state->uapi);
+               intel_crtc_free_hw_state(crtc_state);
                memset(crtc_state, 0, sizeof(*crtc_state));
-               __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->base);
+               __drm_atomic_helper_crtc_reset(&crtc->base, &crtc_state->uapi);
 
-               crtc_state->base.active = crtc_state->base.enable =
+               crtc_state->hw.active = crtc_state->hw.enable =
                        dev_priv->display.get_pipe_config(crtc, crtc_state);
 
-               crtc->base.enabled = crtc_state->base.enable;
-               crtc->active = crtc_state->base.active;
+               crtc->base.enabled = crtc_state->hw.enable;
+               crtc->active = crtc_state->hw.active;
 
-               if (crtc_state->base.active)
-                       dev_priv->active_crtcs |= 1 << crtc->pipe;
+               if (crtc_state->hw.active)
+                       dev_priv->active_pipes |= BIT(crtc->pipe);
 
                DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",
                              crtc->base.base.id, crtc->base.name,
-                             enableddisabled(crtc_state->base.active));
+                             enableddisabled(crtc_state->hw.active));
        }
 
        readout_plane_state(dev_priv);
@@ -16701,7 +17464,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                        struct intel_crtc_state *crtc_state =
                                to_intel_crtc_state(crtc->base.state);
 
-                       if (crtc_state->base.active &&
+                       if (crtc_state->hw.active &&
                            crtc_state->shared_dpll == pll)
                                pll->state.crtc_mask |= 1 << crtc->pipe;
                }
@@ -16735,24 +17498,28 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
        drm_connector_list_iter_begin(dev, &conn_iter);
        for_each_intel_connector_iter(connector, &conn_iter) {
                if (connector->get_hw_state(connector)) {
+                       struct intel_crtc_state *crtc_state;
+                       struct intel_crtc *crtc;
+
                        connector->base.dpms = DRM_MODE_DPMS_ON;
 
                        encoder = connector->encoder;
                        connector->base.encoder = &encoder->base;
 
-                       if (encoder->base.crtc &&
-                           encoder->base.crtc->state->active) {
+                       crtc = to_intel_crtc(encoder->base.crtc);
+                       crtc_state = crtc ? to_intel_crtc_state(crtc->base.state) : NULL;
+
+                       if (crtc_state && crtc_state->hw.active) {
                                /*
                                 * This has to be done during hardware readout
                                 * because anything calling .crtc_disable may
                                 * rely on the connector_mask being accurate.
                                 */
-                               encoder->base.crtc->state->connector_mask |=
+                               crtc_state->uapi.connector_mask |=
                                        drm_connector_mask(&connector->base);
-                               encoder->base.crtc->state->encoder_mask |=
+                               crtc_state->uapi.encoder_mask |=
                                        drm_encoder_mask(&encoder->base);
                        }
-
                } else {
                        connector->base.dpms = DRM_MODE_DPMS_OFF;
                        connector->base.encoder = NULL;
@@ -16771,13 +17538,15 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                struct intel_plane *plane;
                int min_cdclk = 0;
 
-               memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
-               if (crtc_state->base.active) {
-                       intel_mode_from_pipe_config(&crtc->base.mode, crtc_state);
-                       crtc->base.mode.hdisplay = crtc_state->pipe_src_w;
-                       crtc->base.mode.vdisplay = crtc_state->pipe_src_h;
-                       intel_mode_from_pipe_config(&crtc_state->base.adjusted_mode, crtc_state);
-                       WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
+               if (crtc_state->hw.active) {
+                       struct drm_display_mode *mode = &crtc_state->hw.mode;
+
+                       intel_mode_from_pipe_config(&crtc_state->hw.adjusted_mode,
+                                                   crtc_state);
+
+                       *mode = crtc_state->hw.adjusted_mode;
+                       mode->hdisplay = crtc_state->pipe_src_w;
+                       mode->vdisplay = crtc_state->pipe_src_h;
 
                        /*
                         * The initial mode needs to be set in order to keep
@@ -16788,25 +17557,15 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                         * set a flag to indicate that a full recalculation is
                         * needed on the next commit.
                         */
-                       crtc_state->base.mode.private_flags = I915_MODE_FLAG_INHERITED;
+                       mode->private_flags = I915_MODE_FLAG_INHERITED;
 
                        intel_crtc_compute_pixel_rate(crtc_state);
 
-                       if (dev_priv->display.modeset_calc_cdclk) {
-                               min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);
-                               if (WARN_ON(min_cdclk < 0))
-                                       min_cdclk = 0;
-                       }
+                       intel_crtc_update_active_timings(crtc_state);
 
-                       drm_calc_timestamping_constants(&crtc->base,
-                                                       &crtc_state->base.adjusted_mode);
-                       update_scanline_offset(crtc_state);
+                       intel_crtc_copy_hw_to_uapi_state(crtc_state);
                }
 
-               dev_priv->min_cdclk[crtc->pipe] = min_cdclk;
-               dev_priv->min_voltage_level[crtc->pipe] =
-                       crtc_state->min_voltage_level;
-
                for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
                        const struct intel_plane_state *plane_state =
                                to_intel_plane_state(plane->base.state);
@@ -16815,11 +17574,37 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                         * FIXME don't have the fb yet, so can't
                         * use intel_plane_data_rate() :(
                         */
-                       if (plane_state->base.visible)
+                       if (plane_state->uapi.visible)
                                crtc_state->data_rate[plane->id] =
                                        4 * crtc_state->pixel_rate;
+                       /*
+                        * FIXME don't have the fb yet, so can't
+                        * use plane->min_cdclk() :(
+                        */
+                       if (plane_state->uapi.visible && plane->min_cdclk) {
+                               if (crtc_state->double_wide ||
+                                   INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+                                       crtc_state->min_cdclk[plane->id] =
+                                               DIV_ROUND_UP(crtc_state->pixel_rate, 2);
+                               else
+                                       crtc_state->min_cdclk[plane->id] =
+                                               crtc_state->pixel_rate;
+                       }
+                       DRM_DEBUG_KMS("[PLANE:%d:%s] min_cdclk %d kHz\n",
+                                     plane->base.base.id, plane->base.name,
+                                     crtc_state->min_cdclk[plane->id]);
+               }
+
+               if (crtc_state->hw.active) {
+                       min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);
+                       if (WARN_ON(min_cdclk < 0))
+                               min_cdclk = 0;
                }
 
+               dev_priv->min_cdclk[crtc->pipe] = min_cdclk;
+               dev_priv->min_voltage_level[crtc->pipe] =
+                       crtc_state->min_voltage_level;
+
                intel_bw_crtc_update(bw_state, crtc_state);
 
                intel_pipe_config_sanity_check(dev_priv, crtc_state);
@@ -16933,7 +17718,6 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
                             struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc_state *crtc_state;
        struct intel_encoder *encoder;
        struct intel_crtc *crtc;
        intel_wakeref_t wakeref;
@@ -16966,11 +17750,12 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
         * waits, so we need vblank interrupts restored beforehand.
         */
        for_each_intel_crtc(&dev_priv->drm, crtc) {
-               crtc_state = to_intel_crtc_state(crtc->base.state);
+               struct intel_crtc_state *crtc_state =
+                       to_intel_crtc_state(crtc->base.state);
 
                drm_crtc_vblank_reset(&crtc->base);
 
-               if (crtc_state->base.active)
+               if (crtc_state->hw.active)
                        intel_crtc_vblank_on(crtc_state);
        }
 
@@ -16980,7 +17765,9 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
                intel_sanitize_encoder(encoder);
 
        for_each_intel_crtc(&dev_priv->drm, crtc) {
-               crtc_state = to_intel_crtc_state(crtc->base.state);
+               struct intel_crtc_state *crtc_state =
+                       crtc_state = to_intel_crtc_state(crtc->base.state);
+
                intel_sanitize_crtc(crtc, ctx);
                intel_dump_pipe_config(crtc_state, NULL, "[setup_hw_state]");
        }
@@ -17013,9 +17800,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
        }
 
        for_each_intel_crtc(dev, crtc) {
+               struct intel_crtc_state *crtc_state =
+                       to_intel_crtc_state(crtc->base.state);
                u64 put_domains;
 
-               crtc_state = to_intel_crtc_state(crtc->base.state);
                put_domains = modeset_get_crtc_power_domains(crtc_state);
                if (WARN_ON(put_domains))
                        modeset_put_power_domains(dev_priv, put_domains);
@@ -17060,13 +17848,13 @@ void intel_display_resume(struct drm_device *dev)
                drm_atomic_state_put(state);
 }
 
-static void intel_hpd_poll_fini(struct drm_device *dev)
+static void intel_hpd_poll_fini(struct drm_i915_private *i915)
 {
        struct intel_connector *connector;
        struct drm_connector_list_iter conn_iter;
 
        /* Kill all the work that may have been queued by hpd. */
-       drm_connector_list_iter_begin(dev, &conn_iter);
+       drm_connector_list_iter_begin(&i915->drm, &conn_iter);
        for_each_intel_connector_iter(connector, &conn_iter) {
                if (connector->modeset_retry_work.func)
                        cancel_work_sync(&connector->modeset_retry_work);
@@ -17078,78 +17866,56 @@ static void intel_hpd_poll_fini(struct drm_device *dev)
        drm_connector_list_iter_end(&conn_iter);
 }
 
-void intel_modeset_driver_remove(struct drm_device *dev)
+void intel_modeset_driver_remove(struct drm_i915_private *i915)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       flush_workqueue(i915->flip_wq);
+       flush_workqueue(i915->modeset_wq);
 
-       flush_workqueue(dev_priv->modeset_wq);
-
-       flush_work(&dev_priv->atomic_helper.free_work);
-       WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list));
+       flush_work(&i915->atomic_helper.free_work);
+       WARN_ON(!llist_empty(&i915->atomic_helper.free_list));
 
        /*
         * Interrupts and polling as the first thing to avoid creating havoc.
         * Too much stuff here (turning of connectors, ...) would
         * experience fancy races otherwise.
         */
-       intel_irq_uninstall(dev_priv);
+       intel_irq_uninstall(i915);
 
        /*
         * Due to the hpd irq storm handling the hotplug work can re-arm the
         * poll handlers. Hence disable polling after hpd handling is shut down.
         */
-       intel_hpd_poll_fini(dev);
+       intel_hpd_poll_fini(i915);
+
+       /*
+        * MST topology needs to be suspended so we don't have any calls to
+        * fbdev after it's finalized. MST will be destroyed later as part of
+        * drm_mode_config_cleanup()
+        */
+       intel_dp_mst_suspend(i915);
 
        /* poll work can call into fbdev, hence clean that up afterwards */
-       intel_fbdev_fini(dev_priv);
+       intel_fbdev_fini(i915);
 
        intel_unregister_dsm_handler();
 
-       intel_fbc_global_disable(dev_priv);
+       intel_fbc_global_disable(i915);
 
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
 
-       intel_hdcp_component_fini(dev_priv);
+       intel_hdcp_component_fini(i915);
 
-       drm_mode_config_cleanup(dev);
+       drm_mode_config_cleanup(&i915->drm);
 
-       intel_overlay_cleanup(dev_priv);
+       intel_overlay_cleanup(i915);
 
-       intel_gmbus_teardown(dev_priv);
+       intel_gmbus_teardown(i915);
 
-       destroy_workqueue(dev_priv->modeset_wq);
+       destroy_workqueue(i915->flip_wq);
+       destroy_workqueue(i915->modeset_wq);
 
-       intel_fbc_cleanup_cfb(dev_priv);
-}
-
-/*
- * set vga decode state - true == enable VGA decode
- */
-int intel_modeset_vga_set_state(struct drm_i915_private *dev_priv, bool state)
-{
-       unsigned reg = INTEL_GEN(dev_priv) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
-       u16 gmch_ctrl;
-
-       if (pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl)) {
-               DRM_ERROR("failed to read control word\n");
-               return -EIO;
-       }
-
-       if (!!(gmch_ctrl & INTEL_GMCH_VGA_DISABLE) == !state)
-               return 0;
-
-       if (state)
-               gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
-       else
-               gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
-
-       if (pci_write_config_word(dev_priv->bridge_dev, reg, gmch_ctrl)) {
-               DRM_ERROR("failed to write control word\n");
-               return -EIO;
-       }
-
-       return 0;
+       intel_fbc_cleanup_cfb(i915);
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
@@ -17212,7 +17978,7 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
 
        BUILD_BUG_ON(ARRAY_SIZE(transcoders) != ARRAY_SIZE(error->transcoder));
 
-       if (!HAS_DISPLAY(dev_priv))
+       if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv))
                return NULL;
 
        error = kzalloc(sizeof(*error), GFP_ATOMIC);
@@ -17291,7 +18057,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
        if (!error)
                return;
 
-       err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev_priv)->num_pipes);
+       err_printf(m, "Num Pipes: %d\n", INTEL_NUM_PIPES(dev_priv));
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                err_printf(m, "PWR_WELL_CTL2: %08x\n",
                           error->power_well_driver);