drm/i915: Do one shot unclaimed mmio detection less frequently
[linux-2.6-block.git] / drivers / gpu / drm / i915 / intel_display.c
index 22e86d2e408d9493e6c2ea6a60e689a5c03934a9..3edf22ad7673e4ddde8caaacd5fb698f06d50ef8 100644 (file)
@@ -44,6 +44,8 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
 #include <linux/dma_remapping.h>
+#include <linux/reservation.h>
+#include <linux/dma-buf.h>
 
 /* Primary plane formats for gen <= 3 */
 static const uint32_t i8xx_primary_formats[] = {
@@ -83,8 +85,6 @@ static const uint32_t intel_cursor_formats[] = {
        DRM_FORMAT_ARGB8888,
 };
 
-static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
-
 static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
                                struct intel_crtc_state *pipe_config);
 static void ironlake_pch_clock_get(struct intel_crtc *crtc,
@@ -116,6 +116,7 @@ static void skylake_pfit_enable(struct intel_crtc *crtc);
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
+static void intel_pre_disable_primary(struct drm_crtc *crtc);
 
 typedef struct {
        int     min, max;
@@ -185,7 +186,7 @@ int intel_hrawclk(struct drm_device *dev)
        uint32_t clkcfg;
 
        /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
-       if (IS_VALLEYVIEW(dev))
+       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
                return 200;
 
        clkcfg = I915_READ(CLKCFG);
@@ -213,7 +214,7 @@ int intel_hrawclk(struct drm_device *dev)
 
 static void intel_update_czclk(struct drm_i915_private *dev_priv)
 {
-       if (!IS_VALLEYVIEW(dev_priv))
+       if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
                return;
 
        dev_priv->czclk_freq = vlv_get_cck_clock_hpll(dev_priv, "czclk",
@@ -714,11 +715,12 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
        if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
                INTELPllInvalid("m1 out of range\n");
 
-       if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
+       if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) &&
+           !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev))
                if (clock->m1 <= clock->m2)
                        INTELPllInvalid("m1 <= m2\n");
 
-       if (!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev)) {
+       if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) {
                if (clock->p < limit->p.min || limit->p.max < clock->p)
                        INTELPllInvalid("p out of range\n");
                if (clock->m < limit->m.min || limit->m.max < clock->m)
@@ -1095,7 +1097,7 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
 static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 reg = PIPEDSL(pipe);
+       i915_reg_t reg = PIPEDSL(pipe);
        u32 line1, line2;
        u32 line_mask;
 
@@ -1135,7 +1137,7 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
        enum pipe pipe = crtc->pipe;
 
        if (INTEL_INFO(dev)->gen >= 4) {
-               int reg = PIPECONF(cpu_transcoder);
+               i915_reg_t reg = PIPECONF(cpu_transcoder);
 
                /* Wait for the Pipe State to go off */
                if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
@@ -1285,7 +1287,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
                           enum pipe pipe)
 {
        struct drm_device *dev = dev_priv->dev;
-       int pp_reg;
+       i915_reg_t pp_reg;
        u32 val;
        enum pipe panel_pipe = PIPE_A;
        bool locked = true;
@@ -1303,7 +1305,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
                    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
                        panel_pipe = PIPE_B;
                /* XXX: else fix for eDP */
-       } else if (IS_VALLEYVIEW(dev)) {
+       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                /* presumably write lock depends on pipe, not port select */
                pp_reg = VLV_PIPE_PP_CONTROL(pipe);
                panel_pipe = pipe;
@@ -1421,7 +1423,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
                             "plane %d assertion failure, should be off on pipe %c but is still active\n",
                             sprite, pipe_name(pipe));
                }
-       } else if (IS_VALLEYVIEW(dev)) {
+       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                for_each_sprite(dev_priv, pipe, sprite) {
                        u32 val = I915_READ(SPCNTR(pipe, sprite));
                        I915_STATE_WARN(val & SP_ENABLE,
@@ -1480,8 +1482,7 @@ static bool dp_pipe_enabled(struct drm_i915_private *dev_priv,
                return false;
 
        if (HAS_PCH_CPT(dev_priv->dev)) {
-               u32     trans_dp_ctl_reg = TRANS_DP_CTL(pipe);
-               u32     trans_dp_ctl = I915_READ(trans_dp_ctl_reg);
+               u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe));
                if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
                        return false;
        } else if (IS_CHERRYVIEW(dev_priv->dev)) {
@@ -1545,12 +1546,13 @@ static bool adpa_pipe_enabled(struct drm_i915_private *dev_priv,
 }
 
 static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
-                                  enum pipe pipe, int reg, u32 port_sel)
+                                  enum pipe pipe, i915_reg_t reg,
+                                  u32 port_sel)
 {
        u32 val = I915_READ(reg);
        I915_STATE_WARN(dp_pipe_enabled(dev_priv, pipe, port_sel, val),
             "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
-            reg, pipe_name(pipe));
+            i915_mmio_reg_offset(reg), pipe_name(pipe));
 
        I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
             && (val & DP_PIPEB_SELECT),
@@ -1558,12 +1560,12 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
 }
 
 static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
-                                    enum pipe pipe, int reg)
+                                    enum pipe pipe, i915_reg_t reg)
 {
        u32 val = I915_READ(reg);
        I915_STATE_WARN(hdmi_pipe_enabled(dev_priv, pipe, val),
             "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
-            reg, pipe_name(pipe));
+            i915_mmio_reg_offset(reg), pipe_name(pipe));
 
        I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0
             && (val & SDVO_PIPE_B_SELECT),
@@ -1599,14 +1601,11 @@ static void vlv_enable_pll(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int reg = DPLL(crtc->pipe);
+       i915_reg_t reg = DPLL(crtc->pipe);
        u32 dpll = pipe_config->dpll_hw_state.dpll;
 
        assert_pipe_disabled(dev_priv, crtc->pipe);
 
-       /* No really, not for ILK+ */
-       BUG_ON(!IS_VALLEYVIEW(dev_priv->dev));
-
        /* PLL is protected by panel, make sure we can write it */
        if (IS_MOBILE(dev_priv->dev))
                assert_panel_unlocked(dev_priv, crtc->pipe);
@@ -1644,8 +1643,6 @@ static void chv_enable_pll(struct intel_crtc *crtc,
 
        assert_pipe_disabled(dev_priv, crtc->pipe);
 
-       BUG_ON(!IS_CHERRYVIEW(dev_priv->dev));
-
        mutex_lock(&dev_priv->sb_lock);
 
        /* Enable back the 10bit clock to display controller */
@@ -1688,7 +1685,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int reg = DPLL(crtc->pipe);
+       i915_reg_t reg = DPLL(crtc->pipe);
        u32 dpll = crtc->config->dpll_hw_state.dpll;
 
        assert_pipe_disabled(dev_priv, crtc->pipe);
@@ -1837,7 +1834,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
                         unsigned int expected_mask)
 {
        u32 port_mask;
-       int dpll_reg;
+       i915_reg_t dpll_reg;
 
        switch (dport->port) {
        case PORT_B:
@@ -1962,7 +1959,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        struct drm_device *dev = dev_priv->dev;
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       uint32_t reg, val, pipeconf_val;
+       i915_reg_t reg;
+       uint32_t val, pipeconf_val;
 
        /* PCH only available on ILK+ */
        BUG_ON(!HAS_PCH_SPLIT(dev));
@@ -2051,7 +2049,8 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
                                            enum pipe pipe)
 {
        struct drm_device *dev = dev_priv->dev;
-       uint32_t reg, val;
+       i915_reg_t reg;
+       uint32_t val;
 
        /* FDI relies on the transcoder */
        assert_fdi_tx_disabled(dev_priv, pipe);
@@ -2068,7 +2067,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
        if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
                DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
 
-       if (!HAS_PCH_IBX(dev)) {
+       if (HAS_PCH_CPT(dev)) {
                /* Workaround: Clear the timing override chicken bit again. */
                reg = TRANS_CHICKEN2(pipe);
                val = I915_READ(reg);
@@ -2106,10 +2105,9 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe = crtc->pipe;
-       enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
-                                                                     pipe);
+       enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
        enum pipe pch_transcoder;
-       int reg;
+       i915_reg_t reg;
        u32 val;
 
        DRM_DEBUG_KMS("enabling pipe %c\n", pipe_name(pipe));
@@ -2129,7 +2127,7 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
         * need the check.
         */
        if (HAS_GMCH_DISPLAY(dev_priv->dev))
-               if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DSI))
+               if (crtc->config->has_dsi_encoder)
                        assert_dsi_pll_enabled(dev_priv);
                else
                        assert_pll_enabled(dev_priv, pipe);
@@ -2170,7 +2168,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
        struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
        enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
        enum pipe pipe = crtc->pipe;
-       int reg;
+       i915_reg_t reg;
        u32 val;
 
        DRM_DEBUG_KMS("disabling pipe %c\n", pipe_name(pipe));
@@ -2269,20 +2267,20 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height,
                                               fb_format_modifier, 0));
 }
 
-static int
+static void
 intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
                        const struct drm_plane_state *plane_state)
 {
-       struct intel_rotation_info *info = &view->rotation_info;
+       struct intel_rotation_info *info = &view->params.rotation_info;
        unsigned int tile_height, tile_pitch;
 
        *view = i915_ggtt_view_normal;
 
        if (!plane_state)
-               return 0;
+               return;
 
        if (!intel_rotation_90_or_270(plane_state->rotation))
-               return 0;
+               return;
 
        *view = i915_ggtt_view_rotated;
 
@@ -2309,8 +2307,6 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
                info->size_uv = info->width_pages_uv * info->height_pages_uv *
                                PAGE_SIZE;
        }
-
-       return 0;
 }
 
 static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
@@ -2318,7 +2314,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
        if (INTEL_INFO(dev_priv)->gen >= 9)
                return 256 * 1024;
        else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv) ||
-                IS_VALLEYVIEW(dev_priv))
+                IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                return 128 * 1024;
        else if (INTEL_INFO(dev_priv)->gen >= 4)
                return 4 * 1024;
@@ -2329,9 +2325,7 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
 int
 intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                           struct drm_framebuffer *fb,
-                          const struct drm_plane_state *plane_state,
-                          struct intel_engine_cs *pipelined,
-                          struct drm_i915_gem_request **pipelined_request)
+                          const struct drm_plane_state *plane_state)
 {
        struct drm_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2366,9 +2360,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                return -EINVAL;
        }
 
-       ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
-       if (ret)
-               return ret;
+       intel_fill_fb_ggtt_view(&view, fb, plane_state);
 
        /* Note that the w/a also requires 64 PTE of padding following the
         * bo. We currently fill all unused PTE with the shadow page and so
@@ -2387,11 +2379,10 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
         */
        intel_runtime_pm_get(dev_priv);
 
-       dev_priv->mm.interruptible = false;
-       ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined,
-                                                  pipelined_request, &view);
+       ret = i915_gem_object_pin_to_display_plane(obj, alignment,
+                                                  &view);
        if (ret)
-               goto err_interruptible;
+               goto err_pm;
 
        /* Install a fence for tiled scan-out. Pre-i965 always needs a
         * fence, whereas 965+ only requires a fence if using
@@ -2417,14 +2408,12 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                i915_gem_object_pin_fence(obj);
        }
 
-       dev_priv->mm.interruptible = true;
        intel_runtime_pm_put(dev_priv);
        return 0;
 
 err_unpin:
        i915_gem_object_unpin_from_display_plane(obj, &view);
-err_interruptible:
-       dev_priv->mm.interruptible = true;
+err_pm:
        intel_runtime_pm_put(dev_priv);
        return ret;
 }
@@ -2434,12 +2423,10 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
 {
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct i915_ggtt_view view;
-       int ret;
 
        WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
 
-       ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
-       WARN_ONCE(ret, "Couldn't get view from plane state!");
+       intel_fill_fb_ggtt_view(&view, fb, plane_state);
 
        if (view.type == I915_GGTT_VIEW_NORMAL)
                i915_gem_object_unpin_fence(obj);
@@ -2607,6 +2594,10 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        struct drm_i915_gem_object *obj;
        struct drm_plane *primary = intel_crtc->base.primary;
        struct drm_plane_state *plane_state = primary->state;
+       struct drm_crtc_state *crtc_state = intel_crtc->base.state;
+       struct intel_plane *intel_plane = to_intel_plane(primary);
+       struct intel_plane_state *intel_state =
+               to_intel_plane_state(plane_state);
        struct drm_framebuffer *fb;
 
        if (!plane_config->fb)
@@ -2643,6 +2634,18 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
                }
        }
 
+       /*
+        * We've failed to reconstruct the BIOS FB.  Current display state
+        * indicates that the primary plane is visible, but has a NULL FB,
+        * which will lead to problems later if we don't fix it up.  The
+        * simplest solution is to just disable the primary plane now and
+        * pretend the BIOS never had it enabled.
+        */
+       to_intel_plane_state(plane_state)->visible = false;
+       crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
+       intel_pre_disable_primary(&intel_crtc->base);
+       intel_plane->disable_plane(primary, &intel_crtc->base);
+
        return;
 
 valid_fb:
@@ -2656,6 +2659,15 @@ valid_fb:
        plane_state->crtc_w = fb->width;
        plane_state->crtc_h = fb->height;
 
+       intel_state->src.x1 = plane_state->src_x;
+       intel_state->src.y1 = plane_state->src_y;
+       intel_state->src.x2 = plane_state->src_x + plane_state->src_w;
+       intel_state->src.y2 = plane_state->src_y + plane_state->src_h;
+       intel_state->dst.x1 = plane_state->crtc_x;
+       intel_state->dst.y1 = plane_state->crtc_y;
+       intel_state->dst.x2 = plane_state->crtc_x + plane_state->crtc_w;
+       intel_state->dst.y2 = plane_state->crtc_y + plane_state->crtc_h;
+
        obj = intel_fb_obj(fb);
        if (obj->tiling_mode != I915_TILING_NONE)
                dev_priv->preserve_bios_swizzle = true;
@@ -2667,36 +2679,23 @@ valid_fb:
        obj->frontbuffer_bits |= to_intel_plane(primary)->frontbuffer_bit;
 }
 
-static void i9xx_update_primary_plane(struct drm_crtc *crtc,
-                                     struct drm_framebuffer *fb,
-                                     int x, int y)
+static void i9xx_update_primary_plane(struct drm_plane *primary,
+                                     const struct intel_crtc_state *crtc_state,
+                                     const struct intel_plane_state *plane_state)
 {
-       struct drm_device *dev = crtc->dev;
+       struct drm_device *dev = primary->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_plane *primary = crtc->primary;
-       bool visible = to_intel_plane_state(primary->state)->visible;
-       struct drm_i915_gem_object *obj;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_framebuffer *fb = plane_state->base.fb;
+       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        int plane = intel_crtc->plane;
        unsigned long linear_offset;
+       int x = plane_state->src.x1 >> 16;
+       int y = plane_state->src.y1 >> 16;
        u32 dspcntr;
-       u32 reg = DSPCNTR(plane);
+       i915_reg_t reg = DSPCNTR(plane);
        int pixel_size;
 
-       if (!visible || !fb) {
-               I915_WRITE(reg, 0);
-               if (INTEL_INFO(dev)->gen >= 4)
-                       I915_WRITE(DSPSURF(plane), 0);
-               else
-                       I915_WRITE(DSPADDR(plane), 0);
-               POSTING_READ(reg);
-               return;
-       }
-
-       obj = intel_fb_obj(fb);
-       if (WARN_ON(obj == NULL))
-               return;
-
        pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
 
        dspcntr = DISPPLANE_GAMMA_ENABLE;
@@ -2711,13 +2710,13 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
                 * which should always be the user's requested size.
                 */
                I915_WRITE(DSPSIZE(plane),
-                          ((intel_crtc->config->pipe_src_h - 1) << 16) |
-                          (intel_crtc->config->pipe_src_w - 1));
+                          ((crtc_state->pipe_src_h - 1) << 16) |
+                          (crtc_state->pipe_src_w - 1));
                I915_WRITE(DSPPOS(plane), 0);
        } else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) {
                I915_WRITE(PRIMSIZE(plane),
-                          ((intel_crtc->config->pipe_src_h - 1) << 16) |
-                          (intel_crtc->config->pipe_src_w - 1));
+                          ((crtc_state->pipe_src_h - 1) << 16) |
+                          (crtc_state->pipe_src_w - 1));
                I915_WRITE(PRIMPOS(plane), 0);
                I915_WRITE(PRIMCNSTALPHA(plane), 0);
        }
@@ -2768,17 +2767,17 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
                intel_crtc->dspaddr_offset = linear_offset;
        }
 
-       if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
+       if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
                dspcntr |= DISPPLANE_ROTATE_180;
 
-               x += (intel_crtc->config->pipe_src_w - 1);
-               y += (intel_crtc->config->pipe_src_h - 1);
+               x += (crtc_state->pipe_src_w - 1);
+               y += (crtc_state->pipe_src_h - 1);
 
                /* Finding the last pixel of the last line of the display
                data and adding to linear_offset*/
                linear_offset +=
-                       (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
-                       (intel_crtc->config->pipe_src_w - 1) * pixel_size;
+                       (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
+                       (crtc_state->pipe_src_w - 1) * pixel_size;
        }
 
        intel_crtc->adjusted_x = x;
@@ -2797,37 +2796,40 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
        POSTING_READ(reg);
 }
 
-static void ironlake_update_primary_plane(struct drm_crtc *crtc,
-                                         struct drm_framebuffer *fb,
-                                         int x, int y)
+static void i9xx_disable_primary_plane(struct drm_plane *primary,
+                                      struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_plane *primary = crtc->primary;
-       bool visible = to_intel_plane_state(primary->state)->visible;
-       struct drm_i915_gem_object *obj;
        int plane = intel_crtc->plane;
-       unsigned long linear_offset;
-       u32 dspcntr;
-       u32 reg = DSPCNTR(plane);
-       int pixel_size;
 
-       if (!visible || !fb) {
-               I915_WRITE(reg, 0);
+       I915_WRITE(DSPCNTR(plane), 0);
+       if (INTEL_INFO(dev_priv)->gen >= 4)
                I915_WRITE(DSPSURF(plane), 0);
-               POSTING_READ(reg);
-               return;
-       }
-
-       obj = intel_fb_obj(fb);
-       if (WARN_ON(obj == NULL))
-               return;
+       else
+               I915_WRITE(DSPADDR(plane), 0);
+       POSTING_READ(DSPCNTR(plane));
+}
 
-       pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+static void ironlake_update_primary_plane(struct drm_plane *primary,
+                                         const struct intel_crtc_state *crtc_state,
+                                         const struct intel_plane_state *plane_state)
+{
+       struct drm_device *dev = primary->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_framebuffer *fb = plane_state->base.fb;
+       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       int plane = intel_crtc->plane;
+       unsigned long linear_offset;
+       u32 dspcntr;
+       i915_reg_t reg = DSPCNTR(plane);
+       int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+       int x = plane_state->src.x1 >> 16;
+       int y = plane_state->src.y1 >> 16;
 
        dspcntr = DISPPLANE_GAMMA_ENABLE;
-
        dspcntr |= DISPLAY_PLANE_ENABLE;
 
        if (IS_HASWELL(dev) || IS_BROADWELL(dev))
@@ -2869,18 +2871,18 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
                                               pixel_size,
                                               fb->pitches[0]);
        linear_offset -= intel_crtc->dspaddr_offset;
-       if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
+       if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
                dspcntr |= DISPPLANE_ROTATE_180;
 
                if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
-                       x += (intel_crtc->config->pipe_src_w - 1);
-                       y += (intel_crtc->config->pipe_src_h - 1);
+                       x += (crtc_state->pipe_src_w - 1);
+                       y += (crtc_state->pipe_src_h - 1);
 
                        /* Finding the last pixel of the last line of the display
                        data and adding to linear_offset*/
                        linear_offset +=
-                               (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
-                               (intel_crtc->config->pipe_src_w - 1) * pixel_size;
+                               (crtc_state->pipe_src_h - 1) * fb->pitches[0] +
+                               (crtc_state->pipe_src_w - 1) * pixel_size;
                }
        }
 
@@ -2935,30 +2937,32 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
        }
 }
 
-unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
-                                    struct drm_i915_gem_object *obj,
-                                    unsigned int plane)
+u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
+                          struct drm_i915_gem_object *obj,
+                          unsigned int plane)
 {
-       const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
+       struct i915_ggtt_view view;
        struct i915_vma *vma;
-       unsigned char *offset;
+       u64 offset;
 
-       if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
-               view = &i915_ggtt_view_rotated;
+       intel_fill_fb_ggtt_view(&view, intel_plane->base.fb,
+                               intel_plane->base.state);
 
-       vma = i915_gem_obj_to_ggtt_view(obj, view);
+       vma = i915_gem_obj_to_ggtt_view(obj, &view);
        if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
-               view->type))
+               view.type))
                return -1;
 
-       offset = (unsigned char *)vma->node.start;
+       offset = vma->node.start;
 
        if (plane == 1) {
-               offset += vma->ggtt_view.rotation_info.uv_start_page *
+               offset += vma->ggtt_view.params.rotation_info.uv_start_page *
                          PAGE_SIZE;
        }
 
-       return (unsigned long)offset;
+       WARN_ON(upper_32_bits(offset));
+
+       return lower_32_bits(offset);
 }
 
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3069,36 +3073,30 @@ u32 skl_plane_ctl_rotation(unsigned int rotation)
        return 0;
 }
 
-static void skylake_update_primary_plane(struct drm_crtc *crtc,
-                                        struct drm_framebuffer *fb,
-                                        int x, int y)
+static void skylake_update_primary_plane(struct drm_plane *plane,
+                                        const struct intel_crtc_state *crtc_state,
+                                        const struct intel_plane_state *plane_state)
 {
-       struct drm_device *dev = crtc->dev;
+       struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_plane *plane = crtc->primary;
-       bool visible = to_intel_plane_state(plane->state)->visible;
-       struct drm_i915_gem_object *obj;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_framebuffer *fb = plane_state->base.fb;
+       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        int pipe = intel_crtc->pipe;
        u32 plane_ctl, stride_div, stride;
        u32 tile_height, plane_offset, plane_size;
-       unsigned int rotation;
+       unsigned int rotation = plane_state->base.rotation;
        int x_offset, y_offset;
-       unsigned long surf_addr;
-       struct intel_crtc_state *crtc_state = intel_crtc->config;
-       struct intel_plane_state *plane_state;
-       int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
-       int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
-       int scaler_id = -1;
-
-       plane_state = to_intel_plane_state(plane->state);
-
-       if (!visible || !fb) {
-               I915_WRITE(PLANE_CTL(pipe, 0), 0);
-               I915_WRITE(PLANE_SURF(pipe, 0), 0);
-               POSTING_READ(PLANE_CTL(pipe, 0));
-               return;
-       }
+       u32 surf_addr;
+       int scaler_id = plane_state->scaler_id;
+       int src_x = plane_state->src.x1 >> 16;
+       int src_y = plane_state->src.y1 >> 16;
+       int src_w = drm_rect_width(&plane_state->src) >> 16;
+       int src_h = drm_rect_height(&plane_state->src) >> 16;
+       int dst_x = plane_state->dst.x1;
+       int dst_y = plane_state->dst.y1;
+       int dst_w = drm_rect_width(&plane_state->dst);
+       int dst_h = drm_rect_height(&plane_state->dst);
 
        plane_ctl = PLANE_CTL_ENABLE |
                    PLANE_CTL_PIPE_GAMMA_ENABLE |
@@ -3107,41 +3105,26 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
        plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
        plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
        plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
-
-       rotation = plane->state->rotation;
        plane_ctl |= skl_plane_ctl_rotation(rotation);
 
-       obj = intel_fb_obj(fb);
        stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
                                               fb->pixel_format);
        surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
 
        WARN_ON(drm_rect_width(&plane_state->src) == 0);
 
-       scaler_id = plane_state->scaler_id;
-       src_x = plane_state->src.x1 >> 16;
-       src_y = plane_state->src.y1 >> 16;
-       src_w = drm_rect_width(&plane_state->src) >> 16;
-       src_h = drm_rect_height(&plane_state->src) >> 16;
-       dst_x = plane_state->dst.x1;
-       dst_y = plane_state->dst.y1;
-       dst_w = drm_rect_width(&plane_state->dst);
-       dst_h = drm_rect_height(&plane_state->dst);
-
-       WARN_ON(x != src_x || y != src_y);
-
        if (intel_rotation_90_or_270(rotation)) {
                /* stride = Surface height in tiles */
                tile_height = intel_tile_height(dev, fb->pixel_format,
                                                fb->modifier[0], 0);
                stride = DIV_ROUND_UP(fb->height, tile_height);
-               x_offset = stride * tile_height - y - src_h;
-               y_offset = x;
+               x_offset = stride * tile_height - src_y - src_h;
+               y_offset = src_x;
                plane_size = (src_w - 1) << 16 | (src_h - 1);
        } else {
                stride = fb->pitches[0] / stride_div;
-               x_offset = x;
-               y_offset = y;
+               x_offset = src_x;
+               y_offset = src_y;
                plane_size = (src_h - 1) << 16 | (src_w - 1);
        }
        plane_offset = y_offset << 16 | x_offset;
@@ -3174,20 +3157,30 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
        POSTING_READ(PLANE_SURF(pipe, 0));
 }
 
-/* Assume fb object is pinned & idle & fenced and just update base pointers */
-static int
-intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-                          int x, int y, enum mode_set_atomic state)
+static void skylake_disable_primary_plane(struct drm_plane *primary,
+                                         struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       int pipe = to_intel_crtc(crtc)->pipe;
 
-       if (dev_priv->fbc.disable_fbc)
-               dev_priv->fbc.disable_fbc(dev_priv);
+       if (dev_priv->fbc.deactivate)
+               dev_priv->fbc.deactivate(dev_priv);
 
-       dev_priv->display.update_primary_plane(crtc, fb, x, y);
+       I915_WRITE(PLANE_CTL(pipe, 0), 0);
+       I915_WRITE(PLANE_SURF(pipe, 0), 0);
+       POSTING_READ(PLANE_SURF(pipe, 0));
+}
 
-       return 0;
+/* Assume fb object is pinned & idle & fenced and just update base pointers */
+static int
+intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+                          int x, int y, enum mode_set_atomic state)
+{
+       /* Support for kgdboc is disabled, this needs a major rework. */
+       DRM_ERROR("legacy panic handler not supported any more.\n");
+
+       return -ENODEV;
 }
 
 static void intel_complete_page_flips(struct drm_device *dev)
@@ -3212,11 +3205,12 @@ static void intel_update_primary_planes(struct drm_device *dev)
                struct intel_plane_state *plane_state;
 
                drm_modeset_lock_crtc(crtc, &plane->base);
-
                plane_state = to_intel_plane_state(plane->base.state);
 
-               if (plane_state->base.fb)
-                       plane->commit_plane(&plane->base, plane_state);
+               if (plane_state->visible)
+                       plane->update_plane(&plane->base,
+                                           to_intel_crtc_state(crtc->state),
+                                           plane_state);
 
                drm_modeset_unlock_crtc(crtc);
        }
@@ -3291,32 +3285,6 @@ void intel_finish_reset(struct drm_device *dev)
        drm_modeset_unlock_all(dev);
 }
 
-static void
-intel_finish_fb(struct drm_framebuffer *old_fb)
-{
-       struct drm_i915_gem_object *obj = intel_fb_obj(old_fb);
-       struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
-       bool was_interruptible = dev_priv->mm.interruptible;
-       int ret;
-
-       /* Big Hammer, we also need to ensure that any pending
-        * MI_WAIT_FOR_EVENT inside a user batch buffer on the
-        * current scanout is retired before unpinning the old
-        * framebuffer. Note that we rely on userspace rendering
-        * into the buffer attached to the pipe they are waiting
-        * on. If not, userspace generates a GPU hang with IPEHR
-        * point to the MI_WAIT_FOR_EVENT.
-        *
-        * This should only fail upon a hung GPU, in which case we
-        * can safely continue.
-        */
-       dev_priv->mm.interruptible = false;
-       ret = i915_gem_object_wait_rendering(obj, true);
-       dev_priv->mm.interruptible = was_interruptible;
-
-       WARN_ON(ret);
-}
-
 static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -3386,7 +3354,8 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp;
+       i915_reg_t reg;
+       u32 temp;
 
        /* enable normal train */
        reg = FDI_TX_CTL(pipe);
@@ -3428,7 +3397,8 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp, tries;
+       i915_reg_t reg;
+       u32 temp, tries;
 
        /* FDI needs bits from pipe first */
        assert_pipe_enabled(dev_priv, pipe);
@@ -3528,7 +3498,8 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp, i, retry;
+       i915_reg_t reg;
+       u32 temp, i, retry;
 
        /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
           for train result */
@@ -3660,7 +3631,8 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp, i, j;
+       i915_reg_t reg;
+       u32 temp, i, j;
 
        /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
           for train result */
@@ -3777,8 +3749,8 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = intel_crtc->pipe;
-       u32 reg, temp;
-
+       i915_reg_t reg;
+       u32 temp;
 
        /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
        reg = FDI_RX_CTL(pipe);
@@ -3814,7 +3786,8 @@ static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = intel_crtc->pipe;
-       u32 reg, temp;
+       i915_reg_t reg;
+       u32 temp;
 
        /* Switch from PCDclk to Rawclk */
        reg = FDI_RX_CTL(pipe);
@@ -3844,7 +3817,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp;
+       i915_reg_t reg;
+       u32 temp;
 
        /* disable CPU FDI tx and PCH FDI rx */
        reg = FDI_TX_CTL(pipe);
@@ -3937,15 +3911,23 @@ static void page_flip_completed(struct intel_crtc *intel_crtc)
                                 work->pending_flip_obj);
 }
 
-void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
+static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       long ret;
 
        WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
-       if (WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
-                                      !intel_crtc_has_pending_flip(crtc),
-                                      60*HZ) == 0)) {
+
+       ret = wait_event_interruptible_timeout(
+                                       dev_priv->pending_flip_queue,
+                                       !intel_crtc_has_pending_flip(crtc),
+                                       60*HZ);
+
+       if (ret < 0)
+               return ret;
+
+       if (ret == 0) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
                spin_lock_irq(&dev->event_lock);
@@ -3956,11 +3938,22 @@ void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
                spin_unlock_irq(&dev->event_lock);
        }
 
-       if (crtc->primary->fb) {
-               mutex_lock(&dev->struct_mutex);
-               intel_finish_fb(crtc->primary->fb);
-               mutex_unlock(&dev->struct_mutex);
-       }
+       return 0;
+}
+
+static void lpt_disable_iclkip(struct drm_i915_private *dev_priv)
+{
+       u32 temp;
+
+       I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
+
+       mutex_lock(&dev_priv->sb_lock);
+
+       temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
+       temp |= SBI_SSCCTL_DISABLE;
+       intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
+
+       mutex_unlock(&dev_priv->sb_lock);
 }
 
 /* Program iCLKIP clock to the desired frequency */
@@ -3972,18 +3965,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
        u32 divsel, phaseinc, auxdiv, phasedir = 0;
        u32 temp;
 
-       mutex_lock(&dev_priv->sb_lock);
-
-       /* It is necessary to ungate the pixclk gate prior to programming
-        * the divisors, and gate it back when it is done.
-        */
-       I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_GATE);
-
-       /* Disable SSCCTL */
-       intel_sbi_write(dev_priv, SBI_SSCCTL6,
-                       intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK) |
-                               SBI_SSCCTL_DISABLE,
-                       SBI_ICLK);
+       lpt_disable_iclkip(dev_priv);
 
        /* 20MHz is a corner case which is out of range for the 7-bit divisor */
        if (clock == 20000) {
@@ -4001,7 +3983,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
                u32 iclk_pi_range = 64;
                u32 desired_divisor, msb_divisor_value, pi_value;
 
-               desired_divisor = (iclk_virtual_root_freq / clock);
+               desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
                msb_divisor_value = desired_divisor / iclk_pi_range;
                pi_value = desired_divisor % iclk_pi_range;
 
@@ -4023,6 +4005,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
                        phasedir,
                        phaseinc);
 
+       mutex_lock(&dev_priv->sb_lock);
+
        /* Program SSCDIVINTPHASE6 */
        temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
        temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK;
@@ -4044,12 +4028,12 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
        temp &= ~SBI_SSCCTL_DISABLE;
        intel_sbi_write(dev_priv, SBI_SSCCTL6, temp, SBI_ICLK);
 
+       mutex_unlock(&dev_priv->sb_lock);
+
        /* Wait for initialization time */
        udelay(24);
 
        I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
-
-       mutex_unlock(&dev_priv->sb_lock);
 }
 
 static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
@@ -4120,6 +4104,22 @@ static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
        }
 }
 
+/* Return which DP Port should be selected for Transcoder DP control */
+static enum port
+intel_trans_dp_port_sel(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct intel_encoder *encoder;
+
+       for_each_encoder_on_crtc(dev, crtc, encoder) {
+               if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+                   encoder->type == INTEL_OUTPUT_EDP)
+                       return enc_to_dig_port(&encoder->base)->port;
+       }
+
+       return -1;
+}
+
 /*
  * Enable PCH resources required for PCH ports:
  *   - PCH PLLs
@@ -4134,7 +4134,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 reg, temp;
+       u32 temp;
 
        assert_pch_transcoder_disabled(dev_priv, pipe);
 
@@ -4146,6 +4146,12 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        I915_WRITE(FDI_RX_TUSIZE1(pipe),
                   I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
 
+       /*
+        * Sometimes spurious CPU pipe underruns happen during FDI
+        * training, at least with VGA+HDMI cloning. Suppress them.
+        */
+       intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
        /* For PCH output, training FDI link */
        dev_priv->display.fdi_link_train(crtc);
 
@@ -4179,10 +4185,14 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 
        intel_fdi_normal_train(crtc);
 
+       intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+
        /* For PCH DP, enable TRANS_DP_CTL */
        if (HAS_PCH_CPT(dev) && intel_crtc->config->has_dp_encoder) {
+               const struct drm_display_mode *adjusted_mode =
+                       &intel_crtc->config->base.adjusted_mode;
                u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
-               reg = TRANS_DP_CTL(pipe);
+               i915_reg_t reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
                temp &= ~(TRANS_DP_PORT_SEL_MASK |
                          TRANS_DP_SYNC_MASK |
@@ -4190,19 +4200,19 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
                temp |= TRANS_DP_OUTPUT_ENABLE;
                temp |= bpc << 9; /* same format but at 11:9 */
 
-               if (crtc->mode.flags & DRM_MODE_FLAG_PHSYNC)
+               if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
                        temp |= TRANS_DP_HSYNC_ACTIVE_HIGH;
-               if (crtc->mode.flags & DRM_MODE_FLAG_PVSYNC)
+               if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
                        temp |= TRANS_DP_VSYNC_ACTIVE_HIGH;
 
                switch (intel_trans_dp_port_sel(crtc)) {
-               case PCH_DP_B:
+               case PORT_B:
                        temp |= TRANS_DP_PORT_SEL_B;
                        break;
-               case PCH_DP_C:
+               case PORT_C:
                        temp |= TRANS_DP_PORT_SEL_C;
                        break;
-               case PCH_DP_D:
+               case PORT_D:
                        temp |= TRANS_DP_PORT_SEL_D;
                        break;
                default:
@@ -4342,7 +4352,7 @@ static void intel_shared_dpll_commit(struct drm_atomic_state *state)
 static void cpt_verify_modeset(struct drm_device *dev, int pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int dslreg = PIPEDSL(pipe);
+       i915_reg_t dslreg = PIPEDSL(pipe);
        u32 temp;
 
        temp = I915_READ(dslreg);
@@ -4635,7 +4645,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
                return;
 
        if (HAS_GMCH_DISPLAY(dev_priv->dev)) {
-               if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI))
+               if (intel_crtc->config->has_dsi_encoder)
                        assert_dsi_pll_enabled(dev_priv);
                else
                        assert_pll_enabled(dev_priv, pipe);
@@ -4652,7 +4662,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
        }
 
        for (i = 0; i < 256; i++) {
-               u32 palreg;
+               i915_reg_t palreg;
 
                if (HAS_GMCH_DISPLAY(dev))
                        palreg = PALETTE(pipe, i);
@@ -4705,14 +4715,6 @@ intel_post_enable_primary(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
 
-       /*
-        * BDW signals flip done immediately if the plane
-        * is disabled, even if the plane enable is already
-        * armed to occur at the next vblank :(
-        */
-       if (IS_BROADWELL(dev))
-               intel_wait_for_vblank(dev, pipe);
-
        /*
         * FIXME IPS should be fine as long as one plane is
         * enabled, but in practice it seems to have problems
@@ -4731,9 +4733,9 @@ intel_post_enable_primary(struct drm_crtc *crtc)
        if (IS_GEN2(dev))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
-       /* Underruns don't raise interrupts, so check manually. */
-       if (HAS_GMCH_DISPLAY(dev))
-               i9xx_check_fifo_underruns(dev_priv);
+       /* Underruns don't always raise interrupts, so check manually. */
+       intel_check_cpu_fifo_underruns(dev_priv);
+       intel_check_pch_fifo_underruns(dev_priv);
 }
 
 /**
@@ -4790,31 +4792,26 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
 static void intel_post_plane_update(struct intel_crtc *crtc)
 {
        struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
+       struct intel_crtc_state *pipe_config =
+               to_intel_crtc_state(crtc->base.state);
        struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_plane *plane;
 
        if (atomic->wait_vblank)
                intel_wait_for_vblank(dev, crtc->pipe);
 
        intel_frontbuffer_flip(dev, atomic->fb_bits);
 
-       if (atomic->disable_cxsr)
-               crtc->wm.cxsr_allowed = true;
+       crtc->wm.cxsr_allowed = true;
 
-       if (crtc->atomic.update_wm_post)
+       if (pipe_config->wm_changed && pipe_config->base.active)
                intel_update_watermarks(&crtc->base);
 
        if (atomic->update_fbc)
-               intel_fbc_update(dev_priv);
+               intel_fbc_update(crtc);
 
        if (atomic->post_enable_primary)
                intel_post_enable_primary(&crtc->base);
 
-       drm_for_each_plane_mask(plane, dev, atomic->update_sprite_watermarks)
-               intel_update_sprite_watermarks(plane, &crtc->base,
-                                              0, 0, 0, false, false);
-
        memset(atomic, 0, sizeof(*atomic));
 }
 
@@ -4823,23 +4820,11 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
-       struct drm_plane *p;
-
-       /* Track fb's for any planes being disabled */
-       drm_for_each_plane_mask(p, dev, atomic->disabled_planes) {
-               struct intel_plane *plane = to_intel_plane(p);
-
-               mutex_lock(&dev->struct_mutex);
-               i915_gem_track_fb(intel_fb_obj(plane->base.fb), NULL,
-                                 plane->frontbuffer_bit);
-               mutex_unlock(&dev->struct_mutex);
-       }
-
-       if (atomic->wait_for_flips)
-               intel_crtc_wait_for_pending_flips(&crtc->base);
+       struct intel_crtc_state *pipe_config =
+               to_intel_crtc_state(crtc->base.state);
 
        if (atomic->disable_fbc)
-               intel_fbc_disable_crtc(crtc);
+               intel_fbc_deactivate(crtc);
 
        if (crtc->atomic.disable_ips)
                hsw_disable_ips(crtc);
@@ -4847,10 +4832,48 @@ static void intel_pre_plane_update(struct intel_crtc *crtc)
        if (atomic->pre_disable_primary)
                intel_pre_disable_primary(&crtc->base);
 
-       if (atomic->disable_cxsr) {
+       if (pipe_config->disable_cxsr) {
                crtc->wm.cxsr_allowed = false;
                intel_set_memory_cxsr(dev_priv, false);
        }
+
+       /*
+        * IVB workaround: must disable low power watermarks for at least
+        * one frame before enabling scaling.  LP watermarks can be re-enabled
+        * when scaling is disabled.
+        *
+        * WaCxSRDisabledForSpriteScaling:ivb
+        */
+       if (pipe_config->disable_lp_wm) {
+               ilk_disable_lp_wm(dev);
+               intel_wait_for_vblank(dev, crtc->pipe);
+       }
+
+       /*
+        * If we're doing a modeset, we're done.  No need to do any pre-vblank
+        * watermark programming here.
+        */
+       if (needs_modeset(&pipe_config->base))
+               return;
+
+       /*
+        * For platforms that support atomic watermarks, program the
+        * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these
+        * will be the intermediate values that are safe for both pre- and
+        * post- vblank; when vblank happens, the 'active' values will be set
+        * to the final 'target' values and we'll do this again to get the
+        * optimal watermarks.  For gen9+ platforms, the values we program here
+        * will be the final target values which will get automatically latched
+        * at vblank time; no further programming will be necessary.
+        *
+        * If a platform hasn't been transitioned to atomic watermarks yet,
+        * we'll continue to update watermarks the old way, if flags tell
+        * us to.
+        */
+       if (dev_priv->display.initial_watermarks != NULL)
+               dev_priv->display.initial_watermarks(pipe_config);
+       else if (pipe_config->wm_changed)
+               intel_update_watermarks(&crtc->base);
 }
 
 static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
@@ -4884,6 +4907,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        if (WARN_ON(intel_crtc->active))
                return;
 
+       if (intel_crtc->config->has_pch_encoder)
+               intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
+
        if (intel_crtc->config->has_pch_encoder)
                intel_prepare_shared_dpll(intel_crtc);
 
@@ -4902,7 +4928,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        intel_crtc->active = true;
 
        intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-       intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
                if (encoder->pre_enable)
@@ -4940,6 +4965,13 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
        if (HAS_PCH_CPT(dev))
                cpt_verify_modeset(dev, intel_crtc->pipe);
+
+       /* Must wait for vblank to avoid spurious PCH FIFO underruns */
+       if (intel_crtc->config->has_pch_encoder)
+               intel_wait_for_vblank(dev, pipe);
+       intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
+
+       intel_fbc_enable(intel_crtc);
 }
 
 /* IPS only exists on ULT machines and is tied to pipe A. */
@@ -4957,11 +4989,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        int pipe = intel_crtc->pipe, hsw_workaround_pipe;
        struct intel_crtc_state *pipe_config =
                to_intel_crtc_state(crtc->state);
-       bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
 
        if (WARN_ON(intel_crtc->active))
                return;
 
+       if (intel_crtc->config->has_pch_encoder)
+               intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+                                                     false);
+
        if (intel_crtc_to_shared_dpll(intel_crtc))
                intel_enable_shared_dpll(intel_crtc);
 
@@ -4986,21 +5021,20 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 
        intel_crtc->active = true;
 
-       intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+       if (intel_crtc->config->has_pch_encoder)
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+       else
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+
        for_each_encoder_on_crtc(dev, crtc, encoder) {
-               if (encoder->pre_pll_enable)
-                       encoder->pre_pll_enable(encoder);
                if (encoder->pre_enable)
                        encoder->pre_enable(encoder);
        }
 
-       if (intel_crtc->config->has_pch_encoder) {
-               intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
-                                                     true);
+       if (intel_crtc->config->has_pch_encoder)
                dev_priv->display.fdi_link_train(crtc);
-       }
 
-       if (!is_dsi)
+       if (!intel_crtc->config->has_dsi_encoder)
                intel_ddi_enable_pipe_clock(intel_crtc);
 
        if (INTEL_INFO(dev)->gen >= 9)
@@ -5015,7 +5049,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        intel_crtc_load_lut(crtc);
 
        intel_ddi_set_pipe_settings(crtc);
-       if (!is_dsi)
+       if (!intel_crtc->config->has_dsi_encoder)
                intel_ddi_enable_transcoder_func(crtc);
 
        intel_update_watermarks(crtc);
@@ -5024,7 +5058,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        if (intel_crtc->config->has_pch_encoder)
                lpt_pch_enable(crtc);
 
-       if (intel_crtc->config->dp_encoder_is_mst && !is_dsi)
+       if (intel_crtc->config->dp_encoder_is_mst)
                intel_ddi_set_vc_payload_alloc(crtc, true);
 
        assert_vblank_disabled(crtc);
@@ -5035,6 +5069,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
                intel_opregion_notify_encoder(encoder, true);
        }
 
+       if (intel_crtc->config->has_pch_encoder) {
+               intel_wait_for_vblank(dev, pipe);
+               intel_wait_for_vblank(dev, pipe);
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+               intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+                                                     true);
+       }
+
        /* If we change the relative order between pipe/planes enabling, we need
         * to change the workaround. */
        hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
@@ -5042,6 +5084,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
                intel_wait_for_vblank(dev, hsw_workaround_pipe);
                intel_wait_for_vblank(dev, hsw_workaround_pipe);
        }
+
+       intel_fbc_enable(intel_crtc);
 }
 
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force)
@@ -5066,7 +5110,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
-       u32 reg, temp;
+
+       if (intel_crtc->config->has_pch_encoder)
+               intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->disable(encoder);
@@ -5074,15 +5120,22 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
        drm_crtc_vblank_off(crtc);
        assert_vblank_disabled(crtc);
 
+       /*
+        * Sometimes spurious CPU pipe underruns happen when the
+        * pipe is already disabled, but FDI RX/TX is still enabled.
+        * Happens at least with VGA+HDMI cloning. Suppress them.
+        */
        if (intel_crtc->config->has_pch_encoder)
-               intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
        intel_disable_pipe(intel_crtc);
 
        ironlake_pfit_disable(intel_crtc, false);
 
-       if (intel_crtc->config->has_pch_encoder)
+       if (intel_crtc->config->has_pch_encoder) {
                ironlake_fdi_disable(crtc);
+               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+       }
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
                if (encoder->post_disable)
@@ -5092,6 +5145,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
                ironlake_disable_pch_transcoder(dev_priv, pipe);
 
                if (HAS_PCH_CPT(dev)) {
+                       i915_reg_t reg;
+                       u32 temp;
+
                        /* disable TRANS_DP_CTL */
                        reg = TRANS_DP_CTL(pipe);
                        temp = I915_READ(reg);
@@ -5108,6 +5164,10 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
                ironlake_fdi_pll_disable(intel_crtc);
        }
+
+       intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
+
+       intel_fbc_disable_crtc(intel_crtc);
 }
 
 static void haswell_crtc_disable(struct drm_crtc *crtc)
@@ -5117,7 +5177,10 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
-       bool is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
+
+       if (intel_crtc->config->has_pch_encoder)
+               intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+                                                     false);
 
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                intel_opregion_notify_encoder(encoder, false);
@@ -5127,15 +5190,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
        drm_crtc_vblank_off(crtc);
        assert_vblank_disabled(crtc);
 
-       if (intel_crtc->config->has_pch_encoder)
-               intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
-                                                     false);
        intel_disable_pipe(intel_crtc);
 
        if (intel_crtc->config->dp_encoder_is_mst)
                intel_ddi_set_vc_payload_alloc(crtc, false);
 
-       if (!is_dsi)
+       if (!intel_crtc->config->has_dsi_encoder)
                intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
        if (INTEL_INFO(dev)->gen >= 9)
@@ -5143,17 +5203,23 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
        else
                ironlake_pfit_disable(intel_crtc, false);
 
-       if (!is_dsi)
+       if (!intel_crtc->config->has_dsi_encoder)
                intel_ddi_disable_pipe_clock(intel_crtc);
 
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               if (encoder->post_disable)
+                       encoder->post_disable(encoder);
+
        if (intel_crtc->config->has_pch_encoder) {
                lpt_disable_pch_transcoder(dev_priv);
+               lpt_disable_iclkip(dev_priv);
                intel_ddi_fdi_disable(crtc);
+
+               intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
+                                                     true);
        }
 
-       for_each_encoder_on_crtc(dev, crtc, encoder)
-               if (encoder->post_disable)
-                       encoder->post_disable(encoder);
+       intel_fbc_disable_crtc(intel_crtc);
 }
 
 static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -5184,15 +5250,15 @@ static enum intel_display_power_domain port_to_power_domain(enum port port)
 {
        switch (port) {
        case PORT_A:
-               return POWER_DOMAIN_PORT_DDI_A_4_LANES;
+               return POWER_DOMAIN_PORT_DDI_A_LANES;
        case PORT_B:
-               return POWER_DOMAIN_PORT_DDI_B_4_LANES;
+               return POWER_DOMAIN_PORT_DDI_B_LANES;
        case PORT_C:
-               return POWER_DOMAIN_PORT_DDI_C_4_LANES;
+               return POWER_DOMAIN_PORT_DDI_C_LANES;
        case PORT_D:
-               return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+               return POWER_DOMAIN_PORT_DDI_D_LANES;
        case PORT_E:
-               return POWER_DOMAIN_PORT_DDI_E_2_LANES;
+               return POWER_DOMAIN_PORT_DDI_E_LANES;
        default:
                MISSING_CASE(port);
                return POWER_DOMAIN_PORT_OTHER;
@@ -5219,10 +5285,6 @@ static enum intel_display_power_domain port_to_aux_power_domain(enum port port)
        }
 }
 
-#define for_each_power_domain(domain, mask)                            \
-       for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)     \
-               if ((1 << (domain)) & (mask))
-
 enum intel_display_power_domain
 intel_display_port_power_domain(struct intel_encoder *intel_encoder)
 {
@@ -5287,13 +5349,11 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum pipe pipe = intel_crtc->pipe;
        unsigned long mask;
-       enum transcoder transcoder;
+       enum transcoder transcoder = intel_crtc->config->cpu_transcoder;
 
        if (!crtc->state->active)
                return 0;
 
-       transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
-
        mask = BIT(POWER_DOMAIN_PIPE(pipe));
        mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
        if (intel_crtc->config->pch_pfit.enabled ||
@@ -5335,6 +5395,7 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
 
 static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
 {
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        unsigned long put_domains[I915_MAX_PIPES] = {};
@@ -5348,13 +5409,9 @@ static void modeset_update_crtc_power_domains(struct drm_atomic_state *state)
                                modeset_get_crtc_power_domains(crtc);
        }
 
-       if (dev_priv->display.modeset_commit_cdclk) {
-               unsigned int cdclk = to_intel_atomic_state(state)->cdclk;
-
-               if (cdclk != dev_priv->cdclk_freq &&
-                   !WARN_ON(!state->allow_modeset))
-                       dev_priv->display.modeset_commit_cdclk(state);
-       }
+       if (dev_priv->display.modeset_commit_cdclk &&
+           intel_state->dev_cdclk != dev_priv->cdclk_freq)
+               dev_priv->display.modeset_commit_cdclk(state);
 
        for (i = 0; i < I915_MAX_PIPES; i++)
                if (put_domains[i])
@@ -5380,7 +5437,7 @@ static void intel_update_max_cdclk(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (IS_SKYLAKE(dev)) {
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
 
                if (limit == SKL_DFSM_CDCLK_LIMIT_675)
@@ -5437,7 +5494,7 @@ static void intel_update_cdclk(struct drm_device *dev)
         * BSpec erroneously claims we should aim for 4MHz, but
         * in fact 1MHz is the correct frequency.
         */
-       if (IS_VALLEYVIEW(dev)) {
+       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                /*
                 * Program the gmbus_freq based on the cdclk frequency.
                 * BSpec erroneously claims we should aim for 4MHz, but
@@ -5797,32 +5854,16 @@ void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
        if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
                DRM_ERROR("DBuf power disable timeout\n");
 
-       /*
-        * DMC assumes ownership of LCPLL and will get confused if we touch it.
-        */
-       if (dev_priv->csr.dmc_payload) {
-               /* disable DPLL0 */
-               I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) &
-                                       ~LCPLL_PLL_ENABLE);
-               if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
-                       DRM_ERROR("Couldn't disable DPLL0\n");
-       }
-
-       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+       /* disable DPLL0 */
+       I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
+       if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
+               DRM_ERROR("Couldn't disable DPLL0\n");
 }
 
 void skl_init_cdclk(struct drm_i915_private *dev_priv)
 {
-       u32 val;
        unsigned int required_vco;
 
-       /* enable PCH reset handshake */
-       val = I915_READ(HSW_NDE_RSTWRN_OPT);
-       I915_WRITE(HSW_NDE_RSTWRN_OPT, val | RESET_PCH_HANDSHAKE_ENABLE);
-
-       /* enable PG1 and Misc I/O */
-       intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
-
        /* DPLL0 not enabled (happens on early BIOS versions) */
        if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
                /* enable DPLL0 */
@@ -5843,6 +5884,45 @@ void skl_init_cdclk(struct drm_i915_private *dev_priv)
                DRM_ERROR("DBuf power enable timeout\n");
 }
 
+int skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
+{
+       uint32_t lcpll1 = I915_READ(LCPLL1_CTL);
+       uint32_t cdctl = I915_READ(CDCLK_CTL);
+       int freq = dev_priv->skl_boot_cdclk;
+
+       /*
+        * check if the pre-os intialized the display
+        * There is SWF18 scratchpad register defined which is set by the
+        * pre-os which can be used by the OS drivers to check the status
+        */
+       if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
+               goto sanitize;
+
+       /* Is PLL enabled and locked ? */
+       if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK)))
+               goto sanitize;
+
+       /* DPLL okay; verify the cdclock
+        *
+        * Noticed in some instances that the freq selection is correct but
+        * decimal part is programmed wrong from BIOS where pre-os does not
+        * enable display. Verify the same as well.
+        */
+       if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq)))
+               /* All well; nothing to sanitize */
+               return false;
+sanitize:
+       /*
+        * As of now initialize with max cdclk till
+        * we get dynamic cdclk support
+        * */
+       dev_priv->skl_boot_cdclk = dev_priv->max_cdclk_freq;
+       skl_init_cdclk(dev_priv);
+
+       /* we did have to sanitize */
+       return true;
+}
+
 /* Adjust CDclk dividers to allow high res or save power if possible */
 static void valleyview_set_cdclk(struct drm_device *dev, int cdclk)
 {
@@ -6005,22 +6085,31 @@ static int broxton_calc_cdclk(struct drm_i915_private *dev_priv,
 static int intel_mode_max_pixclk(struct drm_device *dev,
                                 struct drm_atomic_state *state)
 {
-       struct intel_crtc *intel_crtc;
-       struct intel_crtc_state *crtc_state;
-       int max_pixclk = 0;
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       unsigned max_pixclk = 0, i;
+       enum pipe pipe;
 
-       for_each_intel_crtc(dev, intel_crtc) {
-               crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
-               if (IS_ERR(crtc_state))
-                       return PTR_ERR(crtc_state);
+       memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
+              sizeof(intel_state->min_pixclk));
 
-               if (!crtc_state->base.enable)
-                       continue;
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               int pixclk = 0;
+
+               if (crtc_state->enable)
+                       pixclk = crtc_state->adjusted_mode.crtc_clock;
 
-               max_pixclk = max(max_pixclk,
-                                crtc_state->base.adjusted_mode.crtc_clock);
+               intel_state->min_pixclk[i] = pixclk;
        }
 
+       if (!intel_state->active_crtcs)
+               return 0;
+
+       for_each_pipe(dev_priv, pipe)
+               max_pixclk = max(intel_state->min_pixclk[pipe], max_pixclk);
+
        return max_pixclk;
 }
 
@@ -6029,13 +6118,18 @@ static int valleyview_modeset_calc_cdclk(struct drm_atomic_state *state)
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int max_pixclk = intel_mode_max_pixclk(dev, state);
+       struct intel_atomic_state *intel_state =
+               to_intel_atomic_state(state);
 
        if (max_pixclk < 0)
                return max_pixclk;
 
-       to_intel_atomic_state(state)->cdclk =
+       intel_state->cdclk = intel_state->dev_cdclk =
                valleyview_calc_cdclk(dev_priv, max_pixclk);
 
+       if (!intel_state->active_crtcs)
+               intel_state->dev_cdclk = valleyview_calc_cdclk(dev_priv, 0);
+
        return 0;
 }
 
@@ -6044,13 +6138,18 @@ static int broxton_modeset_calc_cdclk(struct drm_atomic_state *state)
        struct drm_device *dev = state->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int max_pixclk = intel_mode_max_pixclk(dev, state);
+       struct intel_atomic_state *intel_state =
+               to_intel_atomic_state(state);
 
        if (max_pixclk < 0)
                return max_pixclk;
 
-       to_intel_atomic_state(state)->cdclk =
+       intel_state->cdclk = intel_state->dev_cdclk =
                broxton_calc_cdclk(dev_priv, max_pixclk);
 
+       if (!intel_state->active_crtcs)
+               intel_state->dev_cdclk = broxton_calc_cdclk(dev_priv, 0);
+
        return 0;
 }
 
@@ -6093,8 +6192,10 @@ static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
 static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
-       unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_atomic_state *old_intel_state =
+               to_intel_atomic_state(old_state);
+       unsigned req_cdclk = old_intel_state->dev_cdclk;
 
        /*
         * FIXME: We can end up here with all power domains off, yet
@@ -6124,13 +6225,10 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
-       bool is_dsi;
 
        if (WARN_ON(intel_crtc->active))
                return;
 
-       is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
-
        if (intel_crtc->config->has_dp_encoder)
                intel_dp_set_m_n(intel_crtc, M1_N1);
 
@@ -6153,7 +6251,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
                if (encoder->pre_pll_enable)
                        encoder->pre_pll_enable(encoder);
 
-       if (!is_dsi) {
+       if (!intel_crtc->config->has_dsi_encoder) {
                if (IS_CHERRYVIEW(dev)) {
                        chv_prepare_pll(intel_crtc, intel_crtc->config);
                        chv_enable_pll(intel_crtc, intel_crtc->config);
@@ -6232,6 +6330,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
+
+       intel_fbc_enable(intel_crtc);
 }
 
 static void i9xx_pfit_disable(struct intel_crtc *crtc)
@@ -6279,7 +6379,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
                if (encoder->post_disable)
                        encoder->post_disable(encoder);
 
-       if (!intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI)) {
+       if (!intel_crtc->config->has_dsi_encoder) {
                if (IS_CHERRYVIEW(dev))
                        chv_disable_pll(dev_priv, pipe);
                else if (IS_VALLEYVIEW(dev))
@@ -6294,6 +6394,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 
        if (!IS_GEN2(dev))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
+       intel_fbc_disable_crtc(intel_crtc);
 }
 
 static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
@@ -6307,11 +6409,14 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
                return;
 
        if (to_intel_plane_state(crtc->primary->state)->visible) {
-               intel_crtc_wait_for_pending_flips(crtc);
+               WARN_ON(intel_crtc->unpin_work);
+
                intel_pre_disable_primary(crtc);
+
+               intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
+               to_intel_plane_state(crtc->primary->state)->visible = false;
        }
 
-       intel_crtc_disable_planes(crtc, crtc->state->plane_mask);
        dev_priv->display.crtc_disable(crtc);
        intel_crtc->active = false;
        intel_update_watermarks(crtc);
@@ -6321,6 +6426,9 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
        for_each_power_domain(domain, domains)
                intel_display_power_put(dev_priv, domain);
        intel_crtc->enabled_power_domains = 0;
+
+       dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
+       dev_priv->min_pixclk[intel_crtc->pipe] = 0;
 }
 
 /*
@@ -6625,6 +6733,15 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc,
                pipe_config_supports_ips(dev_priv, pipe_config);
 }
 
+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 &&
+               (crtc->pipe == PIPE_A || IS_I915G(dev_priv));
+}
+
 static int intel_crtc_compute_config(struct intel_crtc *crtc,
                                     struct intel_crtc_state *pipe_config)
 {
@@ -6634,23 +6751,24 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 
        /* FIXME should check pixel clock limits on all platforms */
        if (INTEL_INFO(dev)->gen < 4) {
-               int clock_limit = dev_priv->max_cdclk_freq;
+               int clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
 
                /*
-                * Enable pixel doubling when the dot clock
+                * Enable double wide mode when the dot clock
                 * is > 90% of the (display) core speed.
-                *
-                * GDG double wide on either pipe,
-                * otherwise pipe A only.
                 */
-               if ((crtc->pipe == PIPE_A || IS_I915G(dev)) &&
-                   adjusted_mode->crtc_clock > clock_limit * 9 / 10) {
+               if (intel_crtc_supports_double_wide(crtc) &&
+                   adjusted_mode->crtc_clock > clock_limit) {
                        clock_limit *= 2;
                        pipe_config->double_wide = true;
                }
 
-               if (adjusted_mode->crtc_clock > clock_limit * 9 / 10)
+               if (adjusted_mode->crtc_clock > clock_limit) {
+                       DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+                                     adjusted_mode->crtc_clock, clock_limit,
+                                     yesno(pipe_config->double_wide));
                        return -EINVAL;
+               }
        }
 
        /*
@@ -7127,7 +7245,7 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
 
        WARN_ON(!crtc_state->base.state);
 
-       if (IS_VALLEYVIEW(dev) || IS_BROXTON(dev)) {
+       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) {
                refclk = 100000;
        } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
            intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
@@ -7415,7 +7533,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = crtc->pipe;
-       int dpll_reg = DPLL(crtc->pipe);
+       i915_reg_t dpll_reg = DPLL(crtc->pipe);
        enum dpio_channel port = vlv_pipe_to_channel(pipe);
        u32 loopfilter, tribuf_calcntr;
        u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
@@ -7826,7 +7944,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
                pipeconf |= PIPECONF_DOUBLE_WIDE;
 
        /* only g4x and later have fancy bpc/dither controls */
-       if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+       if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                /* Bspec claims that we can't use dithering for 30bpp pipes. */
                if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
                        pipeconf |= PIPECONF_DITHER_EN |
@@ -7866,7 +7984,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
        } else
                pipeconf |= PIPECONF_PROGRESSIVE;
 
-       if (IS_VALLEYVIEW(dev) && intel_crtc->config->limited_color_range)
+       if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+            intel_crtc->config->limited_color_range)
                pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
 
        I915_WRITE(PIPECONF(intel_crtc->pipe), pipeconf);
@@ -7881,8 +8000,6 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
        int refclk, num_connectors = 0;
        intel_clock_t clock;
        bool ok;
-       bool is_dsi = false;
-       struct intel_encoder *encoder;
        const intel_limit_t *limit;
        struct drm_atomic_state *state = crtc_state->base.state;
        struct drm_connector *connector;
@@ -7892,26 +8009,14 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
        memset(&crtc_state->dpll_hw_state, 0,
               sizeof(crtc_state->dpll_hw_state));
 
-       for_each_connector_in_state(state, connector, connector_state, i) {
-               if (connector_state->crtc != &crtc->base)
-                       continue;
-
-               encoder = to_intel_encoder(connector_state->best_encoder);
-
-               switch (encoder->type) {
-               case INTEL_OUTPUT_DSI:
-                       is_dsi = true;
-                       break;
-               default:
-                       break;
-               }
+       if (crtc_state->has_dsi_encoder)
+               return 0;
 
-               num_connectors++;
+       for_each_connector_in_state(state, connector, connector_state, i) {
+               if (connector_state->crtc == &crtc->base)
+                       num_connectors++;
        }
 
-       if (is_dsi)
-               return 0;
-
        if (!crtc_state->clock_set) {
                refclk = i9xx_get_refclk(crtc_state, num_connectors);
 
@@ -8127,7 +8232,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        if (!(tmp & PIPECONF_ENABLE))
                return false;
 
-       if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+       if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                switch (tmp & PIPECONF_BPC_MASK) {
                case PIPECONF_6BPC:
                        pipe_config->pipe_bpp = 18;
@@ -8143,7 +8248,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                }
        }
 
-       if (IS_VALLEYVIEW(dev) && (tmp & PIPECONF_COLOR_RANGE_SELECT))
+       if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+           (tmp & PIPECONF_COLOR_RANGE_SELECT))
                pipe_config->limited_color_range = true;
 
        if (INTEL_INFO(dev)->gen < 4)
@@ -8171,7 +8277,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->pixel_multiplier = 1;
        }
        pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
-       if (!IS_VALLEYVIEW(dev)) {
+       if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
                /*
                 * DPLL_DVO_2X_MODE must be enabled for both DPLLs
                 * on 830. Filter it out here so that we don't
@@ -8523,6 +8629,67 @@ static void lpt_disable_clkout_dp(struct drm_device *dev)
        mutex_unlock(&dev_priv->sb_lock);
 }
 
+#define BEND_IDX(steps) ((50 + (steps)) / 5)
+
+static const uint16_t sscdivintphase[] = {
+       [BEND_IDX( 50)] = 0x3B23,
+       [BEND_IDX( 45)] = 0x3B23,
+       [BEND_IDX( 40)] = 0x3C23,
+       [BEND_IDX( 35)] = 0x3C23,
+       [BEND_IDX( 30)] = 0x3D23,
+       [BEND_IDX( 25)] = 0x3D23,
+       [BEND_IDX( 20)] = 0x3E23,
+       [BEND_IDX( 15)] = 0x3E23,
+       [BEND_IDX( 10)] = 0x3F23,
+       [BEND_IDX(  5)] = 0x3F23,
+       [BEND_IDX(  0)] = 0x0025,
+       [BEND_IDX( -5)] = 0x0025,
+       [BEND_IDX(-10)] = 0x0125,
+       [BEND_IDX(-15)] = 0x0125,
+       [BEND_IDX(-20)] = 0x0225,
+       [BEND_IDX(-25)] = 0x0225,
+       [BEND_IDX(-30)] = 0x0325,
+       [BEND_IDX(-35)] = 0x0325,
+       [BEND_IDX(-40)] = 0x0425,
+       [BEND_IDX(-45)] = 0x0425,
+       [BEND_IDX(-50)] = 0x0525,
+};
+
+/*
+ * Bend CLKOUT_DP
+ * steps -50 to 50 inclusive, in steps of 5
+ * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz)
+ * change in clock period = -(steps / 10) * 5.787 ps
+ */
+static void lpt_bend_clkout_dp(struct drm_i915_private *dev_priv, int steps)
+{
+       uint32_t tmp;
+       int idx = BEND_IDX(steps);
+
+       if (WARN_ON(steps % 5 != 0))
+               return;
+
+       if (WARN_ON(idx >= ARRAY_SIZE(sscdivintphase)))
+               return;
+
+       mutex_lock(&dev_priv->sb_lock);
+
+       if (steps % 10 != 0)
+               tmp = 0xAAAAAAAB;
+       else
+               tmp = 0x00000000;
+       intel_sbi_write(dev_priv, SBI_SSCDITHPHASE, tmp, SBI_ICLK);
+
+       tmp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE, SBI_ICLK);
+       tmp &= 0xffff0000;
+       tmp |= sscdivintphase[idx];
+       intel_sbi_write(dev_priv, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK);
+
+       mutex_unlock(&dev_priv->sb_lock);
+}
+
+#undef BEND_IDX
+
 static void lpt_init_pch_refclk(struct drm_device *dev)
 {
        struct intel_encoder *encoder;
@@ -8538,10 +8705,12 @@ static void lpt_init_pch_refclk(struct drm_device *dev)
                }
        }
 
-       if (has_vga)
+       if (has_vga) {
+               lpt_bend_clkout_dp(to_i915(dev), 0);
                lpt_enable_clkout_dp(dev, true, true);
-       else
+       } else {
                lpt_disable_clkout_dp(dev);
+       }
 }
 
 /*
@@ -8904,7 +9073,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
        memset(&crtc_state->dpll_hw_state, 0,
               sizeof(crtc_state->dpll_hw_state));
 
-       is_lvds = intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS);
+       is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS);
 
        WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
             "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
@@ -9333,8 +9502,8 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
 
        I915_STATE_WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on\n");
        I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
-       I915_STATE_WARN(I915_READ(WRPLL_CTL1) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
-       I915_STATE_WARN(I915_READ(WRPLL_CTL2) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
+       I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
+       I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
        I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
        I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
             "CPU PWM1 enabled\n");
@@ -9548,7 +9717,9 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
 static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
-       unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
+       struct intel_atomic_state *old_intel_state =
+               to_intel_atomic_state(old_state);
+       unsigned int req_cdclk = old_intel_state->dev_cdclk;
 
        broxton_set_cdclk(dev, req_cdclk);
 }
@@ -9556,29 +9727,41 @@ static void broxton_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 /* compute the max rate for new configuration */
 static int ilk_max_pixel_rate(struct drm_atomic_state *state)
 {
-       struct intel_crtc *intel_crtc;
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+       struct drm_i915_private *dev_priv = state->dev->dev_private;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *cstate;
        struct intel_crtc_state *crtc_state;
-       int max_pixel_rate = 0;
+       unsigned max_pixel_rate = 0, i;
+       enum pipe pipe;
 
-       for_each_intel_crtc(state->dev, intel_crtc) {
-               int pixel_rate;
+       memcpy(intel_state->min_pixclk, dev_priv->min_pixclk,
+              sizeof(intel_state->min_pixclk));
 
-               crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
-               if (IS_ERR(crtc_state))
-                       return PTR_ERR(crtc_state);
+       for_each_crtc_in_state(state, crtc, cstate, i) {
+               int pixel_rate;
 
-               if (!crtc_state->base.enable)
+               crtc_state = to_intel_crtc_state(cstate);
+               if (!crtc_state->base.enable) {
+                       intel_state->min_pixclk[i] = 0;
                        continue;
+               }
 
                pixel_rate = ilk_pipe_pixel_rate(crtc_state);
 
                /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
-               if (IS_BROADWELL(state->dev) && crtc_state->ips_enabled)
+               if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
                        pixel_rate = DIV_ROUND_UP(pixel_rate * 100, 95);
 
-               max_pixel_rate = max(max_pixel_rate, pixel_rate);
+               intel_state->min_pixclk[i] = pixel_rate;
        }
 
+       if (!intel_state->active_crtcs)
+               return 0;
+
+       for_each_pipe(dev_priv, pipe)
+               max_pixel_rate = max(intel_state->min_pixclk[pipe], max_pixel_rate);
+
        return max_pixel_rate;
 }
 
@@ -9662,6 +9845,7 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
 static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
        struct drm_i915_private *dev_priv = to_i915(state->dev);
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        int max_pixclk = ilk_max_pixel_rate(state);
        int cdclk;
 
@@ -9678,17 +9862,15 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
        else
                cdclk = 337500;
 
-       /*
-        * FIXME move the cdclk caclulation to
-        * compute_config() so we can fail gracegully.
-        */
        if (cdclk > dev_priv->max_cdclk_freq) {
-               DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
-                         cdclk, dev_priv->max_cdclk_freq);
-               cdclk = dev_priv->max_cdclk_freq;
+               DRM_DEBUG_KMS("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+                             cdclk, dev_priv->max_cdclk_freq);
+               return -EINVAL;
        }
 
-       to_intel_atomic_state(state)->cdclk = cdclk;
+       intel_state->cdclk = intel_state->dev_cdclk = cdclk;
+       if (!intel_state->active_crtcs)
+               intel_state->dev_cdclk = 337500;
 
        return 0;
 }
@@ -9696,7 +9878,9 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
 static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
-       unsigned int req_cdclk = to_intel_atomic_state(old_state)->cdclk;
+       struct intel_atomic_state *old_intel_state =
+               to_intel_atomic_state(old_state);
+       unsigned req_cdclk = old_intel_state->dev_cdclk;
 
        broadwell_set_cdclk(dev, req_cdclk);
 }
@@ -9780,6 +9964,7 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
                break;
        case PORT_CLK_SEL_SPLL:
                pipe_config->shared_dpll = DPLL_ID_SPLL;
+               break;
        }
 }
 
@@ -9796,7 +9981,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
 
        port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
 
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                skylake_get_ddi_pll(dev_priv, port, pipe_config);
        else if (IS_BROXTON(dev))
                bxt_get_ddi_pll(dev_priv, port, pipe_config);
@@ -9908,16 +10093,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        return true;
 }
 
-static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
+static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
+                              const struct intel_plane_state *plane_state)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t cntl = 0, size = 0;
 
-       if (base) {
-               unsigned int width = intel_crtc->base.cursor->state->crtc_w;
-               unsigned int height = intel_crtc->base.cursor->state->crtc_h;
+       if (plane_state && plane_state->visible) {
+               unsigned int width = plane_state->base.crtc_w;
+               unsigned int height = plane_state->base.crtc_h;
                unsigned int stride = roundup_pow_of_two(width) * 4;
 
                switch (stride) {
@@ -9970,18 +10156,18 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
        }
 }
 
-static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
+static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base,
+                              const struct intel_plane_state *plane_state)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       uint32_t cntl;
+       uint32_t cntl = 0;
 
-       cntl = 0;
-       if (base) {
+       if (plane_state && plane_state->visible) {
                cntl = MCURSOR_GAMMA_ENABLE;
-               switch (intel_crtc->base.cursor->state->crtc_w) {
+               switch (plane_state->base.crtc_w) {
                        case 64:
                                cntl |= CURSOR_MODE_64_ARGB_AX;
                                break;
@@ -9992,17 +10178,17 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
                                cntl |= CURSOR_MODE_256_ARGB_AX;
                                break;
                        default:
-                               MISSING_CASE(intel_crtc->base.cursor->state->crtc_w);
+                               MISSING_CASE(plane_state->base.crtc_w);
                                return;
                }
                cntl |= pipe << 28; /* Connect to correct pipe */
 
                if (HAS_DDI(dev))
                        cntl |= CURSOR_PIPE_CSC_ENABLE;
-       }
 
-       if (crtc->cursor->state->rotation == BIT(DRM_ROTATE_180))
-               cntl |= CURSOR_ROTATE_180;
+               if (plane_state->base.rotation == BIT(DRM_ROTATE_180))
+                       cntl |= CURSOR_ROTATE_180;
+       }
 
        if (intel_crtc->cursor_cntl != cntl) {
                I915_WRITE(CURCNTR(pipe), cntl);
@@ -10019,60 +10205,45 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
 
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
 static void intel_crtc_update_cursor(struct drm_crtc *crtc,
-                                    bool on)
+                                    const struct intel_plane_state *plane_state)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       struct drm_plane_state *cursor_state = crtc->cursor->state;
-       int x = cursor_state->crtc_x;
-       int y = cursor_state->crtc_y;
-       u32 base = 0, pos = 0;
-
-       if (on)
-               base = intel_crtc->cursor_addr;
-
-       if (x >= intel_crtc->config->pipe_src_w)
-               base = 0;
+       u32 base = intel_crtc->cursor_addr;
+       u32 pos = 0;
 
-       if (y >= intel_crtc->config->pipe_src_h)
-               base = 0;
+       if (plane_state) {
+               int x = plane_state->base.crtc_x;
+               int y = plane_state->base.crtc_y;
 
-       if (x < 0) {
-               if (x + cursor_state->crtc_w <= 0)
-                       base = 0;
-
-               pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
-               x = -x;
-       }
-       pos |= x << CURSOR_X_SHIFT;
+               if (x < 0) {
+                       pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
+                       x = -x;
+               }
+               pos |= x << CURSOR_X_SHIFT;
 
-       if (y < 0) {
-               if (y + cursor_state->crtc_h <= 0)
-                       base = 0;
+               if (y < 0) {
+                       pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
+                       y = -y;
+               }
+               pos |= y << CURSOR_Y_SHIFT;
 
-               pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
-               y = -y;
+               /* ILK+ do this automagically */
+               if (HAS_GMCH_DISPLAY(dev) &&
+                   plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+                       base += (plane_state->base.crtc_h *
+                                plane_state->base.crtc_w - 1) * 4;
+               }
        }
-       pos |= y << CURSOR_Y_SHIFT;
-
-       if (base == 0 && intel_crtc->cursor_base == 0)
-               return;
 
        I915_WRITE(CURPOS(pipe), pos);
 
-       /* ILK+ do this automagically */
-       if (HAS_GMCH_DISPLAY(dev) &&
-           crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) {
-               base += (cursor_state->crtc_h *
-                        cursor_state->crtc_w - 1) * 4;
-       }
-
        if (IS_845G(dev) || IS_I865G(dev))
-               i845_update_cursor(crtc, base);
+               i845_update_cursor(crtc, base, plane_state);
        else
-               i9xx_update_cursor(crtc, base);
+               i9xx_update_cursor(crtc, base, plane_state);
 }
 
 static bool cursor_size_ok(struct drm_device *dev,
@@ -10142,20 +10313,17 @@ __intel_framebuffer_create(struct drm_device *dev,
        int ret;
 
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-       if (!intel_fb) {
-               drm_gem_object_unreference(&obj->base);
+       if (!intel_fb)
                return ERR_PTR(-ENOMEM);
-       }
 
        ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
        if (ret)
                goto err;
 
        return &intel_fb->base;
+
 err:
-       drm_gem_object_unreference(&obj->base);
        kfree(intel_fb);
-
        return ERR_PTR(ret);
 }
 
@@ -10195,6 +10363,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
                                  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 };
 
@@ -10209,7 +10378,11 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
                                                                bpp);
        mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
 
-       return intel_framebuffer_create(dev, &mode_cmd, obj);
+       fb = intel_framebuffer_create(dev, &mode_cmd, obj);
+       if (IS_ERR(fb))
+               drm_gem_object_unreference_unlocked(&obj->base);
+
+       return fb;
 }
 
 static struct drm_framebuffer *
@@ -11112,7 +11285,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
         */
        if (ring->id == RCS) {
                intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit(ring, DERRMR);
+               intel_ring_emit_reg(ring, DERRMR);
                intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
                                        DERRMR_PIPEB_PRI_FLIP_DONE |
                                        DERRMR_PIPEC_PRI_FLIP_DONE));
@@ -11122,7 +11295,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
                else
                        intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
                                              MI_SRM_LRM_GLOBAL_GTT);
-               intel_ring_emit(ring, DERRMR);
+               intel_ring_emit_reg(ring, DERRMR);
                intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
                if (IS_GEN8(dev)) {
                        intel_ring_emit(ring, 0);
@@ -11162,18 +11335,23 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,
                return true;
        else if (i915.enable_execlists)
                return true;
+       else if (obj->base.dma_buf &&
+                !reservation_object_test_signaled_rcu(obj->base.dma_buf->resv,
+                                                      false))
+               return true;
        else
                return ring != i915_gem_request_get_ring(obj->last_write_req);
 }
 
 static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
+                            unsigned int rotation,
                             struct intel_unpin_work *work)
 {
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_framebuffer *fb = intel_crtc->base.primary->fb;
        const enum pipe pipe = intel_crtc->pipe;
-       u32 ctl, stride;
+       u32 ctl, stride, tile_height;
 
        ctl = I915_READ(PLANE_CTL(pipe, 0));
        ctl &= ~PLANE_CTL_TILED_MASK;
@@ -11197,9 +11375,16 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
         * The stride is either expressed as a multiple of 64 bytes chunks for
         * linear buffers or in number of tiles for tiled buffers.
         */
-       stride = fb->pitches[0] /
-                intel_fb_stride_alignment(dev, fb->modifier[0],
-                                          fb->pixel_format);
+       if (intel_rotation_90_or_270(rotation)) {
+               /* stride = Surface height in tiles */
+               tile_height = intel_tile_height(dev, fb->pixel_format,
+                                               fb->modifier[0], 0);
+               stride = DIV_ROUND_UP(fb->height, tile_height);
+       } else {
+               stride = fb->pitches[0] /
+                               intel_fb_stride_alignment(dev, fb->modifier[0],
+                                                         fb->pixel_format);
+       }
 
        /*
         * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
@@ -11220,10 +11405,9 @@ static void ilk_do_mmio_flip(struct intel_crtc *intel_crtc,
        struct intel_framebuffer *intel_fb =
                to_intel_framebuffer(intel_crtc->base.primary->fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
+       i915_reg_t reg = DSPCNTR(intel_crtc->plane);
        u32 dspcntr;
-       u32 reg;
 
-       reg = DSPCNTR(intel_crtc->plane);
        dspcntr = I915_READ(reg);
 
        if (obj->tiling_mode != I915_TILING_NONE)
@@ -11257,7 +11441,7 @@ static void intel_do_mmio_flip(struct intel_mmio_flip *mmio_flip)
        intel_pipe_update_start(crtc);
 
        if (INTEL_INFO(mmio_flip->i915)->gen >= 9)
-               skl_do_mmio_flip(crtc, work);
+               skl_do_mmio_flip(crtc, mmio_flip->rotation, work);
        else
                /* use_mmio_flip() retricts MMIO flips to ilk+ */
                ilk_do_mmio_flip(crtc, work);
@@ -11269,6 +11453,9 @@ static void intel_mmio_flip_work_func(struct work_struct *work)
 {
        struct intel_mmio_flip *mmio_flip =
                container_of(work, struct intel_mmio_flip, work);
+       struct intel_framebuffer *intel_fb =
+               to_intel_framebuffer(mmio_flip->crtc->base.primary->fb);
+       struct drm_i915_gem_object *obj = intel_fb->obj;
 
        if (mmio_flip->req) {
                WARN_ON(__i915_wait_request(mmio_flip->req,
@@ -11278,16 +11465,19 @@ static void intel_mmio_flip_work_func(struct work_struct *work)
                i915_gem_request_unreference__unlocked(mmio_flip->req);
        }
 
+       /* For framebuffer backed by dmabuf, wait for fence */
+       if (obj->base.dma_buf)
+               WARN_ON(reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv,
+                                                           false, false,
+                                                           MAX_SCHEDULE_TIMEOUT) < 0);
+
        intel_do_mmio_flip(mmio_flip);
        kfree(mmio_flip);
 }
 
 static int intel_queue_mmio_flip(struct drm_device *dev,
                                 struct drm_crtc *crtc,
-                                struct drm_framebuffer *fb,
-                                struct drm_i915_gem_object *obj,
-                                struct intel_engine_cs *ring,
-                                uint32_t flags)
+                                struct drm_i915_gem_object *obj)
 {
        struct intel_mmio_flip *mmio_flip;
 
@@ -11298,6 +11488,7 @@ static int intel_queue_mmio_flip(struct drm_device *dev,
        mmio_flip->i915 = to_i915(dev);
        mmio_flip->req = i915_gem_request_reference(obj->last_write_req);
        mmio_flip->crtc = to_intel_crtc(crtc);
+       mmio_flip->rotation = crtc->primary->state->rotation;
 
        INIT_WORK(&mmio_flip->work, intel_mmio_flip_work_func);
        schedule_work(&mmio_flip->work);
@@ -11481,7 +11672,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
                work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
 
-       if (IS_VALLEYVIEW(dev)) {
+       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                ring = &dev_priv->ring[BCS];
                if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
                        /* vlv: DISPLAY_FLIP fails to change tiling */
@@ -11503,9 +11694,14 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
         * synchronisation, so all we want here is to pin the framebuffer
         * into the display plane and skip any waits.
         */
+       if (!mmio_flip) {
+               ret = i915_gem_object_sync(obj, ring, &request);
+               if (ret)
+                       goto cleanup_pending;
+       }
+
        ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
-                                        crtc->primary->state,
-                                        mmio_flip ? i915_gem_request_get_ring(obj->last_write_req) : ring, &request);
+                                        crtc->primary->state);
        if (ret)
                goto cleanup_pending;
 
@@ -11514,8 +11710,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        work->gtt_offset += intel_crtc->dspaddr_offset;
 
        if (mmio_flip) {
-               ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
-                                           page_flip_flags);
+               ret = intel_queue_mmio_flip(dev, crtc, obj);
                if (ret)
                        goto cleanup_unpin;
 
@@ -11546,7 +11741,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                          to_intel_plane(primary)->frontbuffer_bit);
        mutex_unlock(&dev->struct_mutex);
 
-       intel_fbc_disable_crtc(intel_crtc);
+       intel_fbc_deactivate(intel_crtc);
        intel_frontbuffer_flip_prepare(dev,
                                       to_intel_plane(primary)->frontbuffer_bit);
 
@@ -11629,21 +11824,41 @@ retry:
 static bool intel_wm_need_update(struct drm_plane *plane,
                                 struct drm_plane_state *state)
 {
-       /* Update watermarks on tiling changes. */
-       if (!plane->state->fb || !state->fb ||
-           plane->state->fb->modifier[0] != state->fb->modifier[0] ||
-           plane->state->rotation != state->rotation)
+       struct intel_plane_state *new = to_intel_plane_state(state);
+       struct intel_plane_state *cur = to_intel_plane_state(plane->state);
+
+       /* Update watermarks on tiling or size changes. */
+       if (new->visible != cur->visible)
                return true;
 
-       if (plane->state->crtc_w != state->crtc_w)
+       if (!cur->base.fb || !new->base.fb)
+               return false;
+
+       if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
+           cur->base.rotation != new->base.rotation ||
+           drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
+           drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
+           drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
+           drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
                return true;
 
        return false;
 }
 
+static bool needs_scaling(struct intel_plane_state *state)
+{
+       int src_w = drm_rect_width(&state->src) >> 16;
+       int src_h = drm_rect_height(&state->src) >> 16;
+       int dst_w = drm_rect_width(&state->dst);
+       int dst_h = drm_rect_height(&state->dst);
+
+       return (src_w != dst_w || src_h != dst_h);
+}
+
 int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
                                    struct drm_plane_state *plane_state)
 {
+       struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
        struct drm_crtc *crtc = crtc_state->crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_plane *plane = plane_state->plane;
@@ -11656,7 +11871,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        bool mode_changed = needs_modeset(crtc_state);
        bool was_crtc_enabled = crtc->state->active;
        bool is_crtc_enabled = crtc_state->active;
-
        bool turn_off, turn_on, visible, was_visible;
        struct drm_framebuffer *fb = plane_state->fb;
 
@@ -11669,22 +11883,19 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
                        return ret;
        }
 
-       /*
-        * Disabling a plane is always okay; we just need to update
-        * fb tracking in a special way since cleanup_fb() won't
-        * get called by the plane helpers.
-        */
-       if (old_plane_state->base.fb && !fb)
-               intel_crtc->atomic.disabled_planes |= 1 << i;
-
        was_visible = old_plane_state->visible;
        visible = to_intel_plane_state(plane_state)->visible;
 
        if (!was_crtc_enabled && WARN_ON(was_visible))
                was_visible = false;
 
-       if (!is_crtc_enabled && WARN_ON(visible))
-               visible = false;
+       /*
+        * Visibility is calculated as if the crtc was on, but
+        * after scaler setup everything depends on it being off
+        * when the crtc isn't active.
+        */
+       if (!is_crtc_enabled)
+               to_intel_plane_state(plane_state)->visible = visible = false;
 
        if (!was_visible && !visible)
                return 0;
@@ -11699,34 +11910,30 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
                         plane->base.id, was_visible, visible,
                         turn_off, turn_on, mode_changed);
 
-       if (turn_on) {
-               intel_crtc->atomic.update_wm_pre = true;
-               /* must disable cxsr around plane enable/disable */
-               if (plane->type != DRM_PLANE_TYPE_CURSOR) {
-                       intel_crtc->atomic.disable_cxsr = true;
-                       /* to potentially re-enable cxsr */
-                       intel_crtc->atomic.wait_vblank = true;
-                       intel_crtc->atomic.update_wm_post = true;
-               }
-       } else if (turn_off) {
-               intel_crtc->atomic.update_wm_post = true;
+       if (turn_on || turn_off) {
+               pipe_config->wm_changed = true;
+
                /* must disable cxsr around plane enable/disable */
                if (plane->type != DRM_PLANE_TYPE_CURSOR) {
                        if (is_crtc_enabled)
                                intel_crtc->atomic.wait_vblank = true;
-                       intel_crtc->atomic.disable_cxsr = true;
+                       pipe_config->disable_cxsr = true;
                }
        } else if (intel_wm_need_update(plane, plane_state)) {
-               intel_crtc->atomic.update_wm_pre = true;
+               pipe_config->wm_changed = true;
        }
 
+       /* Pre-gen9 platforms need two-step watermark updates */
+       if (pipe_config->wm_changed && INTEL_INFO(dev)->gen < 9 &&
+           dev_priv->display.optimize_watermarks)
+               to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
+
        if (visible || was_visible)
                intel_crtc->atomic.fb_bits |=
                        to_intel_plane(plane)->frontbuffer_bit;
 
        switch (plane->type) {
        case DRM_PLANE_TYPE_PRIMARY:
-               intel_crtc->atomic.wait_for_flips = true;
                intel_crtc->atomic.pre_disable_primary = turn_off;
                intel_crtc->atomic.post_enable_primary = turn_on;
 
@@ -11774,11 +11981,23 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        case DRM_PLANE_TYPE_CURSOR:
                break;
        case DRM_PLANE_TYPE_OVERLAY:
-               if (turn_off && !mode_changed) {
+               /*
+                * WaCxSRDisabledForSpriteScaling:ivb
+                *
+                * cstate->update_wm was already set above, so this flag will
+                * take effect when we commit and program watermarks.
+                */
+               if (IS_IVYBRIDGE(dev) &&
+                   needs_scaling(to_intel_plane_state(plane_state)) &&
+                   !needs_scaling(old_plane_state)) {
+                       to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
+               } else if (turn_off && !mode_changed) {
                        intel_crtc->atomic.wait_vblank = true;
                        intel_crtc->atomic.update_sprite_watermarks |=
                                1 << i;
                }
+
+               break;
        }
        return 0;
 }
@@ -11851,7 +12070,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
        }
 
        if (mode_changed && !crtc_state->active)
-               intel_crtc->atomic.update_wm_post = true;
+               pipe_config->wm_changed = true;
 
        if (mode_changed && crtc_state->enable &&
            dev_priv->display.crtc_compute_clock &&
@@ -11863,6 +12082,33 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
        }
 
        ret = 0;
+       if (dev_priv->display.compute_pipe_wm) {
+               ret = dev_priv->display.compute_pipe_wm(intel_crtc, state);
+               if (ret) {
+                       DRM_DEBUG_KMS("Target pipe watermarks are invalid\n");
+                       return ret;
+               }
+       }
+
+       if (dev_priv->display.compute_intermediate_wm &&
+           !to_intel_atomic_state(state)->skip_intermediate_wm) {
+               if (WARN_ON(!dev_priv->display.compute_pipe_wm))
+                       return 0;
+
+               /*
+                * Calculate 'intermediate' watermarks that satisfy both the
+                * old state and the new state.  We can program these
+                * immediately.
+                */
+               ret = dev_priv->display.compute_intermediate_wm(crtc->dev,
+                                                               intel_crtc,
+                                                               pipe_config);
+               if (ret) {
+                       DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
+                       return ret;
+               }
+       }
+
        if (INTEL_INFO(dev)->gen >= 9) {
                if (mode_changed)
                        ret = skl_update_scaler_crtc(pipe_config);
@@ -11936,7 +12182,7 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
        struct drm_connector_state *connector_state;
        int bpp, i;
 
-       if ((IS_G4X(dev) || IS_VALLEYVIEW(dev)))
+       if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
                bpp = 10*3;
        else if (INTEL_INFO(dev)->gen >= 5)
                bpp = 12*3;
@@ -12052,7 +12298,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                              pipe_config->dpll_hw_state.pll9,
                              pipe_config->dpll_hw_state.pll10,
                              pipe_config->dpll_hw_state.pcsdw12);
-       } else if (IS_SKYLAKE(dev)) {
+       } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: "
                              "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
                              pipe_config->ddi_pll_sel,
@@ -12111,18 +12357,22 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
-       struct intel_encoder *encoder;
        struct drm_connector *connector;
-       struct drm_connector_state *connector_state;
        unsigned int used_ports = 0;
-       int i;
 
        /*
         * Walk the connector list instead of the encoder
         * list to detect the problem on ddi platforms
         * where there's just one encoder per digital port.
         */
-       for_each_connector_in_state(state, connector, connector_state, i) {
+       drm_for_each_connector(connector, dev) {
+               struct drm_connector_state *connector_state;
+               struct intel_encoder *encoder;
+
+               connector_state = drm_atomic_get_existing_connector_state(state, connector);
+               if (!connector_state)
+                       connector_state = connector->state;
+
                if (!connector_state->best_encoder)
                        continue;
 
@@ -12306,6 +12556,18 @@ intel_modeset_update_crtc_state(struct drm_atomic_state *state)
                        crtc->hwmode = crtc->state->adjusted_mode;
                else
                        crtc->hwmode.crtc_clock = 0;
+
+               /*
+                * 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;
+               }
        }
 }
 
@@ -12331,7 +12593,7 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2)
        list_for_each_entry((intel_crtc), \
                            &(dev)->mode_config.crtc_list, \
                            base.head) \
-               if (mask & (1 <<(intel_crtc)->pipe))
+               for_each_if (mask & (1 <<(intel_crtc)->pipe))
 
 static bool
 intel_compare_m_n(unsigned int m, unsigned int n,
@@ -12346,19 +12608,22 @@ intel_compare_m_n(unsigned int m, unsigned int n,
 
        BUILD_BUG_ON(DATA_LINK_M_N_MASK > INT_MAX);
 
-       if (m > m2) {
-               while (m > m2) {
+       if (n > n2) {
+               while (n > n2) {
                        m2 <<= 1;
                        n2 <<= 1;
                }
-       } else if (m < m2) {
-               while (m < m2) {
+       } else if (n < n2) {
+               while (n < n2) {
                        m <<= 1;
                        n <<= 1;
                }
        }
 
-       return m == m2 && n == n2;
+       if (n != n2)
+               return false;
+
+       return intel_fuzzy_clock_check(m, m2);
 }
 
 static bool
@@ -12515,6 +12780,8 @@ intel_pipe_config_compare(struct drm_device *dev,
        } else
                PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
 
+       PIPE_CONF_CHECK_I(has_dsi_encoder);
+
        PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hdisplay);
        PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_htotal);
        PIPE_CONF_CHECK_I(base.adjusted_mode.crtc_hblank_start);
@@ -12532,7 +12799,7 @@ intel_pipe_config_compare(struct drm_device *dev,
        PIPE_CONF_CHECK_I(pixel_multiplier);
        PIPE_CONF_CHECK_I(has_hdmi_sink);
        if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) ||
-           IS_VALLEYVIEW(dev))
+           IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
                PIPE_CONF_CHECK_I(limited_color_range);
        PIPE_CONF_CHECK_I(has_infoframe);
 
@@ -13031,15 +13298,27 @@ static int intel_modeset_all_pipes(struct drm_atomic_state *state)
 
 static int intel_modeset_checks(struct drm_atomic_state *state)
 {
-       struct drm_device *dev = state->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int ret;
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+       struct drm_i915_private *dev_priv = state->dev->dev_private;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       int ret = 0, i;
 
        if (!check_digital_port_conflicts(state)) {
                DRM_DEBUG_KMS("rejecting conflicting digital port configuration\n");
                return -EINVAL;
        }
 
+       intel_state->modeset = true;
+       intel_state->active_crtcs = dev_priv->active_crtcs;
+
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               if (crtc_state->active)
+                       intel_state->active_crtcs |= 1 << i;
+               else
+                       intel_state->active_crtcs &= ~(1 << i);
+       }
+
        /*
         * See if the config requires any additional preparation, e.g.
         * to adjust global state with pipes off.  We need to do this
@@ -13048,27 +13327,63 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
         * adjusted_mode bits in the crtc directly.
         */
        if (dev_priv->display.modeset_calc_cdclk) {
-               unsigned int cdclk;
-
                ret = dev_priv->display.modeset_calc_cdclk(state);
 
-               cdclk = to_intel_atomic_state(state)->cdclk;
-               if (!ret && cdclk != dev_priv->cdclk_freq)
+               if (!ret && intel_state->dev_cdclk != dev_priv->cdclk_freq)
                        ret = intel_modeset_all_pipes(state);
 
                if (ret < 0)
                        return ret;
        } else
-               to_intel_atomic_state(state)->cdclk = dev_priv->cdclk_freq;
+               to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
 
        intel_modeset_clear_plls(state);
 
-       if (IS_HASWELL(dev))
+       if (IS_HASWELL(dev_priv))
                return haswell_mode_set_planes_workaround(state);
 
        return 0;
 }
 
+/*
+ * Handle calculation of various watermark data at the end of the atomic check
+ * phase.  The code here should be run after the per-crtc and per-plane 'check'
+ * handlers to ensure that all derived state has been updated.
+ */
+static void calc_watermark_data(struct drm_atomic_state *state)
+{
+       struct drm_device *dev = state->dev;
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *cstate;
+       struct drm_plane *plane;
+       struct drm_plane_state *pstate;
+
+       /*
+        * Calculate watermark configuration details now that derived
+        * plane/crtc state is all properly updated.
+        */
+       drm_for_each_crtc(crtc, dev) {
+               cstate = drm_atomic_get_existing_crtc_state(state, crtc) ?:
+                       crtc->state;
+
+               if (cstate->active)
+                       intel_state->wm_config.num_pipes_active++;
+       }
+       drm_for_each_legacy_plane(plane, dev) {
+               pstate = drm_atomic_get_existing_plane_state(state, plane) ?:
+                       plane->state;
+
+               if (!to_intel_plane_state(pstate)->visible)
+                       continue;
+
+               intel_state->wm_config.sprites_enabled = true;
+               if (pstate->crtc_w != pstate->src_w >> 16 ||
+                   pstate->crtc_h != pstate->src_h >> 16)
+                       intel_state->wm_config.sprites_scaled = true;
+       }
+}
+
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -13077,6 +13392,7 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
 static int intel_atomic_check(struct drm_device *dev,
                              struct drm_atomic_state *state)
 {
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
        int ret, i;
@@ -13144,10 +13460,81 @@ static int intel_atomic_check(struct drm_device *dev,
                if (ret)
                        return ret;
        } else
-               to_intel_atomic_state(state)->cdclk =
-                       to_i915(state->dev)->cdclk_freq;
+               intel_state->cdclk = to_i915(state->dev)->cdclk_freq;
+
+       ret = drm_atomic_helper_check_planes(state->dev, state);
+       if (ret)
+               return ret;
+
+       calc_watermark_data(state);
+
+       return 0;
+}
+
+static int intel_atomic_prepare_commit(struct drm_device *dev,
+                                      struct drm_atomic_state *state,
+                                      bool async)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_plane_state *plane_state;
+       struct drm_crtc_state *crtc_state;
+       struct drm_plane *plane;
+       struct drm_crtc *crtc;
+       int i, ret;
+
+       if (async) {
+               DRM_DEBUG_KMS("i915 does not yet support async commit\n");
+               return -EINVAL;
+       }
+
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               ret = intel_crtc_wait_for_pending_flips(crtc);
+               if (ret)
+                       return ret;
+
+               if (atomic_read(&to_intel_crtc(crtc)->unpin_work_count) >= 2)
+                       flush_workqueue(dev_priv->wq);
+       }
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
-       return drm_atomic_helper_check_planes(state->dev, state);
+       ret = drm_atomic_helper_prepare_planes(dev, state);
+       if (!ret && !async && !i915_reset_in_progress(&dev_priv->gpu_error)) {
+               u32 reset_counter;
+
+               reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
+               mutex_unlock(&dev->struct_mutex);
+
+               for_each_plane_in_state(state, plane, plane_state, i) {
+                       struct intel_plane_state *intel_plane_state =
+                               to_intel_plane_state(plane_state);
+
+                       if (!intel_plane_state->wait_req)
+                               continue;
+
+                       ret = __i915_wait_request(intel_plane_state->wait_req,
+                                                 reset_counter, true,
+                                                 NULL, NULL);
+
+                       /* Swallow -EIO errors to allow updates during hw lockup. */
+                       if (ret == -EIO)
+                               ret = 0;
+
+                       if (ret)
+                               break;
+               }
+
+               if (!ret)
+                       return 0;
+
+               mutex_lock(&dev->struct_mutex);
+               drm_atomic_helper_cleanup_planes(dev, state);
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
 }
 
 /**
@@ -13170,23 +13557,29 @@ static int intel_atomic_commit(struct drm_device *dev,
                               struct drm_atomic_state *state,
                               bool async)
 {
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *crtc;
        struct drm_crtc_state *crtc_state;
-       int ret = 0;
-       int i;
-       bool any_ms = false;
-
-       if (async) {
-               DRM_DEBUG_KMS("i915 does not yet support async commit\n");
-               return -EINVAL;
-       }
+       struct drm_crtc *crtc;
+       struct intel_crtc_state *intel_cstate;
+       int ret = 0, i;
+       bool hw_check = intel_state->modeset;
 
-       ret = drm_atomic_helper_prepare_planes(dev, state);
-       if (ret)
+       ret = intel_atomic_prepare_commit(dev, state, async);
+       if (ret) {
+               DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
                return ret;
+       }
 
        drm_atomic_helper_swap_state(dev, state);
+       dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
+
+       if (intel_state->modeset) {
+               memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
+                      sizeof(intel_state->min_pixclk));
+               dev_priv->active_crtcs = intel_state->active_crtcs;
+               dev_priv->atomic_cdclk_freq = intel_state->cdclk;
+       }
 
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -13194,7 +13587,6 @@ static int intel_atomic_commit(struct drm_device *dev,
                if (!needs_modeset(crtc->state))
                        continue;
 
-               any_ms = true;
                intel_pre_plane_update(intel_crtc);
 
                if (crtc_state->active) {
@@ -13202,6 +13594,16 @@ static int intel_atomic_commit(struct drm_device *dev,
                        dev_priv->display.crtc_disable(crtc);
                        intel_crtc->active = false;
                        intel_disable_shared_dpll(intel_crtc);
+
+                       /*
+                        * Underruns don't always raise
+                        * interrupts, so check manually.
+                        */
+                       intel_check_cpu_fifo_underruns(dev_priv);
+                       intel_check_pch_fifo_underruns(dev_priv);
+
+                       if (!crtc->state->active)
+                               intel_update_watermarks(crtc);
                }
        }
 
@@ -13209,7 +13611,7 @@ static int intel_atomic_commit(struct drm_device *dev,
         * update the the output configuration. */
        intel_modeset_update_crtc_state(state);
 
-       if (any_ms) {
+       if (intel_state->modeset) {
                intel_shared_dpll_commit(state);
 
                drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
@@ -13224,6 +13626,9 @@ static int intel_atomic_commit(struct drm_device *dev,
                        to_intel_crtc_state(crtc->state)->update_pipe;
                unsigned long put_domains = 0;
 
+               if (modeset)
+                       intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
+
                if (modeset && crtc->state->active) {
                        update_scanline_offset(to_intel_crtc(crtc));
                        dev_priv->display.crtc_enable(crtc);
@@ -13233,30 +13638,65 @@ static int intel_atomic_commit(struct drm_device *dev,
                        put_domains = modeset_get_crtc_power_domains(crtc);
 
                        /* make sure intel_modeset_check_state runs */
-                       any_ms = true;
+                       hw_check = true;
                }
 
                if (!modeset)
                        intel_pre_plane_update(intel_crtc);
 
-               drm_atomic_helper_commit_planes_on_crtc(crtc_state);
+               if (crtc->state->active &&
+                   (crtc->state->planes_changed || update_pipe))
+                       drm_atomic_helper_commit_planes_on_crtc(crtc_state);
 
                if (put_domains)
                        modeset_put_power_domains(dev_priv, put_domains);
 
                intel_post_plane_update(intel_crtc);
+
+               if (modeset)
+                       intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
        }
 
        /* FIXME: add subpixel order */
 
        drm_atomic_helper_wait_for_vblanks(dev, state);
+
+       /*
+        * Now that the vblank has passed, we can go ahead and program the
+        * optimal watermarks on platforms that need two-step watermark
+        * programming.
+        *
+        * TODO: Move this (and other cleanup) to an async worker eventually.
+        */
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               intel_cstate = to_intel_crtc_state(crtc->state);
+
+               if (dev_priv->display.optimize_watermarks)
+                       dev_priv->display.optimize_watermarks(intel_cstate);
+       }
+
+       mutex_lock(&dev->struct_mutex);
        drm_atomic_helper_cleanup_planes(dev, state);
+       mutex_unlock(&dev->struct_mutex);
 
-       if (any_ms)
+       if (hw_check)
                intel_modeset_check_state(dev, state);
 
        drm_atomic_state_free(state);
 
+       /* As one of the primary mmio accessors, KMS has a high likelihood
+        * of triggering bugs in unclaimed access. After we finish
+        * modesetting, see if an error has been flagged, and if so
+        * enable debugging for the next modeset - and hope we catch
+        * the culprit.
+        *
+        * XXX note that we assume display power is on at this point.
+        * This might hold true now but we need to add pm helper to check
+        * unclaimed only when the hardware is on, as atomic commits
+        * can happen also when the device is completely off.
+        */
+       intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
+
        return 0;
 }
 
@@ -13419,6 +13859,8 @@ static void intel_shared_dpll_init(struct drm_device *dev)
  * bits.  Some older platforms need special physical address handling for
  * cursor planes.
  *
+ * Must be called with struct_mutex held.
+ *
  * Returns 0 on success, negative error code on failure.
  */
 int
@@ -13429,28 +13871,69 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        struct drm_framebuffer *fb = new_state->fb;
        struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-       struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
+       struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
        int ret = 0;
 
-       if (!obj)
+       if (!obj && !old_obj)
                return 0;
 
-       mutex_lock(&dev->struct_mutex);
+       if (old_obj) {
+               struct drm_crtc_state *crtc_state =
+                       drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc);
+
+               /* Big Hammer, we also need to ensure that any pending
+                * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+                * current scanout is retired before unpinning the old
+                * framebuffer. Note that we rely on userspace rendering
+                * into the buffer attached to the pipe they are waiting
+                * on. If not, userspace generates a GPU hang with IPEHR
+                * point to the MI_WAIT_FOR_EVENT.
+                *
+                * This should only fail upon a hung GPU, in which case we
+                * can safely continue.
+                */
+               if (needs_modeset(crtc_state))
+                       ret = i915_gem_object_wait_rendering(old_obj, true);
 
-       if (plane->type == DRM_PLANE_TYPE_CURSOR &&
+               /* Swallow -EIO errors to allow updates during hw lockup. */
+               if (ret && ret != -EIO)
+                       return ret;
+       }
+
+       /* For framebuffer backed by dmabuf, wait for fence */
+       if (obj && obj->base.dma_buf) {
+               ret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv,
+                                                         false, true,
+                                                         MAX_SCHEDULE_TIMEOUT);
+               if (ret == -ERESTARTSYS)
+                       return ret;
+
+               WARN_ON(ret < 0);
+       }
+
+       if (!obj) {
+               ret = 0;
+       } else if (plane->type == DRM_PLANE_TYPE_CURSOR &&
            INTEL_INFO(dev)->cursor_needs_physical) {
                int align = IS_I830(dev) ? 16 * 1024 : 256;
                ret = i915_gem_object_attach_phys(obj, align);
                if (ret)
                        DRM_DEBUG_KMS("failed to attach phys object\n");
        } else {
-               ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL, NULL);
+               ret = intel_pin_and_fence_fb_obj(plane, fb, new_state);
        }
 
-       if (ret == 0)
-               i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+       if (ret == 0) {
+               if (obj) {
+                       struct intel_plane_state *plane_state =
+                               to_intel_plane_state(new_state);
 
-       mutex_unlock(&dev->struct_mutex);
+                       i915_gem_request_assign(&plane_state->wait_req,
+                                               obj->last_write_req);
+               }
+
+               i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+       }
 
        return ret;
 }
@@ -13461,23 +13944,35 @@ intel_prepare_plane_fb(struct drm_plane *plane,
  * @fb: old framebuffer that was on plane
  *
  * Cleans up a framebuffer that has just been removed from a plane.
+ *
+ * Must be called with struct_mutex held.
  */
 void
 intel_cleanup_plane_fb(struct drm_plane *plane,
                       const struct drm_plane_state *old_state)
 {
        struct drm_device *dev = plane->dev;
-       struct drm_i915_gem_object *obj = intel_fb_obj(old_state->fb);
+       struct intel_plane *intel_plane = to_intel_plane(plane);
+       struct intel_plane_state *old_intel_state;
+       struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
+       struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
 
-       if (!obj)
+       old_intel_state = to_intel_plane_state(old_state);
+
+       if (!obj && !old_obj)
                return;
 
-       if (plane->type != DRM_PLANE_TYPE_CURSOR ||
-           !INTEL_INFO(dev)->cursor_needs_physical) {
-               mutex_lock(&dev->struct_mutex);
+       if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
+           !INTEL_INFO(dev)->cursor_needs_physical))
                intel_unpin_fb_obj(old_state->fb, old_state);
-               mutex_unlock(&dev->struct_mutex);
-       }
+
+       /* prepare_fb aborted? */
+       if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
+           (obj && !(obj->frontbuffer_bits & intel_plane->frontbuffer_bit)))
+               i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
+
+       i915_gem_request_assign(&old_intel_state->wait_req, NULL);
+
 }
 
 int
@@ -13488,7 +13983,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
        struct drm_i915_private *dev_priv;
        int crtc_clock, cdclk;
 
-       if (!intel_crtc || !crtc_state)
+       if (!intel_crtc || !crtc_state->base.enable)
                return DRM_PLANE_HELPER_NO_SCALING;
 
        dev = intel_crtc->base.dev;
@@ -13496,7 +13991,7 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
        crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
        cdclk = to_intel_atomic_state(crtc_state->base.state)->cdclk;
 
-       if (!crtc_clock || !cdclk)
+       if (WARN_ON_ONCE(!crtc_clock || cdclk < crtc_clock))
                return DRM_PLANE_HELPER_NO_SCALING;
 
        /*
@@ -13536,42 +14031,6 @@ intel_check_primary_plane(struct drm_plane *plane,
                                             &state->visible);
 }
 
-static void
-intel_commit_primary_plane(struct drm_plane *plane,
-                          struct intel_plane_state *state)
-{
-       struct drm_crtc *crtc = state->base.crtc;
-       struct drm_framebuffer *fb = state->base.fb;
-       struct drm_device *dev = plane->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc;
-       struct drm_rect *src = &state->src;
-
-       crtc = crtc ? crtc : plane->crtc;
-       intel_crtc = to_intel_crtc(crtc);
-
-       plane->fb = fb;
-       crtc->x = src->x1 >> 16;
-       crtc->y = src->y1 >> 16;
-
-       if (!crtc->state->active)
-               return;
-
-       dev_priv->display.update_primary_plane(crtc, fb,
-                                              state->src.x1 >> 16,
-                                              state->src.y1 >> 16);
-}
-
-static void
-intel_disable_primary_plane(struct drm_plane *plane,
-                           struct drm_crtc *crtc)
-{
-       struct drm_device *dev = plane->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       dev_priv->display.update_primary_plane(crtc, NULL, 0, 0);
-}
-
 static void intel_begin_crtc_commit(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_crtc_state)
 {
@@ -13581,12 +14040,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
                to_intel_crtc_state(old_crtc_state);
        bool modeset = needs_modeset(crtc->state);
 
-       if (intel_crtc->atomic.update_wm_pre)
-               intel_update_watermarks(crtc);
-
        /* Perform vblank evasion around commit operation */
-       if (crtc->state->active)
-               intel_pipe_update_start(intel_crtc);
+       intel_pipe_update_start(intel_crtc);
 
        if (modeset)
                return;
@@ -13602,8 +14057,7 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       if (crtc->state->active)
-               intel_pipe_update_end(intel_crtc);
+       intel_pipe_update_end(intel_crtc);
 }
 
 /**
@@ -13661,20 +14115,33 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
        primary->plane = pipe;
        primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
        primary->check_plane = intel_check_primary_plane;
-       primary->commit_plane = intel_commit_primary_plane;
-       primary->disable_plane = intel_disable_primary_plane;
        if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
                primary->plane = !pipe;
 
        if (INTEL_INFO(dev)->gen >= 9) {
                intel_primary_formats = skl_primary_formats;
                num_formats = ARRAY_SIZE(skl_primary_formats);
+
+               primary->update_plane = skylake_update_primary_plane;
+               primary->disable_plane = skylake_disable_primary_plane;
+       } else if (HAS_PCH_SPLIT(dev)) {
+               intel_primary_formats = i965_primary_formats;
+               num_formats = ARRAY_SIZE(i965_primary_formats);
+
+               primary->update_plane = ironlake_update_primary_plane;
+               primary->disable_plane = i9xx_disable_primary_plane;
        } else if (INTEL_INFO(dev)->gen >= 4) {
                intel_primary_formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
+
+               primary->update_plane = i9xx_update_primary_plane;
+               primary->disable_plane = i9xx_disable_primary_plane;
        } else {
                intel_primary_formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
+
+               primary->update_plane = i9xx_update_primary_plane;
+               primary->disable_plane = i9xx_disable_primary_plane;
        }
 
        drm_universal_plane_init(dev, &primary->base, 0,
@@ -13716,6 +14183,7 @@ intel_check_cursor_plane(struct drm_plane *plane,
        struct drm_crtc *crtc = crtc_state->base.crtc;
        struct drm_framebuffer *fb = state->base.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       enum pipe pipe = to_intel_plane(plane)->pipe;
        unsigned stride;
        int ret;
 
@@ -13749,6 +14217,22 @@ intel_check_cursor_plane(struct drm_plane *plane,
                return -EINVAL;
        }
 
+       /*
+        * There's something wrong with the cursor on CHV pipe C.
+        * If it straddles the left edge of the screen then
+        * moving it away from the edge or disabling it often
+        * results in a pipe underrun, and often that can lead to
+        * dead pipe (constant underrun reported, and it scans
+        * out just a solid color). To recover from that, the
+        * display power well must be turned off and on again.
+        * Refuse the put the cursor into that compromised position.
+        */
+       if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C &&
+           state->visible && state->base.crtc_x < 0) {
+               DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -13756,25 +14240,23 @@ static void
 intel_disable_cursor_plane(struct drm_plane *plane,
                           struct drm_crtc *crtc)
 {
-       intel_crtc_update_cursor(crtc, false);
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       intel_crtc->cursor_addr = 0;
+       intel_crtc_update_cursor(crtc, NULL);
 }
 
 static void
-intel_commit_cursor_plane(struct drm_plane *plane,
-                         struct intel_plane_state *state)
+intel_update_cursor_plane(struct drm_plane *plane,
+                         const struct intel_crtc_state *crtc_state,
+                         const struct intel_plane_state *state)
 {
-       struct drm_crtc *crtc = state->base.crtc;
+       struct drm_crtc *crtc = crtc_state->base.crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_device *dev = plane->dev;
-       struct intel_crtc *intel_crtc;
        struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
        uint32_t addr;
 
-       crtc = crtc ? crtc : plane->crtc;
-       intel_crtc = to_intel_crtc(crtc);
-
-       if (intel_crtc->cursor_bo == obj)
-               goto update;
-
        if (!obj)
                addr = 0;
        else if (!INTEL_INFO(dev)->cursor_needs_physical)
@@ -13783,11 +14265,7 @@ intel_commit_cursor_plane(struct drm_plane *plane,
                addr = obj->phys_handle->busaddr;
 
        intel_crtc->cursor_addr = addr;
-       intel_crtc->cursor_bo = obj;
-
-update:
-       if (crtc->state->active)
-               intel_crtc_update_cursor(crtc, state->visible);
+       intel_crtc_update_cursor(crtc, state);
 }
 
 static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
@@ -13813,7 +14291,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
        cursor->plane = pipe;
        cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
        cursor->check_plane = intel_check_cursor_plane;
-       cursor->commit_plane = intel_commit_cursor_plane;
+       cursor->update_plane = intel_update_cursor_plane;
        cursor->disable_plane = intel_disable_cursor_plane;
 
        drm_universal_plane_init(dev, &cursor->base, 0,
@@ -14023,7 +14501,14 @@ static bool intel_crt_present(struct drm_device *dev)
        if (IS_CHERRYVIEW(dev))
                return false;
 
-       if (IS_VALLEYVIEW(dev) && !dev_priv->vbt.int_crt_support)
+       if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
+               return false;
+
+       /* DDI E can't be used if DDI A requires 4 lanes */
+       if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
+               return false;
+
+       if (!dev_priv->vbt.int_crt_support)
                return false;
 
        return true;
@@ -14059,7 +14544,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                 */
                found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
                /* WaIgnoreDDIAStrap: skl */
-               if (found || IS_SKYLAKE(dev))
+               if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                        intel_ddi_init(dev, PORT_A);
 
                /* DDI B, C and D detection is indicated by the SFUSE_STRAP
@@ -14075,7 +14560,7 @@ static void intel_setup_outputs(struct drm_device *dev)
                /*
                 * On SKL we don't have a way to detect DDI-E so we rely on VBT.
                 */
-               if (IS_SKYLAKE(dev) &&
+               if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
                    (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
                     dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
                     dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
@@ -14090,7 +14575,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 
                if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
                        /* PCH SDVOB multiplex with HDMIB */
-                       found = intel_sdvo_init(dev, PCH_SDVOB, true);
+                       found = intel_sdvo_init(dev, PCH_SDVOB, PORT_B);
                        if (!found)
                                intel_hdmi_init(dev, PCH_HDMIB, PORT_B);
                        if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
@@ -14108,7 +14593,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 
                if (I915_READ(PCH_DP_D) & DP_DETECTED)
                        intel_dp_init(dev, PCH_DP_D, PORT_D);
-       } else if (IS_VALLEYVIEW(dev)) {
+       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                /*
                 * The DP_DETECTED bit is the latched state of the DDC
                 * SDA pin at boot. However since eDP doesn't require DDC
@@ -14146,7 +14631,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 
                if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
                        DRM_DEBUG_KMS("probing SDVOB\n");
-                       found = intel_sdvo_init(dev, GEN3_SDVOB, true);
+                       found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B);
                        if (!found && IS_G4X(dev)) {
                                DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
                                intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
@@ -14160,7 +14645,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 
                if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
                        DRM_DEBUG_KMS("probing SDVOC\n");
-                       found = intel_sdvo_init(dev, GEN3_SDVOC, false);
+                       found = intel_sdvo_init(dev, GEN3_SDVOC, PORT_C);
                }
 
                if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
@@ -14257,7 +14742,7 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
                 *  pixels and 32K bytes."
                 */
                 return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
-       } else if (gen >= 5 && !IS_VALLEYVIEW(dev)) {
+       } else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
                return 32*1024;
        } else if (gen >= 4) {
                if (fb_modifier == I915_FORMAT_MOD_X_TILED)
@@ -14361,7 +14846,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
                }
                break;
        case DRM_FORMAT_ABGR8888:
-               if (!IS_VALLEYVIEW(dev) && INTEL_INFO(dev)->gen < 9) {
+               if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
+                   INTEL_INFO(dev)->gen < 9) {
                        DRM_DEBUG("unsupported pixel format: %s\n",
                                  drm_get_format_name(mode_cmd->pixel_format));
                        return -EINVAL;
@@ -14377,7 +14863,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
                }
                break;
        case DRM_FORMAT_ABGR2101010:
-               if (!IS_VALLEYVIEW(dev)) {
+               if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
                        DRM_DEBUG("unsupported pixel format: %s\n",
                                  drm_get_format_name(mode_cmd->pixel_format));
                        return -EINVAL;
@@ -14426,8 +14912,9 @@ static int intel_framebuffer_init(struct drm_device *dev,
 static struct drm_framebuffer *
 intel_user_framebuffer_create(struct drm_device *dev,
                              struct drm_file *filp,
-                             struct drm_mode_fb_cmd2 *user_mode_cmd)
+                             const struct drm_mode_fb_cmd2 *user_mode_cmd)
 {
+       struct drm_framebuffer *fb;
        struct drm_i915_gem_object *obj;
        struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
 
@@ -14436,7 +14923,11 @@ intel_user_framebuffer_create(struct drm_device *dev,
        if (&obj->base == NULL)
                return ERR_PTR(-ENOENT);
 
-       return intel_framebuffer_create(dev, &mode_cmd, obj);
+       fb = intel_framebuffer_create(dev, &mode_cmd, obj);
+       if (IS_ERR(fb))
+               drm_gem_object_unreference_unlocked(&obj->base);
+
+       return fb;
 }
 
 #ifndef CONFIG_DRM_FBDEV_EMULATION
@@ -14478,8 +14969,6 @@ static void intel_init_display(struct drm_device *dev)
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
-               dev_priv->display.update_primary_plane =
-                       skylake_update_primary_plane;
        } else if (HAS_DDI(dev)) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
@@ -14488,8 +14977,6 @@ static void intel_init_display(struct drm_device *dev)
                        haswell_crtc_compute_clock;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
-               dev_priv->display.update_primary_plane =
-                       ironlake_update_primary_plane;
        } else if (HAS_PCH_SPLIT(dev)) {
                dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
@@ -14498,17 +14985,13 @@ static void intel_init_display(struct drm_device *dev)
                        ironlake_crtc_compute_clock;
                dev_priv->display.crtc_enable = ironlake_crtc_enable;
                dev_priv->display.crtc_disable = ironlake_crtc_disable;
-               dev_priv->display.update_primary_plane =
-                       ironlake_update_primary_plane;
-       } else if (IS_VALLEYVIEW(dev)) {
+       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
                        i9xx_get_initial_plane_config;
                dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
                dev_priv->display.crtc_enable = valleyview_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
-               dev_priv->display.update_primary_plane =
-                       i9xx_update_primary_plane;
        } else {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
@@ -14516,12 +14999,10 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
                dev_priv->display.crtc_enable = i9xx_crtc_enable;
                dev_priv->display.crtc_disable = i9xx_crtc_disable;
-               dev_priv->display.update_primary_plane =
-                       i9xx_update_primary_plane;
        }
 
        /* Returns the core display clock speed */
-       if (IS_SKYLAKE(dev))
+       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
                dev_priv->display.get_display_clock_speed =
                        skylake_get_display_clock_speed;
        else if (IS_BROXTON(dev))
@@ -14533,7 +15014,7 @@ static void intel_init_display(struct drm_device *dev)
        else if (IS_HASWELL(dev))
                dev_priv->display.get_display_clock_speed =
                        haswell_get_display_clock_speed;
-       else if (IS_VALLEYVIEW(dev))
+       else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
                dev_priv->display.get_display_clock_speed =
                        valleyview_get_display_clock_speed;
        else if (IS_GEN5(dev))
@@ -14561,9 +15042,6 @@ static void intel_init_display(struct drm_device *dev)
        else if (IS_I945GM(dev) || IS_845G(dev))
                dev_priv->display.get_display_clock_speed =
                        i9xx_misc_get_display_clock_speed;
-       else if (IS_PINEVIEW(dev))
-               dev_priv->display.get_display_clock_speed =
-                       pnv_get_display_clock_speed;
        else if (IS_I915GM(dev))
                dev_priv->display.get_display_clock_speed =
                        i915gm_get_display_clock_speed;
@@ -14594,7 +15072,7 @@ static void intel_init_display(struct drm_device *dev)
                        dev_priv->display.modeset_calc_cdclk =
                                broadwell_modeset_calc_cdclk;
                }
-       } else if (IS_VALLEYVIEW(dev)) {
+       } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                dev_priv->display.modeset_commit_cdclk =
                        valleyview_modeset_commit_cdclk;
                dev_priv->display.modeset_calc_cdclk =
@@ -14810,7 +15288,7 @@ static void i915_disable_vga(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u8 sr1;
-       u32 vga_reg = i915_vgacntrl_reg(dev);
+       i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
 
        /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
        vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
@@ -14826,12 +15304,97 @@ static void i915_disable_vga(struct drm_device *dev)
 
 void intel_modeset_init_hw(struct drm_device *dev)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
        intel_update_cdclk(dev);
+
+       dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
+
        intel_prepare_ddi(dev);
        intel_init_clock_gating(dev);
        intel_enable_gt_powersave(dev);
 }
 
+/*
+ * Calculate what we think the watermarks should be for the state we've read
+ * out of the hardware and then immediately program those watermarks so that
+ * we ensure the hardware settings match our internal state.
+ *
+ * We can calculate what we think WM's should be by creating a duplicate of the
+ * current state (which was constructed during hardware readout) and running it
+ * through the atomic check code to calculate new watermark values in the
+ * state object.
+ */
+static void sanitize_watermarks(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_atomic_state *state;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *cstate;
+       struct drm_modeset_acquire_ctx ctx;
+       int ret;
+       int i;
+
+       /* Only supported on platforms that use atomic watermark design */
+       if (!dev_priv->display.optimize_watermarks)
+               return;
+
+       /*
+        * We need to hold connection_mutex before calling duplicate_state so
+        * that the connector loop is protected.
+        */
+       drm_modeset_acquire_init(&ctx, 0);
+retry:
+       ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx);
+       if (ret == -EDEADLK) {
+               drm_modeset_backoff(&ctx);
+               goto retry;
+       } else if (WARN_ON(ret)) {
+               return;
+       }
+
+       state = drm_atomic_helper_duplicate_state(dev, &ctx);
+       if (WARN_ON(IS_ERR(state)))
+               return;
+
+       /*
+        * Hardware readout is the only time we don't want to calculate
+        * intermediate watermarks (since we don't trust the current
+        * watermarks).
+        */
+       to_intel_atomic_state(state)->skip_intermediate_wm = true;
+
+       ret = intel_atomic_check(dev, state);
+       if (ret) {
+               /*
+                * If we fail here, it means that the hardware appears to be
+                * programmed in a way that shouldn't be possible, given our
+                * understanding of watermark requirements.  This might mean a
+                * mistake in the hardware readout code or a mistake in the
+                * watermark calculations for a given platform.  Raise a WARN
+                * so that this is noticeable.
+                *
+                * If this actually happens, we'll have to just leave the
+                * BIOS-programmed watermarks untouched and hope for the best.
+                */
+               WARN(true, "Could not determine valid watermarks for inherited state\n");
+               return;
+       }
+
+       /* Write calculated watermark values back */
+       to_i915(dev)->wm.config = to_intel_atomic_state(state)->wm_config;
+       for_each_crtc_in_state(state, crtc, cstate, i) {
+               struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
+
+               cs->wm.need_postvbl_update = true;
+               dev_priv->display.optimize_watermarks(cs);
+       }
+
+       drm_atomic_state_free(state);
+       drm_modeset_drop_locks(&ctx);
+       drm_modeset_acquire_fini(&ctx);
+}
+
 void intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -14926,9 +15489,6 @@ void intel_modeset_init(struct drm_device *dev)
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
 
-       /* Just in case the BIOS is doing something questionable. */
-       intel_fbc_disable(dev_priv);
-
        drm_modeset_lock_all(dev);
        intel_modeset_setup_hw_state(dev);
        drm_modeset_unlock_all(dev);
@@ -14955,6 +15515,13 @@ void intel_modeset_init(struct drm_device *dev)
                 */
                intel_find_initial_plane_obj(crtc, &plane_config);
        }
+
+       /*
+        * Make sure hardware watermarks really match the state we read out.
+        * Note that we need to do this after reconstructing the BIOS fb's
+        * since the watermark calculation done here will use pstate->fb.
+        */
+       sanitize_watermarks(dev);
 }
 
 static void intel_enable_pipe_a(struct drm_device *dev)
@@ -15015,10 +15582,9 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 reg;
+       i915_reg_t reg = PIPECONF(crtc->config->cpu_transcoder);
 
        /* Clear any frame start delays used for debugging left by the BIOS */
-       reg = PIPECONF(crtc->config->cpu_transcoder);
        I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 
        /* restore vblank interrupts to correct state */
@@ -15172,7 +15738,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
 void i915_redisable_vga_power_on(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 vga_reg = i915_vgacntrl_reg(dev);
+       i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
 
        if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
                DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
@@ -15211,7 +15777,7 @@ static void readout_plane_state(struct intel_crtc *crtc)
        struct intel_plane_state *plane_state =
                to_intel_plane_state(primary->state);
 
-       plane_state->visible =
+       plane_state->visible = crtc->active &&
                primary_get_hw_state(to_intel_plane(primary));
 
        if (plane_state->visible)
@@ -15227,16 +15793,40 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
        struct intel_connector *connector;
        int i;
 
+       dev_priv->active_crtcs = 0;
+
        for_each_intel_crtc(dev, crtc) {
-               __drm_atomic_helper_crtc_destroy_state(&crtc->base, crtc->base.state);
-               memset(crtc->config, 0, sizeof(*crtc->config));
-               crtc->config->base.crtc = &crtc->base;
+               struct intel_crtc_state *crtc_state = crtc->config;
+               int pixclk = 0;
 
-               crtc->active = dev_priv->display.get_pipe_config(crtc,
-                                                                crtc->config);
+               __drm_atomic_helper_crtc_destroy_state(&crtc->base, &crtc_state->base);
+               memset(crtc_state, 0, sizeof(*crtc_state));
+               crtc_state->base.crtc = &crtc->base;
 
-               crtc->base.state->active = crtc->active;
-               crtc->base.enabled = crtc->active;
+               crtc_state->base.active = crtc_state->base.enable =
+                       dev_priv->display.get_pipe_config(crtc, crtc_state);
+
+               crtc->base.enabled = crtc_state->base.enable;
+               crtc->active = crtc_state->base.active;
+
+               if (crtc_state->base.active) {
+                       dev_priv->active_crtcs |= 1 << crtc->pipe;
+
+                       if (IS_BROADWELL(dev_priv)) {
+                               pixclk = ilk_pipe_pixel_rate(crtc_state);
+
+                               /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
+                               if (crtc_state->ips_enabled)
+                                       pixclk = DIV_ROUND_UP(pixclk * 100, 95);
+                       } else if (IS_VALLEYVIEW(dev_priv) ||
+                                  IS_CHERRYVIEW(dev_priv) ||
+                                  IS_BROXTON(dev_priv))
+                               pixclk = crtc_state->base.adjusted_mode.crtc_clock;
+                       else
+                               WARN_ON(dev_priv->display.modeset_calc_cdclk);
+               }
+
+               dev_priv->min_pixclk[crtc->pipe] = pixclk;
 
                readout_plane_state(crtc);
 
@@ -15372,7 +15962,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
                pll->on = false;
        }
 
-       if (IS_VALLEYVIEW(dev))
+       if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
                vlv_wm_get_hw_state(dev);
        else if (IS_GEN9(dev))
                skl_wm_get_hw_state(dev);
@@ -15468,8 +16058,7 @@ void intel_modeset_gem_init(struct drm_device *dev)
                mutex_lock(&dev->struct_mutex);
                ret = intel_pin_and_fence_fb_obj(c->primary,
                                                 c->primary->fb,
-                                                c->primary->state,
-                                                NULL, NULL);
+                                                c->primary->state);
                mutex_unlock(&dev->struct_mutex);
                if (ret) {
                        DRM_ERROR("failed to pin boot fb on pipe %d\n",
@@ -15496,7 +16085,7 @@ void intel_connector_unregister(struct intel_connector *intel_connector)
 void intel_modeset_cleanup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_connector *connector;
+       struct intel_connector *connector;
 
        intel_disable_gt_powersave(dev);
 
@@ -15523,12 +16112,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
        flush_scheduled_work();
 
        /* destroy the backlight and sysfs files before encoders/connectors */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               struct intel_connector *intel_connector;
-
-               intel_connector = to_intel_connector(connector);
-               intel_connector->unregister(intel_connector);
-       }
+       for_each_intel_connector(dev, connector)
+               connector->unregister(connector);
 
        drm_mode_config_cleanup(dev);