]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
Merge airlied/drm-next into drm-misc-next
[linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 123585eeb87db849d84e78b0892e10f962b14d9b..3b48fd2561feccc48b5e0c549ee68e5d25214555 100644 (file)
@@ -219,10 +219,8 @@ intel_fdi_link_freq(struct drm_i915_private *dev_priv,
 {
        if (HAS_DDI(dev_priv))
                return pipe_config->port_clock; /* SPLL */
-       else if (IS_GEN5(dev_priv))
-               return ((I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2) * 10000;
        else
-               return 270000;
+               return dev_priv->fdi_pll_freq;
 }
 
 static const struct intel_limit intel_limits_i8xx_dac = {
@@ -491,7 +489,7 @@ static const struct intel_limit intel_limits_bxt = {
 };
 
 static bool
-needs_modeset(struct drm_crtc_state *state)
+needs_modeset(const struct drm_crtc_state *state)
 {
        return drm_atomic_crtc_needs_modeset(state);
 }
@@ -560,11 +558,11 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock)
 }
 
 #define INTELPllInvalid(s)   do { /* DRM_DEBUG(s); */ return false; } while (0)
-/**
+
+/*
  * Returns whether the given set of divisors are valid for a given refclk with
  * the given connectors.
  */
-
 static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv,
                               const struct intel_limit *limit,
                               const struct dpll *clock)
@@ -1040,28 +1038,14 @@ static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc)
        wait_for_pipe_scanline_moving(crtc, true);
 }
 
-/*
- * intel_wait_for_pipe_off - wait for pipe to turn off
- * @crtc: crtc whose pipe to wait for
- *
- * After disabling a pipe, we can't wait for vblank in the usual way,
- * spinning on the vblank interrupt status bit, since we won't actually
- * see an interrupt when the pipe is disabled.
- *
- * On Gen4 and above:
- *   wait for the pipe register state bit to turn off
- *
- * Otherwise:
- *   wait for the display line value to settle (it usually
- *   ends up stopping at the start of the next frame).
- *
- */
-static void intel_wait_for_pipe_off(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 drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
 
        if (INTEL_GEN(dev_priv) >= 4) {
+               enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
                i915_reg_t reg = PIPECONF(cpu_transcoder);
 
                /* Wait for the Pipe State to go off */
@@ -1211,23 +1195,6 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)
             pipe_name(pipe));
 }
 
-static void assert_cursor(struct drm_i915_private *dev_priv,
-                         enum pipe pipe, bool state)
-{
-       bool cur_state;
-
-       if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
-               cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
-       else
-               cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
-
-       I915_STATE_WARN(cur_state != state,
-            "cursor on pipe %c assertion failure (expected %s, current %s)\n",
-                       pipe_name(pipe), onoff(state), onoff(cur_state));
-}
-#define assert_cursor_enabled(d, p) assert_cursor(d, p, true)
-#define assert_cursor_disabled(d, p) assert_cursor(d, p, false)
-
 void assert_pipe(struct drm_i915_private *dev_priv,
                 enum pipe pipe, bool state)
 {
@@ -1255,77 +1222,25 @@ void assert_pipe(struct drm_i915_private *dev_priv,
                        pipe_name(pipe), onoff(state), onoff(cur_state));
 }
 
-static void assert_plane(struct drm_i915_private *dev_priv,
-                        enum plane plane, bool state)
+static void assert_plane(struct intel_plane *plane, bool state)
 {
-       u32 val;
-       bool cur_state;
+       bool cur_state = plane->get_hw_state(plane);
 
-       val = I915_READ(DSPCNTR(plane));
-       cur_state = !!(val & DISPLAY_PLANE_ENABLE);
        I915_STATE_WARN(cur_state != state,
-            "plane %c assertion failure (expected %s, current %s)\n",
-                       plane_name(plane), onoff(state), onoff(cur_state));
+                       "%s assertion failure (expected %s, current %s)\n",
+                       plane->base.name, onoff(state), onoff(cur_state));
 }
 
-#define assert_plane_enabled(d, p) assert_plane(d, p, true)
-#define assert_plane_disabled(d, p) assert_plane(d, p, false)
-
-static void assert_planes_disabled(struct drm_i915_private *dev_priv,
-                                  enum pipe pipe)
-{
-       int i;
-
-       /* Primary planes are fixed to pipes on gen4+ */
-       if (INTEL_GEN(dev_priv) >= 4) {
-               u32 val = I915_READ(DSPCNTR(pipe));
-               I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE,
-                    "plane %c assertion failure, should be disabled but not\n",
-                    plane_name(pipe));
-               return;
-       }
-
-       /* Need to check both planes against the pipe */
-       for_each_pipe(dev_priv, i) {
-               u32 val = I915_READ(DSPCNTR(i));
-               enum pipe cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
-                       DISPPLANE_SEL_PIPE_SHIFT;
-               I915_STATE_WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
-                    "plane %c assertion failure, should be off on pipe %c but is still active\n",
-                    plane_name(i), pipe_name(pipe));
-       }
-}
+#define assert_plane_enabled(p) assert_plane(p, true)
+#define assert_plane_disabled(p) assert_plane(p, false)
 
-static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
-                                   enum pipe pipe)
+static void assert_planes_disabled(struct intel_crtc *crtc)
 {
-       int sprite;
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_plane *plane;
 
-       if (INTEL_GEN(dev_priv) >= 9) {
-               for_each_sprite(dev_priv, pipe, sprite) {
-                       u32 val = I915_READ(PLANE_CTL(pipe, sprite));
-                       I915_STATE_WARN(val & PLANE_CTL_ENABLE,
-                            "plane %d assertion failure, should be off on pipe %c but is still active\n",
-                            sprite, pipe_name(pipe));
-               }
-       } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               for_each_sprite(dev_priv, pipe, sprite) {
-                       u32 val = I915_READ(SPCNTR(pipe, PLANE_SPRITE0 + sprite));
-                       I915_STATE_WARN(val & SP_ENABLE,
-                            "sprite %c assertion failure, should be off on pipe %c but is still active\n",
-                            sprite_name(pipe, sprite), pipe_name(pipe));
-               }
-       } else if (INTEL_GEN(dev_priv) >= 7) {
-               u32 val = I915_READ(SPRCTL(pipe));
-               I915_STATE_WARN(val & SPRITE_ENABLE,
-                    "sprite %c assertion failure, should be off on pipe %c but is still active\n",
-                    plane_name(pipe), pipe_name(pipe));
-       } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) {
-               u32 val = I915_READ(DVSCNTR(pipe));
-               I915_STATE_WARN(val & DVS_ENABLE,
-                    "sprite %c assertion failure, should be off on pipe %c but is still active\n",
-                    plane_name(pipe), pipe_name(pipe));
-       }
+       for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane)
+               assert_plane_disabled(plane);
 }
 
 static void assert_vblank_disabled(struct drm_crtc *crtc)
@@ -1722,7 +1637,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
        u32 port_mask;
        i915_reg_t dpll_reg;
 
-       switch (dport->port) {
+       switch (dport->base.port) {
        case PORT_B:
                port_mask = DPLL_PORTB_READY_MASK;
                dpll_reg = DPLL(0);
@@ -1744,7 +1659,8 @@ void vlv_wait_port_ready(struct drm_i915_private *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->port), I915_READ(dpll_reg) & port_mask, expected_mask);
+                    port_name(dport->base.port),
+                    I915_READ(dpll_reg) & port_mask, expected_mask);
 }
 
 static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
@@ -1892,35 +1808,24 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
-       WARN_ON(!crtc->config->has_pch_encoder);
-
        if (HAS_PCH_LPT(dev_priv))
                return PIPE_A;
        else
                return crtc->pipe;
 }
 
-/**
- * intel_enable_pipe - enable a pipe, asserting requirements
- * @crtc: crtc responsible for the pipe
- *
- * Enable @crtc's pipe, making sure that various hardware specific requirements
- * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
- */
-static void intel_enable_pipe(struct intel_crtc *crtc)
+static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.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;
-       enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
        i915_reg_t reg;
        u32 val;
 
        DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe));
 
-       assert_planes_disabled(dev_priv, pipe);
-       assert_cursor_disabled(dev_priv, pipe);
-       assert_sprites_disabled(dev_priv, pipe);
+       assert_planes_disabled(crtc);
 
        /*
         * A pipe without a PLL won't actually be able to drive bits from
@@ -1928,12 +1833,12 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
         * need the check.
         */
        if (HAS_GMCH_DISPLAY(dev_priv)) {
-               if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI))
+               if (intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI))
                        assert_dsi_pll_enabled(dev_priv);
                else
                        assert_pll_enabled(dev_priv, pipe);
        } else {
-               if (crtc->config->has_pch_encoder) {
+               if (new_crtc_state->has_pch_encoder) {
                        /* if driving the PCH, we need FDI enabled */
                        assert_fdi_rx_pll_enabled(dev_priv,
                                                  intel_crtc_pch_transcoder(crtc));
@@ -1961,24 +1866,15 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
         * when it's derived from the timestamps. So let's wait for the
         * pipe to start properly before we call drm_crtc_vblank_on()
         */
-       if (dev->max_vblank_count == 0)
+       if (dev_priv->drm.max_vblank_count == 0)
                intel_wait_for_pipe_scanline_moving(crtc);
 }
 
-/**
- * intel_disable_pipe - disable a pipe, asserting requirements
- * @crtc: crtc whose pipes is to be disabled
- *
- * Disable the pipe of @crtc, making sure that various hardware
- * specific requirements are met, if applicable, e.g. plane
- * disabled, panel fitter off, etc.
- *
- * Will wait until the pipe has shut down before returning.
- */
-static void intel_disable_pipe(struct intel_crtc *crtc)
+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 drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
+       enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
        enum pipe pipe = crtc->pipe;
        i915_reg_t reg;
        u32 val;
@@ -1989,9 +1885,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
         * Make sure planes won't keep trying to pump pixels to us,
         * or we might hang the display.
         */
-       assert_planes_disabled(dev_priv, pipe);
-       assert_cursor_disabled(dev_priv, pipe);
-       assert_sprites_disabled(dev_priv, pipe);
+       assert_planes_disabled(crtc);
 
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
@@ -2002,7 +1896,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
         * Double wide has implications for planes
         * so best keep it disabled when not needed.
         */
-       if (crtc->config->double_wide)
+       if (old_crtc_state->double_wide)
                val &= ~PIPECONF_DOUBLE_WIDE;
 
        /* Don't disable pipe or pipe PLLs if needed */
@@ -2011,7 +1905,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
 
        I915_WRITE(reg, val);
        if ((val & PIPECONF_ENABLE) == 0)
-               intel_wait_for_pipe_off(crtc);
+               intel_wait_for_pipe_off(old_crtc_state);
 }
 
 static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
@@ -2135,12 +2029,12 @@ static unsigned int intel_cursor_alignment(const struct drm_i915_private *dev_pr
 
 static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
 {
-       if (INTEL_INFO(dev_priv)->gen >= 9)
+       if (INTEL_GEN(dev_priv) >= 9)
                return 256 * 1024;
        else if (IS_I965G(dev_priv) || IS_I965GM(dev_priv) ||
                 IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                return 128 * 1024;
-       else if (INTEL_INFO(dev_priv)->gen >= 4)
+       else if (INTEL_GEN(dev_priv) >= 4)
                return 4 * 1024;
        else
                return 0;
@@ -2173,14 +2067,26 @@ 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 drm_i915_private *dev_priv = to_i915(plane->base.dev);
+
+       return INTEL_GEN(dev_priv) < 4 || plane->has_fbc;
+}
+
 struct i915_vma *
-intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
+                          unsigned int rotation,
+                          bool uses_fence,
+                          unsigned long *out_flags)
 {
        struct drm_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct i915_ggtt_view view;
        struct i915_vma *vma;
+       unsigned int pinctl;
        u32 alignment;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -2208,11 +2114,26 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
 
        atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
 
-       vma = i915_gem_object_pin_to_display_plane(obj, alignment, &view);
+       pinctl = 0;
+
+       /* 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.
+        */
+       if (HAS_GMCH_DISPLAY(dev_priv))
+               pinctl |= PIN_MAPPABLE;
+
+       vma = i915_gem_object_pin_to_display_plane(obj,
+                                                  alignment, &view, pinctl);
        if (IS_ERR(vma))
                goto err;
 
-       if (i915_vma_is_map_and_fenceable(vma)) {
+       if (uses_fence && i915_vma_is_map_and_fenceable(vma)) {
+               int ret;
+
                /* 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
@@ -2229,7 +2150,15 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
                 * something and try to run the system in a "less than optimal"
                 * mode that matches the user configuration.
                 */
-               i915_vma_pin_fence(vma);
+               ret = i915_vma_pin_fence(vma);
+               if (ret != 0 && INTEL_GEN(dev_priv) < 4) {
+                       i915_gem_object_unpin_from_display_plane(vma);
+                       vma = ERR_PTR(ret);
+                       goto err;
+               }
+
+               if (ret == 0 && vma->fence)
+                       *out_flags |= PLANE_HAS_FENCE;
        }
 
        i915_vma_get(vma);
@@ -2240,11 +2169,12 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
        return vma;
 }
 
-void intel_unpin_fb_vma(struct i915_vma *vma)
+void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags)
 {
        lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
 
-       i915_vma_unpin_fence(vma);
+       if (flags & PLANE_HAS_FENCE)
+               i915_vma_unpin_fence(vma);
        i915_gem_object_unpin_from_display_plane(vma);
        i915_vma_put(vma);
 }
@@ -2493,6 +2423,20 @@ static unsigned int intel_fb_modifier_to_tiling(uint64_t fb_modifier)
        }
 }
 
+/*
+ * From the Sky Lake PRM:
+ * "The Color Control Surface (CCS) contains the compression status of
+ *  the cache-line pairs. The compression state of the cache-line pair
+ *  is specified by 2 bits in the CCS. Each CCS cache-line represents
+ *  an area on the main surface of 16 x16 sets of 128 byte Y-tiled
+ *  cache-line-pairs. CCS is always Y tiled."
+ *
+ * Since cache line pairs refers to horizontally adjacent cache lines,
+ * each cache line in the CCS corresponds to an area of 32x16 cache
+ * lines on the main surface. Since each pixel is 4 bytes, this gives
+ * us a ratio of one byte in the CCS for each 8x16 pixels in the
+ * main surface.
+ */
 static const struct drm_format_info ccs_formats[] = {
        { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
        { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2, .cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
@@ -2745,7 +2689,6 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct i915_ggtt *ggtt = &dev_priv->ggtt;
        struct drm_i915_gem_object *obj = NULL;
        struct drm_mode_fb_cmd2 mode_cmd = { 0 };
        struct drm_framebuffer *fb = &plane_config->fb->base;
@@ -2761,7 +2704,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
        /* If the FB is too big, just don't use it since fbdev is not very
         * important and we should probably use that space with FBC or other
         * features. */
-       if (size_aligned * 2 > ggtt->stolen_usable_size)
+       if (size_aligned * 2 > dev_priv->stolen_usable_size)
                return false;
 
        mutex_lock(&dev->struct_mutex);
@@ -2820,6 +2763,23 @@ intel_set_plane_visible(struct intel_crtc_state *crtc_state,
                      crtc_state->active_planes);
 }
 
+static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
+                                        struct intel_plane *plane)
+{
+       struct intel_crtc_state *crtc_state =
+               to_intel_crtc_state(crtc->base.state);
+       struct intel_plane_state *plane_state =
+               to_intel_plane_state(plane->base.state);
+
+       intel_set_plane_visible(crtc_state, plane_state, false);
+
+       if (plane->id == PLANE_PRIMARY)
+               intel_pre_disable_primary_noatomic(&crtc->base);
+
+       trace_intel_disable_plane(&plane->base, crtc);
+       plane->disable_plane(plane, crtc);
+}
+
 static void
 intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
                             struct intel_initial_plane_config *plane_config)
@@ -2877,19 +2837,17 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
         * simplest solution is to just disable the primary plane now and
         * pretend the BIOS never had it enabled.
         */
-       intel_set_plane_visible(to_intel_crtc_state(crtc_state),
-                               to_intel_plane_state(plane_state),
-                               false);
-       intel_pre_disable_primary_noatomic(&intel_crtc->base);
-       trace_intel_disable_plane(primary, intel_crtc);
-       intel_plane->disable_plane(intel_plane, intel_crtc);
+       intel_plane_disable_noatomic(intel_crtc, intel_plane);
 
        return;
 
 valid_fb:
        mutex_lock(&dev->struct_mutex);
        intel_state->vma =
-               intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
+               intel_pin_and_fence_fb_obj(fb,
+                                          primary->state->rotation,
+                                          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",
@@ -3012,14 +2970,19 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state
        return true;
 }
 
-static int skl_check_main_surface(struct intel_plane_state *plane_state)
+static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,
+                                 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;
+       int dst_x = plane_state->base.dst.x1;
+       int pipe_src_w = crtc_state->pipe_src_w;
        int max_width = skl_max_plane_width(fb, 0, rotation);
        int max_height = 4096;
        u32 alignment, offset, aux_offset = plane_state->aux.offset;
@@ -3030,6 +2993,24 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
                return -EINVAL;
        }
 
+       /*
+        * Display WA #1175: cnl,glk
+        * Planes other than the cursor may cause FIFO underflow and display
+        * corruption if starting less than 4 pixels from the right edge of
+        * the screen.
+        * Besides the above WA fix the similar problem, where planes other
+        * than the cursor ending less than 4 pixels from the left edge of the
+        * screen may cause FIFO underflow and display corruption.
+        */
+       if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
+           (dst_x + w < 4 || dst_x > pipe_src_w - 4)) {
+               DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
+                             dst_x + w < 4 ? "end" : "start",
+                             dst_x + w < 4 ? dst_x + w : dst_x,
+                             4, pipe_src_w - 4);
+               return -ERANGE;
+       }
+
        intel_add_fb_offsets(&x, &y, plane_state, 0);
        offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
        alignment = intel_surf_alignment(fb, 0);
@@ -3121,8 +3102,6 @@ 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)
 {
-       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
-       struct intel_crtc *crtc = to_intel_crtc(plane_state->base.crtc);
        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;
@@ -3132,20 +3111,6 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
        int y = src_y / vsub;
        u32 offset;
 
-       switch (plane->id) {
-       case PLANE_PRIMARY:
-       case PLANE_SPRITE0:
-               break;
-       default:
-               DRM_DEBUG_KMS("RC support only on plane 1 and 2\n");
-               return -EINVAL;
-       }
-
-       if (crtc->pipe == PIPE_C) {
-               DRM_DEBUG_KMS("No RC support on pipe C\n");
-               return -EINVAL;
-       }
-
        if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) {
                DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n",
                              plane_state->base.rotation);
@@ -3162,12 +3127,19 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
        return 0;
 }
 
-int skl_check_plane_surface(struct intel_plane_state *plane_state)
+int skl_check_plane_surface(const struct intel_crtc_state *crtc_state,
+                           struct intel_plane_state *plane_state)
 {
        const struct drm_framebuffer *fb = plane_state->base.fb;
        unsigned int rotation = plane_state->base.rotation;
        int ret;
 
+       if (rotation & DRM_MODE_REFLECT_X &&
+           fb->modifier == DRM_FORMAT_MOD_LINEAR) {
+               DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
+               return -EINVAL;
+       }
+
        if (!plane_state->base.visible)
                return 0;
 
@@ -3196,7 +3168,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
                plane_state->aux.y = 0;
        }
 
-       ret = skl_check_main_surface(plane_state);
+       ret = skl_check_main_surface(crtc_state, plane_state);
        if (ret)
                return ret;
 
@@ -3222,7 +3194,7 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
 
-       if (INTEL_GEN(dev_priv) < 4)
+       if (INTEL_GEN(dev_priv) < 5)
                dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
 
        switch (fb->format->format) {
@@ -3302,16 +3274,16 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
        return 0;
 }
 
-static void i9xx_update_primary_plane(struct intel_plane *primary,
-                                     const struct intel_crtc_state *crtc_state,
-                                     const struct intel_plane_state *plane_state)
+static void i9xx_update_plane(struct intel_plane *plane,
+                             const struct intel_crtc_state *crtc_state,
+                             const struct intel_plane_state *plane_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(primary->base.dev);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        const struct drm_framebuffer *fb = plane_state->base.fb;
-       enum plane plane = primary->plane;
+       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
        u32 linear_offset;
        u32 dspcntr = plane_state->ctl;
-       i915_reg_t reg = DSPCNTR(plane);
+       i915_reg_t reg = DSPCNTR(i9xx_plane);
        int x = plane_state->main.x;
        int y = plane_state->main.y;
        unsigned long irqflags;
@@ -3330,34 +3302,34 @@ static void i9xx_update_primary_plane(struct intel_plane *primary,
                /* pipesrc and dspsize control the size that is scaled from,
                 * which should always be the user's requested size.
                 */
-               I915_WRITE_FW(DSPSIZE(plane),
+               I915_WRITE_FW(DSPSIZE(i9xx_plane),
                              ((crtc_state->pipe_src_h - 1) << 16) |
                              (crtc_state->pipe_src_w - 1));
-               I915_WRITE_FW(DSPPOS(plane), 0);
-       } else if (IS_CHERRYVIEW(dev_priv) && plane == PLANE_B) {
-               I915_WRITE_FW(PRIMSIZE(plane),
+               I915_WRITE_FW(DSPPOS(i9xx_plane), 0);
+       } else if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) {
+               I915_WRITE_FW(PRIMSIZE(i9xx_plane),
                              ((crtc_state->pipe_src_h - 1) << 16) |
                              (crtc_state->pipe_src_w - 1));
-               I915_WRITE_FW(PRIMPOS(plane), 0);
-               I915_WRITE_FW(PRIMCNSTALPHA(plane), 0);
+               I915_WRITE_FW(PRIMPOS(i9xx_plane), 0);
+               I915_WRITE_FW(PRIMCNSTALPHA(i9xx_plane), 0);
        }
 
        I915_WRITE_FW(reg, dspcntr);
 
-       I915_WRITE_FW(DSPSTRIDE(plane), fb->pitches[0]);
+       I915_WRITE_FW(DSPSTRIDE(i9xx_plane), fb->pitches[0]);
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
-               I915_WRITE_FW(DSPSURF(plane),
+               I915_WRITE_FW(DSPSURF(i9xx_plane),
                              intel_plane_ggtt_offset(plane_state) +
                              dspaddr_offset);
-               I915_WRITE_FW(DSPOFFSET(plane), (y << 16) | x);
+               I915_WRITE_FW(DSPOFFSET(i9xx_plane), (y << 16) | x);
        } else if (INTEL_GEN(dev_priv) >= 4) {
-               I915_WRITE_FW(DSPSURF(plane),
+               I915_WRITE_FW(DSPSURF(i9xx_plane),
                              intel_plane_ggtt_offset(plane_state) +
                              dspaddr_offset);
-               I915_WRITE_FW(DSPTILEOFF(plane), (y << 16) | x);
-               I915_WRITE_FW(DSPLINOFF(plane), linear_offset);
+               I915_WRITE_FW(DSPTILEOFF(i9xx_plane), (y << 16) | x);
+               I915_WRITE_FW(DSPLINOFF(i9xx_plane), linear_offset);
        } else {
-               I915_WRITE_FW(DSPADDR(plane),
+               I915_WRITE_FW(DSPADDR(i9xx_plane),
                              intel_plane_ggtt_offset(plane_state) +
                              dspaddr_offset);
        }
@@ -3366,25 +3338,49 @@ static void i9xx_update_primary_plane(struct intel_plane *primary,
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-static void i9xx_disable_primary_plane(struct intel_plane *primary,
-                                      struct intel_crtc *crtc)
+static void i9xx_disable_plane(struct intel_plane *plane,
+                              struct intel_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = to_i915(primary->base.dev);
-       enum plane plane = primary->plane;
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
-       I915_WRITE_FW(DSPCNTR(plane), 0);
-       if (INTEL_INFO(dev_priv)->gen >= 4)
-               I915_WRITE_FW(DSPSURF(plane), 0);
+       I915_WRITE_FW(DSPCNTR(i9xx_plane), 0);
+       if (INTEL_GEN(dev_priv) >= 4)
+               I915_WRITE_FW(DSPSURF(i9xx_plane), 0);
        else
-               I915_WRITE_FW(DSPADDR(plane), 0);
-       POSTING_READ_FW(DSPCNTR(plane));
+               I915_WRITE_FW(DSPADDR(i9xx_plane), 0);
+       POSTING_READ_FW(DSPCNTR(i9xx_plane));
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static bool i9xx_plane_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+       enum pipe pipe = plane->pipe;
+       bool ret;
+
+       /*
+        * Not 100% correct for planes that can move between pipes,
+        * but that's only the case for gen2-4 which don't have any
+        * display power wells.
+        */
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(DSPCNTR(i9xx_plane)) & DISPLAY_PLANE_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static u32
 intel_fb_stride_alignment(const struct drm_framebuffer *fb, int plane)
 {
@@ -3451,20 +3447,11 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format)
        case DRM_FORMAT_RGB565:
                return PLANE_CTL_FORMAT_RGB_565;
        case DRM_FORMAT_XBGR8888:
+       case DRM_FORMAT_ABGR8888:
                return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX;
        case DRM_FORMAT_XRGB8888:
-               return PLANE_CTL_FORMAT_XRGB_8888;
-       /*
-        * XXX: For ARBG/ABGR formats we default to expecting scanout buffers
-        * to be already pre-multiplied. We need to add a knob (or a different
-        * DRM_FORMAT) for user-space to configure that.
-        */
-       case DRM_FORMAT_ABGR8888:
-               return PLANE_CTL_FORMAT_XRGB_8888 | PLANE_CTL_ORDER_RGBX |
-                       PLANE_CTL_ALPHA_SW_PREMULTIPLY;
        case DRM_FORMAT_ARGB8888:
-               return PLANE_CTL_FORMAT_XRGB_8888 |
-                       PLANE_CTL_ALPHA_SW_PREMULTIPLY;
+               return PLANE_CTL_FORMAT_XRGB_8888;
        case DRM_FORMAT_XRGB2101010:
                return PLANE_CTL_FORMAT_XRGB_2101010;
        case DRM_FORMAT_XBGR2101010:
@@ -3484,6 +3471,33 @@ static u32 skl_plane_ctl_format(uint32_t pixel_format)
        return 0;
 }
 
+/*
+ * XXX: For ARBG/ABGR formats we default to expecting scanout buffers
+ * to be already pre-multiplied. We need to add a knob (or a different
+ * DRM_FORMAT) for user-space to configure that.
+ */
+static u32 skl_plane_ctl_alpha(uint32_t pixel_format)
+{
+       switch (pixel_format) {
+       case DRM_FORMAT_ABGR8888:
+       case DRM_FORMAT_ARGB8888:
+               return PLANE_CTL_ALPHA_SW_PREMULTIPLY;
+       default:
+               return PLANE_CTL_ALPHA_DISABLE;
+       }
+}
+
+static u32 glk_plane_color_ctl_alpha(uint32_t pixel_format)
+{
+       switch (pixel_format) {
+       case DRM_FORMAT_ABGR8888:
+       case DRM_FORMAT_ARGB8888:
+               return PLANE_COLOR_ALPHA_SW_PREMULTIPLY;
+       default:
+               return PLANE_COLOR_ALPHA_DISABLE;
+       }
+}
+
 static u32 skl_plane_ctl_tiling(uint64_t fb_modifier)
 {
        switch (fb_modifier) {
@@ -3506,9 +3520,9 @@ static u32 skl_plane_ctl_tiling(uint64_t fb_modifier)
        return 0;
 }
 
-static u32 skl_plane_ctl_rotation(unsigned int rotation)
+static u32 skl_plane_ctl_rotate(unsigned int rotate)
 {
-       switch (rotation) {
+       switch (rotate) {
        case DRM_MODE_ROTATE_0:
                break;
        /*
@@ -3522,7 +3536,22 @@ static u32 skl_plane_ctl_rotation(unsigned int rotation)
        case DRM_MODE_ROTATE_270:
                return PLANE_CTL_ROTATE_90;
        default:
-               MISSING_CASE(rotation);
+               MISSING_CASE(rotate);
+       }
+
+       return 0;
+}
+
+static u32 cnl_plane_ctl_flip(unsigned int reflect)
+{
+       switch (reflect) {
+       case 0:
+               break;
+       case DRM_MODE_REFLECT_X:
+               return PLANE_CTL_FLIP_HORIZONTAL;
+       case DRM_MODE_REFLECT_Y:
+       default:
+               MISSING_CASE(reflect);
        }
 
        return 0;
@@ -3540,16 +3569,27 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
 
        plane_ctl = PLANE_CTL_ENABLE;
 
-       if (!IS_GEMINILAKE(dev_priv) && !IS_CANNONLAKE(dev_priv)) {
+       if (INTEL_GEN(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) {
+               plane_ctl |= skl_plane_ctl_alpha(fb->format->format);
                plane_ctl |=
                        PLANE_CTL_PIPE_GAMMA_ENABLE |
                        PLANE_CTL_PIPE_CSC_ENABLE |
                        PLANE_CTL_PLANE_GAMMA_DISABLE;
+
+               if (plane_state->base.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)
+                       plane_ctl |= PLANE_CTL_YUV_RANGE_CORRECTION_DISABLE;
        }
 
        plane_ctl |= skl_plane_ctl_format(fb->format->format);
        plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
-       plane_ctl |= skl_plane_ctl_rotation(rotation);
+       plane_ctl |= skl_plane_ctl_rotate(rotation & DRM_MODE_ROTATE_MASK);
+
+       if (INTEL_GEN(dev_priv) >= 10)
+               plane_ctl |= cnl_plane_ctl_flip(rotation &
+                                               DRM_MODE_REFLECT_MASK);
 
        if (key->flags & I915_SET_COLORKEY_DESTINATION)
                plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION;
@@ -3559,6 +3599,30 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
        return plane_ctl;
 }
 
+u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
+                       const struct intel_plane_state *plane_state)
+{
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       u32 plane_color_ctl = 0;
+
+       plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
+       plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
+       plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
+       plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format);
+
+       if (intel_format_is_yuv(fb->format->format)) {
+               if (plane_state->base.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)
+                       plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
+       }
+
+       return plane_color_ctl;
+}
+
 static int
 __intel_display_resume(struct drm_device *dev,
                       struct drm_atomic_state *state,
@@ -4501,7 +4565,7 @@ intel_trans_dp_port_sel(struct intel_crtc *crtc)
        for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
                if (encoder->type == INTEL_OUTPUT_DP ||
                    encoder->type == INTEL_OUTPUT_EDP)
-                       return enc_to_dig_port(&encoder->base)->port;
+                       return encoder->port;
        }
 
        return -1;
@@ -4739,8 +4803,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
 
 /**
  * skl_update_scaler_plane - Stages update to scaler state for a given plane.
- *
- * @state: crtc's scaler state
+ * @crtc_state: crtc's scaler state
  * @plane_state: atomic plane state to update
  *
  * Return
@@ -4770,7 +4833,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
                return ret;
 
        /* check colorkey */
-       if (plane_state->ckey.flags != I915_SET_COLORKEY_NONE) {
+       if (plane_state->ckey.flags) {
                DRM_DEBUG_KMS("[PLANE:%d:%s] scaling with color key not allowed",
                              intel_plane->base.base.id,
                              intel_plane->base.name);
@@ -4852,12 +4915,13 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc)
        }
 }
 
-void hsw_enable_ips(struct intel_crtc *crtc)
+void hsw_enable_ips(const struct intel_crtc_state *crtc_state)
 {
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
-       if (!crtc->config->ips_enabled)
+       if (!crtc_state->ips_enabled)
                return;
 
        /*
@@ -4865,8 +4929,8 @@ void hsw_enable_ips(struct intel_crtc *crtc)
         * This function is called from post_plane_update, which is run after
         * a vblank wait.
         */
+       WARN_ON(!(crtc_state->active_planes & ~BIT(PLANE_CURSOR)));
 
-       assert_plane_enabled(dev_priv, crtc->plane);
        if (IS_BROADWELL(dev_priv)) {
                mutex_lock(&dev_priv->pcu_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL,
@@ -4891,15 +4955,15 @@ void hsw_enable_ips(struct intel_crtc *crtc)
        }
 }
 
-void hsw_disable_ips(struct intel_crtc *crtc)
+void hsw_disable_ips(const struct intel_crtc_state *crtc_state)
 {
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
-       if (!crtc->config->ips_enabled)
+       if (!crtc_state->ips_enabled)
                return;
 
-       assert_plane_enabled(dev_priv, crtc->plane);
        if (IS_BROADWELL(dev_priv)) {
                mutex_lock(&dev_priv->pcu_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
@@ -4936,6 +5000,7 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
 /**
  * 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
@@ -4944,21 +5009,14 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
  * completely hide the primary plane.
  */
 static void
-intel_post_enable_primary(struct drm_crtc *crtc)
+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;
 
-       /*
-        * FIXME IPS should be fine as long as one plane is
-        * enabled, but in practice it seems to have problems
-        * when going from primary only to sprite only and vice
-        * versa.
-        */
-       hsw_enable_ips(intel_crtc);
-
        /*
         * Gen2 reports pipe underruns whenever all planes are disabled.
         * So don't enable underrun reporting before at least some planes
@@ -4974,9 +5032,9 @@ intel_post_enable_primary(struct drm_crtc *crtc)
        intel_check_pch_fifo_underruns(dev_priv);
 }
 
-/* FIXME move all this to pre_plane_update() with proper state tracking */
+/* FIXME get rid of this and use pre_plane_update */
 static void
-intel_pre_disable_primary(struct drm_crtc *crtc)
+intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -4985,32 +5043,12 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
 
        /*
         * Gen2 reports pipe underruns whenever all planes are disabled.
-        * So diasble underrun reporting before all the planes get disabled.
-        * FIXME: Need to fix the logic to work when we turn off all planes
-        * but leave the pipe running.
+        * So disable underrun reporting before all the planes get disabled.
         */
        if (IS_GEN2(dev_priv))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
-       /*
-        * FIXME IPS should be fine as long as one plane is
-        * enabled, but in practice it seems to have problems
-        * when going from primary only to sprite only and vice
-        * versa.
-        */
-       hsw_disable_ips(intel_crtc);
-}
-
-/* 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;
-
-       intel_pre_disable_primary(crtc);
+       hsw_disable_ips(to_intel_crtc_state(crtc->state));
 
        /*
         * Vblank time updates from the shadow to live plane control register
@@ -5026,6 +5064,38 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
                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)
+{
+       if (!old_crtc_state->ips_enabled)
+               return false;
+
+       if (needs_modeset(&new_crtc_state->base))
+               return true;
+
+       return !new_crtc_state->ips_enabled;
+}
+
+static bool hsw_post_update_enable_ips(const struct intel_crtc_state *old_crtc_state,
+                                      const struct intel_crtc_state *new_crtc_state)
+{
+       if (!new_crtc_state->ips_enabled)
+               return false;
+
+       if (needs_modeset(&new_crtc_state->base))
+               return true;
+
+       /*
+        * We can't read out IPS on broadwell, assume the worst and
+        * 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)
+               return true;
+
+       return !old_crtc_state->ips_enabled;
+}
+
 static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
@@ -5042,6 +5112,9 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
        if (pipe_config->update_wm_post && pipe_config->base.active)
                intel_update_watermarks(crtc);
 
+       if (hsw_post_update_enable_ips(old_crtc_state, pipe_config))
+               hsw_enable_ips(pipe_config);
+
        if (old_pri_state) {
                struct intel_plane_state *primary_state =
                        intel_atomic_get_new_plane_state(to_intel_atomic_state(old_state),
@@ -5054,7 +5127,7 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
                if (primary_state->base.visible &&
                    (needs_modeset(&pipe_config->base) ||
                     !old_primary_state->base.visible))
-                       intel_post_enable_primary(&crtc->base);
+                       intel_post_enable_primary(&crtc->base, pipe_config);
        }
 }
 
@@ -5072,6 +5145,9 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
        struct intel_atomic_state *old_intel_state =
                to_intel_atomic_state(old_state);
 
+       if (hsw_pre_update_disable_ips(old_crtc_state, pipe_config))
+               hsw_disable_ips(old_crtc_state);
+
        if (old_pri_state) {
                struct intel_plane_state *primary_state =
                        intel_atomic_get_new_plane_state(old_intel_state,
@@ -5080,10 +5156,13 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
                        to_intel_plane_state(old_pri_state);
 
                intel_fbc_pre_update(crtc, pipe_config, primary_state);
-
-               if (old_primary_state->base.visible &&
+               /*
+                * Gen2 reports pipe underruns whenever all planes are disabled.
+                * So disable underrun reporting before all the planes get disabled.
+                */
+               if (IS_GEN2(dev_priv) && old_primary_state->base.visible &&
                    (modeset || !primary_state->base.visible))
-                       intel_pre_disable_primary(&crtc->base);
+                       intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
        }
 
        /*
@@ -5346,7 +5425,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
 
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state, intel_crtc->config);
-       intel_enable_pipe(intel_crtc);
+       intel_enable_pipe(pipe_config);
 
        if (intel_crtc->config->has_pch_encoder)
                ironlake_pch_enable(pipe_config);
@@ -5386,6 +5465,20 @@ static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv,
        I915_WRITE(CLKGATE_DIS_PSL(pipe), val);
 }
 
+static void icl_pipe_mbus_enable(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
+       uint32_t val;
+
+       val = MBUS_DBOX_BW_CREDIT(1) | MBUS_DBOX_A_CREDIT(2);
+
+       /* Program B credit equally to all pipes */
+       val |= MBUS_DBOX_B_CREDIT(24 / INTEL_INFO(dev_priv)->num_pipes);
+
+       I915_WRITE(PIPE_MBUS_DBOX_CTL(pipe), val);
+}
+
 static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
                                struct drm_atomic_state *old_state)
 {
@@ -5463,9 +5556,12 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state, pipe_config);
 
+       if (INTEL_GEN(dev_priv) >= 11)
+               icl_pipe_mbus_enable(intel_crtc);
+
        /* XXX: Do the pipe assertions at the right place for BXT DSI. */
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_enable_pipe(intel_crtc);
+               intel_enable_pipe(pipe_config);
 
        if (intel_crtc->config->has_pch_encoder)
                lpt_pch_enable(pipe_config);
@@ -5531,7 +5627,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state,
        drm_crtc_vblank_off(crtc);
        assert_vblank_disabled(crtc);
 
-       intel_disable_pipe(intel_crtc);
+       intel_disable_pipe(old_crtc_state);
 
        ironlake_pfit_disable(intel_crtc, false);
 
@@ -5583,7 +5679,7 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
 
        /* XXX: Do the pipe assertions at the right place for BXT DSI. */
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_disable_pipe(intel_crtc);
+               intel_disable_pipe(old_crtc_state);
 
        if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))
                intel_ddi_set_vc_payload_alloc(intel_crtc->config, false);
@@ -5639,6 +5735,8 @@ enum intel_display_power_domain intel_port_to_power_domain(enum port port)
                return POWER_DOMAIN_PORT_DDI_D_LANES;
        case PORT_E:
                return POWER_DOMAIN_PORT_DDI_E_LANES;
+       case PORT_F:
+               return POWER_DOMAIN_PORT_DDI_F_LANES;
        default:
                MISSING_CASE(port);
                return POWER_DOMAIN_PORT_OTHER;
@@ -5659,8 +5757,8 @@ static u64 get_crtc_power_domains(struct drm_crtc *crtc,
        if (!crtc_state->base.active)
                return 0;
 
-       mask = BIT(POWER_DOMAIN_PIPE(pipe));
-       mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
+       mask = BIT_ULL(POWER_DOMAIN_PIPE(pipe));
+       mask |= BIT_ULL(POWER_DOMAIN_TRANSCODER(transcoder));
        if (crtc_state->pch_pfit.enabled ||
            crtc_state->pch_pfit.force_thru)
                mask |= BIT_ULL(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
@@ -5672,7 +5770,7 @@ static u64 get_crtc_power_domains(struct drm_crtc *crtc,
        }
 
        if (HAS_DDI(dev_priv) && crtc_state->has_audio)
-               mask |= BIT(POWER_DOMAIN_AUDIO);
+               mask |= BIT_ULL(POWER_DOMAIN_AUDIO);
 
        if (crtc_state->shared_dpll)
                mask |= BIT_ULL(POWER_DOMAIN_PLLS);
@@ -5761,7 +5859,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
 
        dev_priv->display.initial_watermarks(old_intel_state,
                                             pipe_config);
-       intel_enable_pipe(intel_crtc);
+       intel_enable_pipe(pipe_config);
 
        assert_vblank_disabled(crtc);
        drm_crtc_vblank_on(crtc);
@@ -5820,7 +5918,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
                                                     intel_crtc->config);
        else
                intel_update_watermarks(intel_crtc);
-       intel_enable_pipe(intel_crtc);
+       intel_enable_pipe(pipe_config);
 
        assert_vblank_disabled(crtc);
        drm_crtc_vblank_on(crtc);
@@ -5864,7 +5962,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
        drm_crtc_vblank_off(crtc);
        assert_vblank_disabled(crtc);
 
-       intel_disable_pipe(intel_crtc);
+       intel_disable_pipe(old_crtc_state);
 
        i9xx_pfit_disable(intel_crtc);
 
@@ -5899,6 +5997,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        enum intel_display_power_domain domain;
+       struct intel_plane *plane;
        u64 domains;
        struct drm_atomic_state *state;
        struct intel_crtc_state *crtc_state;
@@ -5907,11 +6006,12 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
        if (!intel_crtc->active)
                return;
 
-       if (crtc->primary->state->visible) {
-               intel_pre_disable_primary_noatomic(crtc);
+       for_each_intel_plane_on_crtc(&dev_priv->drm, intel_crtc, plane) {
+               const struct intel_plane_state *plane_state =
+                       to_intel_plane_state(plane->base.state);
 
-               intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
-               crtc->primary->state->visible = false;
+               if (plane_state->base.visible)
+                       intel_plane_disable_noatomic(intel_crtc, plane);
        }
 
        state = drm_atomic_state_alloc(crtc->dev);
@@ -5957,6 +6057,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
 
        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;
 }
 
 /*
@@ -6211,18 +6312,20 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
        return ret;
 }
 
-static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
-                                    struct intel_crtc_state *pipe_config)
+bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state)
 {
-       if (pipe_config->ips_force_disable)
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+       /* IPS only exists on ULT machines and is tied to pipe A. */
+       if (!hsw_crtc_supports_ips(crtc))
                return false;
 
-       if (pipe_config->pipe_bpp > 24)
+       if (!i915_modparams.enable_ips)
                return false;
 
-       /* HSW can handle pixel rate up to cdclk? */
-       if (IS_HASWELL(dev_priv))
-               return true;
+       if (crtc_state->pipe_bpp > 24)
+               return false;
 
        /*
         * We compare against max which means we must take
@@ -6231,19 +6334,36 @@ static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
         *
         * Should measure whether using a lower cdclk w/o IPS
         */
-       return pipe_config->pixel_rate <=
-               dev_priv->max_cdclk_freq * 95 / 100;
+       if (IS_BROADWELL(dev_priv) &&
+           crtc_state->pixel_rate > dev_priv->max_cdclk_freq * 95 / 100)
+               return false;
+
+       return true;
 }
 
-static void hsw_compute_ips_config(struct intel_crtc *crtc,
-                                  struct intel_crtc_state *pipe_config)
+static bool hsw_compute_ips_config(struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *dev_priv =
+               to_i915(crtc_state->base.crtc->dev);
+       struct intel_atomic_state *intel_state =
+               to_intel_atomic_state(crtc_state->base.state);
+
+       if (!hsw_crtc_state_ips_capable(crtc_state))
+               return false;
+
+       if (crtc_state->ips_force_disable)
+               return false;
 
-       pipe_config->ips_enabled = i915_modparams.enable_ips &&
-               hsw_crtc_supports_ips(crtc) &&
-               pipe_config_supports_ips(dev_priv, pipe_config);
+       /* IPS should be fine as long as at least one plane is enabled. */
+       if (!(crtc_state->active_planes & ~BIT(PLANE_CURSOR)))
+               return false;
+
+       /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
+       if (IS_BROADWELL(dev_priv) &&
+           crtc_state->pixel_rate > intel_state->cdclk.logical.cdclk * 95 / 100)
+               return false;
+
+       return true;
 }
 
 static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
@@ -6251,7 +6371,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc)
        const struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
        /* GDG double wide on either pipe, otherwise pipe A only */
-       return INTEL_INFO(dev_priv)->gen < 4 &&
+       return INTEL_GEN(dev_priv) < 4 &&
                (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
 }
 
@@ -6348,11 +6468,20 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
         * - LVDS dual channel mode
         * - Double wide pipe
         */
-       if ((intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
-            intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
-               pipe_config->pipe_src_w &= ~1;
+       if (pipe_config->pipe_src_w & 1) {
+               if (pipe_config->double_wide) {
+                       DRM_DEBUG_KMS("Odd pipe source width not supported with double wide pipe\n");
+                       return -EINVAL;
+               }
 
-       /* Cantiga+ cannot handle modes with a hsync front porch of 0.
+               if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
+                   intel_is_dual_link_lvds(dev)) {
+                       DRM_DEBUG_KMS("Odd pipe source width not supported with dual link LVDS\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* Cantiga+ cannot handle modes with a hsync front porch of 0.
         * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
         */
        if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
@@ -6361,9 +6490,6 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 
        intel_crtc_compute_pixel_rate(pipe_config);
 
-       if (HAS_IPS(dev_priv))
-               hsw_compute_ips_config(crtc, pipe_config);
-
        if (pipe_config->has_pch_encoder)
                return ironlake_fdi_compute_config(crtc, pipe_config);
 
@@ -7420,15 +7546,16 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
+       struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+       enum pipe pipe = crtc->pipe;
        u32 val, base, offset;
-       int pipe = crtc->pipe, plane = crtc->plane;
        int fourcc, pixel_format;
        unsigned int aligned_height;
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
 
-       val = I915_READ(DSPCNTR(plane));
-       if (!(val & DISPLAY_PLANE_ENABLE))
+       if (!plane->get_hw_state(plane))
                return;
 
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
@@ -7441,6 +7568,8 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
 
        fb->dev = dev;
 
+       val = I915_READ(DSPCNTR(i9xx_plane));
+
        if (INTEL_GEN(dev_priv) >= 4) {
                if (val & DISPPLANE_TILED) {
                        plane_config->tiling = I915_TILING_X;
@@ -7452,14 +7581,17 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
        fourcc = i9xx_format_to_fourcc(pixel_format);
        fb->format = drm_format_info(fourcc);
 
-       if (INTEL_GEN(dev_priv) >= 4) {
+       if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
+               offset = I915_READ(DSPOFFSET(i9xx_plane));
+               base = I915_READ(DSPSURF(i9xx_plane)) & 0xfffff000;
+       } else if (INTEL_GEN(dev_priv) >= 4) {
                if (plane_config->tiling)
-                       offset = I915_READ(DSPTILEOFF(plane));
+                       offset = I915_READ(DSPTILEOFF(i9xx_plane));
                else
-                       offset = I915_READ(DSPLINOFF(plane));
-               base = I915_READ(DSPSURF(plane)) & 0xfffff000;
+                       offset = I915_READ(DSPLINOFF(i9xx_plane));
+               base = I915_READ(DSPSURF(i9xx_plane)) & 0xfffff000;
        } else {
-               base = I915_READ(DSPADDR(plane));
+               base = I915_READ(DSPADDR(i9xx_plane));
        }
        plane_config->base = base;
 
@@ -7467,15 +7599,15 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
        fb->width = ((val >> 16) & 0xfff) + 1;
        fb->height = ((val >> 0) & 0xfff) + 1;
 
-       val = I915_READ(DSPSTRIDE(pipe));
+       val = I915_READ(DSPSTRIDE(i9xx_plane));
        fb->pitches[0] = val & 0xffffffc0;
 
        aligned_height = intel_fb_align_height(fb, 0, fb->height);
 
        plane_config->size = fb->pitches[0] * aligned_height;
 
-       DRM_DEBUG_KMS("pipe/plane %c/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
-                     pipe_name(pipe), plane, fb->width, fb->height,
+       DRM_DEBUG_KMS("%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
+                     crtc->base.name, plane->base.name, fb->width, fb->height,
                      fb->format->cpp[0] * 8, base, fb->pitches[0],
                      plane_config->size);
 
@@ -7651,7 +7783,7 @@ static void ironlake_init_pch_refclk(struct drm_i915_private *dev_priv)
                        break;
                case INTEL_OUTPUT_EDP:
                        has_panel = true;
-                       if (enc_to_dig_port(&encoder->base)->port == PORT_A)
+                       if (encoder->port == PORT_A)
                                has_cpu_edp = true;
                        break;
                default:
@@ -8126,7 +8258,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_crtc_state *config = intel_crtc->config;
 
-       if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
+       if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) {
                u32 val = 0;
 
                switch (intel_crtc->config->pipe_bpp) {
@@ -8444,13 +8576,18 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       u32 val, base, offset, stride_mult, tiling;
-       int pipe = crtc->pipe;
+       struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+       enum plane_id plane_id = plane->id;
+       enum pipe pipe = crtc->pipe;
+       u32 val, base, offset, stride_mult, tiling, alpha;
        int fourcc, pixel_format;
        unsigned int aligned_height;
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
 
+       if (!plane->get_hw_state(plane))
+               return;
+
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
        if (!intel_fb) {
                DRM_DEBUG_KMS("failed to alloc fb\n");
@@ -8461,14 +8598,22 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
 
        fb->dev = dev;
 
-       val = I915_READ(PLANE_CTL(pipe, 0));
-       if (!(val & PLANE_CTL_ENABLE))
-               goto error;
+       val = I915_READ(PLANE_CTL(pipe, plane_id));
+
+       if (INTEL_GEN(dev_priv) >= 11)
+               pixel_format = val & ICL_PLANE_CTL_FORMAT_MASK;
+       else
+               pixel_format = val & PLANE_CTL_FORMAT_MASK;
+
+       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
+               alpha = I915_READ(PLANE_COLOR_CTL(pipe, plane_id));
+               alpha &= PLANE_COLOR_ALPHA_MASK;
+       } else {
+               alpha = val & PLANE_CTL_ALPHA_MASK;
+       }
 
-       pixel_format = val & PLANE_CTL_FORMAT_MASK;
        fourcc = skl_format_to_fourcc(pixel_format,
-                                     val & PLANE_CTL_ORDER_RGBX,
-                                     val & PLANE_CTL_ALPHA_MASK);
+                                     val & PLANE_CTL_ORDER_RGBX, alpha);
        fb->format = drm_format_info(fourcc);
 
        tiling = val & PLANE_CTL_TILED_MASK;
@@ -8497,16 +8642,16 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
                goto error;
        }
 
-       base = I915_READ(PLANE_SURF(pipe, 0)) & 0xfffff000;
+       base = I915_READ(PLANE_SURF(pipe, plane_id)) & 0xfffff000;
        plane_config->base = base;
 
-       offset = I915_READ(PLANE_OFFSET(pipe, 0));
+       offset = I915_READ(PLANE_OFFSET(pipe, plane_id));
 
-       val = I915_READ(PLANE_SIZE(pipe, 0));
+       val = I915_READ(PLANE_SIZE(pipe, plane_id));
        fb->height = ((val >> 16) & 0xfff) + 1;
        fb->width = ((val >> 0) & 0x1fff) + 1;
 
-       val = I915_READ(PLANE_STRIDE(pipe, 0));
+       val = I915_READ(PLANE_STRIDE(pipe, plane_id));
        stride_mult = intel_fb_stride_alignment(fb, 0);
        fb->pitches[0] = (val & 0x3ff) * stride_mult;
 
@@ -8514,8 +8659,8 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
 
        plane_config->size = fb->pitches[0] * aligned_height;
 
-       DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
-                     pipe_name(pipe), fb->width, fb->height,
+       DRM_DEBUG_KMS("%s/%s with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
+                     crtc->base.name, plane->base.name, fb->width, fb->height,
                      fb->format->cpp[0] * 8, base, fb->pitches[0],
                      plane_config->size);
 
@@ -8550,74 +8695,6 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,
        }
 }
 
-static void
-ironlake_get_initial_plane_config(struct intel_crtc *crtc,
-                                 struct intel_initial_plane_config *plane_config)
-{
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       u32 val, base, offset;
-       int pipe = crtc->pipe;
-       int fourcc, pixel_format;
-       unsigned int aligned_height;
-       struct drm_framebuffer *fb;
-       struct intel_framebuffer *intel_fb;
-
-       val = I915_READ(DSPCNTR(pipe));
-       if (!(val & DISPLAY_PLANE_ENABLE))
-               return;
-
-       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-       if (!intel_fb) {
-               DRM_DEBUG_KMS("failed to alloc fb\n");
-               return;
-       }
-
-       fb = &intel_fb->base;
-
-       fb->dev = dev;
-
-       if (INTEL_GEN(dev_priv) >= 4) {
-               if (val & DISPPLANE_TILED) {
-                       plane_config->tiling = I915_TILING_X;
-                       fb->modifier = I915_FORMAT_MOD_X_TILED;
-               }
-       }
-
-       pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
-       fourcc = i9xx_format_to_fourcc(pixel_format);
-       fb->format = drm_format_info(fourcc);
-
-       base = I915_READ(DSPSURF(pipe)) & 0xfffff000;
-       if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
-               offset = I915_READ(DSPOFFSET(pipe));
-       } else {
-               if (plane_config->tiling)
-                       offset = I915_READ(DSPTILEOFF(pipe));
-               else
-                       offset = I915_READ(DSPLINOFF(pipe));
-       }
-       plane_config->base = base;
-
-       val = I915_READ(PIPESRC(pipe));
-       fb->width = ((val >> 16) & 0xfff) + 1;
-       fb->height = ((val >> 0) & 0xfff) + 1;
-
-       val = I915_READ(DSPSTRIDE(pipe));
-       fb->pitches[0] = val & 0xffffffc0;
-
-       aligned_height = intel_fb_align_height(fb, 0, fb->height);
-
-       plane_config->size = fb->pitches[0] * aligned_height;
-
-       DRM_DEBUG_KMS("pipe %c with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
-                     pipe_name(pipe), fb->width, fb->height,
-                     fb->format->cpp[0] * 8, base, fb->pitches[0],
-                     plane_config->size);
-
-       plane_config->fb = intel_fb;
-}
-
 static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
                                     struct intel_crtc_state *pipe_config)
 {
@@ -8875,7 +8952,9 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
        }
 
        intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
        intel_update_cdclk(dev_priv);
+       intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
 }
 
 /*
@@ -9249,9 +9328,18 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                        ironlake_get_pfit_config(crtc, pipe_config);
        }
 
-       if (IS_HASWELL(dev_priv))
-               pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
-                       (I915_READ(IPS_CTL) & IPS_ENABLE);
+       if (hsw_crtc_supports_ips(crtc)) {
+               if (IS_HASWELL(dev_priv))
+                       pipe_config->ips_enabled = I915_READ(IPS_CTL) & IPS_ENABLE;
+               else {
+                       /*
+                        * We cannot readout IPS state on broadwell, set to
+                        * true so we can set it to a defined state on first
+                        * commit.
+                        */
+                       pipe_config->ips_enabled = true;
+               }
+       }
 
        if (pipe_config->cpu_transcoder != TRANSCODER_EDP &&
            !transcoder_is_dsi(pipe_config->cpu_transcoder)) {
@@ -9332,11 +9420,11 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
        u32 offset;
        int ret;
 
-       ret = drm_plane_helper_check_state(&plane_state->base,
-                                          &plane_state->clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          true, true);
+       ret = drm_atomic_helper_check_plane_state(&plane_state->base,
+                                                 &crtc_state->base,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 true, true);
        if (ret)
                return ret;
 
@@ -9477,6 +9565,23 @@ static void i845_disable_cursor(struct intel_plane *plane,
        i845_update_cursor(plane, NULL, NULL);
 }
 
+static bool i845_cursor_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       bool ret;
+
+       power_domain = POWER_DOMAIN_PIPE(PIPE_A);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
+
 static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
                           const struct intel_plane_state *plane_state)
 {
@@ -9490,7 +9595,8 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
        if (HAS_DDI(dev_priv))
                cntl |= CURSOR_PIPE_CSC_ENABLE;
 
-       cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
+       if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
+               cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
 
        switch (plane_state->base.crtc_w) {
        case 64:
@@ -9670,6 +9776,28 @@ static void i9xx_disable_cursor(struct intel_plane *plane,
        i9xx_update_cursor(plane, NULL, NULL);
 }
 
+static bool i9xx_cursor_get_hw_state(struct intel_plane *plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum intel_display_power_domain power_domain;
+       enum pipe pipe = plane->pipe;
+       bool ret;
+
+       /*
+        * Not 100% correct for planes that can move between pipes,
+        * but that's only the case for gen2-3 which don't have any
+        * display power wells.
+        */
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               return false;
+
+       ret = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
+
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
+}
 
 /* VESA 640x480x72Hz mode to set on the pipe */
 static const struct drm_display_mode load_detect_mode = {
@@ -9699,111 +9827,27 @@ intel_framebuffer_create(struct drm_i915_gem_object *obj,
        return ERR_PTR(ret);
 }
 
-static u32
-intel_framebuffer_pitch_for_width(int width, int bpp)
-{
-       u32 pitch = DIV_ROUND_UP(width * bpp, 8);
-       return ALIGN(pitch, 64);
-}
-
-static u32
-intel_framebuffer_size_for_mode(const struct drm_display_mode *mode, int bpp)
-{
-       u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
-       return PAGE_ALIGN(pitch * mode->vdisplay);
-}
-
-static struct drm_framebuffer *
-intel_framebuffer_create_for_mode(struct drm_device *dev,
-                                 const struct drm_display_mode *mode,
-                                 int depth, int bpp)
-{
-       struct drm_framebuffer *fb;
-       struct drm_i915_gem_object *obj;
-       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
-
-       obj = i915_gem_object_create(to_i915(dev),
-                                   intel_framebuffer_size_for_mode(mode, bpp));
-       if (IS_ERR(obj))
-               return ERR_CAST(obj);
-
-       mode_cmd.width = mode->hdisplay;
-       mode_cmd.height = mode->vdisplay;
-       mode_cmd.pitches[0] = intel_framebuffer_pitch_for_width(mode_cmd.width,
-                                                               bpp);
-       mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
-
-       fb = intel_framebuffer_create(obj, &mode_cmd);
-       if (IS_ERR(fb))
-               i915_gem_object_put(obj);
-
-       return fb;
-}
-
-static struct drm_framebuffer *
-mode_fits_in_fbdev(struct drm_device *dev,
-                  const struct drm_display_mode *mode)
-{
-#ifdef CONFIG_DRM_FBDEV_EMULATION
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct drm_i915_gem_object *obj;
-       struct drm_framebuffer *fb;
-
-       if (!dev_priv->fbdev)
-               return NULL;
-
-       if (!dev_priv->fbdev->fb)
-               return NULL;
-
-       obj = dev_priv->fbdev->fb->obj;
-       BUG_ON(!obj);
-
-       fb = &dev_priv->fbdev->fb->base;
-       if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
-                                                              fb->format->cpp[0] * 8))
-               return NULL;
-
-       if (obj->base.size < mode->vdisplay * fb->pitches[0])
-               return NULL;
-
-       drm_framebuffer_get(fb);
-       return fb;
-#else
-       return NULL;
-#endif
-}
-
-static int intel_modeset_setup_plane_state(struct drm_atomic_state *state,
-                                          struct drm_crtc *crtc,
-                                          const struct drm_display_mode *mode,
-                                          struct drm_framebuffer *fb,
-                                          int x, int y)
+static int intel_modeset_disable_planes(struct drm_atomic_state *state,
+                                       struct drm_crtc *crtc)
 {
+       struct drm_plane *plane;
        struct drm_plane_state *plane_state;
-       int hdisplay, vdisplay;
-       int ret;
-
-       plane_state = drm_atomic_get_plane_state(state, crtc->primary);
-       if (IS_ERR(plane_state))
-               return PTR_ERR(plane_state);
-
-       if (mode)
-               drm_mode_get_hv_timing(mode, &hdisplay, &vdisplay);
-       else
-               hdisplay = vdisplay = 0;
+       int ret, i;
 
-       ret = drm_atomic_set_crtc_for_plane(plane_state, fb ? crtc : NULL);
+       ret = drm_atomic_add_affected_planes(state, crtc);
        if (ret)
                return ret;
-       drm_atomic_set_fb_for_plane(plane_state, fb);
-       plane_state->crtc_x = 0;
-       plane_state->crtc_y = 0;
-       plane_state->crtc_w = hdisplay;
-       plane_state->crtc_h = vdisplay;
-       plane_state->src_x = x << 16;
-       plane_state->src_y = y << 16;
-       plane_state->src_w = hdisplay << 16;
-       plane_state->src_h = vdisplay << 16;
+
+       for_each_new_plane_in_state(state, plane, plane_state, i) {
+               if (plane_state->crtc != crtc)
+                       continue;
+
+               ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+               if (ret)
+                       return ret;
+
+               drm_atomic_set_fb_for_plane(plane_state, NULL);
+       }
 
        return 0;
 }
@@ -9821,7 +9865,6 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
        struct drm_crtc *crtc = NULL;
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct drm_framebuffer *fb;
        struct drm_mode_config *config = &dev->mode_config;
        struct drm_atomic_state *state = NULL, *restore_state = NULL;
        struct drm_connector_state *connector_state;
@@ -9889,10 +9932,6 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
 found:
        intel_crtc = to_intel_crtc(crtc);
 
-       ret = drm_modeset_lock(&crtc->primary->mutex, ctx);
-       if (ret)
-               goto fail;
-
        state = drm_atomic_state_alloc(dev);
        restore_state = drm_atomic_state_alloc(dev);
        if (!state || !restore_state) {
@@ -9924,39 +9963,17 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
        if (!mode)
                mode = &load_detect_mode;
 
-       /* We need a framebuffer large enough to accommodate all accesses
-        * that the plane may generate whilst we perform load detection.
-        * We can not rely on the fbcon either being present (we get called
-        * during its initialisation to detect all boot displays, or it may
-        * not even exist) or that it is large enough to satisfy the
-        * requested mode.
-        */
-       fb = mode_fits_in_fbdev(dev, mode);
-       if (fb == NULL) {
-               DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
-               fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
-       } else
-               DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
-       if (IS_ERR(fb)) {
-               DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
-               ret = PTR_ERR(fb);
-               goto fail;
-       }
-
-       ret = intel_modeset_setup_plane_state(state, crtc, mode, fb, 0, 0);
-       drm_framebuffer_put(fb);
+       ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, mode);
        if (ret)
                goto fail;
 
-       ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, mode);
+       ret = intel_modeset_disable_planes(state, crtc);
        if (ret)
                goto fail;
 
        ret = PTR_ERR_OR_ZERO(drm_atomic_get_connector_state(restore_state, connector));
        if (!ret)
                ret = PTR_ERR_OR_ZERO(drm_atomic_get_crtc_state(restore_state, crtc));
-       if (!ret)
-               ret = PTR_ERR_OR_ZERO(drm_atomic_get_plane_state(restore_state, crtc->primary));
        if (ret) {
                DRM_DEBUG_KMS("Failed to create a copy of old state to restore: %i\n", ret);
                goto fail;
@@ -10465,6 +10482,9 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
                                                         pipe_config);
        }
 
+       if (HAS_IPS(dev_priv))
+               pipe_config->ips_enabled = hsw_compute_ips_config(pipe_config);
+
        return ret;
 }
 
@@ -10594,7 +10614,7 @@ static const char * const output_type_str[] = {
        OUTPUT_TYPE(DP),
        OUTPUT_TYPE(EDP),
        OUTPUT_TYPE(DSI),
-       OUTPUT_TYPE(UNKNOWN),
+       OUTPUT_TYPE(DDI),
        OUTPUT_TYPE(DP_MST),
 };
 
@@ -10741,6 +10761,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
        struct drm_connector_list_iter conn_iter;
        unsigned int used_ports = 0;
        unsigned int used_mst_ports = 0;
+       bool ret = true;
 
        /*
         * Walk the connector list instead of the encoder
@@ -10765,23 +10786,23 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 
                switch (encoder->type) {
                        unsigned int port_mask;
-               case INTEL_OUTPUT_UNKNOWN:
+               case INTEL_OUTPUT_DDI:
                        if (WARN_ON(!HAS_DDI(to_i915(dev))))
                                break;
                case INTEL_OUTPUT_DP:
                case INTEL_OUTPUT_HDMI:
                case INTEL_OUTPUT_EDP:
-                       port_mask = 1 << enc_to_dig_port(&encoder->base)->port;
+                       port_mask = 1 << encoder->port;
 
                        /* the same port mustn't appear more than once */
                        if (used_ports & port_mask)
-                               return false;
+                               ret = false;
 
                        used_ports |= port_mask;
                        break;
                case INTEL_OUTPUT_DP_MST:
                        used_mst_ports |=
-                               1 << enc_to_mst(&encoder->base)->primary->port;
+                               1 << encoder->port;
                        break;
                default:
                        break;
@@ -10793,7 +10814,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
        if (used_ports & used_mst_ports)
                return false;
 
-       return true;
+       return ret;
 }
 
 static void
@@ -10898,7 +10919,12 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
                 * Determine output_types before calling the .compute_config()
                 * hooks so that the hooks can use this information safely.
                 */
-               pipe_config->output_types |= 1 << encoder->type;
+               if (encoder->compute_output_type)
+                       pipe_config->output_types |=
+                               BIT(encoder->compute_output_type(encoder, pipe_config,
+                                                                connector_state));
+               else
+                       pipe_config->output_types |= BIT(encoder->type);
        }
 
 encoder_retry:
@@ -10962,31 +10988,6 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
        return ret;
 }
 
-static void
-intel_modeset_update_crtc_state(struct drm_atomic_state *state)
-{
-       struct drm_crtc *crtc;
-       struct drm_crtc_state *new_crtc_state;
-       int i;
-
-       /* Double check state. */
-       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-               to_intel_crtc(crtc)->config = to_intel_crtc_state(new_crtc_state);
-
-               /*
-                * Update legacy state to satisfy fbc code. This can
-                * be removed when fbc uses the atomic state.
-                */
-               if (drm_atomic_get_existing_plane_state(state, crtc->primary)) {
-                       struct drm_plane_state *plane_state = crtc->primary->state;
-
-                       crtc->primary->fb = plane_state->fb;
-                       crtc->x = plane_state->src_x >> 16;
-                       crtc->y = plane_state->src_y >> 16;
-               }
-       }
-}
-
 static bool intel_fuzzy_clock_check(int clock1, int clock2)
 {
        int diff;
@@ -11058,24 +11059,17 @@ intel_compare_link_m_n(const struct intel_link_m_n *m_n,
 static void __printf(3, 4)
 pipe_config_err(bool adjust, const char *name, const char *format, ...)
 {
-       char *level;
-       unsigned int category;
        struct va_format vaf;
        va_list args;
 
-       if (adjust) {
-               level = KERN_DEBUG;
-               category = DRM_UT_KMS;
-       } else {
-               level = KERN_ERR;
-               category = DRM_UT_NONE;
-       }
-
        va_start(args, format);
        vaf.fmt = format;
        vaf.va = &args;
 
-       drm_printk(level, category, "mismatch in %s %pV", name, &vaf);
+       if (adjust)
+               drm_dbg(DRM_UT_KMS, "mismatch in %s %pV", name, &vaf);
+       else
+               drm_err("mismatch in %s %pV", name, &vaf);
 
        va_end(args);
 }
@@ -11087,6 +11081,9 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                          bool adjust)
 {
        bool ret = true;
+       bool fixup_inherited = adjust &&
+               (current_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED) &&
+               !(pipe_config->base.mode.private_flags & I915_MODE_FLAG_INHERITED);
 
 #define PIPE_CONF_CHECK_X(name)        \
        if (current_config->name != pipe_config->name) { \
@@ -11106,6 +11103,31 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                ret = false; \
        }
 
+#define PIPE_CONF_CHECK_BOOL(name)     \
+       if (current_config->name != pipe_config->name) { \
+               pipe_config_err(adjust, __stringify(name), \
+                         "(expected %s, found %s)\n", \
+                         yesno(current_config->name), \
+                         yesno(pipe_config->name)); \
+               ret = false; \
+       }
+
+/*
+ * Checks state where we only read out the enabling, but not the entire
+ * state itself (like full infoframes or ELD for audio). These states
+ * require a full modeset on bootup to fix up.
+ */
+#define PIPE_CONF_CHECK_BOOL_INCOMPLETE(name) \
+       if (!fixup_inherited || (!current_config->name && !pipe_config->name)) { \
+               PIPE_CONF_CHECK_BOOL(name); \
+       } else { \
+               pipe_config_err(adjust, __stringify(name), \
+                         "unable to verify whether state matches exactly, forcing modeset (expected %s, found %s)\n", \
+                         yesno(current_config->name), \
+                         yesno(pipe_config->name)); \
+               ret = false; \
+       }
+
 #define PIPE_CONF_CHECK_P(name)        \
        if (current_config->name != pipe_config->name) { \
                pipe_config_err(adjust, __stringify(name), \
@@ -11191,7 +11213,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 
        PIPE_CONF_CHECK_I(cpu_transcoder);
 
-       PIPE_CONF_CHECK_I(has_pch_encoder);
+       PIPE_CONF_CHECK_BOOL(has_pch_encoder);
        PIPE_CONF_CHECK_I(fdi_lanes);
        PIPE_CONF_CHECK_M_N(fdi_m_n);
 
@@ -11223,17 +11245,17 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
        PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_vsync_end);
 
        PIPE_CONF_CHECK_I(pixel_multiplier);
-       PIPE_CONF_CHECK_I(has_hdmi_sink);
+       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))
-               PIPE_CONF_CHECK_I(limited_color_range);
+               PIPE_CONF_CHECK_BOOL(limited_color_range);
 
-       PIPE_CONF_CHECK_I(hdmi_scrambling);
-       PIPE_CONF_CHECK_I(hdmi_high_tmds_clock_ratio);
-       PIPE_CONF_CHECK_I(has_infoframe);
-       PIPE_CONF_CHECK_I(ycbcr420);
+       PIPE_CONF_CHECK_BOOL(hdmi_scrambling);
+       PIPE_CONF_CHECK_BOOL(hdmi_high_tmds_clock_ratio);
+       PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_infoframe);
+       PIPE_CONF_CHECK_BOOL(ycbcr420);
 
-       PIPE_CONF_CHECK_I(has_audio);
+       PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio);
 
        PIPE_CONF_CHECK_FLAGS(base.adjusted_mode.flags,
                              DRM_MODE_FLAG_INTERLACE);
@@ -11259,7 +11281,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                PIPE_CONF_CHECK_I(pipe_src_w);
                PIPE_CONF_CHECK_I(pipe_src_h);
 
-               PIPE_CONF_CHECK_I(pch_pfit.enabled);
+               PIPE_CONF_CHECK_BOOL(pch_pfit.enabled);
                if (current_config->pch_pfit.enabled) {
                        PIPE_CONF_CHECK_X(pch_pfit.pos);
                        PIPE_CONF_CHECK_X(pch_pfit.size);
@@ -11269,11 +11291,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate);
        }
 
-       /* BDW+ don't expose a synchronous way to read the state */
-       if (IS_HASWELL(dev_priv))
-               PIPE_CONF_CHECK_I(ips_enabled);
-
-       PIPE_CONF_CHECK_I(double_wide);
+       PIPE_CONF_CHECK_BOOL(double_wide);
 
        PIPE_CONF_CHECK_P(shared_dpll);
        PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
@@ -11307,8 +11325,12 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
        PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock);
        PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock);
 
+       PIPE_CONF_CHECK_I(min_voltage_level);
+
 #undef PIPE_CONF_CHECK_X
 #undef PIPE_CONF_CHECK_I
+#undef PIPE_CONF_CHECK_BOOL
+#undef PIPE_CONF_CHECK_BOOL_INCOMPLETE
 #undef PIPE_CONF_CHECK_P
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_CHECK_CLOCK_FUZZY
@@ -11575,10 +11597,8 @@ verify_crtc_state(struct drm_crtc *crtc,
                                "Encoder connected to wrong pipe %c\n",
                                pipe_name(pipe));
 
-               if (active) {
-                       pipe_config->output_types |= 1 << encoder->type;
+               if (active)
                        encoder->get_config(encoder, pipe_config);
-               }
        }
 
        intel_crtc_compute_pixel_rate(pipe_config);
@@ -11599,6 +11619,18 @@ verify_crtc_state(struct drm_crtc *crtc,
        }
 }
 
+static void
+intel_verify_planes(struct intel_atomic_state *state)
+{
+       struct intel_plane *plane;
+       const struct intel_plane_state *plane_state;
+       int i;
+
+       for_each_new_intel_plane_in_state(state, plane,
+                                         plane_state, i)
+               assert_plane(plane, plane_state->base.visible);
+}
+
 static void
 verify_single_dpll_state(struct drm_i915_private *dev_priv,
                         struct intel_shared_dpll *pll,
@@ -11949,16 +11981,16 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                 * holding all the crtc locks, even if we don't end up
                 * touching the hardware
                 */
-               if (!intel_cdclk_state_compare(&dev_priv->cdclk.logical,
-                                              &intel_state->cdclk.logical)) {
+               if (intel_cdclk_changed(&dev_priv->cdclk.logical,
+                                       &intel_state->cdclk.logical)) {
                        ret = intel_lock_all_pipes(state);
                        if (ret < 0)
                                return ret;
                }
 
                /* All pipes must be switched off while we change the cdclk. */
-               if (!intel_cdclk_state_compare(&dev_priv->cdclk.actual,
-                                              &intel_state->cdclk.actual)) {
+               if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual,
+                                             &intel_state->cdclk.actual)) {
                        ret = intel_modeset_all_pipes(state);
                        if (ret < 0)
                                return ret;
@@ -11967,6 +11999,9 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n",
                              intel_state->cdclk.logical.cdclk,
                              intel_state->cdclk.actual.cdclk);
+               DRM_DEBUG_KMS("New voltage level calculated to be logical %u, actual %u\n",
+                             intel_state->cdclk.logical.voltage_level,
+                             intel_state->cdclk.actual.voltage_level);
        } else {
                to_intel_atomic_state(state)->cdclk.logical = dev_priv->cdclk.logical;
        }
@@ -12011,6 +12046,14 @@ static int intel_atomic_check(struct drm_device *dev,
        int ret, i;
        bool any_ms = false;
 
+       /* Catch I915_MODE_FLAG_INHERITED */
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
+                                     crtc_state, i) {
+               if (crtc_state->mode.private_flags !=
+                   old_crtc_state->mode.private_flags)
+                       crtc_state->mode_changed = true;
+       }
+
        ret = drm_atomic_helper_check_modeset(dev, state);
        if (ret)
                return ret;
@@ -12019,10 +12062,6 @@ static int intel_atomic_check(struct drm_device *dev,
                struct intel_crtc_state *pipe_config =
                        to_intel_crtc_state(crtc_state);
 
-               /* Catch I915_MODE_FLAG_INHERITED */
-               if (crtc_state->mode.private_flags != old_crtc_state->mode.private_flags)
-                       crtc_state->mode_changed = true;
-
                if (!needs_modeset(crtc_state))
                        continue;
 
@@ -12031,13 +12070,6 @@ static int intel_atomic_check(struct drm_device *dev,
                        continue;
                }
 
-               /* FIXME: For only active_changed we shouldn't need to do any
-                * state recomputation at all. */
-
-               ret = drm_atomic_add_affected_connectors(state, crtc);
-               if (ret)
-                       return ret;
-
                ret = intel_modeset_pipe_config(crtc, pipe_config);
                if (ret) {
                        intel_dump_pipe_config(to_intel_crtc(crtc),
@@ -12056,10 +12088,6 @@ static int intel_atomic_check(struct drm_device *dev,
                if (needs_modeset(crtc_state))
                        any_ms = true;
 
-               ret = drm_atomic_add_affected_planes(state, crtc);
-               if (ret)
-                       return ret;
-
                intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
                                       needs_modeset(crtc_state) ?
                                       "[modeset]" : "[fastset]");
@@ -12078,7 +12106,7 @@ static int intel_atomic_check(struct drm_device *dev,
        if (ret)
                return ret;
 
-       intel_fbc_choose_crtc(dev_priv, state);
+       intel_fbc_choose_crtc(dev_priv, intel_state);
        return calc_watermark_data(state);
 }
 
@@ -12093,7 +12121,7 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
        struct drm_device *dev = crtc->base.dev;
 
        if (!dev->max_vblank_count)
-               return drm_crtc_accurate_vblank_count(&crtc->base);
+               return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
 
        return dev->driver->get_vblank_counter(dev, crtc->pipe);
 }
@@ -12318,9 +12346,9 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
                }
        }
 
-       /* Only after disabling all output pipelines that will be changed can we
-        * update the the output configuration. */
-       intel_modeset_update_crtc_state(state);
+       /* FIXME: Eventually get rid of our intel_crtc->config pointer */
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i)
+               to_intel_crtc(crtc)->config = to_intel_crtc_state(new_crtc_state);
 
        if (intel_state->modeset) {
                drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
@@ -12389,6 +12417,9 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
                intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state);
        }
 
+       if (intel_state->modeset)
+               intel_verify_planes(intel_state);
+
        if (intel_state->modeset && intel_can_enable_sagv(state))
                intel_enable_sagv(dev_priv);
 
@@ -12535,6 +12566,9 @@ static int intel_atomic_commit(struct drm_device *dev,
        if (intel_state->modeset) {
                memcpy(dev_priv->min_cdclk, intel_state->min_cdclk,
                       sizeof(intel_state->min_cdclk));
+               memcpy(dev_priv->min_voltage_level,
+                      intel_state->min_voltage_level,
+                      sizeof(intel_state->min_voltage_level));
                dev_priv->active_crtcs = intel_state->active_crtcs;
                dev_priv->cdclk.logical = intel_state->cdclk.logical;
                dev_priv->cdclk.actual = intel_state->cdclk.actual;
@@ -12571,17 +12605,23 @@ struct wait_rps_boost {
        struct wait_queue_entry wait;
 
        struct drm_crtc *crtc;
-       struct drm_i915_gem_request *request;
+       struct i915_request *request;
 };
 
 static int do_rps_boost(struct wait_queue_entry *_wait,
                        unsigned mode, int sync, void *key)
 {
        struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait);
-       struct drm_i915_gem_request *rq = wait->request;
+       struct i915_request *rq = wait->request;
 
-       gen6_rps_boost(rq, NULL);
-       i915_gem_request_put(rq);
+       /*
+        * If we missed the vblank, but the request is already running it
+        * is reasonable to assume that it will complete before the next
+        * vblank without our intervention, so leave RPS alone.
+        */
+       if (!i915_request_started(rq))
+               gen6_rps_boost(rq, NULL);
+       i915_request_put(rq);
 
        drm_crtc_vblank_put(wait->crtc);
 
@@ -12619,10 +12659,46 @@ static void add_rps_boost_after_vblank(struct drm_crtc *crtc,
        add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
 }
 
+static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       struct drm_framebuffer *fb = plane_state->base.fb;
+       struct i915_vma *vma;
+
+       if (plane->id == PLANE_CURSOR &&
+           INTEL_INFO(dev_priv)->cursor_needs_physical) {
+               struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+               const int align = intel_cursor_alignment(dev_priv);
+
+               return i915_gem_object_attach_phys(obj, align);
+       }
+
+       vma = intel_pin_and_fence_fb_obj(fb,
+                                        plane_state->base.rotation,
+                                        intel_plane_uses_fence(plane_state),
+                                        &plane_state->flags);
+       if (IS_ERR(vma))
+               return PTR_ERR(vma);
+
+       plane_state->vma = vma;
+
+       return 0;
+}
+
+static void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state)
+{
+       struct i915_vma *vma;
+
+       vma = fetch_and_zero(&old_plane_state->vma);
+       if (vma)
+               intel_unpin_fb_vma(vma, old_plane_state->flags);
+}
+
 /**
  * intel_prepare_plane_fb - Prepare fb for usage on plane
  * @plane: drm plane to prepare for
- * @fb: framebuffer to prepare for presentation
+ * @new_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
@@ -12693,20 +12769,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                return ret;
        }
 
-       if (plane->type == DRM_PLANE_TYPE_CURSOR &&
-           INTEL_INFO(dev_priv)->cursor_needs_physical) {
-               const int align = intel_cursor_alignment(dev_priv);
-
-               ret = i915_gem_object_attach_phys(obj, align);
-       } else {
-               struct i915_vma *vma;
-
-               vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
-               if (!IS_ERR(vma))
-                       to_intel_plane_state(new_state)->vma = vma;
-               else
-                       ret =  PTR_ERR(vma);
-       }
+       ret = intel_plane_pin_fb(to_intel_plane_state(new_state));
 
        i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
 
@@ -12740,7 +12803,7 @@ 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
- * @fb: old framebuffer that was on plane
+ * @old_state: the state from the previous modeset
  *
  * Cleans up a framebuffer that has just been removed from a plane.
  *
@@ -12750,15 +12813,12 @@ void
 intel_cleanup_plane_fb(struct drm_plane *plane,
                       struct drm_plane_state *old_state)
 {
-       struct i915_vma *vma;
+       struct drm_i915_private *dev_priv = to_i915(plane->dev);
 
        /* Should only be called after a successful intel_prepare_plane_fb()! */
-       vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
-       if (vma) {
-               mutex_lock(&plane->dev->struct_mutex);
-               intel_unpin_fb_vma(vma);
-               mutex_unlock(&plane->dev->struct_mutex);
-       }
+       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
@@ -12776,7 +12836,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
        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))
+       if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10)
                max_dotclk *= 2;
 
        if (WARN_ON_ONCE(!crtc_clock || max_dotclk < crtc_clock))
@@ -12808,17 +12868,17 @@ intel_check_primary_plane(struct intel_plane *plane,
 
        if (INTEL_GEN(dev_priv) >= 9) {
                /* use scaler when colorkey is not required */
-               if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
+               if (!state->ckey.flags) {
                        min_scale = 1;
                        max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
                }
                can_position = true;
        }
 
-       ret = drm_plane_helper_check_state(&state->base,
-                                          &state->clip,
-                                          min_scale, max_scale,
-                                          can_position, true);
+       ret = drm_atomic_helper_check_plane_state(&state->base,
+                                                 &crtc_state->base,
+                                                 min_scale, max_scale,
+                                                 can_position, true);
        if (ret)
                return ret;
 
@@ -12826,7 +12886,7 @@ intel_check_primary_plane(struct intel_plane *plane,
                return 0;
 
        if (INTEL_GEN(dev_priv) >= 9) {
-               ret = skl_check_plane_surface(state);
+               ret = skl_check_plane_surface(crtc_state, state);
                if (ret)
                        return ret;
 
@@ -12839,6 +12899,9 @@ intel_check_primary_plane(struct intel_plane *plane,
                state->ctl = i9xx_plane_ctl(crtc_state, state);
        }
 
+       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               state->color_ctl = glk_plane_color_ctl(crtc_state, state);
+
        return 0;
 }
 
@@ -12883,6 +12946,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
 static void intel_finish_crtc_commit(struct drm_crtc *crtc,
                                     struct drm_crtc_state *old_crtc_state)
 {
+       struct drm_i915_private *dev_priv = to_i915(crtc->dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_atomic_state *old_intel_state =
                to_intel_atomic_state(old_crtc_state->state);
@@ -12890,6 +12954,20 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
                intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc);
 
        intel_pipe_update_end(new_crtc_state);
+
+       if (new_crtc_state->update_pipe &&
+           !needs_modeset(&new_crtc_state->base) &&
+           old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED) {
+               if (!IS_GEN2(dev_priv))
+                       intel_set_cpu_fifo_underrun_reporting(dev_priv, intel_crtc->pipe, true);
+
+               if (new_crtc_state->has_pch_encoder) {
+                       enum pipe pch_transcoder =
+                               intel_crtc_pch_transcoder(intel_crtc);
+
+                       intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, true);
+               }
+       }
 }
 
 /**
@@ -12986,8 +13064,6 @@ static bool intel_primary_plane_format_mod_supported(struct drm_plane *plane,
                return i965_mod_supported(format, modifier);
        else
                return i8xx_mod_supported(format, modifier);
-
-       unreachable();
 }
 
 static bool intel_cursor_plane_format_mod_supported(struct drm_plane *plane,
@@ -13027,7 +13103,6 @@ intel_legacy_cursor_update(struct drm_plane *plane,
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_framebuffer *old_fb;
        struct drm_crtc_state *crtc_state = crtc->state;
-       struct i915_vma *old_vma, *vma;
 
        /*
         * When crtc is inactive or there is a modeset pending,
@@ -13086,25 +13161,9 @@ intel_legacy_cursor_update(struct drm_plane *plane,
        if (ret)
                goto out_free;
 
-       if (INTEL_INFO(dev_priv)->cursor_needs_physical) {
-               int align = intel_cursor_alignment(dev_priv);
-
-               ret = i915_gem_object_attach_phys(intel_fb_obj(fb), align);
-               if (ret) {
-                       DRM_DEBUG_KMS("failed to attach phys object\n");
-                       goto out_unlock;
-               }
-       } else {
-               vma = intel_pin_and_fence_fb_obj(fb, new_plane_state->rotation);
-               if (IS_ERR(vma)) {
-                       DRM_DEBUG_KMS("failed to pin object\n");
-
-                       ret = PTR_ERR(vma);
-                       goto out_unlock;
-               }
-
-               to_intel_plane_state(new_plane_state)->vma = vma;
-       }
+       ret = intel_plane_pin_fb(to_intel_plane_state(new_plane_state));
+       if (ret)
+               goto out_unlock;
 
        old_fb = old_plane_state->fb;
 
@@ -13124,9 +13183,7 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
        }
 
-       old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma);
-       if (old_vma)
-               intel_unpin_fb_vma(old_vma);
+       intel_plane_unpin_fb(to_intel_plane_state(old_plane_state));
 
 out_unlock:
        mutex_unlock(&dev_priv->drm.struct_mutex);
@@ -13154,6 +13211,32 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = {
        .format_mod_supported = intel_cursor_plane_format_mod_supported,
 };
 
+static bool i9xx_plane_has_fbc(struct drm_i915_private *dev_priv,
+                              enum i9xx_plane_id i9xx_plane)
+{
+       if (!HAS_FBC(dev_priv))
+               return false;
+
+       if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
+               return i9xx_plane == PLANE_A; /* tied to pipe A */
+       else if (IS_IVYBRIDGE(dev_priv))
+               return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
+                       i9xx_plane == PLANE_C;
+       else if (INTEL_GEN(dev_priv) >= 4)
+               return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
+       else
+               return i9xx_plane == PLANE_A;
+}
+
+static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
+                             enum pipe pipe, enum plane_id plane_id)
+{
+       if (!HAS_FBC(dev_priv))
+               return false;
+
+       return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
+}
+
 static struct intel_plane *
 intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
@@ -13191,44 +13274,56 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
         * port is hooked to pipe B. Hence we want plane A feeding pipe B.
         */
        if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4)
-               primary->plane = (enum plane) !pipe;
+               primary->i9xx_plane = (enum i9xx_plane_id) !pipe;
        else
-               primary->plane = (enum plane) pipe;
+               primary->i9xx_plane = (enum i9xx_plane_id) pipe;
        primary->id = PLANE_PRIMARY;
-       primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
+       primary->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, primary->id);
+
+       if (INTEL_GEN(dev_priv) >= 9)
+               primary->has_fbc = skl_plane_has_fbc(dev_priv,
+                                                    primary->pipe,
+                                                    primary->id);
+       else
+               primary->has_fbc = i9xx_plane_has_fbc(dev_priv,
+                                                     primary->i9xx_plane);
+
+       if (primary->has_fbc) {
+               struct intel_fbc *fbc = &dev_priv->fbc;
+
+               fbc->possible_framebuffer_bits |= primary->frontbuffer_bit;
+       }
+
        primary->check_plane = intel_check_primary_plane;
 
-       if (INTEL_GEN(dev_priv) >= 10) {
+       if (INTEL_GEN(dev_priv) >= 9) {
                intel_primary_formats = skl_primary_formats;
                num_formats = ARRAY_SIZE(skl_primary_formats);
-               modifiers = skl_format_modifiers_ccs;
 
-               primary->update_plane = skl_update_plane;
-               primary->disable_plane = skl_disable_plane;
-       } else if (INTEL_GEN(dev_priv) >= 9) {
-               intel_primary_formats = skl_primary_formats;
-               num_formats = ARRAY_SIZE(skl_primary_formats);
-               if (pipe < PIPE_C)
+               if (skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY))
                        modifiers = skl_format_modifiers_ccs;
                else
                        modifiers = skl_format_modifiers_noccs;
 
                primary->update_plane = skl_update_plane;
                primary->disable_plane = skl_disable_plane;
+               primary->get_hw_state = skl_plane_get_hw_state;
        } else if (INTEL_GEN(dev_priv) >= 4) {
                intel_primary_formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
                modifiers = i9xx_format_modifiers;
 
-               primary->update_plane = i9xx_update_primary_plane;
-               primary->disable_plane = i9xx_disable_primary_plane;
+               primary->update_plane = i9xx_update_plane;
+               primary->disable_plane = i9xx_disable_plane;
+               primary->get_hw_state = i9xx_plane_get_hw_state;
        } else {
                intel_primary_formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
                modifiers = i9xx_format_modifiers;
 
-               primary->update_plane = i9xx_update_primary_plane;
-               primary->disable_plane = i9xx_disable_primary_plane;
+               primary->update_plane = i9xx_update_plane;
+               primary->disable_plane = i9xx_disable_plane;
+               primary->get_hw_state = i9xx_plane_get_hw_state;
        }
 
        if (INTEL_GEN(dev_priv) >= 9)
@@ -13251,11 +13346,17 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                                               intel_primary_formats, num_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_PRIMARY,
-                                              "plane %c", plane_name(primary->plane));
+                                              "plane %c",
+                                              plane_name(primary->i9xx_plane));
        if (ret)
                goto fail;
 
-       if (INTEL_GEN(dev_priv) >= 9) {
+       if (INTEL_GEN(dev_priv) >= 10) {
+               supported_rotations =
+                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
+                       DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 |
+                       DRM_MODE_REFLECT_X;
+       } else if (INTEL_GEN(dev_priv) >= 9) {
                supported_rotations =
                        DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
                        DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
@@ -13275,6 +13376,15 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                                                   DRM_MODE_ROTATE_0,
                                                   supported_rotations);
 
+       if (INTEL_GEN(dev_priv) >= 9)
+               drm_plane_create_color_properties(&primary->base,
+                                                 BIT(DRM_COLOR_YCBCR_BT601) |
+                                                 BIT(DRM_COLOR_YCBCR_BT709),
+                                                 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+                                                 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
+                                                 DRM_COLOR_YCBCR_BT709,
+                                                 DRM_COLOR_YCBCR_LIMITED_RANGE);
+
        drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
 
        return primary;
@@ -13311,17 +13421,19 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
        cursor->can_scale = false;
        cursor->max_downscale = 1;
        cursor->pipe = pipe;
-       cursor->plane = pipe;
+       cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
        cursor->id = PLANE_CURSOR;
-       cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
+       cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
 
        if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
                cursor->update_plane = i845_update_cursor;
                cursor->disable_plane = i845_disable_cursor;
+               cursor->get_hw_state = i845_cursor_get_hw_state;
                cursor->check_plane = i845_check_cursor;
        } else {
                cursor->update_plane = i9xx_update_cursor;
                cursor->disable_plane = i9xx_disable_cursor;
+               cursor->get_hw_state = i9xx_cursor_get_hw_state;
                cursor->check_plane = i9xx_check_cursor;
        }
 
@@ -13437,14 +13549,13 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
                goto fail;
 
        intel_crtc->pipe = pipe;
-       intel_crtc->plane = primary->plane;
 
        /* initialize shared scalers */
        intel_crtc_init_scalers(intel_crtc, crtc_state);
 
        BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
-              dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
-       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = intel_crtc;
+              dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] != NULL);
+       dev_priv->plane_to_crtc_mapping[primary->i9xx_plane] = intel_crtc;
        dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc;
 
        drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
@@ -13478,8 +13589,8 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
        return to_intel_crtc(connector->base.state->crtc)->pipe;
 }
 
-int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
-                               struct drm_file *file)
+int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
+                                     struct drm_file *file)
 {
        struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
        struct drm_crtc *drmmode_crtc;
@@ -13628,7 +13739,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
                if (found || IS_GEN9_BC(dev_priv))
                        intel_ddi_init(dev_priv, PORT_A);
 
-               /* DDI B, C and D detection is indicated by the SFUSE_STRAP
+               /* DDI B, C, D, and F detection is indicated by the SFUSE_STRAP
                 * register */
                found = I915_READ(SFUSE_STRAP);
 
@@ -13638,6 +13749,8 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
                        intel_ddi_init(dev_priv, PORT_C);
                if (found & SFUSE_STRAP_DDID_DETECTED)
                        intel_ddi_init(dev_priv, PORT_D);
+               if (found & SFUSE_STRAP_DDIF_DETECTED)
+                       intel_ddi_init(dev_priv, PORT_F);
                /*
                 * On SKL we don't have a way to detect DDI-E so we rely on VBT.
                 */
@@ -13925,7 +14038,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
         * gen2/3 display engine uses the fence if present,
         * so the tiling mode must match the fb modifier exactly.
         */
-       if (INTEL_INFO(dev_priv)->gen < 4 &&
+       if (INTEL_GEN(dev_priv) < 4 &&
            tiling != intel_fb_modifier_to_tiling(mode_cmd->modifier[0])) {
                DRM_DEBUG_KMS("tiling_mode must match fb modifier exactly on gen2/3\n");
                goto err;
@@ -14094,10 +14207,37 @@ static void intel_atomic_state_free(struct drm_atomic_state *state)
        kfree(state);
 }
 
+static enum drm_mode_status
+intel_mode_valid(struct drm_device *dev,
+                const struct drm_display_mode *mode)
+{
+       if (mode->vscan > 1)
+               return MODE_NO_VSCAN;
+
+       if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+               return MODE_NO_DBLESCAN;
+
+       if (mode->flags & DRM_MODE_FLAG_HSKEW)
+               return MODE_H_ILLEGAL;
+
+       if (mode->flags & (DRM_MODE_FLAG_CSYNC |
+                          DRM_MODE_FLAG_NCSYNC |
+                          DRM_MODE_FLAG_PCSYNC))
+               return MODE_HSYNC;
+
+       if (mode->flags & (DRM_MODE_FLAG_BCAST |
+                          DRM_MODE_FLAG_PIXMUX |
+                          DRM_MODE_FLAG_CLKDIV2))
+               return MODE_BAD;
+
+       return MODE_OK;
+}
+
 static const struct drm_mode_config_funcs intel_mode_funcs = {
        .fb_create = intel_user_framebuffer_create,
        .get_format_info = intel_get_format_info,
        .output_poll_changed = intel_fbdev_output_poll_changed,
+       .mode_valid = intel_mode_valid,
        .atomic_check = intel_atomic_check,
        .atomic_commit = intel_atomic_commit,
        .atomic_state_alloc = intel_atomic_state_alloc,
@@ -14113,7 +14253,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 {
        intel_init_cdclk_hooks(dev_priv);
 
-       if (INTEL_INFO(dev_priv)->gen >= 9) {
+       if (INTEL_GEN(dev_priv) >= 9) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        skylake_get_initial_plane_config;
@@ -14124,7 +14264,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
        } else if (HAS_DDI(dev_priv)) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
-                       ironlake_get_initial_plane_config;
+                       i9xx_get_initial_plane_config;
                dev_priv->display.crtc_compute_clock =
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
@@ -14132,7 +14272,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
        } else if (HAS_PCH_SPLIT(dev_priv)) {
                dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
-                       ironlake_get_initial_plane_config;
+                       i9xx_get_initial_plane_config;
                dev_priv->display.crtc_compute_clock =
                        ironlake_crtc_compute_clock;
                dev_priv->display.crtc_enable = ironlake_crtc_enable;
@@ -14371,6 +14511,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
        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;
 }
 
@@ -14450,6 +14591,8 @@ static void sanitize_watermarks(struct drm_device *dev)
 
                cs->wm.need_postvbl_update = true;
                dev_priv->display.optimize_watermarks(intel_state, cs);
+
+               to_intel_crtc_state(crtc->state)->wm = cs->wm;
        }
 
 put_state:
@@ -14459,6 +14602,22 @@ static void sanitize_watermarks(struct drm_device *dev)
        drm_modeset_acquire_fini(&ctx);
 }
 
+static void intel_update_fdi_pll_freq(struct drm_i915_private *dev_priv)
+{
+       if (IS_GEN5(dev_priv)) {
+               u32 fdi_pll_clk =
+                       I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK;
+
+               dev_priv->fdi_pll_freq = (fdi_pll_clk + 2) * 10000;
+       } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) {
+               dev_priv->fdi_pll_freq = 270000;
+       } else {
+               return;
+       }
+
+       DRM_DEBUG_DRIVER("FDI PLL freq=%d\n", dev_priv->fdi_pll_freq);
+}
+
 int intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -14531,7 +14690,7 @@ int intel_modeset_init(struct drm_device *dev)
                dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT;
        }
 
-       dev->mode_config.fb_base = ggtt->mappable_base;
+       dev->mode_config.fb_base = ggtt->gmadr.start;
 
        DRM_DEBUG_KMS("%d display pipe%s available.\n",
                      INTEL_INFO(dev_priv)->num_pipes,
@@ -14548,6 +14707,7 @@ int intel_modeset_init(struct drm_device *dev)
        }
 
        intel_shared_dpll_init(dev);
+       intel_update_fdi_pll_freq(dev_priv);
 
        intel_update_czclk(dev_priv);
        intel_modeset_init_hw(dev);
@@ -14599,6 +14759,7 @@ int intel_modeset_init(struct drm_device *dev)
 
 void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
+       struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
        /* 640x480@60Hz, ~25175 kHz */
        struct dpll clock = {
                .m1 = 18,
@@ -14662,6 +14823,8 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 
        I915_WRITE(PIPECONF(pipe), PIPECONF_ENABLE | PIPECONF_PROGRESSIVE);
        POSTING_READ(PIPECONF(pipe));
+
+       intel_wait_for_pipe_scanline_moving(crtc);
 }
 
 void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
@@ -14671,8 +14834,11 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
        DRM_DEBUG_KMS("disabling pipe %c due to force quirk\n",
                      pipe_name(pipe));
 
-       assert_plane_disabled(dev_priv, PLANE_A);
-       assert_plane_disabled(dev_priv, PLANE_B);
+       WARN_ON(I915_READ(DSPCNTR(PLANE_A)) & DISPLAY_PLANE_ENABLE);
+       WARN_ON(I915_READ(DSPCNTR(PLANE_B)) & DISPLAY_PLANE_ENABLE);
+       WARN_ON(I915_READ(DSPCNTR(PLANE_C)) & DISPLAY_PLANE_ENABLE);
+       WARN_ON(I915_READ(CURCNTR(PIPE_A)) & CURSOR_MODE);
+       WARN_ON(I915_READ(CURCNTR(PIPE_B)) & CURSOR_MODE);
 
        I915_WRITE(PIPECONF(pipe), 0);
        POSTING_READ(PIPECONF(pipe));
@@ -14683,22 +14849,36 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
        POSTING_READ(DPLL(pipe));
 }
 
-static bool
-intel_check_plane_mapping(struct intel_crtc *crtc)
+static bool intel_plane_mapping_ok(struct intel_crtc *crtc,
+                                  struct intel_plane *plane)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       u32 val;
+       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+       u32 val = I915_READ(DSPCNTR(i9xx_plane));
 
-       if (INTEL_INFO(dev_priv)->num_pipes == 1)
-               return true;
+       return (val & DISPLAY_PLANE_ENABLE) == 0 ||
+               (val & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE(crtc->pipe);
+}
 
-       val = I915_READ(DSPCNTR(!crtc->plane));
+static void
+intel_sanitize_plane_mapping(struct drm_i915_private *dev_priv)
+{
+       struct intel_crtc *crtc;
 
-       if ((val & DISPLAY_PLANE_ENABLE) &&
-           (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
-               return false;
+       if (INTEL_GEN(dev_priv) >= 4)
+               return;
 
-       return true;
+       for_each_intel_crtc(&dev_priv->drm, crtc) {
+               struct intel_plane *plane =
+                       to_intel_plane(crtc->base.primary);
+
+               if (intel_plane_mapping_ok(crtc, plane))
+                       continue;
+
+               DRM_DEBUG_KMS("%s attached to the wrong pipe, disabling plane\n",
+                             plane->base.name);
+               intel_plane_disable_noatomic(crtc, plane);
+       }
 }
 
 static bool intel_crtc_has_encoders(struct intel_crtc *crtc)
@@ -14738,7 +14918,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
        enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
 
        /* Clear any frame start delays used for debugging left by the BIOS */
-       if (!transcoder_is_dsi(cpu_transcoder)) {
+       if (crtc->active && !transcoder_is_dsi(cpu_transcoder)) {
                i915_reg_t reg = PIPECONF(cpu_transcoder);
 
                I915_WRITE(reg,
@@ -14754,33 +14934,15 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
 
                /* Disable everything but the primary plane */
                for_each_intel_plane_on_crtc(dev, crtc, plane) {
-                       if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
-                               continue;
+                       const struct intel_plane_state *plane_state =
+                               to_intel_plane_state(plane->base.state);
 
-                       trace_intel_disable_plane(&plane->base, crtc);
-                       plane->disable_plane(plane, crtc);
+                       if (plane_state->base.visible &&
+                           plane->base.type != DRM_PLANE_TYPE_PRIMARY)
+                               intel_plane_disable_noatomic(crtc, plane);
                }
        }
 
-       /* We need to sanitize the plane -> pipe mapping first because this will
-        * disable the crtc (and hence change the state) if it is wrong. Note
-        * that gen4+ has a fixed plane -> pipe mapping.  */
-       if (INTEL_GEN(dev_priv) < 4 && !intel_check_plane_mapping(crtc)) {
-               bool plane;
-
-               DRM_DEBUG_KMS("[CRTC:%d:%s] wrong plane connection detected!\n",
-                             crtc->base.base.id, crtc->base.name);
-
-               /* Pipe has the wrong plane attached and the plane is active.
-                * Temporarily change the plane mapping and disable everything
-                * ...  */
-               plane = crtc->plane;
-               crtc->base.primary->state->visible = true;
-               crtc->plane = !plane;
-               intel_crtc_disable_noatomic(&crtc->base, ctx);
-               crtc->plane = plane;
-       }
-
        /* Adjust the state of the output pipe according to whether we
         * have active connectors/encoders. */
        if (crtc->active && !intel_crtc_has_encoders(crtc))
@@ -14854,8 +15016,6 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                connector->base.dpms = DRM_MODE_DPMS_OFF;
                connector->base.encoder = NULL;
        }
-       /* Enabled encoders without active connectors will be fixed in
-        * the crtc fixup. */
 }
 
 void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
@@ -14885,24 +15045,21 @@ void i915_redisable_vga(struct drm_i915_private *dev_priv)
        intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
 }
 
-static bool primary_get_hw_state(struct intel_plane *plane)
-{
-       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-
-       return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE;
-}
-
 /* FIXME read out full plane state for all planes */
 static void readout_plane_state(struct intel_crtc *crtc)
 {
-       struct intel_plane *primary = to_intel_plane(crtc->base.primary);
-       bool visible;
+       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 *plane;
 
-       visible = crtc->active && primary_get_hw_state(primary);
+       for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
+               struct intel_plane_state *plane_state =
+                       to_intel_plane_state(plane->base.state);
+               bool visible = plane->get_hw_state(plane);
 
-       intel_set_plane_visible(to_intel_crtc_state(crtc->base.state),
-                               to_intel_plane_state(primary->base.state),
-                               visible);
+               intel_set_plane_visible(crtc_state, plane_state, visible);
+       }
 }
 
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -14971,7 +15128,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                        crtc_state = to_intel_crtc_state(crtc->base.state);
 
                        encoder->base.crtc = &crtc->base;
-                       crtc_state->output_types |= 1 << encoder->type;
                        encoder->get_config(encoder, crtc_state);
                } else {
                        encoder->base.crtc = NULL;
@@ -15050,6 +15206,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                }
 
                dev_priv->min_cdclk[crtc->pipe] = min_cdclk;
+               dev_priv->min_voltage_level[crtc->pipe] =
+                       crtc_state->min_voltage_level;
 
                intel_pipe_config_sanity_check(dev_priv, crtc_state);
        }
@@ -15073,6 +15231,23 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
        }
 }
 
+static void intel_early_display_was(struct drm_i915_private *dev_priv)
+{
+       /* Display WA #1185 WaDisableDARBFClkGating:cnl,glk */
+       if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
+               I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) |
+                          DARBF_GATING_DIS);
+
+       if (IS_HASWELL(dev_priv)) {
+               /*
+                * WaRsPkgCStateDisplayPMReq:hsw
+                * System hang if this isn't done before disabling all planes!
+                */
+               I915_WRITE(CHICKEN_PAR1_1,
+                          I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES);
+       }
+}
+
 /* Scan out the current hw modeset state,
  * and sanitizes it to the current state
  */
@@ -15086,20 +15261,14 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
        struct intel_encoder *encoder;
        int i;
 
-       if (IS_HASWELL(dev_priv)) {
-               /*
-                * WaRsPkgCStateDisplayPMReq:hsw
-                * System hang if this isn't done before disabling all planes!
-                */
-               I915_WRITE(CHICKEN_PAR1_1,
-                          I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES);
-       }
-
+       intel_early_display_was(dev_priv);
        intel_modeset_readout_hw_state(dev);
 
        /* HW state is read out, now we need to sanitize this mess. */
        get_encoder_power_domains(dev_priv);
 
+       intel_sanitize_plane_mapping(dev_priv);
+
        for_each_intel_encoder(dev, encoder) {
                intel_sanitize_encoder(encoder);
        }
@@ -15186,17 +15355,6 @@ void intel_display_resume(struct drm_device *dev)
                drm_atomic_state_put(state);
 }
 
-void intel_modeset_gem_init(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = to_i915(dev);
-
-       intel_init_gt_powersave(dev_priv);
-
-       intel_init_clock_gating(dev_priv);
-
-       intel_setup_overlay(dev_priv);
-}
-
 int intel_connector_register(struct drm_connector *connector)
 {
        struct intel_connector *intel_connector = to_intel_connector(connector);
@@ -15225,14 +15383,15 @@ static void intel_hpd_poll_fini(struct drm_device *dev)
        struct intel_connector *connector;
        struct drm_connector_list_iter conn_iter;
 
-       /* First disable polling... */
-       drm_kms_helper_poll_fini(dev);
-
-       /* Then kill the work that may have been queued by hpd. */
+       /* Kill all the work that may have been queued by hpd. */
        drm_connector_list_iter_begin(dev, &conn_iter);
        for_each_intel_connector_iter(connector, &conn_iter) {
                if (connector->modeset_retry_work.func)
                        cancel_work_sync(&connector->modeset_retry_work);
+               if (connector->hdcp_shim) {
+                       cancel_delayed_work_sync(&connector->hdcp_check_work);
+                       cancel_work_sync(&connector->hdcp_prop_work);
+               }
        }
        drm_connector_list_iter_end(&conn_iter);
 }