]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/atomic: Add encoder_mask to crtc_state, v3.
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / i915 / intel_display.c
index 32cf973469785cb916eb3c2bdd125a741efb5e4c..e1e7cdee3bbd6f3f2148fad011f507924a7c7918 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,
@@ -186,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);
@@ -214,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",
@@ -715,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)
@@ -1096,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;
 
@@ -1136,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,
@@ -1149,11 +1150,6 @@ static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
        }
 }
 
-static const char *state_string(bool enabled)
-{
-       return enabled ? "on" : "off";
-}
-
 /* Only for pre-ILK configs */
 void assert_pll(struct drm_i915_private *dev_priv,
                enum pipe pipe, bool state)
@@ -1165,7 +1161,7 @@ void assert_pll(struct drm_i915_private *dev_priv,
        cur_state = !!(val & DPLL_VCO_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "PLL state assertion failure (expected %s, current %s)\n",
-            state_string(state), state_string(cur_state));
+                       onoff(state), onoff(cur_state));
 }
 
 /* XXX: the dsi pll is shared between MIPI DSI ports */
@@ -1181,7 +1177,7 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
        cur_state = val & DSI_PLL_VCO_EN;
        I915_STATE_WARN(cur_state != state,
             "DSI PLL state assertion failure (expected %s, current %s)\n",
-            state_string(state), state_string(cur_state));
+                       onoff(state), onoff(cur_state));
 }
 #define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
 #define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
@@ -1205,14 +1201,13 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv,
        bool cur_state;
        struct intel_dpll_hw_state hw_state;
 
-       if (WARN (!pll,
-                 "asserting DPLL %s with no DPLL\n", state_string(state)))
+       if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
                return;
 
        cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
        I915_STATE_WARN(cur_state != state,
             "%s assertion failure (expected %s, current %s)\n",
-            pll->name, state_string(state), state_string(cur_state));
+                       pll->name, onoff(state), onoff(cur_state));
 }
 
 static void assert_fdi_tx(struct drm_i915_private *dev_priv,
@@ -1232,7 +1227,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
        }
        I915_STATE_WARN(cur_state != state,
             "FDI TX state assertion failure (expected %s, current %s)\n",
-            state_string(state), state_string(cur_state));
+                       onoff(state), onoff(cur_state));
 }
 #define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
 #define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
@@ -1247,7 +1242,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv,
        cur_state = !!(val & FDI_RX_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "FDI RX state assertion failure (expected %s, current %s)\n",
-            state_string(state), state_string(cur_state));
+                       onoff(state), onoff(cur_state));
 }
 #define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
 #define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
@@ -1279,14 +1274,14 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
        cur_state = !!(val & FDI_RX_PLL_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "FDI RX PLL assertion failure (expected %s, current %s)\n",
-            state_string(state), state_string(cur_state));
+                       onoff(state), onoff(cur_state));
 }
 
 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;
@@ -1304,7 +1299,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;
@@ -1337,7 +1332,7 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
 
        I915_STATE_WARN(cur_state != state,
             "cursor on pipe %c assertion failure (expected %s, current %s)\n",
-            pipe_name(pipe), state_string(state), state_string(cur_state));
+                       pipe_name(pipe), onoff(state), onoff(cur_state));
 }
 #define assert_cursor_enabled(d, p) assert_cursor(d, p, true)
 #define assert_cursor_disabled(d, p) assert_cursor(d, p, false)
@@ -1364,7 +1359,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
 
        I915_STATE_WARN(cur_state != state,
             "pipe %c assertion failure (expected %s, current %s)\n",
-            pipe_name(pipe), state_string(state), state_string(cur_state));
+                       pipe_name(pipe), onoff(state), onoff(cur_state));
 }
 
 static void assert_plane(struct drm_i915_private *dev_priv,
@@ -1377,7 +1372,7 @@ static void assert_plane(struct drm_i915_private *dev_priv,
        cur_state = !!(val & DISPLAY_PLANE_ENABLE);
        I915_STATE_WARN(cur_state != state,
             "plane %c assertion failure (expected %s, current %s)\n",
-            plane_name(plane), state_string(state), state_string(cur_state));
+                       plane_name(plane), onoff(state), onoff(cur_state));
 }
 
 #define assert_plane_enabled(d, p) assert_plane(d, p, true)
@@ -1422,7 +1417,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,
@@ -1481,8 +1476,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)) {
@@ -1546,12 +1540,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),
@@ -1559,12 +1554,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),
@@ -1600,14 +1595,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);
@@ -1645,8 +1637,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 */
@@ -1689,7 +1679,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);
@@ -1838,7 +1828,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:
@@ -1963,7 +1953,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));
@@ -2052,7 +2043,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);
@@ -2069,7 +2061,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);
@@ -2107,10 +2099,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));
@@ -2130,7 +2121,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);
@@ -2154,6 +2145,17 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
 
        I915_WRITE(reg, val | PIPECONF_ENABLE);
        POSTING_READ(reg);
+
+       /*
+        * Until the pipe starts DSL will read as 0, which would cause
+        * an apparent vblank timestamp jump, which messes up also the
+        * frame count when it's derived from the timestamps. So let's
+        * wait for the pipe to start properly before we call
+        * drm_crtc_vblank_on()
+        */
+       if (dev->max_vblank_count == 0 &&
+           wait_for(intel_get_crtc_scanline(crtc) != crtc->scanline_offset, 50))
+               DRM_ERROR("pipe %c didn't start\n", pipe_name(pipe));
 }
 
 /**
@@ -2171,7 +2173,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));
@@ -2215,75 +2217,83 @@ static bool need_vtd_wa(struct drm_device *dev)
        return false;
 }
 
-unsigned int
-intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
-                 uint64_t fb_format_modifier, unsigned int plane)
+static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
 {
-       unsigned int tile_height;
-       uint32_t pixel_bytes;
+       return IS_GEN2(dev_priv) ? 2048 : 4096;
+}
 
-       switch (fb_format_modifier) {
+static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
+                                    uint64_t fb_modifier, unsigned int cpp)
+{
+       switch (fb_modifier) {
        case DRM_FORMAT_MOD_NONE:
-               tile_height = 1;
-               break;
+               return cpp;
        case I915_FORMAT_MOD_X_TILED:
-               tile_height = IS_GEN2(dev) ? 16 : 8;
-               break;
+               if (IS_GEN2(dev_priv))
+                       return 128;
+               else
+                       return 512;
        case I915_FORMAT_MOD_Y_TILED:
-               tile_height = 32;
-               break;
+               if (IS_GEN2(dev_priv) || HAS_128_BYTE_Y_TILING(dev_priv))
+                       return 128;
+               else
+                       return 512;
        case I915_FORMAT_MOD_Yf_TILED:
-               pixel_bytes = drm_format_plane_cpp(pixel_format, plane);
-               switch (pixel_bytes) {
-               default:
+               switch (cpp) {
                case 1:
-                       tile_height = 64;
-                       break;
+                       return 64;
                case 2:
                case 4:
-                       tile_height = 32;
-                       break;
+                       return 128;
                case 8:
-                       tile_height = 16;
-                       break;
                case 16:
-                       WARN_ONCE(1,
-                                 "128-bit pixels are not supported for display!");
-                       tile_height = 16;
-                       break;
+                       return 256;
+               default:
+                       MISSING_CASE(cpp);
+                       return cpp;
                }
                break;
        default:
-               MISSING_CASE(fb_format_modifier);
-               tile_height = 1;
-               break;
+               MISSING_CASE(fb_modifier);
+               return cpp;
        }
+}
 
-       return tile_height;
+unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
+                              uint64_t fb_modifier, unsigned int cpp)
+{
+       if (fb_modifier == DRM_FORMAT_MOD_NONE)
+               return 1;
+       else
+               return intel_tile_size(dev_priv) /
+                       intel_tile_width(dev_priv, fb_modifier, cpp);
 }
 
 unsigned int
 intel_fb_align_height(struct drm_device *dev, unsigned int height,
-                     uint32_t pixel_format, uint64_t fb_format_modifier)
+                     uint32_t pixel_format, uint64_t fb_modifier)
 {
-       return ALIGN(height, intel_tile_height(dev, pixel_format,
-                                              fb_format_modifier, 0));
+       unsigned int cpp = drm_format_plane_cpp(pixel_format, 0);
+       unsigned int tile_height = intel_tile_height(to_i915(dev), fb_modifier, cpp);
+
+       return ALIGN(height, tile_height);
 }
 
-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;
-       unsigned int tile_height, tile_pitch;
+       struct drm_i915_private *dev_priv = to_i915(fb->dev);
+       struct intel_rotation_info *info = &view->params.rotation_info;
+       unsigned int tile_size, tile_width, tile_height, cpp;
 
        *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;
 
@@ -2293,33 +2303,33 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
        info->uv_offset = fb->offsets[1];
        info->fb_modifier = fb->modifier[0];
 
-       tile_height = intel_tile_height(fb->dev, fb->pixel_format,
-                                       fb->modifier[0], 0);
-       tile_pitch = PAGE_SIZE / tile_height;
-       info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
+       tile_size = intel_tile_size(dev_priv);
+
+       cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+       tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
+       tile_height = tile_size / tile_width;
+
+       info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
        info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
-       info->size = info->width_pages * info->height_pages * PAGE_SIZE;
+       info->size = info->width_pages * info->height_pages * tile_size;
 
        if (info->pixel_format == DRM_FORMAT_NV12) {
-               tile_height = intel_tile_height(fb->dev, fb->pixel_format,
-                                               fb->modifier[0], 1);
-               tile_pitch = PAGE_SIZE / tile_height;
-               info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch);
-               info->height_pages_uv = DIV_ROUND_UP(fb->height / 2,
-                                                    tile_height);
-               info->size_uv = info->width_pages_uv * info->height_pages_uv *
-                               PAGE_SIZE;
-       }
+               cpp = drm_format_plane_cpp(fb->pixel_format, 1);
+               tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
+               tile_height = tile_size / tile_width;
 
-       return 0;
+               info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
+               info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
+               info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
+       }
 }
 
-static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
+static unsigned int intel_linear_alignment(const 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;
@@ -2327,12 +2337,29 @@ static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
                return 0;
 }
 
+static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv,
+                                        uint64_t fb_modifier)
+{
+       switch (fb_modifier) {
+       case DRM_FORMAT_MOD_NONE:
+               return intel_linear_alignment(dev_priv);
+       case I915_FORMAT_MOD_X_TILED:
+               if (INTEL_INFO(dev_priv)->gen >= 9)
+                       return 256 * 1024;
+               return 0;
+       case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_Yf_TILED:
+               return 1 * 1024 * 1024;
+       default:
+               MISSING_CASE(fb_modifier);
+               return 0;
+       }
+}
+
 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;
@@ -2343,33 +2370,9 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-       switch (fb->modifier[0]) {
-       case DRM_FORMAT_MOD_NONE:
-               alignment = intel_linear_alignment(dev_priv);
-               break;
-       case I915_FORMAT_MOD_X_TILED:
-               if (INTEL_INFO(dev)->gen >= 9)
-                       alignment = 256 * 1024;
-               else {
-                       /* pin() will align the object as required by fence */
-                       alignment = 0;
-               }
-               break;
-       case I915_FORMAT_MOD_Y_TILED:
-       case I915_FORMAT_MOD_Yf_TILED:
-               if (WARN_ONCE(INTEL_INFO(dev)->gen < 9,
-                         "Y tiling bo slipped through, driver bug!\n"))
-                       return -EINVAL;
-               alignment = 1 * 1024 * 1024;
-               break;
-       default:
-               MISSING_CASE(fb->modifier[0]);
-               return -EINVAL;
-       }
+       alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
 
-       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
@@ -2388,11 +2391,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
@@ -2418,14 +2420,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;
 }
@@ -2435,12 +2435,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);
@@ -2450,22 +2448,27 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
 
 /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
  * is assumed to be a power-of-two. */
-unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
-                                            int *x, int *y,
-                                            unsigned int tiling_mode,
-                                            unsigned int cpp,
-                                            unsigned int pitch)
-{
-       if (tiling_mode != I915_TILING_NONE) {
+unsigned long intel_compute_tile_offset(struct drm_i915_private *dev_priv,
+                                       int *x, int *y,
+                                       uint64_t fb_modifier,
+                                       unsigned int cpp,
+                                       unsigned int pitch)
+{
+       if (fb_modifier != DRM_FORMAT_MOD_NONE) {
+               unsigned int tile_size, tile_width, tile_height;
                unsigned int tile_rows, tiles;
 
-               tile_rows = *y / 8;
-               *y %= 8;
+               tile_size = intel_tile_size(dev_priv);
+               tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
+               tile_height = tile_size / tile_width;
+
+               tile_rows = *y / tile_height;
+               *y %= tile_height;
 
-               tiles = *x / (512/cpp);
-               *x %= 512/cpp;
+               tiles = *x / (tile_width/cpp);
+               *x %= tile_width/cpp;
 
-               return tile_rows * pitch * 8 + tiles * 4096;
+               return tile_rows * pitch * tile_height + tiles * tile_size;
        } else {
                unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
                unsigned int offset;
@@ -2610,6 +2613,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        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)
@@ -2671,6 +2676,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;
@@ -2682,36 +2696,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;
@@ -2726,13 +2727,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);
        }
@@ -2774,26 +2775,26 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 
        if (INTEL_INFO(dev)->gen >= 4) {
                intel_crtc->dspaddr_offset =
-                       intel_gen4_compute_page_offset(dev_priv,
-                                                      &x, &y, obj->tiling_mode,
-                                                      pixel_size,
-                                                      fb->pitches[0]);
+                       intel_compute_tile_offset(dev_priv, &x, &y,
+                                                 fb->modifier[0],
+                                                 pixel_size,
+                                                 fb->pitches[0]);
                linear_offset -= intel_crtc->dspaddr_offset;
        } else {
                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;
@@ -2812,37 +2813,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))
@@ -2879,23 +2883,23 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 
        linear_offset = y * fb->pitches[0] + x * pixel_size;
        intel_crtc->dspaddr_offset =
-               intel_gen4_compute_page_offset(dev_priv,
-                                              &x, &y, obj->tiling_mode,
-                                              pixel_size,
-                                              fb->pitches[0]);
+               intel_compute_tile_offset(dev_priv, &x, &y,
+                                         fb->modifier[0],
+                                         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;
                }
        }
 
@@ -2916,64 +2920,44 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
        POSTING_READ(reg);
 }
 
-u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
-                             uint32_t pixel_format)
+u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
+                             uint64_t fb_modifier, uint32_t pixel_format)
 {
-       u32 bits_per_pixel = drm_format_plane_cpp(pixel_format, 0) * 8;
-
-       /*
-        * The stride is either expressed as a multiple of 64 bytes
-        * chunks for linear buffers or in number of tiles for tiled
-        * buffers.
-        */
-       switch (fb_modifier) {
-       case DRM_FORMAT_MOD_NONE:
-               return 64;
-       case I915_FORMAT_MOD_X_TILED:
-               if (INTEL_INFO(dev)->gen == 2)
-                       return 128;
-               return 512;
-       case I915_FORMAT_MOD_Y_TILED:
-               /* No need to check for old gens and Y tiling since this is
-                * about the display engine and those will be blocked before
-                * we get here.
-                */
-               return 128;
-       case I915_FORMAT_MOD_Yf_TILED:
-               if (bits_per_pixel == 8)
-                       return 64;
-               else
-                       return 128;
-       default:
-               MISSING_CASE(fb_modifier);
+       if (fb_modifier == DRM_FORMAT_MOD_NONE) {
                return 64;
+       } else {
+               int cpp = drm_format_plane_cpp(pixel_format, 0);
+
+               return intel_tile_width(dev_priv, fb_modifier, cpp);
        }
 }
 
-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.state->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)
@@ -3084,36 +3068,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 |
@@ -3122,41 +3100,27 @@ 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],
+       stride_div = intel_fb_stride_alignment(dev_priv, 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)) {
+               int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
+
                /* stride = Surface height in tiles */
-               tile_height = intel_tile_height(dev, fb->pixel_format,
-                                               fb->modifier[0], 0);
+               tile_height = intel_tile_height(dev_priv, fb->modifier[0], cpp);
                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;
@@ -3189,20 +3153,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)
@@ -3227,11 +3201,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);
        }
@@ -3306,32 +3281,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;
@@ -3401,7 +3350,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);
@@ -3443,7 +3393,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);
@@ -3543,7 +3494,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 */
@@ -3675,7 +3627,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 */
@@ -3792,8 +3745,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);
@@ -3829,7 +3782,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);
@@ -3859,7 +3813,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);
@@ -3952,15 +3907,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);
@@ -3971,11 +3934,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 */
@@ -3987,18 +3961,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) {
@@ -4016,7 +3979,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;
 
@@ -4038,6 +4001,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;
@@ -4059,12 +4024,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,
@@ -4135,6 +4100,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
@@ -4149,7 +4130,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);
 
@@ -4161,6 +4142,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);
 
@@ -4194,10 +4181,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 |
@@ -4205,19 +4196,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:
@@ -4357,7 +4348,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);
@@ -4447,7 +4438,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
                      intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX);
 
        return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
-               &state->scaler_state.scaler_id, DRM_ROTATE_0,
+               &state->scaler_state.scaler_id, BIT(DRM_ROTATE_0),
                state->pipe_src_w, state->pipe_src_h,
                adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);
 }
@@ -4650,7 +4641,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);
@@ -4667,7 +4658,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);
@@ -4720,14 +4711,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
@@ -4746,9 +4729,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);
 }
 
 /**
@@ -4805,31 +4788,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));
 }
 
@@ -4838,23 +4816,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);
@@ -4862,10 +4828,13 @@ 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);
        }
+
+       if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed)
+               intel_update_watermarks(&crtc->base);
 }
 
 static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
@@ -4900,7 +4869,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                return;
 
        if (intel_crtc->config->has_pch_encoder)
-               intel_prepare_shared_dpll(intel_crtc);
+               intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
+
+       if (intel_crtc->config->has_pch_encoder)
+               intel_prepare_shared_dpll(intel_crtc);
 
        if (intel_crtc->config->has_dp_encoder)
                intel_dp_set_m_n(intel_crtc, M1_N1);
@@ -4917,7 +4889,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)
@@ -4955,6 +4926,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. */
@@ -4972,11 +4950,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);
 
@@ -5001,21 +4982,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)
@@ -5030,7 +5010,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);
@@ -5039,7 +5019,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);
@@ -5050,6 +5030,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;
@@ -5057,6 +5045,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)
@@ -5081,7 +5071,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);
@@ -5089,15 +5081,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)
@@ -5107,6 +5106,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);
@@ -5123,6 +5125,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)
@@ -5132,7 +5138,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);
@@ -5142,15 +5151,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)
@@ -5158,17 +5164,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)
@@ -5199,15 +5211,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;
@@ -5234,10 +5246,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)
 {
@@ -5302,13 +5310,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 ||
@@ -5350,6 +5356,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] = {};
@@ -5363,13 +5370,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])
@@ -5395,7 +5398,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)
@@ -5452,7 +5455,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
@@ -5812,32 +5815,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 */
@@ -5858,6 +5845,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)
 {
@@ -6020,22 +6046,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;
 }
 
@@ -6044,13 +6079,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;
 }
 
@@ -6059,13 +6099,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;
 }
 
@@ -6108,8 +6153,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
@@ -6139,13 +6186,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);
 
@@ -6168,7 +6212,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);
@@ -6247,6 +6291,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)
@@ -6294,7 +6340,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))
@@ -6309,6 +6355,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)
@@ -6322,7 +6370,8 @@ 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));
@@ -6338,6 +6387,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;
 }
 
 /*
@@ -6447,13 +6499,11 @@ static void intel_connector_check_state(struct intel_connector *connector)
 
 int intel_connector_init(struct intel_connector *connector)
 {
-       struct drm_connector_state *connector_state;
+       drm_atomic_helper_connector_reset(&connector->base);
 
-       connector_state = kzalloc(sizeof *connector_state, GFP_KERNEL);
-       if (!connector_state)
+       if (!connector->base.state)
                return -ENOMEM;
 
-       connector->base.state = connector_state;
        return 0;
 }
 
@@ -6642,6 +6692,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)
 {
@@ -6651,23 +6710,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;
+               }
        }
 
        /*
@@ -7144,7 +7204,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) {
@@ -7432,7 +7492,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;
@@ -7540,26 +7600,34 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
  * in cases where we need the PLL enabled even when @pipe is not going to
  * be enabled.
  */
-void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
-                     const struct dpll *dpll)
+int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
+                    const struct dpll *dpll)
 {
        struct intel_crtc *crtc =
                to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
-       struct intel_crtc_state pipe_config = {
-               .base.crtc = &crtc->base,
-               .pixel_multiplier = 1,
-               .dpll = *dpll,
-       };
+       struct intel_crtc_state *pipe_config;
+
+       pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
+       if (!pipe_config)
+               return -ENOMEM;
+
+       pipe_config->base.crtc = &crtc->base;
+       pipe_config->pixel_multiplier = 1;
+       pipe_config->dpll = *dpll;
 
        if (IS_CHERRYVIEW(dev)) {
-               chv_compute_dpll(crtc, &pipe_config);
-               chv_prepare_pll(crtc, &pipe_config);
-               chv_enable_pll(crtc, &pipe_config);
+               chv_compute_dpll(crtc, pipe_config);
+               chv_prepare_pll(crtc, pipe_config);
+               chv_enable_pll(crtc, pipe_config);
        } else {
-               vlv_compute_dpll(crtc, &pipe_config);
-               vlv_prepare_pll(crtc, &pipe_config);
-               vlv_enable_pll(crtc, &pipe_config);
+               vlv_compute_dpll(crtc, pipe_config);
+               vlv_prepare_pll(crtc, pipe_config);
+               vlv_enable_pll(crtc, pipe_config);
        }
+
+       kfree(pipe_config);
+
+       return 0;
 }
 
 /**
@@ -7843,7 +7911,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 |
@@ -7883,7 +7951,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);
@@ -7898,8 +7967,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;
@@ -7909,26 +7976,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);
 
@@ -8144,7 +8199,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;
@@ -8160,7 +8215,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)
@@ -8188,7 +8244,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
@@ -8540,6 +8596,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;
@@ -8555,10 +8672,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);
+       }
 }
 
 /*
@@ -8921,7 +9040,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));
@@ -9142,7 +9261,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
        fb->width = ((val >> 0) & 0x1fff) + 1;
 
        val = I915_READ(PLANE_STRIDE(pipe, 0));
-       stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
+       stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
                                                fb->pixel_format);
        fb->pitches[0] = (val & 0x3ff) * stride_mult;
 
@@ -9350,8 +9469,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");
@@ -9558,14 +9677,14 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv)
                val |= PCH_LP_PARTITION_LEVEL_DISABLE;
                I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
        }
-
-       intel_prepare_ddi(dev);
 }
 
 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);
 }
@@ -9573,29 +9692,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;
 }
 
@@ -9679,6 +9810,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;
 
@@ -9695,17 +9827,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;
 }
@@ -9713,7 +9843,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);
 }
@@ -9797,6 +9929,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;
        }
 }
 
@@ -9813,7 +9946,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);
@@ -9925,16 +10058,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        return true;
 }
 
-static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
+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 (on) {
-               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) {
@@ -9987,7 +10121,8 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
        }
 }
 
-static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
+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;
@@ -9995,9 +10130,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
        int pipe = intel_crtc->pipe;
        uint32_t cntl = 0;
 
-       if (on) {
+       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;
@@ -10008,17 +10143,17 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
                                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);
@@ -10035,56 +10170,45 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
 
 /* 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;
+       u32 base = intel_crtc->cursor_addr;
+       u32 pos = 0;
 
-       base = intel_crtc->cursor_addr;
+       if (plane_state) {
+               int x = plane_state->base.crtc_x;
+               int y = plane_state->base.crtc_y;
 
-       if (x >= intel_crtc->config->pipe_src_w)
-               on = false;
-
-       if (y >= intel_crtc->config->pipe_src_h)
-               on = false;
-
-       if (x < 0) {
-               if (x + cursor_state->crtc_w <= 0)
-                       on = false;
-
-               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)
-                       on = false;
+               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;
 
        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, on);
+               i845_update_cursor(crtc, base, plane_state);
        else
-               i9xx_update_cursor(crtc, base, on);
+               i9xx_update_cursor(crtc, base, plane_state);
 }
 
 static bool cursor_size_ok(struct drm_device *dev,
@@ -10154,20 +10278,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);
 }
 
@@ -10207,6 +10328,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 };
 
@@ -10221,7 +10343,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 *
@@ -10395,7 +10521,6 @@ retry:
        }
 
        connector_state->crtc = crtc;
-       connector_state->best_encoder = &intel_encoder->base;
 
        crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
        if (IS_ERR(crtc_state)) {
@@ -10491,7 +10616,6 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
                if (IS_ERR(crtc_state))
                        goto fail;
 
-               connector_state->best_encoder = NULL;
                connector_state->crtc = NULL;
 
                crtc_state->base.enable = crtc_state->base.active = false;
@@ -10675,7 +10799,7 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
        struct drm_display_mode *mode;
-       struct intel_crtc_state pipe_config;
+       struct intel_crtc_state *pipe_config;
        int htot = I915_READ(HTOTAL(cpu_transcoder));
        int hsync = I915_READ(HSYNC(cpu_transcoder));
        int vtot = I915_READ(VTOTAL(cpu_transcoder));
@@ -10686,6 +10810,12 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
        if (!mode)
                return NULL;
 
+       pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
+       if (!pipe_config) {
+               kfree(mode);
+               return NULL;
+       }
+
        /*
         * Construct a pipe_config sufficient for getting the clock info
         * back out of crtc_clock_get.
@@ -10693,14 +10823,14 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
         * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need
         * to use a real value here instead.
         */
-       pipe_config.cpu_transcoder = (enum transcoder) pipe;
-       pipe_config.pixel_multiplier = 1;
-       pipe_config.dpll_hw_state.dpll = I915_READ(DPLL(pipe));
-       pipe_config.dpll_hw_state.fp0 = I915_READ(FP0(pipe));
-       pipe_config.dpll_hw_state.fp1 = I915_READ(FP1(pipe));
-       i9xx_crtc_clock_get(intel_crtc, &pipe_config);
-
-       mode->clock = pipe_config.port_clock / pipe_config.pixel_multiplier;
+       pipe_config->cpu_transcoder = (enum transcoder) pipe;
+       pipe_config->pixel_multiplier = 1;
+       pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(pipe));
+       pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(pipe));
+       pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(pipe));
+       i9xx_crtc_clock_get(intel_crtc, pipe_config);
+
+       mode->clock = pipe_config->port_clock / pipe_config->pixel_multiplier;
        mode->hdisplay = (htot & 0xffff) + 1;
        mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
        mode->hsync_start = (hsync & 0xffff) + 1;
@@ -10712,6 +10842,8 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 
        drm_mode_set_name(mode);
 
+       kfree(pipe_config);
+
        return mode;
 }
 
@@ -11124,7 +11256,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));
@@ -11134,7 +11266,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);
@@ -11174,18 +11306,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;
@@ -11209,9 +11346,15 @@ 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_priv, fb->modifier[0], 0);
+               stride = DIV_ROUND_UP(fb->height, tile_height);
+       } else {
+               stride = fb->pitches[0] /
+                       intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+                                                 fb->pixel_format);
+       }
 
        /*
         * Both PLANE_CTL and PLANE_STRIDE are not updated on vblank but on
@@ -11232,10 +11375,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)
@@ -11269,7 +11411,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);
@@ -11281,6 +11423,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,
@@ -11290,16 +11435,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;
 
@@ -11310,6 +11458,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);
@@ -11493,7 +11642,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 */
@@ -11515,9 +11664,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;
 
@@ -11526,8 +11680,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;
 
@@ -11535,9 +11688,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                                        obj->last_write_req);
        } else {
                if (!request) {
-                       ret = i915_gem_request_alloc(ring, ring->default_context, &request);
-                       if (ret)
+                       request = i915_gem_request_alloc(ring, NULL);
+                       if (IS_ERR(request)) {
+                               ret = PTR_ERR(request);
                                goto cleanup_unpin;
+                       }
                }
 
                ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, request,
@@ -11558,7 +11713,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);
 
@@ -11641,21 +11796,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;
@@ -11668,7 +11843,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;
 
@@ -11681,22 +11855,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;
@@ -11711,25 +11882,17 @@ 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;
        }
 
        if (visible || was_visible)
@@ -11738,7 +11901,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
 
        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;
 
@@ -11786,11 +11948,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;
 }
@@ -11863,7 +12037,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 &&
@@ -11875,6 +12049,12 @@ 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)
+                       return ret;
+       }
+
        if (INTEL_INFO(dev)->gen >= 9) {
                if (mode_changed)
                        ret = skl_update_scaler_crtc(pipe_config);
@@ -11930,11 +12110,21 @@ connected_sink_compute_bpp(struct intel_connector *connector,
                pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
        }
 
-       /* Clamp bpp to 8 on screens without EDID 1.4 */
-       if (connector->base.display_info.bpc == 0 && bpp > 24) {
-               DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
-                             bpp);
-               pipe_config->pipe_bpp = 24;
+       /* Clamp bpp to default limit on screens without EDID 1.4 */
+       if (connector->base.display_info.bpc == 0) {
+               int type = connector->base.connector_type;
+               int clamp_bpp = 24;
+
+               /* Fall back to 18 bpp when DP sink capability is unknown. */
+               if (type == DRM_MODE_CONNECTOR_DisplayPort ||
+                   type == DRM_MODE_CONNECTOR_eDP)
+                       clamp_bpp = 18;
+
+               if (bpp > clamp_bpp) {
+                       DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n",
+                                     bpp, clamp_bpp);
+                       pipe_config->pipe_bpp = clamp_bpp;
+               }
        }
 }
 
@@ -11948,7 +12138,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;
@@ -12064,7 +12254,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,
@@ -12322,6 +12512,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;
+               }
        }
 }
 
@@ -12347,7 +12549,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,
@@ -12362,19 +12564,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
@@ -12531,6 +12736,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);
@@ -12548,7 +12755,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);
 
@@ -13047,15 +13254,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
@@ -13064,27 +13283,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
@@ -13093,6 +13348,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;
@@ -13160,10 +13416,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;
+
+       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);
+       }
 
-       return drm_atomic_helper_check_planes(state->dev, state);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
 }
 
 /**
@@ -13186,23 +13513,28 @@ 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;
+       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);
@@ -13210,7 +13542,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) {
@@ -13218,6 +13549,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);
                }
        }
 
@@ -13225,7 +13566,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);
@@ -13240,6 +13581,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);
@@ -13249,30 +13593,51 @@ 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);
+
+       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;
 }
 
@@ -13435,6 +13800,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
@@ -13445,28 +13812,71 @@ 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);
+
+               /* 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) {
+               long lret;
+
+               lret = reservation_object_wait_timeout_rcu(obj->base.dma_buf->resv,
+                                                          false, true,
+                                                          MAX_SCHEDULE_TIMEOUT);
+               if (lret == -ERESTARTSYS)
+                       return lret;
+
+               WARN(lret < 0, "waiting returns %li\n", lret);
+       }
 
-       if (plane->type == DRM_PLANE_TYPE_CURSOR &&
+       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;
 }
@@ -13477,23 +13887,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
@@ -13504,7 +13926,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;
@@ -13512,7 +13934,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;
 
        /*
@@ -13537,11 +13959,12 @@ intel_check_primary_plane(struct drm_plane *plane,
        int max_scale = DRM_PLANE_HELPER_NO_SCALING;
        bool can_position = false;
 
-       /* use scaler when colorkey is not required */
-       if (INTEL_INFO(plane->dev)->gen >= 9 &&
-           state->ckey.flags == I915_SET_COLORKEY_NONE) {
-               min_scale = 1;
-               max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
+       if (INTEL_INFO(plane->dev)->gen >= 9) {
+               /* use scaler when colorkey is not required */
+               if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
+                       min_scale = 1;
+                       max_scale = skl_max_scale(to_intel_crtc(crtc), crtc_state);
+               }
                can_position = true;
        }
 
@@ -13552,42 +13975,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)
 {
@@ -13597,12 +13984,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;
@@ -13618,8 +14001,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);
 }
 
 /**
@@ -13677,26 +14059,39 @@ 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,
                                 &intel_plane_funcs,
                                 intel_primary_formats, num_formats,
-                                DRM_PLANE_TYPE_PRIMARY);
+                                DRM_PLANE_TYPE_PRIMARY, NULL);
 
        if (INTEL_INFO(dev)->gen >= 4)
                intel_create_rotation_property(dev, primary);
@@ -13789,22 +14184,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 (!obj)
                addr = 0;
        else if (!INTEL_INFO(dev)->cursor_needs_physical)
@@ -13813,9 +14209,7 @@ intel_commit_cursor_plane(struct drm_plane *plane,
                addr = obj->phys_handle->busaddr;
 
        intel_crtc->cursor_addr = addr;
-
-       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,
@@ -13841,14 +14235,14 @@ 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,
                                 &intel_plane_funcs,
                                 intel_cursor_formats,
                                 ARRAY_SIZE(intel_cursor_formats),
-                                DRM_PLANE_TYPE_CURSOR);
+                                DRM_PLANE_TYPE_CURSOR, NULL);
 
        if (INTEL_INFO(dev)->gen >= 4) {
                if (!dev->mode_config.rotation_property)
@@ -13925,7 +14319,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
                goto fail;
 
        ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
-                                       cursor, &intel_crtc_funcs);
+                                       cursor, &intel_crtc_funcs, NULL);
        if (ret)
                goto fail;
 
@@ -14051,7 +14445,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;
@@ -14087,7 +14488,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
@@ -14103,7 +14504,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))
@@ -14118,7 +14519,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))
@@ -14136,7 +14537,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
@@ -14174,7 +14575,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);
@@ -14188,7 +14589,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)) {
@@ -14285,7 +14686,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)
@@ -14308,6 +14709,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
                                  struct drm_mode_fb_cmd2 *mode_cmd,
                                  struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *dev_priv = to_i915(dev);
        unsigned int aligned_height;
        int ret;
        u32 pitch_limit, stride_alignment;
@@ -14349,7 +14751,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
                return -EINVAL;
        }
 
-       stride_alignment = intel_fb_stride_alignment(dev, mode_cmd->modifier[0],
+       stride_alignment = intel_fb_stride_alignment(dev_priv,
+                                                    mode_cmd->modifier[0],
                                                     mode_cmd->pixel_format);
        if (mode_cmd->pitches[0] & (stride_alignment - 1)) {
                DRM_DEBUG("pitch (%d) must be at least %u byte aligned\n",
@@ -14389,7 +14792,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;
@@ -14405,7 +14809,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;
@@ -14440,7 +14844,6 @@ static int intel_framebuffer_init(struct drm_device *dev,
 
        drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
        intel_fb->obj = obj;
-       intel_fb->obj->framebuffer_references++;
 
        ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
        if (ret) {
@@ -14448,14 +14851,17 @@ static int intel_framebuffer_init(struct drm_device *dev,
                return ret;
        }
 
+       intel_fb->obj->framebuffer_references++;
+
        return 0;
 }
 
 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;
 
@@ -14464,7 +14870,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
@@ -14506,8 +14916,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 =
@@ -14516,8 +14924,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 =
@@ -14526,17 +14932,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 =
@@ -14544,12 +14946,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))
@@ -14561,7 +14961,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))
@@ -14589,9 +14989,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;
@@ -14622,7 +15019,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 =
@@ -14838,7 +15235,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);
@@ -14854,12 +15251,89 @@ 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);
-       intel_prepare_ddi(dev);
+
+       dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
+
        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.program_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_all_ctx(dev, &ctx);
+       if (ret == -EDEADLK) {
+               drm_modeset_backoff(&ctx);
+               goto retry;
+       } else if (WARN_ON(ret)) {
+               goto fail;
+       }
+
+       state = drm_atomic_helper_duplicate_state(dev, &ctx);
+       if (WARN_ON(IS_ERR(state)))
+               goto fail;
+
+       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");
+               goto fail;
+       }
+
+       /* 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);
+
+               dev_priv->display.program_watermarks(cs);
+       }
+
+       drm_atomic_state_free(state);
+fail:
+       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;
@@ -14954,9 +15428,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);
@@ -14983,6 +15454,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)
@@ -15043,10 +15521,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 */
@@ -15113,6 +15590,8 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0);
                crtc->base.state->active = crtc->active;
                crtc->base.enabled = crtc->active;
+               crtc->base.state->connector_mask = 0;
+               crtc->base.state->encoder_mask = 0;
 
                /* Because we only establish the connector -> encoder ->
                 * crtc links if something is active, this means the
@@ -15200,7 +15679,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");
@@ -15239,7 +15718,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)
@@ -15255,16 +15734,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);
 
@@ -15315,7 +15818,23 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
        for_each_intel_connector(dev, connector) {
                if (connector->get_hw_state(connector)) {
                        connector->base.dpms = DRM_MODE_DPMS_ON;
-                       connector->base.encoder = &connector->encoder->base;
+
+                       encoder = connector->encoder;
+                       connector->base.encoder = &encoder->base;
+
+                       if (encoder->base.crtc &&
+                           encoder->base.crtc->state->active) {
+                               /*
+                                * This has to be done during hardware readout
+                                * because anything calling .crtc_disable may
+                                * rely on the connector_mask being accurate.
+                                */
+                               encoder->base.crtc->state->connector_mask |=
+                                       1 << drm_connector_index(&connector->base);
+                               encoder->base.crtc->state->encoder_mask |=
+                                       1 << drm_encoder_index(&encoder->base);
+                       }
+
                } else {
                        connector->base.dpms = DRM_MODE_DPMS_OFF;
                        connector->base.encoder = NULL;
@@ -15400,7 +15919,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);
@@ -15496,8 +16015,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",
@@ -15524,7 +16042,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);
 
@@ -15551,12 +16069,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);
 
@@ -15565,6 +16079,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
        mutex_lock(&dev->struct_mutex);
        intel_cleanup_gt_powersave(dev);
        mutex_unlock(&dev->struct_mutex);
+
+       intel_teardown_gmbus(dev);
 }
 
 /*
@@ -15757,7 +16273,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
        for_each_pipe(dev_priv, i) {
                err_printf(m, "Pipe [%d]:\n", i);
                err_printf(m, "  Power: %s\n",
-                          error->pipe[i].power_domain_on ? "on" : "off");
+                          onoff(error->pipe[i].power_domain_on));
                err_printf(m, "  SRC: %08x\n", error->pipe[i].source);
                err_printf(m, "  STAT: %08x\n", error->pipe[i].stat);
 
@@ -15785,7 +16301,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                err_printf(m, "CPU transcoder: %c\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
                err_printf(m, "  Power: %s\n",
-                          error->transcoder[i].power_domain_on ? "on" : "off");
+                          onoff(error->transcoder[i].power_domain_on));
                err_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
                err_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
                err_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
@@ -15795,24 +16311,3 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                err_printf(m, "  VSYNC: %08x\n", error->transcoder[i].vsync);
        }
 }
-
-void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
-{
-       struct intel_crtc *crtc;
-
-       for_each_intel_crtc(dev, crtc) {
-               struct intel_unpin_work *work;
-
-               spin_lock_irq(&dev->event_lock);
-
-               work = crtc->unpin_work;
-
-               if (work && work->event &&
-                   work->event->base.file_priv == file) {
-                       kfree(work->event);
-                       work->event = NULL;
-               }
-
-               spin_unlock_irq(&dev->event_lock);
-       }
-}