Merge tag 'topic/drm-misc-2016-02-08' of git://anongit.freedesktop.org/drm-intel...
[cascardo/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 8816ba1..7a5ed95 100644 (file)
@@ -85,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,
@@ -1152,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)
@@ -1168,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 */
@@ -1184,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)
@@ -1208,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,
@@ -1235,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)
@@ -1250,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)
@@ -1282,7 +1274,7 @@ 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,
@@ -1340,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)
@@ -1367,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,
@@ -1380,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)
@@ -2153,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));
 }
 
 /**
@@ -2214,67 +2217,75 @@ 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 void
 intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
                        const struct drm_plane_state *plane_state)
 {
+       struct drm_i915_private *dev_priv = to_i915(fb->dev);
        struct intel_rotation_info *info = &view->params.rotation_info;
-       unsigned int tile_height, tile_pitch;
+       unsigned int tile_size, tile_width, tile_height, cpp;
 
        *view = i915_ggtt_view_normal;
 
@@ -2292,26 +2303,28 @@ 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;
+
+               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;
@@ -2324,6 +2337,25 @@ 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,
@@ -2338,29 +2370,7 @@ 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]);
 
        intel_fill_fb_ggtt_view(&view, fb, plane_state);
 
@@ -2438,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;
 
-               tiles = *x / (512/cpp);
-               *x %= 512/cpp;
+               tile_rows = *y / tile_height;
+               *y %= tile_height;
 
-               return tile_rows * pitch * 8 + tiles * 4096;
+               tiles = *x / (tile_width/cpp);
+               *x %= tile_width/cpp;
+
+               return tile_rows * pitch * tile_height + tiles * tile_size;
        } else {
                unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
                unsigned int offset;
@@ -2598,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)
@@ -2659,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;
@@ -2670,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;
        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;
@@ -2714,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);
        }
@@ -2762,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;
@@ -2800,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;
-       i915_reg_t 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))
@@ -2867,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;
                }
        }
 
@@ -2904,37 +2920,15 @@ 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);
        }
 }
 
@@ -2946,7 +2940,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane,
        struct i915_vma *vma;
        u64 offset;
 
-       intel_fill_fb_ggtt_view(&view, intel_plane->base.fb,
+       intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
                                intel_plane->base.state);
 
        vma = i915_gem_obj_to_ggtt_view(obj, &view);
@@ -3074,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;
        u32 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;
-       }
+       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 |
@@ -3112,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;
@@ -3179,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.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));
+}
+
+/* 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 0;
+       return -ENODEV;
 }
 
 static void intel_complete_page_flips(struct drm_device *dev)
@@ -3219,8 +3203,10 @@ static void intel_update_primary_planes(struct drm_device *dev)
                drm_modeset_lock_crtc(crtc, &plane->base);
                plane_state = to_intel_plane_state(plane->base.state);
 
-               if (crtc->state->active && 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);
        }
@@ -4452,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);
 }
@@ -5370,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] = {};
@@ -5383,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])
@@ -6063,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;
 
-               max_pixclk = max(max_pixclk,
-                                crtc_state->base.adjusted_mode.crtc_clock);
+               if (crtc_state->enable)
+                       pixclk = crtc_state->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;
 }
 
@@ -6087,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;
 }
 
@@ -6102,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;
 }
 
@@ -6151,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
@@ -6383,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;
 }
 
 /*
@@ -7593,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;
 }
 
 /**
@@ -9246,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;
 
@@ -9662,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);
 }
@@ -9677,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;
 }
 
@@ -9783,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;
 
@@ -9805,7 +9833,9 @@ static int broadwell_modeset_calc_cdclk(struct drm_atomic_state *state)
                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;
 }
@@ -9813,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);
 }
@@ -10026,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) {
@@ -10088,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;
@@ -10096,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;
@@ -10109,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);
@@ -10136,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;
-
-       base = intel_crtc->cursor_addr;
-
-       if (x >= intel_crtc->config->pipe_src_w)
-               on = false;
+       u32 base = intel_crtc->cursor_addr;
+       u32 pos = 0;
 
-       if (y >= intel_crtc->config->pipe_src_h)
-               on = false;
+       if (plane_state) {
+               int x = plane_state->base.crtc_x;
+               int y = plane_state->base.crtc_y;
 
-       if (x < 0) {
-               if (x + cursor_state->crtc_w <= 0)
-                       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,
@@ -10778,7 +10801,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));
@@ -10789,6 +10812,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.
@@ -10796,14 +10825,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;
@@ -10815,6 +10844,8 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 
        drm_mode_set_name(mode);
 
+       kfree(pipe_config);
+
        return mode;
 }
 
@@ -11319,13 +11350,12 @@ static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
         */
        if (intel_rotation_90_or_270(rotation)) {
                /* stride = Surface height in tiles */
-               tile_height = intel_tile_height(dev, fb->pixel_format,
-                                               fb->modifier[0], 0);
+               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, fb->modifier[0],
-                                                         fb->pixel_format);
+                       intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+                                                 fb->pixel_format);
        }
 
        /*
@@ -11660,9 +11690,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,
@@ -11831,8 +11863,13 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        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;
@@ -12075,11 +12112,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;
+               }
        }
 }
 
@@ -12268,18 +12315,22 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
-       struct intel_encoder *encoder;
        struct drm_connector *connector;
-       struct drm_connector_state *connector_state;
        unsigned int used_ports = 0;
-       int i;
 
        /*
         * Walk the connector list instead of the encoder
         * list to detect the problem on ddi platforms
         * where there's just one encoder per digital port.
         */
-       for_each_connector_in_state(state, connector, connector_state, i) {
+       drm_for_each_connector(connector, dev) {
+               struct drm_connector_state *connector_state;
+               struct intel_encoder *encoder;
+
+               connector_state = drm_atomic_get_existing_connector_state(state, connector);
+               if (!connector_state)
+                       connector_state = connector->state;
+
                if (!connector_state->best_encoder)
                        continue;
 
@@ -12515,19 +12566,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
@@ -13202,15 +13256,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
@@ -13219,22 +13285,19 @@ 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;
@@ -13452,12 +13515,12 @@ 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_state *crtc_state;
        struct drm_crtc *crtc;
-       int ret = 0;
-       int i;
-       bool any_ms = false;
+       int ret = 0, i;
+       bool hw_check = intel_state->modeset;
 
        ret = intel_atomic_prepare_commit(dev, state, async);
        if (ret) {
@@ -13468,13 +13531,19 @@ static int intel_atomic_commit(struct drm_device *dev,
        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);
 
                if (!needs_modeset(crtc->state))
                        continue;
 
-               any_ms = true;
                intel_pre_plane_update(intel_crtc);
 
                if (crtc_state->active) {
@@ -13499,7 +13568,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);
@@ -13526,7 +13595,7 @@ 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)
@@ -13553,11 +13622,24 @@ static int intel_atomic_commit(struct drm_device *dev,
        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;
 }
 
@@ -13846,7 +13928,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;
@@ -13879,11 +13961,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;
        }
 
@@ -13894,32 +13977,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;
-
-       crtc = crtc ? crtc : plane->crtc;
-
-       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)
 {
@@ -14004,20 +14061,33 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
        primary->plane = pipe;
        primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
        primary->check_plane = intel_check_primary_plane;
-       primary->commit_plane = intel_commit_primary_plane;
-       primary->disable_plane = intel_disable_primary_plane;
        if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
                primary->plane = !pipe;
 
        if (INTEL_INFO(dev)->gen >= 9) {
                intel_primary_formats = skl_primary_formats;
                num_formats = ARRAY_SIZE(skl_primary_formats);
+
+               primary->update_plane = skylake_update_primary_plane;
+               primary->disable_plane = skylake_disable_primary_plane;
+       } else if (HAS_PCH_SPLIT(dev)) {
+               intel_primary_formats = i965_primary_formats;
+               num_formats = ARRAY_SIZE(i965_primary_formats);
+
+               primary->update_plane = ironlake_update_primary_plane;
+               primary->disable_plane = i9xx_disable_primary_plane;
        } else if (INTEL_INFO(dev)->gen >= 4) {
                intel_primary_formats = i965_primary_formats;
                num_formats = ARRAY_SIZE(i965_primary_formats);
+
+               primary->update_plane = i9xx_update_primary_plane;
+               primary->disable_plane = i9xx_disable_primary_plane;
        } else {
                intel_primary_formats = i8xx_primary_formats;
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
+
+               primary->update_plane = i9xx_update_primary_plane;
+               primary->disable_plane = i9xx_disable_primary_plane;
        }
 
        drm_universal_plane_init(dev, &primary->base, 0,
@@ -14116,22 +14186,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)
@@ -14140,9 +14211,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,
@@ -14168,7 +14237,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
        cursor->plane = pipe;
        cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
        cursor->check_plane = intel_check_cursor_plane;
-       cursor->commit_plane = intel_commit_cursor_plane;
+       cursor->update_plane = intel_update_cursor_plane;
        cursor->disable_plane = intel_disable_cursor_plane;
 
        drm_universal_plane_init(dev, &cursor->base, 0,
@@ -14642,6 +14711,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;
@@ -14683,7 +14753,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",
@@ -14775,7 +14846,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) {
@@ -14783,6 +14853,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
                return ret;
        }
 
+       intel_fb->obj->framebuffer_references++;
+
        return 0;
 }
 
@@ -14846,8 +14918,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 =
@@ -14856,8 +14926,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 =
@@ -14866,8 +14934,6 @@ 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) || IS_CHERRYVIEW(dev)) {
                dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
                dev_priv->display.get_initial_plane_config =
@@ -14875,8 +14941,6 @@ static void intel_init_display(struct drm_device *dev)
                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 =
@@ -14884,8 +14948,6 @@ 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 */
@@ -15191,12 +15253,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;
@@ -15317,6 +15456,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)
@@ -15589,16 +15735,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);
 
@@ -16102,7 +16272,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);
 
@@ -16130,7 +16300,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);