drm/i915: Don't use encoder->new_crtc in compute_baseline_pipe_bpp()
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index e730789b53b7b0c141bada8400b398f67149275b..034aa7e8e6836df4d65675e49522259354f36dbd 100644 (file)
@@ -37,6 +37,7 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -82,7 +83,8 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc,
                                   struct intel_crtc_state *pipe_config);
 
 static int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
-                         int x, int y, struct drm_framebuffer *old_fb);
+                         int x, int y, struct drm_framebuffer *old_fb,
+                         struct drm_atomic_state *state);
 static int intel_framebuffer_init(struct drm_device *dev,
                                  struct intel_framebuffer *ifb,
                                  struct drm_mode_fb_cmd2 *mode_cmd,
@@ -390,7 +392,7 @@ static const intel_limit_t intel_limits_chv = {
         * them would make no difference.
         */
        .dot = { .min = 25000 * 5, .max = 540000 * 5},
-       .vco = { .min = 4860000, .max = 6700000 },
+       .vco = { .min = 4800000, .max = 6480000 },
        .n = { .min = 1, .max = 1 },
        .m1 = { .min = 2, .max = 2 },
        .m2 = { .min = 24 << 22, .max = 175 << 22 },
@@ -775,6 +777,46 @@ g4x_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
        return found;
 }
 
+/*
+ * Check if the calculated PLL configuration is more optimal compared to the
+ * best configuration and error found so far. Return the calculated error.
+ */
+static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq,
+                              const intel_clock_t *calculated_clock,
+                              const intel_clock_t *best_clock,
+                              unsigned int best_error_ppm,
+                              unsigned int *error_ppm)
+{
+       /*
+        * For CHV ignore the error and consider only the P value.
+        * Prefer a bigger P value based on HW requirements.
+        */
+       if (IS_CHERRYVIEW(dev)) {
+               *error_ppm = 0;
+
+               return calculated_clock->p > best_clock->p;
+       }
+
+       if (WARN_ON_ONCE(!target_freq))
+               return false;
+
+       *error_ppm = div_u64(1000000ULL *
+                               abs(target_freq - calculated_clock->dot),
+                            target_freq);
+       /*
+        * Prefer a better P value over a better (smaller) error if the error
+        * is small. Ensure this preference for future configurations too by
+        * setting the error to 0.
+        */
+       if (*error_ppm < 100 && calculated_clock->p > best_clock->p) {
+               *error_ppm = 0;
+
+               return true;
+       }
+
+       return *error_ppm + 10 < best_error_ppm;
+}
+
 static bool
 vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
                   int target, int refclk, intel_clock_t *match_clock,
@@ -799,7 +841,7 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
                                clock.p = clock.p1 * clock.p2;
                                /* based on hardware requirement, prefer bigger m1,m2 values */
                                for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
-                                       unsigned int ppm, diff;
+                                       unsigned int ppm;
 
                                        clock.m2 = DIV_ROUND_CLOSEST(target * clock.p * clock.n,
                                                                     refclk * clock.m1);
@@ -810,20 +852,15 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
                                                                &clock))
                                                continue;
 
-                                       diff = abs(clock.dot - target);
-                                       ppm = div_u64(1000000ULL * diff, target);
-
-                                       if (ppm < 100 && clock.p > best_clock->p) {
-                                               bestppm = 0;
-                                               *best_clock = clock;
-                                               found = true;
-                                       }
+                                       if (!vlv_PLL_is_optimal(dev, target,
+                                                               &clock,
+                                                               best_clock,
+                                                               bestppm, &ppm))
+                                               continue;
 
-                                       if (bestppm >= 10 && ppm < bestppm - 10) {
-                                               bestppm = ppm;
-                                               *best_clock = clock;
-                                               found = true;
-                                       }
+                                       *best_clock = clock;
+                                       bestppm = ppm;
+                                       found = true;
                                }
                        }
                }
@@ -838,11 +875,13 @@ chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
                   intel_clock_t *best_clock)
 {
        struct drm_device *dev = crtc->base.dev;
+       unsigned int best_error_ppm;
        intel_clock_t clock;
        uint64_t m2;
        int found = false;
 
        memset(best_clock, 0, sizeof(*best_clock));
+       best_error_ppm = 1000000;
 
        /*
         * Based on hardware doc, the n always set to 1, and m1 always
@@ -856,6 +895,7 @@ chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
                for (clock.p2 = limit->p2.p2_fast;
                                clock.p2 >= limit->p2.p2_slow;
                                clock.p2 -= clock.p2 > 10 ? 2 : 1) {
+                       unsigned int error_ppm;
 
                        clock.p = clock.p1 * clock.p2;
 
@@ -872,12 +912,13 @@ chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc *crtc,
                        if (!intel_PLL_is_valid(dev, limit, &clock))
                                continue;
 
-                       /* based on hardware requirement, prefer bigger p
-                        */
-                       if (clock.p > best_clock->p) {
-                               *best_clock = clock;
-                               found = true;
-                       }
+                       if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock,
+                                               best_error_ppm, &error_ppm))
+                               continue;
+
+                       *best_clock = clock;
+                       best_error_ppm = error_ppm;
+                       found = true;
                }
        }
 
@@ -896,8 +937,12 @@ bool intel_crtc_active(struct drm_crtc *crtc)
         *
         * We can ditch the crtc->primary->fb check as soon as we can
         * properly reconstruct framebuffers.
+        *
+        * FIXME: The intel_crtc->active here should be switched to
+        * crtc->state->active once we have proper CRTC states wired up
+        * for atomic.
         */
-       return intel_crtc->active && crtc->primary->fb &&
+       return intel_crtc->active && crtc->primary->state->fb &&
                intel_crtc->config->base.adjusted_mode.crtc_clock;
 }
 
@@ -1300,14 +1345,14 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
        u32 val;
 
        if (INTEL_INFO(dev)->gen >= 9) {
-               for_each_sprite(pipe, sprite) {
+               for_each_sprite(dev_priv, pipe, sprite) {
                        val = I915_READ(PLANE_CTL(pipe, sprite));
                        I915_STATE_WARN(val & PLANE_CTL_ENABLE,
                             "plane %d assertion failure, should be off on pipe %c but is still active\n",
                             sprite, pipe_name(pipe));
                }
        } else if (IS_VALLEYVIEW(dev)) {
-               for_each_sprite(pipe, sprite) {
+               for_each_sprite(dev_priv, pipe, sprite) {
                        reg = SPCNTR(pipe, sprite);
                        val = I915_READ(reg);
                        I915_STATE_WARN(val & SP_ENABLE,
@@ -2189,30 +2234,111 @@ static bool need_vtd_wa(struct drm_device *dev)
        return false;
 }
 
-int
-intel_fb_align_height(struct drm_device *dev, int height, unsigned int tiling)
+unsigned int
+intel_tile_height(struct drm_device *dev, uint32_t pixel_format,
+                 uint64_t fb_format_modifier)
 {
-       int tile_height;
+       unsigned int tile_height;
+       uint32_t pixel_bytes;
+
+       switch (fb_format_modifier) {
+       case DRM_FORMAT_MOD_NONE:
+               tile_height = 1;
+               break;
+       case I915_FORMAT_MOD_X_TILED:
+               tile_height = IS_GEN2(dev) ? 16 : 8;
+               break;
+       case I915_FORMAT_MOD_Y_TILED:
+               tile_height = 32;
+               break;
+       case I915_FORMAT_MOD_Yf_TILED:
+               pixel_bytes = drm_format_plane_cpp(pixel_format, 0);
+               switch (pixel_bytes) {
+               default:
+               case 1:
+                       tile_height = 64;
+                       break;
+               case 2:
+               case 4:
+                       tile_height = 32;
+                       break;
+               case 8:
+                       tile_height = 16;
+                       break;
+               case 16:
+                       WARN_ONCE(1,
+                                 "128-bit pixels are not supported for display!");
+                       tile_height = 16;
+                       break;
+               }
+               break;
+       default:
+               MISSING_CASE(fb_format_modifier);
+               tile_height = 1;
+               break;
+       }
+
+       return tile_height;
+}
+
+unsigned int
+intel_fb_align_height(struct drm_device *dev, unsigned int height,
+                     uint32_t pixel_format, uint64_t fb_format_modifier)
+{
+       return ALIGN(height, intel_tile_height(dev, pixel_format,
+                                              fb_format_modifier));
+}
+
+static int
+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;
+       static const struct i915_ggtt_view rotated_view =
+                               { .type = I915_GGTT_VIEW_ROTATED };
+
+       *view = i915_ggtt_view_normal;
+
+       if (!plane_state)
+               return 0;
+
+       if (!intel_rotation_90_or_270(plane_state->rotation))
+               return 0;
+
+       *view = rotated_view;
+
+       info->height = fb->height;
+       info->pixel_format = fb->pixel_format;
+       info->pitch = fb->pitches[0];
+       info->fb_modifier = fb->modifier[0];
 
-       tile_height = tiling ? (IS_GEN2(dev) ? 16 : 8) : 1;
-       return ALIGN(height, tile_height);
+       if (!(info->fb_modifier == I915_FORMAT_MOD_Y_TILED ||
+             info->fb_modifier == I915_FORMAT_MOD_Yf_TILED)) {
+               DRM_DEBUG_KMS(
+                             "Y or Yf tiling is needed for 90/270 rotation!\n");
+               return -EINVAL;
+       }
+
+       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_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       struct i915_ggtt_view view;
        u32 alignment;
        int ret;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-       switch (obj->tiling_mode) {
-       case I915_TILING_NONE:
+       switch (fb->modifier[0]) {
+       case DRM_FORMAT_MOD_NONE:
                if (INTEL_INFO(dev)->gen >= 9)
                        alignment = 256 * 1024;
                else if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
@@ -2222,7 +2348,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                else
                        alignment = 64 * 1024;
                break;
-       case I915_TILING_X:
+       case I915_FORMAT_MOD_X_TILED:
                if (INTEL_INFO(dev)->gen >= 9)
                        alignment = 256 * 1024;
                else {
@@ -2230,13 +2356,22 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
                        alignment = 0;
                }
                break;
-       case I915_TILING_Y:
-               WARN(1, "Y tiled bo slipped through, driver bug!\n");
-               return -EINVAL;
+       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:
-               BUG();
+               MISSING_CASE(fb->modifier[0]);
+               return -EINVAL;
        }
 
+       ret = intel_fill_fb_ggtt_view(&view, fb, plane_state);
+       if (ret)
+               return ret;
+
        /* 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
         * we should always have valid PTE following the scanout preventing
@@ -2255,7 +2390,8 @@ 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);
+       ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined,
+                                                  &view);
        if (ret)
                goto err_interruptible;
 
@@ -2275,19 +2411,27 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,
        return 0;
 
 err_unpin:
-       i915_gem_object_unpin_from_display_plane(obj);
+       i915_gem_object_unpin_from_display_plane(obj, &view);
 err_interruptible:
        dev_priv->mm.interruptible = true;
        intel_runtime_pm_put(dev_priv);
        return ret;
 }
 
-void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)
+static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
+                              const struct drm_plane_state *plane_state)
 {
+       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!");
+
        i915_gem_object_unpin_fence(obj);
-       i915_gem_object_unpin_from_display_plane(obj);
+       i915_gem_object_unpin_from_display_plane(obj, &view);
 }
 
 /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
@@ -2365,12 +2509,13 @@ static int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
 }
 
 static bool
-intel_alloc_plane_obj(struct intel_crtc *crtc,
-                     struct intel_initial_plane_config *plane_config)
+intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
+                             struct intel_initial_plane_config *plane_config)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_gem_object *obj = NULL;
        struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+       struct drm_framebuffer *fb = &plane_config->fb->base;
        u32 base_aligned = round_down(plane_config->base, PAGE_SIZE);
        u32 size_aligned = round_up(plane_config->base + plane_config->size,
                                    PAGE_SIZE);
@@ -2389,25 +2534,24 @@ intel_alloc_plane_obj(struct intel_crtc *crtc,
 
        obj->tiling_mode = plane_config->tiling;
        if (obj->tiling_mode == I915_TILING_X)
-               obj->stride = crtc->base.primary->fb->pitches[0];
+               obj->stride = fb->pitches[0];
 
-       mode_cmd.pixel_format = crtc->base.primary->fb->pixel_format;
-       mode_cmd.width = crtc->base.primary->fb->width;
-       mode_cmd.height = crtc->base.primary->fb->height;
-       mode_cmd.pitches[0] = crtc->base.primary->fb->pitches[0];
+       mode_cmd.pixel_format = fb->pixel_format;
+       mode_cmd.width = fb->width;
+       mode_cmd.height = fb->height;
+       mode_cmd.pitches[0] = fb->pitches[0];
+       mode_cmd.modifier[0] = fb->modifier[0];
+       mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
 
        mutex_lock(&dev->struct_mutex);
-
-       if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.primary->fb),
+       if (intel_framebuffer_init(dev, to_intel_framebuffer(fb),
                                   &mode_cmd, obj)) {
                DRM_DEBUG_KMS("intel fb init failed\n");
                goto out_unref_obj;
        }
-
-       obj->frontbuffer_bits = INTEL_FRONTBUFFER_PRIMARY(crtc->pipe);
        mutex_unlock(&dev->struct_mutex);
 
-       DRM_DEBUG_KMS("plane fb obj %p\n", obj);
+       DRM_DEBUG_KMS("initial plane fb obj %p\n", obj);
        return true;
 
 out_unref_obj:
@@ -2416,24 +2560,41 @@ out_unref_obj:
        return false;
 }
 
+/* Update plane->state->fb to match plane->fb after driver-internal updates */
 static void
-intel_find_plane_obj(struct intel_crtc *intel_crtc,
-                    struct intel_initial_plane_config *plane_config)
+update_state_fb(struct drm_plane *plane)
+{
+       if (plane->fb == plane->state->fb)
+               return;
+
+       if (plane->state->fb)
+               drm_framebuffer_unreference(plane->state->fb);
+       plane->state->fb = plane->fb;
+       if (plane->state->fb)
+               drm_framebuffer_reference(plane->state->fb);
+}
+
+static void
+intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
+                            struct intel_initial_plane_config *plane_config)
 {
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *c;
        struct intel_crtc *i;
        struct drm_i915_gem_object *obj;
+       struct drm_plane *primary = intel_crtc->base.primary;
+       struct drm_framebuffer *fb;
 
-       if (!intel_crtc->base.primary->fb)
+       if (!plane_config->fb)
                return;
 
-       if (intel_alloc_plane_obj(intel_crtc, plane_config))
-               return;
+       if (intel_alloc_initial_plane_obj(intel_crtc, plane_config)) {
+               fb = &plane_config->fb->base;
+               goto valid_fb;
+       }
 
-       kfree(intel_crtc->base.primary->fb);
-       intel_crtc->base.primary->fb = NULL;
+       kfree(plane_config->fb);
 
        /*
         * Failed to alloc the obj, check to see if we should share
@@ -2448,20 +2609,29 @@ intel_find_plane_obj(struct intel_crtc *intel_crtc,
                if (!i->active)
                        continue;
 
-               obj = intel_fb_obj(c->primary->fb);
-               if (obj == NULL)
+               fb = c->primary->fb;
+               if (!fb)
                        continue;
 
+               obj = intel_fb_obj(fb);
                if (i915_gem_obj_ggtt_offset(obj) == plane_config->base) {
-                       if (obj->tiling_mode != I915_TILING_NONE)
-                               dev_priv->preserve_bios_swizzle = true;
-
-                       drm_framebuffer_reference(c->primary->fb);
-                       intel_crtc->base.primary->fb = c->primary->fb;
-                       obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
-                       break;
+                       drm_framebuffer_reference(fb);
+                       goto valid_fb;
                }
        }
+
+       return;
+
+valid_fb:
+       obj = intel_fb_obj(fb);
+       if (obj->tiling_mode != I915_TILING_NONE)
+               dev_priv->preserve_bios_swizzle = true;
+
+       primary->fb = fb;
+       primary->state->crtc = &intel_crtc->base;
+       primary->crtc = &intel_crtc->base;
+       update_state_fb(primary);
+       obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
 }
 
 static void i9xx_update_primary_plane(struct drm_crtc *crtc,
@@ -2582,9 +2752,6 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,
 
        I915_WRITE(reg, dspcntr);
 
-       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
-                     i915_gem_obj_ggtt_offset(obj), linear_offset, x, y,
-                     fb->pitches[0]);
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        if (INTEL_INFO(dev)->gen >= 4) {
                I915_WRITE(DSPSURF(plane),
@@ -2686,9 +2853,6 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
 
        I915_WRITE(reg, dspcntr);
 
-       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
-                     i915_gem_obj_ggtt_offset(obj), linear_offset, x, y,
-                     fb->pitches[0]);
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        I915_WRITE(DSPSURF(plane),
                   i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
@@ -2701,6 +2865,51 @@ 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 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);
+               return 64;
+       }
+}
+
+unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
+                                    struct drm_i915_gem_object *obj)
+{
+       enum i915_ggtt_view_type view = I915_GGTT_VIEW_NORMAL;
+
+       if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
+               view = I915_GGTT_VIEW_ROTATED;
+
+       return i915_gem_obj_ggtt_offset_view(obj, view);
+}
+
 static void skylake_update_primary_plane(struct drm_crtc *crtc,
                                         struct drm_framebuffer *fb,
                                         int x, int y)
@@ -2708,10 +2917,10 @@ static void skylake_update_primary_plane(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 intel_framebuffer *intel_fb;
        struct drm_i915_gem_object *obj;
        int pipe = intel_crtc->pipe;
-       u32 plane_ctl, stride;
+       u32 plane_ctl, stride_div;
+       unsigned long surf_addr;
 
        if (!intel_crtc->primary_enabled) {
                I915_WRITE(PLANE_CTL(pipe, 0), 0);
@@ -2755,43 +2964,39 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
                BUG();
        }
 
-       intel_fb = to_intel_framebuffer(fb);
-       obj = intel_fb->obj;
-
-       /*
-        * The stride is either expressed as a multiple of 64 bytes chunks for
-        * linear buffers or in number of tiles for tiled buffers.
-        */
-       switch (obj->tiling_mode) {
-       case I915_TILING_NONE:
-               stride = fb->pitches[0] >> 6;
+       switch (fb->modifier[0]) {
+       case DRM_FORMAT_MOD_NONE:
                break;
-       case I915_TILING_X:
+       case I915_FORMAT_MOD_X_TILED:
                plane_ctl |= PLANE_CTL_TILED_X;
-               stride = fb->pitches[0] >> 9;
+               break;
+       case I915_FORMAT_MOD_Y_TILED:
+               plane_ctl |= PLANE_CTL_TILED_Y;
+               break;
+       case I915_FORMAT_MOD_Yf_TILED:
+               plane_ctl |= PLANE_CTL_TILED_YF;
                break;
        default:
-               BUG();
+               MISSING_CASE(fb->modifier[0]);
        }
 
        plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
        if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180))
                plane_ctl |= PLANE_CTL_ROTATE_180;
 
-       I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
-
-       DRM_DEBUG_KMS("Writing base %08lX %d,%d,%d,%d pitch=%d\n",
-                     i915_gem_obj_ggtt_offset(obj),
-                     x, y, fb->width, fb->height,
-                     fb->pitches[0]);
+       obj = intel_fb_obj(fb);
+       stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
+                                              fb->pixel_format);
+       surf_addr = intel_plane_obj_offset(to_intel_plane(crtc->primary), obj);
 
+       I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
        I915_WRITE(PLANE_POS(pipe, 0), 0);
        I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
        I915_WRITE(PLANE_SIZE(pipe, 0),
                   (intel_crtc->config->pipe_src_h - 1) << 16 |
                   (intel_crtc->config->pipe_src_w - 1));
-       I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
-       I915_WRITE(PLANE_SURF(pipe, 0), i915_gem_obj_ggtt_offset(obj));
+       I915_WRITE(PLANE_STRIDE(pipe, 0), fb->pitches[0] / stride_div);
+       I915_WRITE(PLANE_SURF(pipe, 0), surf_addr);
 
        POSTING_READ(PLANE_SURF(pipe, 0));
 }
@@ -3042,38 +3247,6 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
                           FDI_FE_ERRC_ENABLE);
 }
 
-static bool pipe_has_enabled_pch(struct intel_crtc *crtc)
-{
-       return crtc->base.enabled && crtc->active &&
-               crtc->config->has_pch_encoder;
-}
-
-static void ivb_modeset_global_resources(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *pipe_B_crtc =
-               to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
-       struct intel_crtc *pipe_C_crtc =
-               to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_C]);
-       uint32_t temp;
-
-       /*
-        * When everything is off disable fdi C so that we could enable fdi B
-        * with all lanes. Note that we don't care about enabled pipes without
-        * an enabled pch encoder.
-        */
-       if (!pipe_has_enabled_pch(pipe_B_crtc) &&
-           !pipe_has_enabled_pch(pipe_C_crtc)) {
-               WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
-               WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
-
-               temp = I915_READ(SOUTH_CHICKEN1);
-               temp &= ~FDI_BC_BIFURCATION_SELECT;
-               DRM_DEBUG_KMS("disabling fdi C rx\n");
-               I915_WRITE(SOUTH_CHICKEN1, temp);
-       }
-}
-
 /* The FDI link training functions for ILK/Ibexpeak. */
 static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 {
@@ -3729,20 +3902,23 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
                   I915_READ(VSYNCSHIFT(cpu_transcoder)));
 }
 
-static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
+static void cpt_set_fdi_bc_bifurcation(struct drm_device *dev, bool enable)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t temp;
 
        temp = I915_READ(SOUTH_CHICKEN1);
-       if (temp & FDI_BC_BIFURCATION_SELECT)
+       if (!!(temp & FDI_BC_BIFURCATION_SELECT) == enable)
                return;
 
        WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
        WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
 
-       temp |= FDI_BC_BIFURCATION_SELECT;
-       DRM_DEBUG_KMS("enabling fdi C rx\n");
+       temp &= ~FDI_BC_BIFURCATION_SELECT;
+       if (enable)
+               temp |= FDI_BC_BIFURCATION_SELECT;
+
+       DRM_DEBUG_KMS("%sabling fdi C rx\n", enable ? "en" : "dis");
        I915_WRITE(SOUTH_CHICKEN1, temp);
        POSTING_READ(SOUTH_CHICKEN1);
 }
@@ -3750,20 +3926,19 @@ static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
 static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
 {
        struct drm_device *dev = intel_crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
 
        switch (intel_crtc->pipe) {
        case PIPE_A:
                break;
        case PIPE_B:
                if (intel_crtc->config->fdi_lanes > 2)
-                       WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
+                       cpt_set_fdi_bc_bifurcation(dev, false);
                else
-                       cpt_enable_fdi_bc_bifurcation(dev);
+                       cpt_set_fdi_bc_bifurcation(dev, true);
 
                break;
        case PIPE_C:
-               cpt_enable_fdi_bc_bifurcation(dev);
+               cpt_set_fdi_bc_bifurcation(dev, true);
 
                break;
        default:
@@ -4098,6 +4273,24 @@ static void intel_enable_sprite_planes(struct drm_crtc *crtc)
        }
 }
 
+/*
+ * Disable a plane internally without actually modifying the plane's state.
+ * This will allow us to easily restore the plane later by just reprogramming
+ * its state.
+ */
+static void disable_plane_internal(struct drm_plane *plane)
+{
+       struct intel_plane *intel_plane = to_intel_plane(plane);
+       struct drm_plane_state *state =
+               plane->funcs->atomic_duplicate_state(plane);
+       struct intel_plane_state *intel_state = to_intel_plane_state(state);
+
+       intel_state->visible = false;
+       intel_plane->commit_plane(plane, intel_state);
+
+       intel_plane_destroy_state(plane, state);
+}
+
 static void intel_disable_sprite_planes(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -4107,8 +4300,8 @@ static void intel_disable_sprite_planes(struct drm_crtc *crtc)
 
        drm_for_each_legacy_plane(plane, &dev->mode_config.plane_list) {
                intel_plane = to_intel_plane(plane);
-               if (intel_plane->pipe == pipe)
-                       plane->funcs->disable_plane(plane);
+               if (plane->fb && intel_plane->pipe == pipe)
+                       disable_plane_internal(plane);
        }
 }
 
@@ -4182,7 +4375,7 @@ static void intel_crtc_load_lut(struct drm_crtc *crtc)
        bool reenable_ips = false;
 
        /* The clocks have to be on to load the palette. */
-       if (!crtc->enabled || !intel_crtc->active)
+       if (!crtc->state->enable || !intel_crtc->active)
                return;
 
        if (!HAS_PCH_SPLIT(dev_priv->dev)) {
@@ -4266,11 +4459,10 @@ static void intel_crtc_disable_planes(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;
-       int plane = intel_crtc->plane;
 
        intel_crtc_wait_for_pending_flips(crtc);
 
-       if (dev_priv->fbc.plane == plane)
+       if (dev_priv->fbc.crtc == intel_crtc)
                intel_fbc_disable(dev);
 
        hsw_disable_ips(intel_crtc);
@@ -4296,7 +4488,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
 
-       WARN_ON(!crtc->enabled);
+       WARN_ON(!crtc->state->enable);
 
        if (intel_crtc->active)
                return;
@@ -4305,7 +4497,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
                intel_prepare_shared_dpll(intel_crtc);
 
        if (intel_crtc->config->has_dp_encoder)
-               intel_dp_set_m_n(intel_crtc);
+               intel_dp_set_m_n(intel_crtc, M1_N1);
 
        intel_set_pipe_timings(intel_crtc);
 
@@ -4404,7 +4596,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
 
-       WARN_ON(!crtc->enabled);
+       WARN_ON(!crtc->state->enable);
 
        if (intel_crtc->active)
                return;
@@ -4413,7 +4605,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
                intel_enable_shared_dpll(intel_crtc);
 
        if (intel_crtc->config->has_dp_encoder)
-               intel_dp_set_m_n(intel_crtc);
+               intel_dp_set_m_n(intel_crtc, M1_N1);
 
        intel_set_pipe_timings(intel_crtc);
 
@@ -4751,7 +4943,7 @@ static void modeset_update_crtc_power_domains(struct drm_device *dev)
        for_each_intel_crtc(dev, crtc) {
                enum intel_display_power_domain domain;
 
-               if (!crtc->base.enabled)
+               if (!crtc->base.state->enable)
                        continue;
 
                pipe_domains[crtc->pipe] = get_crtc_power_domains(&crtc->base);
@@ -4878,24 +5070,23 @@ static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
        WARN_ON(dev_priv->display.get_display_clock_speed(dev) != dev_priv->vlv_cdclk_freq);
 
        switch (cdclk) {
-       case 400000:
-               cmd = 3;
-               break;
        case 333333:
        case 320000:
-               cmd = 2;
-               break;
        case 266667:
-               cmd = 1;
-               break;
        case 200000:
-               cmd = 0;
                break;
        default:
                MISSING_CASE(cdclk);
                return;
        }
 
+       /*
+        * Specs are full of misinformation, but testing on actual
+        * hardware has shown that we just need to write the desired
+        * CCK divider into the Punit register.
+        */
+       cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
+
        mutex_lock(&dev_priv->rps.hw_lock);
        val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
        val &= ~DSPFREQGUAR_MASK_CHV;
@@ -4915,27 +5106,25 @@ static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
                                 int max_pixclk)
 {
        int freq_320 = (dev_priv->hpll_freq <<  1) % 320000 != 0 ? 333333 : 320000;
-
-       /* FIXME: Punit isn't quite ready yet */
-       if (IS_CHERRYVIEW(dev_priv->dev))
-               return 400000;
+       int limit = IS_CHERRYVIEW(dev_priv) ? 95 : 90;
 
        /*
         * Really only a few cases to deal with, as only 4 CDclks are supported:
         *   200MHz
         *   267MHz
         *   320/333MHz (depends on HPLL freq)
-        *   400MHz
-        * So we check to see whether we're above 90% of the lower bin and
-        * adjust if needed.
+        *   400MHz (VLV only)
+        * So we check to see whether we're above 90% (VLV) or 95% (CHV)
+        * of the lower bin and adjust if needed.
         *
         * We seem to get an unstable or solid color picture at 200MHz.
         * Not sure what's wrong. For now use 200MHz only when all pipes
         * are off.
         */
-       if (max_pixclk > freq_320*9/10)
+       if (!IS_CHERRYVIEW(dev_priv) &&
+           max_pixclk > freq_320*limit/100)
                return 400000;
-       else if (max_pixclk > 266667*9/10)
+       else if (max_pixclk > 266667*limit/100)
                return freq_320;
        else if (max_pixclk > 0)
                return 266667;
@@ -4972,10 +5161,46 @@ static void valleyview_modeset_global_pipes(struct drm_device *dev,
 
        /* disable/enable all currently active pipes while we change cdclk */
        for_each_intel_crtc(dev, intel_crtc)
-               if (intel_crtc->base.enabled)
+               if (intel_crtc->base.state->enable)
                        *prepare_pipes |= (1 << intel_crtc->pipe);
 }
 
+static void vlv_program_pfi_credits(struct drm_i915_private *dev_priv)
+{
+       unsigned int credits, default_credits;
+
+       if (IS_CHERRYVIEW(dev_priv))
+               default_credits = PFI_CREDIT(12);
+       else
+               default_credits = PFI_CREDIT(8);
+
+       if (DIV_ROUND_CLOSEST(dev_priv->vlv_cdclk_freq, 1000) >= dev_priv->rps.cz_freq) {
+               /* CHV suggested value is 31 or 63 */
+               if (IS_CHERRYVIEW(dev_priv))
+                       credits = PFI_CREDIT_31;
+               else
+                       credits = PFI_CREDIT(15);
+       } else {
+               credits = default_credits;
+       }
+
+       /*
+        * WA - write default credits before re-programming
+        * FIXME: should we also set the resend bit here?
+        */
+       I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
+                  default_credits);
+
+       I915_WRITE(GCI_CONTROL, VGA_FAST_MODE_DISABLE |
+                  credits | PFI_CREDIT_RESEND);
+
+       /*
+        * FIXME is this guaranteed to clear
+        * immediately or should we poll for it?
+        */
+       WARN_ON(I915_READ(GCI_CONTROL) & PFI_CREDIT_RESEND);
+}
+
 static void valleyview_modeset_global_resources(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4999,6 +5224,8 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
                else
                        valleyview_set_cdclk(dev, req_cdclk);
 
+               vlv_program_pfi_credits(dev_priv);
+
                intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
        }
 }
@@ -5012,7 +5239,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
        int pipe = intel_crtc->pipe;
        bool is_dsi;
 
-       WARN_ON(!crtc->enabled);
+       WARN_ON(!crtc->state->enable);
 
        if (intel_crtc->active)
                return;
@@ -5027,7 +5254,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
        }
 
        if (intel_crtc->config->has_dp_encoder)
-               intel_dp_set_m_n(intel_crtc);
+               intel_dp_set_m_n(intel_crtc, M1_N1);
 
        intel_set_pipe_timings(intel_crtc);
 
@@ -5095,7 +5322,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
 
-       WARN_ON(!crtc->enabled);
+       WARN_ON(!crtc->state->enable);
 
        if (intel_crtc->active)
                return;
@@ -5103,7 +5330,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
        i9xx_set_pll_dividers(intel_crtc);
 
        if (intel_crtc->config->has_dp_encoder)
-               intel_dp_set_m_n(intel_crtc);
+               intel_dp_set_m_n(intel_crtc, M1_N1);
 
        intel_set_pipe_timings(intel_crtc);
 
@@ -5294,7 +5521,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        /* crtc should still be enabled when we disable it. */
-       WARN_ON(!crtc->enabled);
+       WARN_ON(!crtc->state->enable);
 
        dev_priv->display.crtc_disable(crtc);
        dev_priv->display.off(crtc);
@@ -5372,7 +5599,8 @@ static void intel_connector_check_state(struct intel_connector *connector)
 
                        crtc = encoder->base.crtc;
 
-                       I915_STATE_WARN(!crtc->enabled, "crtc not enabled\n");
+                       I915_STATE_WARN(!crtc->state->enable,
+                                       "crtc not enabled\n");
                        I915_STATE_WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
                        I915_STATE_WARN(pipe != to_intel_crtc(crtc)->pipe,
                             "encoder active on the wrong pipe\n");
@@ -5411,13 +5639,21 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
        return encoder->get_hw_state(encoder, &pipe);
 }
 
+static int pipe_required_fdi_lanes(struct drm_device *dev, enum pipe pipe)
+{
+       struct intel_crtc *crtc =
+               to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+
+       if (crtc->base.state->enable &&
+           crtc->config->has_pch_encoder)
+               return crtc->config->fdi_lanes;
+
+       return 0;
+}
+
 static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
                                     struct intel_crtc_state *pipe_config)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *pipe_B_crtc =
-               to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_B]);
-
        DRM_DEBUG_KMS("checking fdi config on pipe %c, lanes %i\n",
                      pipe_name(pipe), pipe_config->fdi_lanes);
        if (pipe_config->fdi_lanes > 4) {
@@ -5444,22 +5680,20 @@ static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
        case PIPE_A:
                return true;
        case PIPE_B:
-               if (dev_priv->pipe_to_crtc_mapping[PIPE_C]->enabled &&
-                   pipe_config->fdi_lanes > 2) {
+               if (pipe_config->fdi_lanes > 2 &&
+                   pipe_required_fdi_lanes(dev, PIPE_C) > 0) {
                        DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
                                      pipe_name(pipe), pipe_config->fdi_lanes);
                        return false;
                }
                return true;
        case PIPE_C:
-               if (!pipe_has_enabled_pch(pipe_B_crtc) ||
-                   pipe_B_crtc->config->fdi_lanes <= 2) {
-                       if (pipe_config->fdi_lanes > 2) {
-                               DRM_DEBUG_KMS("invalid shared fdi lane config on pipe %c: %i lanes\n",
-                                             pipe_name(pipe), pipe_config->fdi_lanes);
-                               return false;
-                       }
-               } else {
+               if (pipe_config->fdi_lanes > 2) {
+                       DRM_DEBUG_KMS("only 2 lanes on pipe %c: required %i lanes\n",
+                                     pipe_name(pipe), pipe_config->fdi_lanes);
+                       return false;
+               }
+               if (pipe_required_fdi_lanes(dev, PIPE_B) > 2) {
                        DRM_DEBUG_KMS("fdi link B uses too many lanes to enable link C\n");
                        return false;
                }
@@ -5559,7 +5793,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
         * - LVDS dual channel mode
         * - Double wide pipe
         */
-       if ((intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+       if ((intel_pipe_will_have_type(crtc, INTEL_OUTPUT_LVDS) &&
             intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
                pipe_config->pipe_src_w &= ~1;
 
@@ -5593,10 +5827,6 @@ static int valleyview_get_display_clock_speed(struct drm_device *dev)
        u32 val;
        int divider;
 
-       /* FIXME: Punit isn't quite ready yet */
-       if (IS_CHERRYVIEW(dev))
-               return 400000;
-
        if (dev_priv->hpll_freq == 0)
                dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
 
@@ -5794,7 +6024,7 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
 
        crtc->lowfreq_avail = false;
        if (intel_pipe_will_have_type(crtc, INTEL_OUTPUT_LVDS) &&
-           reduced_clock && i915.powersave) {
+           reduced_clock) {
                crtc_state->dpll_hw_state.fp1 = fp2;
                crtc->lowfreq_avail = true;
        } else {
@@ -5862,7 +6092,7 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
                 * for gen < 8) and if DRRS is supported (to make sure the
                 * registers are not unnecessarily accessed).
                 */
-               if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
+               if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) &&
                        crtc->config->has_drrs) {
                        I915_WRITE(PIPE_DATA_M2(transcoder),
                                        TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
@@ -5878,13 +6108,29 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
        }
 }
 
-void intel_dp_set_m_n(struct intel_crtc *crtc)
+void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n)
 {
+       struct intel_link_m_n *dp_m_n, *dp_m2_n2 = NULL;
+
+       if (m_n == M1_N1) {
+               dp_m_n = &crtc->config->dp_m_n;
+               dp_m2_n2 = &crtc->config->dp_m2_n2;
+       } else if (m_n == M2_N2) {
+
+               /*
+                * M2_N2 registers are not supported. Hence m2_n2 divider value
+                * needs to be programmed into M1_N1.
+                */
+               dp_m_n = &crtc->config->dp_m2_n2;
+       } else {
+               DRM_ERROR("Unsupported divider value\n");
+               return;
+       }
+
        if (crtc->config->has_pch_encoder)
                intel_pch_transcoder_set_m_n(crtc, &crtc->config->dp_m_n);
        else
-               intel_cpu_transcoder_set_m_n(crtc, &crtc->config->dp_m_n,
-                                                  &crtc->config->dp_m2_n2);
+               intel_cpu_transcoder_set_m_n(crtc, dp_m_n, dp_m2_n2);
 }
 
 static void vlv_update_pll(struct intel_crtc *crtc,
@@ -6022,9 +6268,10 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
        int pipe = crtc->pipe;
        int dpll_reg = DPLL(crtc->pipe);
        enum dpio_channel port = vlv_pipe_to_channel(pipe);
-       u32 loopfilter, intcoeff;
+       u32 loopfilter, tribuf_calcntr;
        u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
-       int refclk;
+       u32 dpio_val;
+       int vco;
 
        bestn = pipe_config->dpll.n;
        bestm2_frac = pipe_config->dpll.m2 & 0x3fffff;
@@ -6032,6 +6279,9 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
        bestm2 = pipe_config->dpll.m2 >> 22;
        bestp1 = pipe_config->dpll.p1;
        bestp2 = pipe_config->dpll.p2;
+       vco = pipe_config->dpll.vco;
+       dpio_val = 0;
+       loopfilter = 0;
 
        /*
         * Enable Refclk and SSC
@@ -6057,26 +6307,56 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
                        1 << DPIO_CHV_N_DIV_SHIFT);
 
        /* M2 fraction division */
-       vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
+       if (bestm2_frac)
+               vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
 
        /* M2 fraction division enable */
-       vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port),
-                      DPIO_CHV_FRAC_DIV_EN |
-                      (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT));
+       dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
+       dpio_val &= ~(DPIO_CHV_FEEDFWD_GAIN_MASK | DPIO_CHV_FRAC_DIV_EN);
+       dpio_val |= (2 << DPIO_CHV_FEEDFWD_GAIN_SHIFT);
+       if (bestm2_frac)
+               dpio_val |= DPIO_CHV_FRAC_DIV_EN;
+       vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW3(port), dpio_val);
+
+       /* Program digital lock detect threshold */
+       dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW9(port));
+       dpio_val &= ~(DPIO_CHV_INT_LOCK_THRESHOLD_MASK |
+                                       DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE);
+       dpio_val |= (0x5 << DPIO_CHV_INT_LOCK_THRESHOLD_SHIFT);
+       if (!bestm2_frac)
+               dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
+       vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW9(port), dpio_val);
 
        /* Loop filter */
-       refclk = i9xx_get_refclk(crtc, 0);
-       loopfilter = 5 << DPIO_CHV_PROP_COEFF_SHIFT |
-               2 << DPIO_CHV_GAIN_CTRL_SHIFT;
-       if (refclk == 100000)
-               intcoeff = 11;
-       else if (refclk == 38400)
-               intcoeff = 10;
-       else
-               intcoeff = 9;
-       loopfilter |= intcoeff << DPIO_CHV_INT_COEFF_SHIFT;
+       if (vco == 5400000) {
+               loopfilter |= (0x3 << DPIO_CHV_PROP_COEFF_SHIFT);
+               loopfilter |= (0x8 << DPIO_CHV_INT_COEFF_SHIFT);
+               loopfilter |= (0x1 << DPIO_CHV_GAIN_CTRL_SHIFT);
+               tribuf_calcntr = 0x9;
+       } else if (vco <= 6200000) {
+               loopfilter |= (0x5 << DPIO_CHV_PROP_COEFF_SHIFT);
+               loopfilter |= (0xB << DPIO_CHV_INT_COEFF_SHIFT);
+               loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
+               tribuf_calcntr = 0x9;
+       } else if (vco <= 6480000) {
+               loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
+               loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
+               loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
+               tribuf_calcntr = 0x8;
+       } else {
+               /* Not supported. Apply the same limits as in the max case */
+               loopfilter |= (0x4 << DPIO_CHV_PROP_COEFF_SHIFT);
+               loopfilter |= (0x9 << DPIO_CHV_INT_COEFF_SHIFT);
+               loopfilter |= (0x3 << DPIO_CHV_GAIN_CTRL_SHIFT);
+               tribuf_calcntr = 0;
+       }
        vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW6(port), loopfilter);
 
+       dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW8(port));
+       dpio_val &= ~DPIO_CHV_TDC_TARGET_CNT_MASK;
+       dpio_val |= (tribuf_calcntr << DPIO_CHV_TDC_TARGET_CNT_SHIFT);
+       vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW8(port), dpio_val);
+
        /* AFC Recal */
        vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port),
                        vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) |
@@ -6598,10 +6878,14 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
        u32 val, base, offset;
        int pipe = crtc->pipe, plane = crtc->plane;
        int fourcc, pixel_format;
-       int aligned_height;
+       unsigned int aligned_height;
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
 
+       val = I915_READ(DSPCNTR(plane));
+       if (!(val & DISPLAY_PLANE_ENABLE))
+               return;
+
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
        if (!intel_fb) {
                DRM_DEBUG_KMS("failed to alloc fb\n");
@@ -6610,11 +6894,12 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
 
        fb = &intel_fb->base;
 
-       val = I915_READ(DSPCNTR(plane));
-
-       if (INTEL_INFO(dev)->gen >= 4)
-               if (val & DISPPLANE_TILED)
+       if (INTEL_INFO(dev)->gen >= 4) {
+               if (val & DISPPLANE_TILED) {
                        plane_config->tiling = I915_TILING_X;
+                       fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+               }
+       }
 
        pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
        fourcc = i9xx_format_to_fourcc(pixel_format);
@@ -6640,7 +6925,8 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
        fb->pitches[0] = val & 0xffffffc0;
 
        aligned_height = intel_fb_align_height(dev, fb->height,
-                                              plane_config->tiling);
+                                              fb->pixel_format,
+                                              fb->modifier[0]);
 
        plane_config->size = fb->pitches[0] * aligned_height;
 
@@ -6649,7 +6935,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
                      fb->bits_per_pixel, base, fb->pitches[0],
                      plane_config->size);
 
-       crtc->base.primary->fb = fb;
+       plane_config->fb = intel_fb;
 }
 
 static void chv_crtc_clock_get(struct intel_crtc *crtc,
@@ -7521,7 +7807,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
                }
        }
 
-       if (is_lvds && has_reduced_clock && i915.powersave)
+       if (is_lvds && has_reduced_clock)
                crtc->lowfreq_avail = true;
        else
                crtc->lowfreq_avail = false;
@@ -7627,10 +7913,10 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 val, base, offset, stride_mult;
+       u32 val, base, offset, stride_mult, tiling;
        int pipe = crtc->pipe;
        int fourcc, pixel_format;
-       int aligned_height;
+       unsigned int aligned_height;
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
 
@@ -7643,8 +7929,8 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
        fb = &intel_fb->base;
 
        val = I915_READ(PLANE_CTL(pipe, 0));
-       if (val & PLANE_CTL_TILED_MASK)
-               plane_config->tiling = I915_TILING_X;
+       if (!(val & PLANE_CTL_ENABLE))
+               goto error;
 
        pixel_format = val & PLANE_CTL_FORMAT_MASK;
        fourcc = skl_format_to_fourcc(pixel_format,
@@ -7653,6 +7939,26 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
        fb->pixel_format = fourcc;
        fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
 
+       tiling = val & PLANE_CTL_TILED_MASK;
+       switch (tiling) {
+       case PLANE_CTL_TILED_LINEAR:
+               fb->modifier[0] = DRM_FORMAT_MOD_NONE;
+               break;
+       case PLANE_CTL_TILED_X:
+               plane_config->tiling = I915_TILING_X;
+               fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+               break;
+       case PLANE_CTL_TILED_Y:
+               fb->modifier[0] = I915_FORMAT_MOD_Y_TILED;
+               break;
+       case PLANE_CTL_TILED_YF:
+               fb->modifier[0] = I915_FORMAT_MOD_Yf_TILED;
+               break;
+       default:
+               MISSING_CASE(tiling);
+               goto error;
+       }
+
        base = I915_READ(PLANE_SURF(pipe, 0)) & 0xfffff000;
        plane_config->base = base;
 
@@ -7663,21 +7969,13 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
        fb->width = ((val >> 0) & 0x1fff) + 1;
 
        val = I915_READ(PLANE_STRIDE(pipe, 0));
-       switch (plane_config->tiling) {
-       case I915_TILING_NONE:
-               stride_mult = 64;
-               break;
-       case I915_TILING_X:
-               stride_mult = 512;
-               break;
-       default:
-               MISSING_CASE(plane_config->tiling);
-               goto error;
-       }
+       stride_mult = intel_fb_stride_alignment(dev, fb->modifier[0],
+                                               fb->pixel_format);
        fb->pitches[0] = (val & 0x3ff) * stride_mult;
 
        aligned_height = intel_fb_align_height(dev, fb->height,
-                                              plane_config->tiling);
+                                              fb->pixel_format,
+                                              fb->modifier[0]);
 
        plane_config->size = fb->pitches[0] * aligned_height;
 
@@ -7686,7 +7984,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
                      fb->bits_per_pixel, base, fb->pitches[0],
                      plane_config->size);
 
-       crtc->base.primary->fb = fb;
+       plane_config->fb = intel_fb;
        return;
 
 error:
@@ -7726,10 +8024,14 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
        u32 val, base, offset;
        int pipe = crtc->pipe;
        int fourcc, pixel_format;
-       int aligned_height;
+       unsigned int aligned_height;
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
 
+       val = I915_READ(DSPCNTR(pipe));
+       if (!(val & DISPLAY_PLANE_ENABLE))
+               return;
+
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
        if (!intel_fb) {
                DRM_DEBUG_KMS("failed to alloc fb\n");
@@ -7738,11 +8040,12 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
 
        fb = &intel_fb->base;
 
-       val = I915_READ(DSPCNTR(pipe));
-
-       if (INTEL_INFO(dev)->gen >= 4)
-               if (val & DISPPLANE_TILED)
+       if (INTEL_INFO(dev)->gen >= 4) {
+               if (val & DISPPLANE_TILED) {
                        plane_config->tiling = I915_TILING_X;
+                       fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+               }
+       }
 
        pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
        fourcc = i9xx_format_to_fourcc(pixel_format);
@@ -7768,7 +8071,8 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
        fb->pitches[0] = val & 0xffffffc0;
 
        aligned_height = intel_fb_align_height(dev, fb->height,
-                                              plane_config->tiling);
+                                              fb->pixel_format,
+                                              fb->modifier[0]);
 
        plane_config->size = fb->pitches[0] * aligned_height;
 
@@ -7777,7 +8081,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
                      fb->bits_per_pixel, base, fb->pitches[0],
                      plane_config->size);
 
-       crtc->base.primary->fb = fb;
+       plane_config->fb = intel_fb;
 }
 
 static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
@@ -8263,8 +8567,8 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
        uint32_t cntl = 0, size = 0;
 
        if (base) {
-               unsigned int width = intel_crtc->cursor_width;
-               unsigned int height = intel_crtc->cursor_height;
+               unsigned int width = intel_crtc->base.cursor->state->crtc_w;
+               unsigned int height = intel_crtc->base.cursor->state->crtc_h;
                unsigned int stride = roundup_pow_of_two(width) * 4;
 
                switch (stride) {
@@ -8328,7 +8632,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
        cntl = 0;
        if (base) {
                cntl = MCURSOR_GAMMA_ENABLE;
-               switch (intel_crtc->cursor_width) {
+               switch (intel_crtc->base.cursor->state->crtc_w) {
                        case 64:
                                cntl |= CURSOR_MODE_64_ARGB_AX;
                                break;
@@ -8339,7 +8643,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
                                cntl |= CURSOR_MODE_256_ARGB_AX;
                                break;
                        default:
-                               MISSING_CASE(intel_crtc->cursor_width);
+                               MISSING_CASE(intel_crtc->base.cursor->state->crtc_w);
                                return;
                }
                cntl |= pipe << 28; /* Connect to correct pipe */
@@ -8386,7 +8690,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
                base = 0;
 
        if (x < 0) {
-               if (x + intel_crtc->cursor_width <= 0)
+               if (x + intel_crtc->base.cursor->state->crtc_w <= 0)
                        base = 0;
 
                pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
@@ -8395,7 +8699,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        pos |= x << CURSOR_X_SHIFT;
 
        if (y < 0) {
-               if (y + intel_crtc->cursor_height <= 0)
+               if (y + intel_crtc->base.cursor->state->crtc_h <= 0)
                        base = 0;
 
                pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
@@ -8411,8 +8715,8 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        /* ILK+ do this automagically */
        if (HAS_GMCH_DISPLAY(dev) &&
            crtc->cursor->state->rotation == BIT(DRM_ROTATE_180)) {
-               base += (intel_crtc->cursor_height *
-                       intel_crtc->cursor_width - 1) * 4;
+               base += (intel_crtc->base.cursor->state->crtc_h *
+                       intel_crtc->base.cursor->state->crtc_w - 1) * 4;
        }
 
        if (IS_845G(dev) || IS_I865G(dev))
@@ -8604,6 +8908,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
        struct drm_device *dev = encoder->dev;
        struct drm_framebuffer *fb;
        struct drm_mode_config *config = &dev->mode_config;
+       struct drm_atomic_state *state = NULL;
+       struct drm_connector_state *connector_state;
        int ret, i = -1;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
@@ -8651,7 +8957,7 @@ retry:
                i++;
                if (!(encoder->possible_crtcs & (1 << i)))
                        continue;
-               if (possible_crtc->enabled)
+               if (possible_crtc->state->enable)
                        continue;
                /* This can occur when applying the pipe A quirk on resume. */
                if (to_intel_crtc(possible_crtc)->new_enabled)
@@ -8685,6 +8991,21 @@ retry:
        old->load_detect_temp = true;
        old->release_fb = NULL;
 
+       state = drm_atomic_state_alloc(dev);
+       if (!state)
+               return false;
+
+       state->acquire_ctx = ctx;
+
+       connector_state = drm_atomic_get_connector_state(state, connector);
+       if (IS_ERR(connector_state)) {
+               ret = PTR_ERR(connector_state);
+               goto fail;
+       }
+
+       connector_state->crtc = crtc;
+       connector_state->best_encoder = &intel_encoder->base;
+
        if (!mode)
                mode = &load_detect_mode;
 
@@ -8707,7 +9028,7 @@ retry:
                goto fail;
        }
 
-       if (intel_set_mode(crtc, mode, 0, 0, fb)) {
+       if (intel_set_mode(crtc, mode, 0, 0, fb, state)) {
                DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
                if (old->release_fb)
                        old->release_fb->funcs->destroy(old->release_fb);
@@ -8720,12 +9041,17 @@ retry:
        return true;
 
  fail:
-       intel_crtc->new_enabled = crtc->enabled;
+       intel_crtc->new_enabled = crtc->state->enable;
        if (intel_crtc->new_enabled)
                intel_crtc->new_config = intel_crtc->config;
        else
                intel_crtc->new_config = NULL;
 fail_unlock:
+       if (state) {
+               drm_atomic_state_free(state);
+               state = NULL;
+       }
+
        if (ret == -EDEADLK) {
                drm_modeset_backoff(ctx);
                goto retry;
@@ -8735,24 +9061,44 @@ fail_unlock:
 }
 
 void intel_release_load_detect_pipe(struct drm_connector *connector,
-                                   struct intel_load_detect_pipe *old)
+                                   struct intel_load_detect_pipe *old,
+                                   struct drm_modeset_acquire_ctx *ctx)
 {
+       struct drm_device *dev = connector->dev;
        struct intel_encoder *intel_encoder =
                intel_attached_encoder(connector);
        struct drm_encoder *encoder = &intel_encoder->base;
        struct drm_crtc *crtc = encoder->crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_atomic_state *state;
+       struct drm_connector_state *connector_state;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
                      connector->base.id, connector->name,
                      encoder->base.id, encoder->name);
 
        if (old->load_detect_temp) {
+               state = drm_atomic_state_alloc(dev);
+               if (!state)
+                       goto fail;
+
+               state->acquire_ctx = ctx;
+
+               connector_state = drm_atomic_get_connector_state(state, connector);
+               if (IS_ERR(connector_state))
+                       goto fail;
+
                to_intel_connector(connector)->new_encoder = NULL;
                intel_encoder->new_crtc = NULL;
                intel_crtc->new_enabled = false;
                intel_crtc->new_config = NULL;
-               intel_set_mode(crtc, NULL, 0, 0, NULL);
+
+               connector_state->best_encoder = NULL;
+               connector_state->crtc = NULL;
+
+               intel_set_mode(crtc, NULL, 0, 0, NULL, state);
+
+               drm_atomic_state_free(state);
 
                if (old->release_fb) {
                        drm_framebuffer_unregister_private(old->release_fb);
@@ -8765,6 +9111,11 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
        /* Switch crtc and encoder back off if necessary */
        if (old->dpms_mode != DRM_MODE_DPMS_ON)
                connector->funcs->dpms(connector, old->dpms_mode);
+
+       return;
+fail:
+       DRM_DEBUG_KMS("Couldn't release load detect pipe.\n");
+       drm_atomic_state_free(state);
 }
 
 static int i9xx_pll_refclk(struct drm_device *dev,
@@ -9003,6 +9354,8 @@ void intel_mark_busy(struct drm_device *dev)
 
        intel_runtime_pm_get(dev_priv);
        i915_update_gfx_val(dev_priv);
+       if (INTEL_INFO(dev)->gen >= 6)
+               gen6_rps_busy(dev_priv);
        dev_priv->mm.busy = true;
 }
 
@@ -9016,9 +9369,6 @@ void intel_mark_idle(struct drm_device *dev)
 
        dev_priv->mm.busy = false;
 
-       if (!i915.powersave)
-               goto out;
-
        for_each_crtc(dev, crtc) {
                if (!crtc->primary->fb)
                        continue;
@@ -9029,7 +9379,6 @@ void intel_mark_idle(struct drm_device *dev)
        if (INTEL_INFO(dev)->gen >= 6)
                gen6_rps_idle(dev->dev_private);
 
-out:
        intel_runtime_pm_put(dev_priv);
 }
 
@@ -9071,9 +9420,8 @@ static void intel_unpin_work_fn(struct work_struct *__work)
        enum pipe pipe = to_intel_crtc(work->crtc)->pipe;
 
        mutex_lock(&dev->struct_mutex);
-       intel_unpin_fb_obj(work->old_fb_obj);
+       intel_unpin_fb_obj(work->old_fb, work->crtc->primary->state);
        drm_gem_object_unreference(&work->pending_flip_obj->base);
-       drm_gem_object_unreference(&work->old_fb_obj->base);
 
        intel_fbc_update(dev);
 
@@ -9082,6 +9430,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
        mutex_unlock(&dev->struct_mutex);
 
        intel_frontbuffer_flip_complete(dev, INTEL_FRONTBUFFER_PRIMARY(pipe));
+       drm_framebuffer_unreference(work->old_fb);
 
        BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0);
        atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count);
@@ -9598,69 +9947,6 @@ static int intel_queue_mmio_flip(struct drm_device *dev,
        return 0;
 }
 
-static int intel_gen9_queue_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 intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       uint32_t plane = 0, stride;
-       int ret;
-
-       switch(intel_crtc->pipe) {
-       case PIPE_A:
-               plane = MI_DISPLAY_FLIP_SKL_PLANE_1_A;
-               break;
-       case PIPE_B:
-               plane = MI_DISPLAY_FLIP_SKL_PLANE_1_B;
-               break;
-       case PIPE_C:
-               plane = MI_DISPLAY_FLIP_SKL_PLANE_1_C;
-               break;
-       default:
-               WARN_ONCE(1, "unknown plane in flip command\n");
-               return -ENODEV;
-       }
-
-       switch (obj->tiling_mode) {
-       case I915_TILING_NONE:
-               stride = fb->pitches[0] >> 6;
-               break;
-       case I915_TILING_X:
-               stride = fb->pitches[0] >> 9;
-               break;
-       default:
-               WARN_ONCE(1, "unknown tiling in flip command\n");
-               return -ENODEV;
-       }
-
-       ret = intel_ring_begin(ring, 10);
-       if (ret)
-               return ret;
-
-       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-       intel_ring_emit(ring, DERRMR);
-       intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
-                               DERRMR_PIPEB_PRI_FLIP_DONE |
-                               DERRMR_PIPEC_PRI_FLIP_DONE));
-       intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8(1) |
-                             MI_SRM_LRM_GLOBAL_GTT);
-       intel_ring_emit(ring, DERRMR);
-       intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
-       intel_ring_emit(ring, 0);
-
-       intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane);
-       intel_ring_emit(ring, stride << 6 | obj->tiling_mode);
-       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-
-       intel_mark_page_flip_active(intel_crtc);
-       __intel_ring_advance(ring);
-
-       return 0;
-}
-
 static int intel_default_queue_flip(struct drm_device *dev,
                                    struct drm_crtc *crtc,
                                    struct drm_framebuffer *fb,
@@ -9690,10 +9976,10 @@ static bool __intel_pageflip_stall_check(struct drm_device *dev,
                    !i915_gem_request_completed(work->flip_queued_req, true))
                        return false;
 
-               work->flip_ready_vblank = drm_vblank_count(dev, intel_crtc->pipe);
+               work->flip_ready_vblank = drm_crtc_vblank_count(crtc);
        }
 
-       if (drm_vblank_count(dev, intel_crtc->pipe) - work->flip_ready_vblank < 3)
+       if (drm_crtc_vblank_count(crtc) - work->flip_ready_vblank < 3)
                return false;
 
        /* Potential stall - if we see that the flip has happened,
@@ -9716,7 +10002,7 @@ void intel_check_page_flip(struct drm_device *dev, int pipe)
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-       WARN_ON(!in_irq());
+       WARN_ON(!in_interrupt());
 
        if (crtc == NULL)
                return;
@@ -9724,7 +10010,8 @@ void intel_check_page_flip(struct drm_device *dev, int pipe)
        spin_lock(&dev->event_lock);
        if (intel_crtc->unpin_work && __intel_pageflip_stall_check(dev, crtc)) {
                WARN_ONCE(1, "Kicking stuck page flip: queued at %d, now %d\n",
-                        intel_crtc->unpin_work->flip_queued_vblank, drm_vblank_count(dev, pipe));
+                        intel_crtc->unpin_work->flip_queued_vblank,
+                        drm_vblank_count(dev, pipe));
                page_flip_completed(intel_crtc);
        }
        spin_unlock(&dev->event_lock);
@@ -9776,7 +10063,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
        work->event = event;
        work->crtc = crtc;
-       work->old_fb_obj = intel_fb_obj(old_fb);
+       work->old_fb = old_fb;
        INIT_WORK(&work->work, intel_unpin_work_fn);
 
        ret = drm_crtc_vblank_get(crtc);
@@ -9807,18 +10094,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
                flush_workqueue(dev_priv->wq);
 
-       ret = i915_mutex_lock_interruptible(dev);
-       if (ret)
-               goto cleanup;
-
        /* Reference the objects for the scheduled work. */
-       drm_gem_object_reference(&work->old_fb_obj->base);
+       drm_framebuffer_reference(work->old_fb);
        drm_gem_object_reference(&obj->base);
 
        crtc->primary->fb = fb;
+       update_state_fb(crtc->primary);
 
        work->pending_flip_obj = obj;
 
+       ret = i915_mutex_lock_interruptible(dev);
+       if (ret)
+               goto cleanup;
+
        atomic_inc(&intel_crtc->unpin_work_count);
        intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 
@@ -9827,7 +10115,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
        if (IS_VALLEYVIEW(dev)) {
                ring = &dev_priv->ring[BCS];
-               if (obj->tiling_mode != work->old_fb_obj->tiling_mode)
+               if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
                        /* vlv: DISPLAY_FLIP fails to change tiling */
                        ring = NULL;
        } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
@@ -9840,12 +10128,13 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                ring = &dev_priv->ring[RCS];
        }
 
-       ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, ring);
+       ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
+                                        crtc->primary->state, ring);
        if (ret)
                goto cleanup_pending;
 
-       work->gtt_offset =
-               i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
+       work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), obj)
+                                                 + intel_crtc->dspaddr_offset;
 
        if (use_mmio_flip(ring, obj)) {
                ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
@@ -9865,10 +10154,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                                        intel_ring_get_request(ring));
        }
 
-       work->flip_queued_vblank = drm_vblank_count(dev, intel_crtc->pipe);
+       work->flip_queued_vblank = drm_crtc_vblank_count(crtc);
        work->enable_stall_check = true;
 
-       i915_gem_track_fb(work->old_fb_obj, obj,
+       i915_gem_track_fb(intel_fb_obj(work->old_fb), obj,
                          INTEL_FRONTBUFFER_PRIMARY(pipe));
 
        intel_fbc_disable(dev);
@@ -9880,15 +10169,17 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        return 0;
 
 cleanup_unpin:
-       intel_unpin_fb_obj(obj);
+       intel_unpin_fb_obj(fb, crtc->primary->state);
 cleanup_pending:
        atomic_dec(&intel_crtc->unpin_work_count);
-       crtc->primary->fb = old_fb;
-       drm_gem_object_unreference(&work->old_fb_obj->base);
-       drm_gem_object_unreference(&obj->base);
        mutex_unlock(&dev->struct_mutex);
-
 cleanup:
+       crtc->primary->fb = old_fb;
+       update_state_fb(crtc->primary);
+
+       drm_gem_object_unreference_unlocked(&obj->base);
+       drm_framebuffer_unreference(work->old_fb);
+
        spin_lock_irq(&dev->event_lock);
        intel_crtc->unpin_work = NULL;
        spin_unlock_irq(&dev->event_lock);
@@ -9928,8 +10219,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
        struct intel_encoder *encoder;
        struct intel_connector *connector;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                connector->new_encoder =
                        to_intel_encoder(connector->base.encoder);
        }
@@ -9940,7 +10230,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
        }
 
        for_each_intel_crtc(dev, crtc) {
-               crtc->new_enabled = crtc->base.enabled;
+               crtc->new_enabled = crtc->base.state->enable;
 
                if (crtc->new_enabled)
                        crtc->new_config = crtc->config;
@@ -9949,6 +10239,27 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
        }
 }
 
+/* Transitional helper to copy current connector/encoder state to
+ * connector->state. This is needed so that code that is partially
+ * converted to atomic does the right thing.
+ */
+static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
+{
+       struct intel_connector *connector;
+
+       for_each_intel_connector(dev, connector) {
+               if (connector->base.encoder) {
+                       connector->base.state->best_encoder =
+                               connector->base.encoder;
+                       connector->base.state->crtc =
+                               connector->base.encoder->crtc;
+               } else {
+                       connector->base.state->best_encoder = NULL;
+                       connector->base.state->crtc = NULL;
+               }
+       }
+}
+
 /**
  * intel_modeset_commit_output_state
  *
@@ -9960,8 +10271,7 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
        struct intel_encoder *encoder;
        struct intel_connector *connector;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                connector->base.encoder = &connector->new_encoder->base;
        }
 
@@ -9970,8 +10280,11 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
        }
 
        for_each_intel_crtc(dev, crtc) {
+               crtc->base.state->enable = crtc->new_enabled;
                crtc->base.enabled = crtc->new_enabled;
        }
+
+       intel_modeset_update_connector_atomic_state(dev);
 }
 
 static void
@@ -10006,8 +10319,9 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
                          struct intel_crtc_state *pipe_config)
 {
        struct drm_device *dev = crtc->base.dev;
+       struct drm_atomic_state *state;
        struct intel_connector *connector;
-       int bpp;
+       int bpp, i;
 
        switch (fb->pixel_format) {
        case DRM_FORMAT_C8:
@@ -10047,11 +10361,15 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
 
        pipe_config->pipe_bpp = bpp;
 
+       state = pipe_config->base.state;
+
        /* Clamp display bpp to EDID value */
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
-               if (!connector->new_encoder ||
-                   connector->new_encoder->new_crtc != crtc)
+       for (i = 0; i < state->num_connector; i++) {
+               if (!state->connectors[i])
+                       continue;
+
+               connector = to_intel_connector(state->connectors[i]);
+               if (state->connector_states[i]->crtc != &crtc->base)
                        continue;
 
                connected_sink_compute_bpp(connector, pipe_config);
@@ -10176,8 +10494,7 @@ static bool check_digital_port_conflicts(struct drm_device *dev)
         * list to detect the problem on ddi platforms
         * where there's just one encoder per digital port.
         */
-       list_for_each_entry(connector,
-                           &dev->mode_config.connector_list, base.head) {
+       for_each_intel_connector(dev, connector) {
                struct intel_encoder *encoder = connector->new_encoder;
 
                if (!encoder)
@@ -10208,15 +10525,30 @@ static bool check_digital_port_conflicts(struct drm_device *dev)
        return true;
 }
 
+static void
+clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
+{
+       struct drm_crtc_state tmp_state;
+
+       /* Clear only the intel specific part of the crtc state */
+       tmp_state = crtc_state->base;
+       memset(crtc_state, 0, sizeof *crtc_state);
+       crtc_state->base = tmp_state;
+}
+
 static struct intel_crtc_state *
 intel_modeset_pipe_config(struct drm_crtc *crtc,
                          struct drm_framebuffer *fb,
-                         struct drm_display_mode *mode)
+                         struct drm_display_mode *mode,
+                         struct drm_atomic_state *state)
 {
        struct drm_device *dev = crtc->dev;
        struct intel_encoder *encoder;
+       struct intel_connector *connector;
+       struct drm_connector_state *connector_state;
        struct intel_crtc_state *pipe_config;
        int plane_bpp, ret = -EINVAL;
+       int i;
        bool retry = true;
 
        if (!check_encoder_cloning(to_intel_crtc(crtc))) {
@@ -10229,10 +10561,13 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
                return ERR_PTR(-EINVAL);
        }
 
-       pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
-       if (!pipe_config)
-               return ERR_PTR(-ENOMEM);
+       pipe_config = intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));
+       if (IS_ERR(pipe_config))
+               return pipe_config;
 
+       clear_intel_crtc_state(pipe_config);
+
+       pipe_config->base.crtc = crtc;
        drm_mode_copy(&pipe_config->base.adjusted_mode, mode);
        drm_mode_copy(&pipe_config->base.mode, mode);
 
@@ -10287,11 +10622,17 @@ encoder_retry:
         * adjust it according to limitations or connector properties, and also
         * a chance to reject the mode entirely.
         */
-       for_each_intel_encoder(dev, encoder) {
+       for (i = 0; i < state->num_connector; i++) {
+               connector = to_intel_connector(state->connectors[i]);
+               if (!connector)
+                       continue;
 
-               if (&encoder->new_crtc->base != crtc)
+               connector_state = state->connector_states[i];
+               if (connector_state->crtc != crtc)
                        continue;
 
+               encoder = to_intel_encoder(connector_state->best_encoder);
+
                if (!(encoder->compute_config(encoder, pipe_config))) {
                        DRM_DEBUG_KMS("Encoder config failure\n");
                        goto fail;
@@ -10327,7 +10668,6 @@ encoder_retry:
 
        return pipe_config;
 fail:
-       kfree(pipe_config);
        return ERR_PTR(ret);
 }
 
@@ -10349,8 +10689,7 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
         * to be part of the prepare_pipes mask. We don't (yet) support global
         * modeset across multiple crtcs, so modeset_pipes will only have one
         * bit set at most. */
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                if (connector->base.encoder == &connector->new_encoder->base)
                        continue;
 
@@ -10381,7 +10720,7 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
 
        /* Check for pipes that will be enabled/disabled ... */
        for_each_intel_crtc(dev, intel_crtc) {
-               if (intel_crtc->base.enabled == intel_crtc->new_enabled)
+               if (intel_crtc->base.state->enable == intel_crtc->new_enabled)
                        continue;
 
                if (!intel_crtc->new_enabled)
@@ -10456,10 +10795,10 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 
        /* Double check state. */
        for_each_intel_crtc(dev, intel_crtc) {
-               WARN_ON(intel_crtc->base.enabled != intel_crtc_in_use(&intel_crtc->base));
+               WARN_ON(intel_crtc->base.state->enable != intel_crtc_in_use(&intel_crtc->base));
                WARN_ON(intel_crtc->new_config &&
                        intel_crtc->new_config != intel_crtc->config);
-               WARN_ON(intel_crtc->base.enabled != !!intel_crtc->new_config);
+               WARN_ON(intel_crtc->base.state->enable != !!intel_crtc->new_config);
        }
 
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -10719,7 +11058,7 @@ static void check_wm_state(struct drm_device *dev)
                        continue;
 
                /* planes */
-               for_each_plane(pipe, plane) {
+               for_each_plane(dev_priv, pipe, plane) {
                        hw_entry = &hw_ddb.plane[pipe][plane];
                        sw_entry = &sw_ddb->plane[pipe][plane];
 
@@ -10753,8 +11092,7 @@ check_connector_state(struct drm_device *dev)
 {
        struct intel_connector *connector;
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                /* This also checks the encoder/connector hw state with the
                 * ->get_hw_state callbacks. */
                intel_connector_check_state(connector);
@@ -10784,8 +11122,7 @@ check_encoder_state(struct drm_device *dev)
                I915_STATE_WARN(encoder->connectors_active && !encoder->base.crtc,
                     "encoder's active_connectors set, but no crtc\n");
 
-               list_for_each_entry(connector, &dev->mode_config.connector_list,
-                                   base.head) {
+               for_each_intel_connector(dev, connector) {
                        if (connector->base.encoder != &encoder->base)
                                continue;
                        enabled = true;
@@ -10846,7 +11183,7 @@ check_crtc_state(struct drm_device *dev)
                DRM_DEBUG_KMS("[CRTC:%d]\n",
                              crtc->base.base.id);
 
-               I915_STATE_WARN(crtc->active && !crtc->base.enabled,
+               I915_STATE_WARN(crtc->active && !crtc->base.state->enable,
                     "active crtc, but not enabled in sw tracking\n");
 
                for_each_intel_encoder(dev, encoder) {
@@ -10860,9 +11197,10 @@ check_crtc_state(struct drm_device *dev)
                I915_STATE_WARN(active != crtc->active,
                     "crtc's computed active state doesn't match tracked active state "
                     "(expected %i, found %i)\n", active, crtc->active);
-               I915_STATE_WARN(enabled != crtc->base.enabled,
+               I915_STATE_WARN(enabled != crtc->base.state->enable,
                     "crtc's computed enabled state doesn't match tracked enabled state "
-                    "(expected %i, found %i)\n", enabled, crtc->base.enabled);
+                    "(expected %i, found %i)\n", enabled,
+                               crtc->base.state->enable);
 
                active = dev_priv->display.get_pipe_config(crtc,
                                                           &pipe_config);
@@ -10926,7 +11264,7 @@ check_shared_dpll_state(struct drm_device *dev)
                     pll->on, active);
 
                for_each_intel_crtc(dev, crtc) {
-                       if (crtc->base.enabled && intel_crtc_to_shared_dpll(crtc) == pll)
+                       if (crtc->base.state->enable && intel_crtc_to_shared_dpll(crtc) == pll)
                                enabled_crtcs++;
                        if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
                                active_crtcs++;
@@ -11008,17 +11346,30 @@ static struct intel_crtc_state *
 intel_modeset_compute_config(struct drm_crtc *crtc,
                             struct drm_display_mode *mode,
                             struct drm_framebuffer *fb,
+                            struct drm_atomic_state *state,
                             unsigned *modeset_pipes,
                             unsigned *prepare_pipes,
                             unsigned *disable_pipes)
 {
+       struct drm_device *dev = crtc->dev;
        struct intel_crtc_state *pipe_config = NULL;
+       struct intel_crtc *intel_crtc;
+       int ret = 0;
+
+       ret = drm_atomic_add_affected_connectors(state, crtc);
+       if (ret)
+               return ERR_PTR(ret);
 
        intel_modeset_affected_pipes(crtc, modeset_pipes,
                                     prepare_pipes, disable_pipes);
 
-       if ((*modeset_pipes) == 0)
-               goto out;
+       for_each_intel_crtc_masked(dev, *disable_pipes, intel_crtc) {
+               pipe_config = intel_atomic_get_crtc_state(state, intel_crtc);
+               if (IS_ERR(pipe_config))
+                       return pipe_config;
+
+               pipe_config->base.enable = false;
+       }
 
        /*
         * Note this needs changes when we start tracking multiple modes
@@ -11026,15 +11377,21 @@ intel_modeset_compute_config(struct drm_crtc *crtc,
         * (i.e. one pipe_config for each crtc) rather than just the one
         * for this crtc.
         */
-       pipe_config = intel_modeset_pipe_config(crtc, fb, mode);
-       if (IS_ERR(pipe_config)) {
-               goto out;
+       for_each_intel_crtc_masked(dev, *modeset_pipes, intel_crtc) {
+               /* FIXME: For now we still expect modeset_pipes has at most
+                * one bit set. */
+               if (WARN_ON(&intel_crtc->base != crtc))
+                       continue;
+
+               pipe_config = intel_modeset_pipe_config(crtc, fb, mode, state);
+               if (IS_ERR(pipe_config))
+                       return pipe_config;
+
+               intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
+                                      "[modeset]");
        }
-       intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
-                              "[modeset]");
 
-out:
-       return pipe_config;
+       return intel_atomic_get_crtc_state(state, to_intel_crtc(crtc));;
 }
 
 static int __intel_set_mode_setup_plls(struct drm_device *dev,
@@ -11078,6 +11435,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_display_mode *saved_mode;
+       struct intel_crtc_state *crtc_state_copy = NULL;
        struct intel_crtc *intel_crtc;
        int ret = 0;
 
@@ -11085,6 +11443,12 @@ static int __intel_set_mode(struct drm_crtc *crtc,
        if (!saved_mode)
                return -ENOMEM;
 
+       crtc_state_copy = kmalloc(sizeof(*crtc_state_copy), GFP_KERNEL);
+       if (!crtc_state_copy) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
        *saved_mode = crtc->mode;
 
        if (modeset_pipes)
@@ -11112,7 +11476,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
                intel_crtc_disable(&intel_crtc->base);
 
        for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
-               if (intel_crtc->base.enabled)
+               if (intel_crtc->base.state->enable)
                        dev_priv->display.crtc_disable(&intel_crtc->base);
        }
 
@@ -11168,9 +11532,25 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 
        /* FIXME: add subpixel order */
 done:
-       if (ret && crtc->enabled)
+       if (ret && crtc->state->enable)
                crtc->mode = *saved_mode;
 
+       if (ret == 0 && pipe_config) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+               /* The pipe_config will be freed with the atomic state, so
+                * make a copy. */
+               memcpy(crtc_state_copy, intel_crtc->config,
+                      sizeof *crtc_state_copy);
+               intel_crtc->config = crtc_state_copy;
+               intel_crtc->base.state = &crtc_state_copy->base;
+
+               if (modeset_pipes)
+                       intel_crtc->new_config = intel_crtc->config;
+       } else {
+               kfree(crtc_state_copy);
+       }
+
        kfree(saved_mode);
        return ret;
 }
@@ -11196,27 +11576,81 @@ static int intel_set_mode_pipes(struct drm_crtc *crtc,
 
 static int intel_set_mode(struct drm_crtc *crtc,
                          struct drm_display_mode *mode,
-                         int x, int y, struct drm_framebuffer *fb)
+                         int x, int y, struct drm_framebuffer *fb,
+                         struct drm_atomic_state *state)
 {
        struct intel_crtc_state *pipe_config;
        unsigned modeset_pipes, prepare_pipes, disable_pipes;
+       int ret = 0;
 
-       pipe_config = intel_modeset_compute_config(crtc, mode, fb,
+       pipe_config = intel_modeset_compute_config(crtc, mode, fb, state,
                                                   &modeset_pipes,
                                                   &prepare_pipes,
                                                   &disable_pipes);
 
-       if (IS_ERR(pipe_config))
-               return PTR_ERR(pipe_config);
+       if (IS_ERR(pipe_config)) {
+               ret = PTR_ERR(pipe_config);
+               goto out;
+       }
 
-       return intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config,
-                                   modeset_pipes, prepare_pipes,
-                                   disable_pipes);
+       ret = intel_set_mode_pipes(crtc, mode, x, y, fb, pipe_config,
+                                  modeset_pipes, prepare_pipes,
+                                  disable_pipes);
+       if (ret)
+               goto out;
+
+out:
+       return ret;
 }
 
 void intel_crtc_restore_mode(struct drm_crtc *crtc)
 {
-       intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb);
+       struct drm_device *dev = crtc->dev;
+       struct drm_atomic_state *state;
+       struct intel_encoder *encoder;
+       struct intel_connector *connector;
+       struct drm_connector_state *connector_state;
+
+       state = drm_atomic_state_alloc(dev);
+       if (!state) {
+               DRM_DEBUG_KMS("[CRTC:%d] mode restore failed, out of memory",
+                             crtc->base.id);
+               return;
+       }
+
+       state->acquire_ctx = dev->mode_config.acquire_ctx;
+
+       /* The force restore path in the HW readout code relies on the staged
+        * config still keeping the user requested config while the actual
+        * state has been overwritten by the configuration read from HW. We
+        * need to copy the staged config to the atomic state, otherwise the
+        * mode set will just reapply the state the HW is already in. */
+       for_each_intel_encoder(dev, encoder) {
+               if (&encoder->new_crtc->base != crtc)
+                       continue;
+
+               for_each_intel_connector(dev, connector) {
+                       if (connector->new_encoder != encoder)
+                               continue;
+
+                       connector_state = drm_atomic_get_connector_state(state, &connector->base);
+                       if (IS_ERR(connector_state)) {
+                               DRM_DEBUG_KMS("Failed to add [CONNECTOR:%d:%s] to state: %ld\n",
+                                             connector->base.base.id,
+                                             connector->base.name,
+                                             PTR_ERR(connector_state));
+                               continue;
+                       }
+
+                       connector_state->crtc = crtc;
+                       connector_state->best_encoder = &encoder->base;
+               }
+       }
+
+       intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->primary->fb,
+                      state);
+
+       drm_atomic_state_free(state);
 }
 
 #undef for_each_intel_crtc_masked
@@ -11264,7 +11698,7 @@ static int intel_set_config_save_state(struct drm_device *dev,
         */
        count = 0;
        for_each_crtc(dev, crtc) {
-               config->save_crtc_enabled[count++] = crtc->enabled;
+               config->save_crtc_enabled[count++] = crtc->state->enable;
        }
 
        count = 0;
@@ -11305,7 +11739,7 @@ static void intel_set_config_restore_state(struct drm_device *dev,
        }
 
        count = 0;
-       list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
+       for_each_intel_connector(dev, connector) {
                connector->new_encoder =
                        to_intel_encoder(config->save_connector_encoders[count++]);
        }
@@ -11385,9 +11819,11 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 static int
 intel_modeset_stage_output_state(struct drm_device *dev,
                                 struct drm_mode_set *set,
-                                struct intel_set_config *config)
+                                struct intel_set_config *config,
+                                struct drm_atomic_state *state)
 {
        struct intel_connector *connector;
+       struct drm_connector_state *connector_state;
        struct intel_encoder *encoder;
        struct intel_crtc *crtc;
        int ro;
@@ -11397,8 +11833,7 @@ intel_modeset_stage_output_state(struct drm_device *dev,
        WARN_ON(!set->fb && (set->num_connectors != 0));
        WARN_ON(set->fb && (set->num_connectors == 0));
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                /* Otherwise traverse passed in connector list and get encoders
                 * for them. */
                for (ro = 0; ro < set->num_connectors; ro++) {
@@ -11423,15 +11858,16 @@ intel_modeset_stage_output_state(struct drm_device *dev,
 
 
                if (&connector->new_encoder->base != connector->base.encoder) {
-                       DRM_DEBUG_KMS("encoder changed, full mode switch\n");
+                       DRM_DEBUG_KMS("[CONNECTOR:%d:%s] encoder changed, full mode switch\n",
+                                     connector->base.base.id,
+                                     connector->base.name);
                        config->mode_changed = true;
                }
        }
        /* connector->new_encoder is now updated for all connectors. */
 
        /* Update crtc of enabled connectors. */
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                struct drm_crtc *new_crtc;
 
                if (!connector->new_encoder)
@@ -11451,6 +11887,14 @@ intel_modeset_stage_output_state(struct drm_device *dev,
                }
                connector->new_encoder->new_crtc = to_intel_crtc(new_crtc);
 
+               connector_state =
+                       drm_atomic_get_connector_state(state, &connector->base);
+               if (IS_ERR(connector_state))
+                       return PTR_ERR(connector_state);
+
+               connector_state->crtc = new_crtc;
+               connector_state->best_encoder = &connector->new_encoder->base;
+
                DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
                        connector->base.base.id,
                        connector->base.name,
@@ -11460,9 +11904,7 @@ intel_modeset_stage_output_state(struct drm_device *dev,
        /* Check for any encoders that needs to be disabled. */
        for_each_intel_encoder(dev, encoder) {
                int num_connectors = 0;
-               list_for_each_entry(connector,
-                                   &dev->mode_config.connector_list,
-                                   base.head) {
+               for_each_intel_connector(dev, connector) {
                        if (connector->new_encoder == encoder) {
                                WARN_ON(!connector->new_encoder->new_crtc);
                                num_connectors++;
@@ -11477,16 +11919,23 @@ intel_modeset_stage_output_state(struct drm_device *dev,
                /* Only now check for crtc changes so we don't miss encoders
                 * that will be disabled. */
                if (&encoder->new_crtc->base != encoder->base.crtc) {
-                       DRM_DEBUG_KMS("crtc changed, full mode switch\n");
+                       DRM_DEBUG_KMS("[ENCODER:%d:%s] crtc changed, full mode switch\n",
+                                     encoder->base.base.id,
+                                     encoder->base.name);
                        config->mode_changed = true;
                }
        }
        /* Now we've also updated encoder->new_crtc for all encoders. */
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
-               if (connector->new_encoder)
+       for_each_intel_connector(dev, connector) {
+               connector_state =
+                       drm_atomic_get_connector_state(state, &connector->base);
+
+               if (connector->new_encoder) {
                        if (connector->new_encoder != connector->encoder)
                                connector->encoder = connector->new_encoder;
+               } else {
+                       connector_state->crtc = NULL;
+               }
        }
        for_each_intel_crtc(dev, crtc) {
                crtc->new_enabled = false;
@@ -11498,8 +11947,9 @@ intel_modeset_stage_output_state(struct drm_device *dev,
                        }
                }
 
-               if (crtc->new_enabled != crtc->base.enabled) {
-                       DRM_DEBUG_KMS("crtc %sabled, full mode switch\n",
+               if (crtc->new_enabled != crtc->base.state->enable) {
+                       DRM_DEBUG_KMS("[CRTC:%d] %sabled, full mode switch\n",
+                                     crtc->base.base.id,
                                      crtc->new_enabled ? "en" : "dis");
                        config->mode_changed = true;
                }
@@ -11522,7 +11972,7 @@ static void disable_crtc_nofb(struct intel_crtc *crtc)
        DRM_DEBUG_KMS("Trying to restore without FB -> disabling pipe %c\n",
                      pipe_name(crtc->pipe));
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
+       for_each_intel_connector(dev, connector) {
                if (connector->new_encoder &&
                    connector->new_encoder->new_crtc == crtc)
                        connector->new_encoder = NULL;
@@ -11541,6 +11991,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 {
        struct drm_device *dev;
        struct drm_mode_set save_set;
+       struct drm_atomic_state *state = NULL;
        struct intel_set_config *config;
        struct intel_crtc_state *pipe_config;
        unsigned modeset_pipes, prepare_pipes, disable_pipes;
@@ -11585,12 +12036,20 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
         * such cases. */
        intel_set_config_compute_mode_changes(set, config);
 
-       ret = intel_modeset_stage_output_state(dev, set, config);
+       state = drm_atomic_state_alloc(dev);
+       if (!state) {
+               ret = -ENOMEM;
+               goto out_config;
+       }
+
+       state->acquire_ctx = dev->mode_config.acquire_ctx;
+
+       ret = intel_modeset_stage_output_state(dev, set, config, state);
        if (ret)
                goto fail;
 
        pipe_config = intel_modeset_compute_config(set->crtc, set->mode,
-                                                  set->fb,
+                                                  set->fb, state,
                                                   &modeset_pipes,
                                                   &prepare_pipes,
                                                   &disable_pipes);
@@ -11610,10 +12069,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
                 */
        }
 
-       /* set_mode will free it in the mode_changed case */
-       if (!config->mode_changed)
-               kfree(pipe_config);
-
        intel_update_pipe_size(to_intel_crtc(set->crtc));
 
        if (config->mode_changed) {
@@ -11659,6 +12114,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 fail:
                intel_set_config_restore_state(dev, config);
 
+               drm_atomic_state_clear(state);
+
                /*
                 * HACK: if the pipe was on, but we didn't have a framebuffer,
                 * force the pipe off to avoid oopsing in the modeset code
@@ -11671,11 +12128,15 @@ fail:
                /* Try to restore the config */
                if (config->mode_changed &&
                    intel_set_mode(save_set.crtc, save_set.mode,
-                                  save_set.x, save_set.y, save_set.fb))
+                                  save_set.x, save_set.y, save_set.fb,
+                                  state))
                        DRM_ERROR("failed to restore config after modeset failure\n");
        }
 
 out_config:
+       if (state)
+               drm_atomic_state_free(state);
+
        intel_set_config_free(config);
        return ret;
 }
@@ -11789,6 +12250,28 @@ static void intel_shared_dpll_init(struct drm_device *dev)
        BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
 }
 
+/**
+ * intel_wm_need_update - Check whether watermarks need updating
+ * @plane: drm plane
+ * @state: new plane state
+ *
+ * Check current plane state versus the new one to determine whether
+ * watermarks need to be recalculated.
+ *
+ * Returns true or false.
+ */
+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)
+               return true;
+
+       return false;
+}
+
 /**
  * intel_prepare_plane_fb - Prepare fb for usage on plane
  * @plane: drm plane to prepare for
@@ -11803,7 +12286,8 @@ static void intel_shared_dpll_init(struct drm_device *dev)
  */
 int
 intel_prepare_plane_fb(struct drm_plane *plane,
-                      struct drm_framebuffer *fb)
+                      struct drm_framebuffer *fb,
+                      const struct drm_plane_state *new_state)
 {
        struct drm_device *dev = plane->dev;
        struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -11837,7 +12321,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                if (ret)
                        DRM_DEBUG_KMS("failed to attach phys object\n");
        } else {
-               ret = intel_pin_and_fence_fb_obj(plane, fb, NULL);
+               ret = intel_pin_and_fence_fb_obj(plane, fb, new_state, NULL);
        }
 
        if (ret == 0)
@@ -11857,7 +12341,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
  */
 void
 intel_cleanup_plane_fb(struct drm_plane *plane,
-                      struct drm_framebuffer *fb)
+                      struct drm_framebuffer *fb,
+                      const struct drm_plane_state *old_state)
 {
        struct drm_device *dev = plane->dev;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
@@ -11868,7 +12353,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
        if (plane->type != DRM_PLANE_TYPE_CURSOR ||
            !INTEL_INFO(dev)->cursor_needs_physical) {
                mutex_lock(&dev->struct_mutex);
-               intel_unpin_fb_obj(obj);
+               intel_unpin_fb_obj(fb, old_state);
                mutex_unlock(&dev->struct_mutex);
        }
 }
@@ -11913,7 +12398,7 @@ intel_check_primary_plane(struct drm_plane *plane,
                 */
                if (intel_crtc->primary_enabled &&
                    INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) &&
-                   dev_priv->fbc.plane == intel_crtc->plane &&
+                   dev_priv->fbc.crtc == intel_crtc &&
                    state->base.rotation != BIT(DRM_ROTATE_0)) {
                        intel_crtc->atomic.disable_fbc = true;
                }
@@ -11932,6 +12417,9 @@ intel_check_primary_plane(struct drm_plane *plane,
                        INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
 
                intel_crtc->atomic.update_fbc = true;
+
+               if (intel_wm_need_update(plane, &state->base))
+                       intel_crtc->atomic.update_wm = true;
        }
 
        return 0;
@@ -11946,8 +12434,6 @@ intel_commit_primary_plane(struct drm_plane *plane,
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc;
-       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-       struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_rect *src = &state->src;
 
        crtc = crtc ? crtc : plane->crtc;
@@ -11957,8 +12443,6 @@ intel_commit_primary_plane(struct drm_plane *plane,
        crtc->x = src->x1 >> 16;
        crtc->y = src->y1 >> 16;
 
-       intel_plane->obj = obj;
-
        if (intel_crtc->active) {
                if (state->visible) {
                        /* FIXME: kill this fastboot hack */
@@ -12198,17 +12682,14 @@ intel_check_cursor_plane(struct drm_plane *plane,
                return -ENOMEM;
        }
 
-       /* we only need to pin inside GTT if cursor is non-phy */
-       mutex_lock(&dev->struct_mutex);
-       if (!INTEL_INFO(dev)->cursor_needs_physical && obj->tiling_mode) {
+       if (fb->modifier[0] != DRM_FORMAT_MOD_NONE) {
                DRM_DEBUG_KMS("cursor cannot be tiled\n");
                ret = -EINVAL;
        }
-       mutex_unlock(&dev->struct_mutex);
 
 finish:
        if (intel_crtc->active) {
-               if (intel_crtc->cursor_width != state->base.crtc_w)
+               if (plane->state->crtc_w != state->base.crtc_w)
                        intel_crtc->atomic.update_wm = true;
 
                intel_crtc->atomic.fb_bits |=
@@ -12225,7 +12706,6 @@ intel_commit_cursor_plane(struct drm_plane *plane,
        struct drm_crtc *crtc = state->base.crtc;
        struct drm_device *dev = plane->dev;
        struct intel_crtc *intel_crtc;
-       struct intel_plane *intel_plane = to_intel_plane(plane);
        struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
        uint32_t addr;
 
@@ -12236,8 +12716,6 @@ intel_commit_cursor_plane(struct drm_plane *plane,
        crtc->cursor_x = state->base.crtc_x;
        crtc->cursor_y = state->base.crtc_y;
 
-       intel_plane->obj = obj;
-
        if (intel_crtc->cursor_bo == obj)
                goto update;
 
@@ -12251,8 +12729,6 @@ intel_commit_cursor_plane(struct drm_plane *plane,
        intel_crtc->cursor_addr = addr;
        intel_crtc->cursor_bo = obj;
 update:
-       intel_crtc->cursor_width = state->base.crtc_w;
-       intel_crtc->cursor_height = state->base.crtc_h;
 
        if (intel_crtc->active)
                intel_crtc_update_cursor(crtc, state->visible);
@@ -12322,6 +12798,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
        if (!crtc_state)
                goto fail;
        intel_crtc_set_state(intel_crtc, crtc_state);
+       crtc_state->base.crtc = &intel_crtc->base;
 
        primary = intel_primary_plane_create(dev, pipe);
        if (!primary)
@@ -12399,9 +12876,6 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
        struct drm_crtc *drmmode_crtc;
        struct intel_crtc *crtc;
 
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -ENODEV;
-
        drmmode_crtc = drm_crtc_find(dev, pipe_from_crtc_id->crtc_id);
 
        if (!drmmode_crtc) {
@@ -12482,10 +12956,15 @@ static void intel_setup_outputs(struct drm_device *dev)
        if (HAS_DDI(dev)) {
                int found;
 
-               /* Haswell uses DDI functions to detect digital outputs */
+               /*
+                * Haswell uses DDI functions to detect digital outputs.
+                * On SKL pre-D0 the strap isn't connected, so we assume
+                * it's there.
+                */
                found = I915_READ(DDI_BUF_CTL_A) & DDI_INIT_DISPLAY_DETECTED;
-               /* DDI A only supports eDP */
-               if (found)
+               /* WaIgnoreDDIAStrap: skl */
+               if (found ||
+                   (IS_SKYLAKE(dev) && INTEL_REVID(dev) < SKL_REVID_D0))
                        intel_ddi_init(dev, PORT_A);
 
                /* DDI B, C and D detection is indicated by the SFUSE_STRAP
@@ -12617,19 +13096,21 @@ static void intel_setup_outputs(struct drm_device *dev)
         * testing/debug of the plane operations (and only when a specific
         * kernel module option is given), that shouldn't really matter.
         *
+        * We are also relying on these states to convert the legacy mode set
+        * to use a drm_atomic_state struct. The states are kept consistent
+        * with actual state, so that it is safe to rely on that instead of
+        * the staged config.
+        *
         * Once atomic support for crtc's + connectors lands, this loop should
         * be removed since we'll be setting up real connector state, which
         * will contain Intel-specific properties.
         */
-       if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
-               list_for_each_entry(connector,
-                                   &dev->mode_config.connector_list,
-                                   head) {
-                       if (!WARN_ON(connector->state)) {
-                               connector->state =
-                                       kzalloc(sizeof(*connector->state),
-                                               GFP_KERNEL);
-                       }
+       list_for_each_entry(connector,
+                           &dev->mode_config.connector_list,
+                           head) {
+               if (!WARN_ON(connector->state)) {
+                       connector->state = kzalloc(sizeof(*connector->state),
+                                                  GFP_KERNEL);
                }
        }
 
@@ -12674,52 +13155,100 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
        .create_handle = intel_user_framebuffer_create_handle,
 };
 
+static
+u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
+                        uint32_t pixel_format)
+{
+       u32 gen = INTEL_INFO(dev)->gen;
+
+       if (gen >= 9) {
+               /* "The stride in bytes must not exceed the of the size of 8K
+                *  pixels and 32K bytes."
+                */
+                return min(8192*drm_format_plane_cpp(pixel_format, 0), 32768);
+       } else if (gen >= 5 && !IS_VALLEYVIEW(dev)) {
+               return 32*1024;
+       } else if (gen >= 4) {
+               if (fb_modifier == I915_FORMAT_MOD_X_TILED)
+                       return 16*1024;
+               else
+                       return 32*1024;
+       } else if (gen >= 3) {
+               if (fb_modifier == I915_FORMAT_MOD_X_TILED)
+                       return 8*1024;
+               else
+                       return 16*1024;
+       } else {
+               /* XXX DSPC is limited to 4k tiled */
+               return 8*1024;
+       }
+}
+
 static int intel_framebuffer_init(struct drm_device *dev,
                                  struct intel_framebuffer *intel_fb,
                                  struct drm_mode_fb_cmd2 *mode_cmd,
                                  struct drm_i915_gem_object *obj)
 {
-       int aligned_height;
-       int pitch_limit;
+       unsigned int aligned_height;
        int ret;
+       u32 pitch_limit, stride_alignment;
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-       if (obj->tiling_mode == I915_TILING_Y) {
-               DRM_DEBUG("hardware does not support tiling Y\n");
-               return -EINVAL;
+       if (mode_cmd->flags & DRM_MODE_FB_MODIFIERS) {
+               /* Enforce that fb modifier and tiling mode match, but only for
+                * X-tiled. This is needed for FBC. */
+               if (!!(obj->tiling_mode == I915_TILING_X) !=
+                   !!(mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED)) {
+                       DRM_DEBUG("tiling_mode doesn't match fb modifier\n");
+                       return -EINVAL;
+               }
+       } else {
+               if (obj->tiling_mode == I915_TILING_X)
+                       mode_cmd->modifier[0] = I915_FORMAT_MOD_X_TILED;
+               else if (obj->tiling_mode == I915_TILING_Y) {
+                       DRM_DEBUG("No Y tiling for legacy addfb\n");
+                       return -EINVAL;
+               }
        }
 
-       if (mode_cmd->pitches[0] & 63) {
-               DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n",
-                         mode_cmd->pitches[0]);
+       /* Passed in modifier sanity checking. */
+       switch (mode_cmd->modifier[0]) {
+       case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_Yf_TILED:
+               if (INTEL_INFO(dev)->gen < 9) {
+                       DRM_DEBUG("Unsupported tiling 0x%llx!\n",
+                                 mode_cmd->modifier[0]);
+                       return -EINVAL;
+               }
+       case DRM_FORMAT_MOD_NONE:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               DRM_DEBUG("Unsupported fb modifier 0x%llx!\n",
+                         mode_cmd->modifier[0]);
                return -EINVAL;
        }
 
-       if (INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev)) {
-               pitch_limit = 32*1024;
-       } else if (INTEL_INFO(dev)->gen >= 4) {
-               if (obj->tiling_mode)
-                       pitch_limit = 16*1024;
-               else
-                       pitch_limit = 32*1024;
-       } else if (INTEL_INFO(dev)->gen >= 3) {
-               if (obj->tiling_mode)
-                       pitch_limit = 8*1024;
-               else
-                       pitch_limit = 16*1024;
-       } else
-               /* XXX DSPC is limited to 4k tiled */
-               pitch_limit = 8*1024;
+       stride_alignment = intel_fb_stride_alignment(dev, 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",
+                         mode_cmd->pitches[0], stride_alignment);
+               return -EINVAL;
+       }
 
+       pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0],
+                                          mode_cmd->pixel_format);
        if (mode_cmd->pitches[0] > pitch_limit) {
-               DRM_DEBUG("%s pitch (%d) must be at less than %d\n",
-                         obj->tiling_mode ? "tiled" : "linear",
+               DRM_DEBUG("%s pitch (%u) must be at less than %d\n",
+                         mode_cmd->modifier[0] != DRM_FORMAT_MOD_NONE ?
+                         "tiled" : "linear",
                          mode_cmd->pitches[0], pitch_limit);
                return -EINVAL;
        }
 
-       if (obj->tiling_mode != I915_TILING_NONE &&
+       if (mode_cmd->modifier[0] == I915_FORMAT_MOD_X_TILED &&
            mode_cmd->pitches[0] != obj->stride) {
                DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
                          mode_cmd->pitches[0], obj->stride);
@@ -12774,7 +13303,8 @@ static int intel_framebuffer_init(struct drm_device *dev,
                return -EINVAL;
 
        aligned_height = intel_fb_align_height(dev, mode_cmd->height,
-                                              obj->tiling_mode);
+                                              mode_cmd->pixel_format,
+                                              mode_cmd->modifier[0]);
        /* FIXME drm helper for size checks (especially planar formats)? */
        if (obj->base.size < aligned_height * mode_cmd->pitches[0])
                return -EINVAL;
@@ -12927,8 +13457,6 @@ static void intel_init_display(struct drm_device *dev)
        } else if (IS_IVYBRIDGE(dev)) {
                /* FIXME: detect B0+ stepping and use auto training */
                dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
-               dev_priv->display.modeset_global_resources =
-                       ivb_modeset_global_resources;
        } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                dev_priv->display.fdi_link_train = hsw_fdi_link_train;
        } else if (IS_VALLEYVIEW(dev)) {
@@ -12936,9 +13464,6 @@ static void intel_init_display(struct drm_device *dev)
                        valleyview_modeset_global_resources;
        }
 
-       /* Default just returns -ENODEV to indicate unsupported */
-       dev_priv->display.queue_flip = intel_default_queue_flip;
-
        switch (INTEL_INFO(dev)->gen) {
        case 2:
                dev_priv->display.queue_flip = intel_gen2_queue_flip;
@@ -12961,8 +13486,10 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.queue_flip = intel_gen7_queue_flip;
                break;
        case 9:
-               dev_priv->display.queue_flip = intel_gen9_queue_flip;
-               break;
+               /* Drop through - unsupported since execlist only. */
+       default:
+               /* Default just returns -ENODEV to indicate unsupported */
+               dev_priv->display.queue_flip = intel_default_queue_flip;
        }
 
        intel_panel_init_backlight_funcs(dev);
@@ -13181,6 +13708,8 @@ void intel_modeset_init(struct drm_device *dev)
        dev->mode_config.preferred_depth = 24;
        dev->mode_config.prefer_shadow = 1;
 
+       dev->mode_config.allow_fb_modifiers = true;
+
        dev->mode_config.funcs = &intel_mode_funcs;
 
        intel_init_quirks(dev);
@@ -13223,7 +13752,7 @@ void intel_modeset_init(struct drm_device *dev)
 
        for_each_pipe(dev_priv, pipe) {
                intel_crtc_init(dev, pipe);
-               for_each_sprite(pipe, sprite) {
+               for_each_sprite(dev_priv, pipe, sprite) {
                        ret = intel_plane_init(dev, pipe, sprite);
                        if (ret)
                                DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
@@ -13264,7 +13793,7 @@ void intel_modeset_init(struct drm_device *dev)
                         * If the fb is shared between multiple heads, we'll
                         * just get the first one.
                         */
-                       intel_find_plane_obj(crtc, &crtc->plane_config);
+                       intel_find_initial_plane_obj(crtc, &crtc->plane_config);
                }
        }
 }
@@ -13279,9 +13808,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
        /* We can't just switch on the pipe A, we need to set things up with a
         * proper mode and output configuration. As a gross hack, enable pipe A
         * by enabling the load detect pipe once. */
-       list_for_each_entry(connector,
-                           &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
                        crt = &connector->base;
                        break;
@@ -13292,7 +13819,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
                return;
 
        if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx))
-               intel_release_load_detect_pipe(crt, &load_detect_temp);
+               intel_release_load_detect_pipe(crt, &load_detect_temp, ctx);
 }
 
 static bool
@@ -13326,11 +13853,11 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
        I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 
        /* restore vblank interrupts to correct state */
+       drm_crtc_vblank_reset(&crtc->base);
        if (crtc->active) {
                update_scanline_offset(crtc);
-               drm_vblank_on(dev, crtc->pipe);
-       } else
-               drm_vblank_off(dev, crtc->pipe);
+               drm_crtc_vblank_on(&crtc->base);
+       }
 
        /* We need to sanitize the plane -> pipe mapping first because this will
         * disable the crtc (and hence change the state) if it is wrong. Note
@@ -13352,8 +13879,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                crtc->plane = plane;
 
                /* ... and break all links. */
-               list_for_each_entry(connector, &dev->mode_config.connector_list,
-                                   base.head) {
+               for_each_intel_connector(dev, connector) {
                        if (connector->encoder->base.crtc != &crtc->base)
                                continue;
 
@@ -13362,14 +13888,14 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                }
                /* multiple connectors may have the same encoder:
                 *  handle them and break crtc link separately */
-               list_for_each_entry(connector, &dev->mode_config.connector_list,
-                                   base.head)
+               for_each_intel_connector(dev, connector)
                        if (connector->encoder->base.crtc == &crtc->base) {
                                connector->encoder->base.crtc = NULL;
                                connector->encoder->connectors_active = false;
                        }
 
                WARN_ON(crtc->active);
+               crtc->base.state->enable = false;
                crtc->base.enabled = false;
        }
 
@@ -13386,7 +13912,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
         * have active connectors/encoders. */
        intel_crtc_update_dpms(&crtc->base);
 
-       if (crtc->active != crtc->base.enabled) {
+       if (crtc->active != crtc->base.state->enable) {
                struct intel_encoder *encoder;
 
                /* This can happen either due to bugs in the get_hw_state
@@ -13394,9 +13920,10 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                 * pipe A quirk. */
                DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
                              crtc->base.base.id,
-                             crtc->base.enabled ? "enabled" : "disabled",
+                             crtc->base.state->enable ? "enabled" : "disabled",
                              crtc->active ? "enabled" : "disabled");
 
+               crtc->base.state->enable = crtc->active;
                crtc->base.enabled = crtc->active;
 
                /* Because we only establish the connector -> encoder ->
@@ -13465,9 +13992,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                 * a bug in one of the get_hw_state functions. Or someplace else
                 * in our code, like the register restore mess on resume. Clamp
                 * things to off as a safer default. */
-               list_for_each_entry(connector,
-                                   &dev->mode_config.connector_list,
-                                   base.head) {
+               for_each_intel_connector(dev, connector) {
                        if (connector->encoder != encoder)
                                continue;
                        connector->base.dpms = DRM_MODE_DPMS_OFF;
@@ -13533,6 +14058,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                crtc->active = dev_priv->display.get_pipe_config(crtc,
                                                                 crtc->config);
 
+               crtc->base.state->enable = crtc->active;
                crtc->base.enabled = crtc->active;
                crtc->primary_enabled = primary_get_hw_state(crtc);
 
@@ -13581,8 +14107,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                              pipe_name(pipe));
        }
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           base.head) {
+       for_each_intel_connector(dev, connector) {
                if (connector->get_hw_state(connector)) {
                        connector->base.dpms = DRM_MODE_DPMS_ON;
                        connector->encoder->connectors_active = true;
@@ -13638,6 +14163,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                                       "[setup_hw_state]");
        }
 
+       intel_modeset_update_connector_atomic_state(dev);
+
        for (i = 0; i < dev_priv->num_shared_dpll; i++) {
                struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
@@ -13666,8 +14193,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                        struct drm_crtc *crtc =
                                dev_priv->pipe_to_crtc_mapping[pipe];
 
-                       intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
-                                      crtc->primary->fb);
+                       intel_crtc_restore_mode(crtc);
                }
        } else {
                intel_modeset_update_staged_output_state(dev);
@@ -13713,11 +14239,13 @@ void intel_modeset_gem_init(struct drm_device *dev)
 
                if (intel_pin_and_fence_fb_obj(c->primary,
                                               c->primary->fb,
+                                              c->primary->state,
                                               NULL)) {
                        DRM_ERROR("failed to pin boot fb on pipe %d\n",
                                  to_intel_crtc(c)->pipe);
                        drm_framebuffer_unreference(c->primary->fb);
                        c->primary->fb = NULL;
+                       update_state_fb(c->primary);
                }
        }
        mutex_unlock(&dev->struct_mutex);
@@ -13761,8 +14289,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        intel_fbc_disable(dev);
 
-       ironlake_teardown_rc6(dev);
-
        mutex_unlock(&dev->struct_mutex);
 
        /* flush any delayed tasks or pending work */
This page took 0.070287 seconds and 5 git commands to generate.