drm/i915: s/pm._irqs_disabled/pm.irqs_enabled/
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 7e20b00d56a3cd5e26465f63a6910431b85c2587..6fc77a100cc66ea9d29fb00df145e4d44e6894e7 100644 (file)
@@ -76,8 +76,6 @@ static const uint32_t intel_cursor_formats[] = {
 #define DIV_ROUND_CLOSEST_ULL(ll, d)   \
 ({ unsigned long long _tmp = (ll)+(d)/2; do_div(_tmp, d); _tmp; })
 
-static void intel_increase_pllclock(struct drm_device *dev,
-                                   enum pipe pipe);
 static void intel_crtc_update_cursor(struct drm_crtc *crtc, bool on);
 
 static void i9xx_crtc_clock_get(struct intel_crtc *crtc,
@@ -892,60 +890,6 @@ enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
        return intel_crtc->config.cpu_transcoder;
 }
 
-static void g4x_wait_for_vblank(struct drm_device *dev, int pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 frame, frame_reg = PIPE_FRMCOUNT_GM45(pipe);
-
-       frame = I915_READ(frame_reg);
-
-       if (wait_for(I915_READ_NOTRACE(frame_reg) != frame, 50))
-               WARN(1, "vblank wait on pipe %c timed out\n",
-                    pipe_name(pipe));
-}
-
-/**
- * intel_wait_for_vblank - wait for vblank on a given pipe
- * @dev: drm device
- * @pipe: pipe to wait for
- *
- * Wait for vblank to occur on a given pipe.  Needed for various bits of
- * mode setting code.
- */
-void intel_wait_for_vblank(struct drm_device *dev, int pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipestat_reg = PIPESTAT(pipe);
-
-       if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
-               g4x_wait_for_vblank(dev, pipe);
-               return;
-       }
-
-       /* Clear existing vblank status. Note this will clear any other
-        * sticky status fields as well.
-        *
-        * This races with i915_driver_irq_handler() with the result
-        * that either function could miss a vblank event.  Here it is not
-        * fatal, as we will either wait upon the next vblank interrupt or
-        * timeout.  Generally speaking intel_wait_for_vblank() is only
-        * called during modeset at which time the GPU should be idle and
-        * should *not* be performing page flips and thus not waiting on
-        * vblanks...
-        * Currently, the result of us stealing a vblank from the irq
-        * handler is that a single frame will be skipped during swapbuffers.
-        */
-       I915_WRITE(pipestat_reg,
-                  I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS);
-
-       /* Wait for vblank interrupt bit to set */
-       if (wait_for(I915_READ(pipestat_reg) &
-                    PIPE_VBLANK_INTERRUPT_STATUS,
-                    50))
-               DRM_DEBUG_KMS("vblank wait on pipe %c timed out\n",
-                             pipe_name(pipe));
-}
-
 static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1192,8 +1136,8 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
             state_string(state), state_string(cur_state));
 }
 
-static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
-                                 enum pipe pipe)
+void assert_panel_unlocked(struct drm_i915_private *dev_priv,
+                          enum pipe pipe)
 {
        struct drm_device *dev = dev_priv->dev;
        int pp_reg;
@@ -1266,7 +1210,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
            (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
                state = true;
 
-       if (!intel_display_power_enabled(dev_priv,
+       if (!intel_display_power_is_enabled(dev_priv,
                                POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
                cur_state = false;
        } else {
@@ -1335,7 +1279,14 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
        int reg, sprite;
        u32 val;
 
-       if (IS_VALLEYVIEW(dev)) {
+       if (INTEL_INFO(dev)->gen >= 9) {
+               for_each_sprite(pipe, sprite) {
+                       val = I915_READ(PLANE_CTL(pipe, sprite));
+                       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) {
                        reg = SPCNTR(pipe, sprite);
                        val = I915_READ(reg);
@@ -1358,6 +1309,12 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
        }
 }
 
+static void assert_vblank_disabled(struct drm_crtc *crtc)
+{
+       if (WARN_ON(drm_crtc_vblank_get(crtc) == 0))
+               drm_crtc_vblank_put(crtc);
+}
+
 static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
 {
        u32 val;
@@ -1606,6 +1563,18 @@ static void chv_enable_pll(struct intel_crtc *crtc)
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
+static int intel_num_dvo_pipes(struct drm_device *dev)
+{
+       struct intel_crtc *crtc;
+       int count = 0;
+
+       for_each_intel_crtc(dev, crtc)
+               count += crtc->active &&
+                       intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO);
+
+       return count;
+}
+
 static void i9xx_enable_pll(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
@@ -1622,7 +1591,18 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
        if (IS_MOBILE(dev) && !IS_I830(dev))
                assert_panel_unlocked(dev_priv, crtc->pipe);
 
-       I915_WRITE(reg, dpll);
+       /* Enable DVO 2x clock on both PLLs if necessary */
+       if (IS_I830(dev) && intel_num_dvo_pipes(dev) > 0) {
+               /*
+                * It appears to be important that we don't enable this
+                * for the current pipe before otherwise configuring the
+                * PLL. No idea how this should be handled if multiple
+                * DVO outputs are enabled simultaneosly.
+                */
+               dpll |= DPLL_DVO_2X_MODE;
+               I915_WRITE(DPLL(!crtc->pipe),
+                          I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
+       }
 
        /* Wait for the clocks to stabilize. */
        POSTING_READ(reg);
@@ -1661,8 +1641,22 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
  *
  * Note!  This is for pre-ILK only.
  */
-static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+static void i9xx_disable_pll(struct intel_crtc *crtc)
 {
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum pipe pipe = crtc->pipe;
+
+       /* Disable DVO 2x clock on both PLLs if necessary */
+       if (IS_I830(dev) &&
+           intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO) &&
+           intel_num_dvo_pipes(dev) == 1) {
+               I915_WRITE(DPLL(PIPE_B),
+                          I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
+               I915_WRITE(DPLL(PIPE_A),
+                          I915_READ(DPLL(PIPE_A)) & ~DPLL_DVO_2X_MODE);
+       }
+
        /* Don't disable pipe or pipe PLLs if needed */
        if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
            (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
@@ -1858,7 +1852,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        uint32_t reg, val, pipeconf_val;
 
        /* PCH only available on ILK+ */
-       BUG_ON(INTEL_INFO(dev)->gen < 5);
+       BUG_ON(!HAS_PCH_SPLIT(dev));
 
        /* Make sure PCH DPLL is enabled */
        assert_shared_dpll_enabled(dev_priv,
@@ -1911,7 +1905,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        u32 val, pipeconf_val;
 
        /* PCH only available on ILK+ */
-       BUG_ON(INTEL_INFO(dev_priv->dev)->gen < 5);
+       BUG_ON(!HAS_PCH_SPLIT(dev_priv->dev));
 
        /* FDI must be feeding us bits for PCH ports */
        assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
@@ -2193,7 +2187,9 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
 
        switch (obj->tiling_mode) {
        case I915_TILING_NONE:
-               if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
+               if (INTEL_INFO(dev)->gen >= 9)
+                       alignment = 256 * 1024;
+               else if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
                        alignment = 128 * 1024;
                else if (INTEL_INFO(dev)->gen >= 4)
                        alignment = 4 * 1024;
@@ -2201,8 +2197,12 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
                        alignment = 64 * 1024;
                break;
        case I915_TILING_X:
-               /* pin() will align the object as required by fence */
-               alignment = 0;
+               if (INTEL_INFO(dev)->gen >= 9)
+                       alignment = 256 * 1024;
+               else {
+                       /* pin() will align the object as required by fence */
+                       alignment = 0;
+               }
                break;
        case I915_TILING_Y:
                WARN(1, "Y tiled bo slipped through, driver bug!\n");
@@ -2219,6 +2219,15 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
        if (need_vtd_wa(dev) && alignment < 256 * 1024)
                alignment = 256 * 1024;
 
+       /*
+        * Global gtt pte registers are special registers which actually forward
+        * writes to a chunk of system memory. Which means that there is no risk
+        * that the register values disappear as soon as we call
+        * intel_runtime_pm_put(), so it is correct to wrap only the
+        * pin/unpin/fence and not more.
+        */
+       intel_runtime_pm_get(dev_priv);
+
        dev_priv->mm.interruptible = false;
        ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
        if (ret)
@@ -2236,12 +2245,14 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
        i915_gem_object_pin_fence(obj);
 
        dev_priv->mm.interruptible = true;
+       intel_runtime_pm_put(dev_priv);
        return 0;
 
 err_unpin:
        i915_gem_object_unpin_from_display_plane(obj);
 err_interruptible:
        dev_priv->mm.interruptible = true;
+       intel_runtime_pm_put(dev_priv);
        return ret;
 }
 
@@ -2621,6 +2632,90 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,
        POSTING_READ(reg);
 }
 
+static void skylake_update_primary_plane(struct drm_crtc *crtc,
+                                        struct drm_framebuffer *fb,
+                                        int x, int y)
+{
+       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;
+
+       if (!intel_crtc->primary_enabled) {
+               I915_WRITE(PLANE_CTL(pipe, 0), 0);
+               I915_WRITE(PLANE_SURF(pipe, 0), 0);
+               POSTING_READ(PLANE_CTL(pipe, 0));
+               return;
+       }
+
+       plane_ctl = PLANE_CTL_ENABLE |
+                   PLANE_CTL_PIPE_GAMMA_ENABLE |
+                   PLANE_CTL_PIPE_CSC_ENABLE;
+
+       switch (fb->pixel_format) {
+       case DRM_FORMAT_RGB565:
+               plane_ctl |= PLANE_CTL_FORMAT_RGB_565;
+               break;
+       case DRM_FORMAT_XRGB8888:
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888;
+               break;
+       case DRM_FORMAT_XBGR8888:
+               plane_ctl |= PLANE_CTL_ORDER_RGBX;
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_8888;
+               break;
+       case DRM_FORMAT_XRGB2101010:
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_2101010;
+               break;
+       case DRM_FORMAT_XBGR2101010:
+               plane_ctl |= PLANE_CTL_ORDER_RGBX;
+               plane_ctl |= PLANE_CTL_FORMAT_XRGB_2101010;
+               break;
+       default:
+               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;
+               break;
+       case I915_TILING_X:
+               plane_ctl |= PLANE_CTL_TILED_X;
+               stride = fb->pitches[0] >> 9;
+               break;
+       default:
+               BUG();
+       }
+
+       plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
+
+       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]);
+
+       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));
+
+       POSTING_READ(PLANE_SURF(pipe, 0));
+}
+
 /* Assume fb object is pinned & idle & fenced and just update base pointers */
 static int
 intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
@@ -2631,7 +2726,6 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
        if (dev_priv->display.disable_fbc)
                dev_priv->display.disable_fbc(dev);
-       intel_increase_pllclock(dev, to_intel_crtc(crtc)->pipe);
 
        dev_priv->display.update_primary_plane(crtc, fb, x, y);
 
@@ -2711,20 +2805,58 @@ static bool intel_crtc_has_pending_flip(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);
-       unsigned long flags;
        bool pending;
 
        if (i915_reset_in_progress(&dev_priv->gpu_error) ||
            intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
                return false;
 
-       spin_lock_irqsave(&dev->event_lock, flags);
+       spin_lock_irq(&dev->event_lock);
        pending = to_intel_crtc(crtc)->unpin_work != NULL;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+       spin_unlock_irq(&dev->event_lock);
 
        return pending;
 }
 
+static void intel_update_pipe_size(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       const struct drm_display_mode *adjusted_mode;
+
+       if (!i915.fastboot)
+               return;
+
+       /*
+        * Update pipe size and adjust fitter if needed: the reason for this is
+        * that in compute_mode_changes we check the native mode (not the pfit
+        * mode) to see if we can flip rather than do a full mode set. In the
+        * fastboot case, we'll flip, but if we don't update the pipesrc and
+        * pfit state, we'll end up with a big fb scanned out into the wrong
+        * sized surface.
+        *
+        * To fix this properly, we need to hoist the checks up into
+        * compute_mode_changes (or above), check the actual pfit state and
+        * whether the platform allows pfit disable with pipe active, and only
+        * then update the pipesrc and pfit state, even on the flip path.
+        */
+
+       adjusted_mode = &crtc->config.adjusted_mode;
+
+       I915_WRITE(PIPESRC(crtc->pipe),
+                  ((adjusted_mode->crtc_hdisplay - 1) << 16) |
+                  (adjusted_mode->crtc_vdisplay - 1));
+       if (!crtc->config.pch_pfit.enabled &&
+           (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) ||
+            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP))) {
+               I915_WRITE(PF_CTL(crtc->pipe), 0);
+               I915_WRITE(PF_WIN_POS(crtc->pipe), 0);
+               I915_WRITE(PF_WIN_SZ(crtc->pipe), 0);
+       }
+       crtc->config.pipe_src_w = adjusted_mode->crtc_hdisplay;
+       crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay;
+}
+
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                    struct drm_framebuffer *fb)
@@ -2767,36 +2899,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                return ret;
        }
 
-       /*
-        * Update pipe size and adjust fitter if needed: the reason for this is
-        * that in compute_mode_changes we check the native mode (not the pfit
-        * mode) to see if we can flip rather than do a full mode set. In the
-        * fastboot case, we'll flip, but if we don't update the pipesrc and
-        * pfit state, we'll end up with a big fb scanned out into the wrong
-        * sized surface.
-        *
-        * To fix this properly, we need to hoist the checks up into
-        * compute_mode_changes (or above), check the actual pfit state and
-        * whether the platform allows pfit disable with pipe active, and only
-        * then update the pipesrc and pfit state, even on the flip path.
-        */
-       if (i915.fastboot) {
-               const struct drm_display_mode *adjusted_mode =
-                       &intel_crtc->config.adjusted_mode;
-
-               I915_WRITE(PIPESRC(intel_crtc->pipe),
-                          ((adjusted_mode->crtc_hdisplay - 1) << 16) |
-                          (adjusted_mode->crtc_vdisplay - 1));
-               if (!intel_crtc->config.pch_pfit.enabled &&
-                   (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
-                    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
-                       I915_WRITE(PF_CTL(intel_crtc->pipe), 0);
-                       I915_WRITE(PF_WIN_POS(intel_crtc->pipe), 0);
-                       I915_WRITE(PF_WIN_SZ(intel_crtc->pipe), 0);
-               }
-               intel_crtc->config.pipe_src_w = adjusted_mode->crtc_hdisplay;
-               intel_crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay;
-       }
+       intel_update_pipe_size(intel_crtc);
 
        dev_priv->display.update_primary_plane(crtc, fb, x, y);
 
@@ -3388,15 +3491,47 @@ bool intel_has_pending_fb_unpin(struct drm_device *dev)
        return false;
 }
 
+static void page_flip_completed(struct intel_crtc *intel_crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+       struct intel_unpin_work *work = intel_crtc->unpin_work;
+
+       /* ensure that the unpin work is consistent wrt ->pending. */
+       smp_rmb();
+       intel_crtc->unpin_work = NULL;
+
+       if (work->event)
+               drm_send_vblank_event(intel_crtc->base.dev,
+                                     intel_crtc->pipe,
+                                     work->event);
+
+       drm_crtc_vblank_put(&intel_crtc->base);
+
+       wake_up_all(&dev_priv->pending_flip_queue);
+       queue_work(dev_priv->wq, &work->work);
+
+       trace_i915_flip_complete(intel_crtc->plane,
+                                work->pending_flip_obj);
+}
+
 void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
-       WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
-                                  !intel_crtc_has_pending_flip(crtc),
-                                  60*HZ) == 0);
+       if (WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
+                                      !intel_crtc_has_pending_flip(crtc),
+                                      60*HZ) == 0)) {
+               struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+               spin_lock_irq(&dev->event_lock);
+               if (intel_crtc->unpin_work) {
+                       WARN_ONCE(1, "Removing stuck page flip\n");
+                       page_flip_completed(intel_crtc);
+               }
+               spin_unlock_irq(&dev->event_lock);
+       }
 
        if (crtc->primary->fb) {
                mutex_lock(&dev->struct_mutex);
@@ -3954,8 +4089,6 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
 
-       drm_vblank_on(dev, pipe);
-
        intel_enable_primary_hw_plane(crtc->primary, crtc);
        intel_enable_planes(crtc);
        intel_crtc_update_cursor(crtc, true);
@@ -4001,8 +4134,6 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc)
         * consider this a flip to a NULL plane.
         */
        intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
-
-       drm_vblank_off(dev, pipe);
 }
 
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
@@ -4072,6 +4203,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        if (HAS_PCH_CPT(dev))
                cpt_verify_modeset(dev, intel_crtc->pipe);
 
+       assert_vblank_disabled(crtc);
+       drm_crtc_vblank_on(crtc);
+
        intel_crtc_enable_planes(crtc);
 }
 
@@ -4179,6 +4313,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
                intel_opregion_notify_encoder(encoder, true);
        }
 
+       assert_vblank_disabled(crtc);
+       drm_crtc_vblank_on(crtc);
+
        /* If we change the relative order between pipe/planes enabling, we need
         * to change the workaround. */
        haswell_mode_set_planes_workaround(intel_crtc);
@@ -4214,6 +4351,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
        intel_crtc_disable_planes(crtc);
 
+       drm_crtc_vblank_off(crtc);
+       assert_vblank_disabled(crtc);
+
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->disable(encoder);
 
@@ -4222,9 +4362,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
        intel_disable_pipe(intel_crtc);
 
-       if (intel_crtc->config.dp_encoder_is_mst)
-               intel_ddi_set_vc_payload_alloc(crtc, false);
-
        ironlake_pfit_disable(intel_crtc);
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4279,6 +4416,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
        intel_crtc_disable_planes(crtc);
 
+       drm_crtc_vblank_off(crtc);
+       assert_vblank_disabled(crtc);
+
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                intel_opregion_notify_encoder(encoder, false);
                encoder->disable(encoder);
@@ -4288,6 +4428,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
                intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
        intel_disable_pipe(intel_crtc);
 
+       if (intel_crtc->config.dp_encoder_is_mst)
+               intel_ddi_set_vc_payload_alloc(crtc, false);
+
        intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
        ironlake_pfit_disable(intel_crtc);
@@ -4417,20 +4560,6 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
        return mask;
 }
 
-void intel_display_set_init_power(struct drm_i915_private *dev_priv,
-                                 bool enable)
-{
-       if (dev_priv->power_domains.init_power_on == enable)
-               return;
-
-       if (enable)
-               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
-       else
-               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-
-       dev_priv->power_domains.init_power_on = enable;
-}
-
 static void modeset_update_crtc_power_domains(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4742,6 +4871,9 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
 
+       assert_vblank_disabled(crtc);
+       drm_crtc_vblank_on(crtc);
+
        intel_crtc_enable_planes(crtc);
 
        /* Underruns don't raise interrupts, so check manually. */
@@ -4799,6 +4931,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
        for_each_encoder_on_crtc(dev, crtc, encoder)
                encoder->enable(encoder);
 
+       assert_vblank_disabled(crtc);
+       drm_crtc_vblank_on(crtc);
+
        intel_crtc_enable_planes(crtc);
 
        /*
@@ -4862,9 +4997,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        intel_set_memory_cxsr(dev_priv, false);
        intel_crtc_disable_planes(crtc);
 
-       for_each_encoder_on_crtc(dev, crtc, encoder)
-               encoder->disable(encoder);
-
        /*
         * On gen2 planes are double buffered but the pipe isn't, so we must
         * wait for planes to fully turn off before disabling the pipe.
@@ -4873,6 +5005,12 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
         */
        intel_wait_for_vblank(dev, pipe);
 
+       drm_crtc_vblank_off(crtc);
+       assert_vblank_disabled(crtc);
+
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               encoder->disable(encoder);
+
        intel_disable_pipe(intel_crtc);
 
        i9xx_pfit_disable(intel_crtc);
@@ -4887,7 +5025,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
                else if (IS_VALLEYVIEW(dev))
                        vlv_disable_pll(dev_priv, pipe);
                else
-                       i9xx_disable_pll(dev_priv, pipe);
+                       i9xx_disable_pll(intel_crtc);
        }
 
        if (!IS_GEN2(dev))
@@ -5891,7 +6029,7 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
                        dpll |= PLL_P2_DIVIDE_BY_4;
        }
 
-       if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO))
+       if (!IS_I830(dev) && intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DVO))
                dpll |= DPLL_DVO_2X_MODE;
 
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
@@ -6341,8 +6479,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
-       if (!intel_display_power_enabled(dev_priv,
-                                        POWER_DOMAIN_PIPE(crtc->pipe)))
+       if (!intel_display_power_is_enabled(dev_priv,
+                                           POWER_DOMAIN_PIPE(crtc->pipe)))
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
@@ -6397,6 +6535,14 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        }
        pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
        if (!IS_VALLEYVIEW(dev)) {
+               /*
+                * DPLL_DVO_2X_MODE must be enabled for both DPLLs
+                * on 830. Filter it out here so that we don't
+                * report errors due to that.
+                */
+               if (IS_I830(dev))
+                       pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE;
+
                pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe));
                pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(crtc->pipe));
        } else {
@@ -6920,7 +7066,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc)
        I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
        POSTING_READ(GAMMA_MODE(intel_crtc->pipe));
 
-       if (IS_BROADWELL(dev)) {
+       if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
                val = 0;
 
                switch (intel_crtc->config.pipe_bpp) {
@@ -7343,8 +7489,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
-       if (!intel_display_power_enabled(dev_priv,
-                                        POWER_DOMAIN_PIPE(crtc->pipe)))
+       if (!intel_display_power_is_enabled(dev_priv,
+                                           POWER_DOMAIN_PIPE(crtc->pipe)))
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
@@ -7537,7 +7683,6 @@ static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
 static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
 {
        uint32_t val;
-       unsigned long irqflags;
 
        val = I915_READ(LCPLL_CTL);
 
@@ -7557,10 +7702,10 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
         * to call special forcewake code that doesn't touch runtime PM and
         * doesn't enable the forcewake delayed work.
         */
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       spin_lock_irq(&dev_priv->uncore.lock);
        if (dev_priv->uncore.forcewake_count++ == 0)
                dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+       spin_unlock_irq(&dev_priv->uncore.lock);
 
        if (val & LCPLL_POWER_DOWN_ALLOW) {
                val &= ~LCPLL_POWER_DOWN_ALLOW;
@@ -7591,10 +7736,10 @@ static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
        }
 
        /* See the big comment above. */
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       spin_lock_irq(&dev_priv->uncore.lock);
        if (--dev_priv->uncore.forcewake_count == 0)
                dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+       spin_unlock_irq(&dev_priv->uncore.lock);
 }
 
 /*
@@ -7723,7 +7868,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
         * DDI E. So just check whether this pipe is wired to DDI E and whether
         * the PCH transcoder is on.
         */
-       if ((port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
+       if (INTEL_INFO(dev)->gen < 9 &&
+           (port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
                pipe_config->has_pch_encoder = true;
 
                tmp = I915_READ(FDI_RX_CTL(PIPE_A));
@@ -7742,7 +7888,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        enum intel_display_power_domain pfit_domain;
        uint32_t tmp;
 
-       if (!intel_display_power_enabled(dev_priv,
+       if (!intel_display_power_is_enabled(dev_priv,
                                         POWER_DOMAIN_PIPE(crtc->pipe)))
                return false;
 
@@ -7771,7 +7917,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                        pipe_config->cpu_transcoder = TRANSCODER_EDP;
        }
 
-       if (!intel_display_power_enabled(dev_priv,
+       if (!intel_display_power_is_enabled(dev_priv,
                        POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
                return false;
 
@@ -7784,7 +7930,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        intel_get_pipe_timings(crtc, pipe_config);
 
        pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
-       if (intel_display_power_enabled(dev_priv, pfit_domain))
+       if (intel_display_power_is_enabled(dev_priv, pfit_domain))
                ironlake_get_pfit_config(crtc, pipe_config);
 
        if (IS_HASWELL(dev))
@@ -8149,8 +8295,10 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
                intel_crtc->cursor_cntl = 0;
        }
 
-       if (intel_crtc->cursor_base != base)
+       if (intel_crtc->cursor_base != base) {
                I915_WRITE(_CURABASE, base);
+               intel_crtc->cursor_base = base;
+       }
 
        if (intel_crtc->cursor_size != size) {
                I915_WRITE(CURSIZE, size);
@@ -8190,9 +8338,10 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
                                return;
                }
                cntl |= pipe << 28; /* Connect to correct pipe */
+
+               if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+                       cntl |= CURSOR_PIPE_CSC_ENABLE;
        }
-       if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-               cntl |= CURSOR_PIPE_CSC_ENABLE;
 
        if (intel_crtc->cursor_cntl != cntl) {
                I915_WRITE(CURCNTR(pipe), cntl);
@@ -8203,6 +8352,8 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
        /* and commit changes on next vblank */
        I915_WRITE(CURBASE(pipe), base);
        POSTING_READ(CURBASE(pipe));
+
+       intel_crtc->cursor_base = base;
 }
 
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
@@ -8253,7 +8404,6 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
                i845_update_cursor(crtc, base);
        else
                i9xx_update_cursor(crtc, base);
-       intel_crtc->cursor_base = base;
 }
 
 static bool cursor_size_ok(struct drm_device *dev,
@@ -8305,6 +8455,7 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
                                     uint32_t width, uint32_t height)
 {
        struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum pipe pipe = intel_crtc->pipe;
        unsigned old_width, stride;
@@ -8343,6 +8494,15 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
                        goto fail_locked;
                }
 
+               /*
+                * Global gtt pte registers are special registers which actually
+                * forward writes to a chunk of system memory. Which means that
+                * there is no risk that the register values disappear as soon
+                * as we call intel_runtime_pm_put(), so it is correct to wrap
+                * only the pin/unpin/fence and not more.
+                */
+               intel_runtime_pm_get(dev_priv);
+
                /* Note that the w/a also requires 2 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
@@ -8355,16 +8515,20 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
                ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
                if (ret) {
                        DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n");
+                       intel_runtime_pm_put(dev_priv);
                        goto fail_locked;
                }
 
                ret = i915_gem_object_put_fence(obj);
                if (ret) {
                        DRM_DEBUG_KMS("failed to release fence for cursor");
+                       intel_runtime_pm_put(dev_priv);
                        goto fail_unpin;
                }
 
                addr = i915_gem_obj_ggtt_offset(obj);
+
+               intel_runtime_pm_put(dev_priv);
        } else {
                int align = IS_I830(dev) ? 16 * 1024 : 256;
                ret = i915_gem_object_attach_phys(obj, align);
@@ -8903,35 +9067,6 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
        return mode;
 }
 
-static void intel_increase_pllclock(struct drm_device *dev,
-                                   enum pipe pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int dpll_reg = DPLL(pipe);
-       int dpll;
-
-       if (!HAS_GMCH_DISPLAY(dev))
-               return;
-
-       if (!dev_priv->lvds_downclock_avail)
-               return;
-
-       dpll = I915_READ(dpll_reg);
-       if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
-               DRM_DEBUG_DRIVER("upclocking LVDS\n");
-
-               assert_panel_unlocked(dev_priv, pipe);
-
-               dpll &= ~DISPLAY_RATE_SELECT_FPA1;
-               I915_WRITE(dpll_reg, dpll);
-               intel_wait_for_vblank(dev, pipe);
-
-               dpll = I915_READ(dpll_reg);
-               if (dpll & DISPLAY_RATE_SELECT_FPA1)
-                       DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
-       }
-}
-
 static void intel_decrease_pllclock(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -9007,194 +9142,16 @@ out:
        intel_runtime_pm_put(dev_priv);
 }
 
-
-/**
- * intel_mark_fb_busy - mark given planes as busy
- * @dev: DRM device
- * @frontbuffer_bits: bits for the affected planes
- * @ring: optional ring for asynchronous commands
- *
- * This function gets called every time the screen contents change. It can be
- * used to keep e.g. the update rate at the nominal refresh rate with DRRS.
- */
-static void intel_mark_fb_busy(struct drm_device *dev,
-                              unsigned frontbuffer_bits,
-                              struct intel_engine_cs *ring)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       enum pipe pipe;
-
-       if (!i915.powersave)
-               return;
-
-       for_each_pipe(dev_priv, pipe) {
-               if (!(frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe)))
-                       continue;
-
-               intel_increase_pllclock(dev, pipe);
-               if (ring && intel_fbc_enabled(dev))
-                       ring->fbc_dirty = true;
-       }
-}
-
-/**
- * intel_fb_obj_invalidate - invalidate frontbuffer object
- * @obj: GEM object to invalidate
- * @ring: set for asynchronous rendering
- *
- * This function gets called every time rendering on the given object starts and
- * frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must
- * be invalidated. If @ring is non-NULL any subsequent invalidation will be delayed
- * until the rendering completes or a flip on this frontbuffer plane is
- * scheduled.
- */
-void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
-                            struct intel_engine_cs *ring)
-{
-       struct drm_device *dev = obj->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
-       if (!obj->frontbuffer_bits)
-               return;
-
-       if (ring) {
-               mutex_lock(&dev_priv->fb_tracking.lock);
-               dev_priv->fb_tracking.busy_bits
-                       |= obj->frontbuffer_bits;
-               dev_priv->fb_tracking.flip_bits
-                       &= ~obj->frontbuffer_bits;
-               mutex_unlock(&dev_priv->fb_tracking.lock);
-       }
-
-       intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring);
-
-       intel_edp_psr_invalidate(dev, obj->frontbuffer_bits);
-}
-
-/**
- * intel_frontbuffer_flush - flush frontbuffer
- * @dev: DRM device
- * @frontbuffer_bits: frontbuffer plane tracking bits
- *
- * This function gets called every time rendering on the given planes has
- * completed and frontbuffer caching can be started again. Flushes will get
- * delayed if they're blocked by some oustanding asynchronous rendering.
- *
- * Can be called without any locks held.
- */
-void intel_frontbuffer_flush(struct drm_device *dev,
-                            unsigned frontbuffer_bits)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       /* Delay flushing when rings are still busy.*/
-       mutex_lock(&dev_priv->fb_tracking.lock);
-       frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits;
-       mutex_unlock(&dev_priv->fb_tracking.lock);
-
-       intel_mark_fb_busy(dev, frontbuffer_bits, NULL);
-
-       intel_edp_psr_flush(dev, frontbuffer_bits);
-
-       if (IS_GEN8(dev))
-               gen8_fbc_sw_flush(dev, FBC_REND_CACHE_CLEAN);
-}
-
-/**
- * intel_fb_obj_flush - flush frontbuffer object
- * @obj: GEM object to flush
- * @retire: set when retiring asynchronous rendering
- *
- * This function gets called every time rendering on the given object has
- * completed and frontbuffer caching can be started again. If @retire is true
- * then any delayed flushes will be unblocked.
- */
-void intel_fb_obj_flush(struct drm_i915_gem_object *obj,
-                       bool retire)
-{
-       struct drm_device *dev = obj->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned frontbuffer_bits;
-
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
-       if (!obj->frontbuffer_bits)
-               return;
-
-       frontbuffer_bits = obj->frontbuffer_bits;
-
-       if (retire) {
-               mutex_lock(&dev_priv->fb_tracking.lock);
-               /* Filter out new bits since rendering started. */
-               frontbuffer_bits &= dev_priv->fb_tracking.busy_bits;
-
-               dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits;
-               mutex_unlock(&dev_priv->fb_tracking.lock);
-       }
-
-       intel_frontbuffer_flush(dev, frontbuffer_bits);
-}
-
-/**
- * intel_frontbuffer_flip_prepare - prepare asnychronous frontbuffer flip
- * @dev: DRM device
- * @frontbuffer_bits: frontbuffer plane tracking bits
- *
- * This function gets called after scheduling a flip on @obj. The actual
- * frontbuffer flushing will be delayed until completion is signalled with
- * intel_frontbuffer_flip_complete. If an invalidate happens in between this
- * flush will be cancelled.
- *
- * Can be called without any locks held.
- */
-void intel_frontbuffer_flip_prepare(struct drm_device *dev,
-                                   unsigned frontbuffer_bits)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       mutex_lock(&dev_priv->fb_tracking.lock);
-       dev_priv->fb_tracking.flip_bits
-               |= frontbuffer_bits;
-       mutex_unlock(&dev_priv->fb_tracking.lock);
-}
-
-/**
- * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flush
- * @dev: DRM device
- * @frontbuffer_bits: frontbuffer plane tracking bits
- *
- * This function gets called after the flip has been latched and will complete
- * on the next vblank. It will execute the fush if it hasn't been cancalled yet.
- *
- * Can be called without any locks held.
- */
-void intel_frontbuffer_flip_complete(struct drm_device *dev,
-                                    unsigned frontbuffer_bits)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       mutex_lock(&dev_priv->fb_tracking.lock);
-       /* Mask any cancelled flips. */
-       frontbuffer_bits &= dev_priv->fb_tracking.flip_bits;
-       dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits;
-       mutex_unlock(&dev_priv->fb_tracking.lock);
-
-       intel_frontbuffer_flush(dev, frontbuffer_bits);
-}
-
 static void intel_crtc_destroy(struct drm_crtc *crtc)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct intel_unpin_work *work;
-       unsigned long flags;
 
-       spin_lock_irqsave(&dev->event_lock, flags);
+       spin_lock_irq(&dev->event_lock);
        work = intel_crtc->unpin_work;
        intel_crtc->unpin_work = NULL;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+       spin_unlock_irq(&dev->event_lock);
 
        if (work) {
                cancel_work_sync(&work->work);
@@ -9232,7 +9189,6 @@ static void intel_unpin_work_fn(struct work_struct *__work)
 static void do_intel_finish_page_flip(struct drm_device *dev,
                                      struct drm_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_unpin_work *work;
        unsigned long flags;
@@ -9241,6 +9197,10 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
        if (intel_crtc == NULL)
                return;
 
+       /*
+        * This is called both by irq handlers and the reset code (to complete
+        * lost pageflips) so needs the full irqsave spinlocks.
+        */
        spin_lock_irqsave(&dev->event_lock, flags);
        work = intel_crtc->unpin_work;
 
@@ -9252,23 +9212,9 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
                return;
        }
 
-       /* and that the unpin work is consistent wrt ->pending. */
-       smp_rmb();
-
-       intel_crtc->unpin_work = NULL;
-
-       if (work->event)
-               drm_send_vblank_event(dev, intel_crtc->pipe, work->event);
-
-       drm_crtc_vblank_put(crtc);
+       page_flip_completed(intel_crtc);
 
        spin_unlock_irqrestore(&dev->event_lock, flags);
-
-       wake_up_all(&dev_priv->pending_flip_queue);
-
-       queue_work(dev_priv->wq, &work->work);
-
-       trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
 }
 
 void intel_finish_page_flip(struct drm_device *dev, int pipe)
@@ -9336,7 +9282,12 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
                to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
        unsigned long flags;
 
-       /* NB: An MMIO update of the plane base pointer will also
+
+       /*
+        * This is called both by irq handlers and the reset code (to complete
+        * lost pageflips) so needs the full irqsave spinlocks.
+        *
+        * NB: An MMIO update of the plane base pointer will also
         * generate a page-flip completion irq, i.e. every modeset
         * is also accompanied by a spurious intel_prepare_page_flip().
         */
@@ -9711,7 +9662,6 @@ static int intel_queue_mmio_flip(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       unsigned long irq_flags;
        int ret;
 
        if (WARN_ON(intel_crtc->mmio_flip.seqno))
@@ -9725,10 +9675,10 @@ static int intel_queue_mmio_flip(struct drm_device *dev,
                return 0;
        }
 
-       spin_lock_irqsave(&dev_priv->mmio_flip_lock, irq_flags);
+       spin_lock_irq(&dev_priv->mmio_flip_lock);
        intel_crtc->mmio_flip.seqno = obj->last_write_seqno;
        intel_crtc->mmio_flip.ring_id = obj->ring->id;
-       spin_unlock_irqrestore(&dev_priv->mmio_flip_lock, irq_flags);
+       spin_unlock_irq(&dev_priv->mmio_flip_lock);
 
        /*
         * Double check to catch cases where irq fired before
@@ -9748,6 +9698,66 @@ static int intel_default_queue_flip(struct drm_device *dev,
        return -ENODEV;
 }
 
+static bool __intel_pageflip_stall_check(struct drm_device *dev,
+                                        struct drm_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_unpin_work *work = intel_crtc->unpin_work;
+       u32 addr;
+
+       if (atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE)
+               return true;
+
+       if (!work->enable_stall_check)
+               return false;
+
+       if (work->flip_ready_vblank == 0) {
+               if (work->flip_queued_ring &&
+                   !i915_seqno_passed(work->flip_queued_ring->get_seqno(work->flip_queued_ring, true),
+                                      work->flip_queued_seqno))
+                       return false;
+
+               work->flip_ready_vblank = drm_vblank_count(dev, intel_crtc->pipe);
+       }
+
+       if (drm_vblank_count(dev, intel_crtc->pipe) - work->flip_ready_vblank < 3)
+               return false;
+
+       /* Potential stall - if we see that the flip has happened,
+        * assume a missed interrupt. */
+       if (INTEL_INFO(dev)->gen >= 4)
+               addr = I915_HI_DISPBASE(I915_READ(DSPSURF(intel_crtc->plane)));
+       else
+               addr = I915_READ(DSPADDR(intel_crtc->plane));
+
+       /* There is a potential issue here with a false positive after a flip
+        * to the same address. We could address this by checking for a
+        * non-incrementing frame counter.
+        */
+       return addr == work->gtt_offset;
+}
+
+void intel_check_page_flip(struct drm_device *dev, int pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       WARN_ON(!in_irq());
+
+       if (crtc == NULL)
+               return;
+
+       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));
+               page_flip_completed(intel_crtc);
+       }
+       spin_unlock(&dev->event_lock);
+}
+
 static int intel_crtc_page_flip(struct drm_crtc *crtc,
                                struct drm_framebuffer *fb,
                                struct drm_pending_vblank_event *event,
@@ -9761,7 +9771,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        enum pipe pipe = intel_crtc->pipe;
        struct intel_unpin_work *work;
        struct intel_engine_cs *ring;
-       unsigned long flags;
        int ret;
 
        //trigger software GT busyness calculation
@@ -9805,17 +9814,25 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                goto free_work;
 
        /* We borrow the event spin lock for protecting unpin_work */
-       spin_lock_irqsave(&dev->event_lock, flags);
+       spin_lock_irq(&dev->event_lock);
        if (intel_crtc->unpin_work) {
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-               kfree(work);
-               drm_crtc_vblank_put(crtc);
+               /* Before declaring the flip queue wedged, check if
+                * the hardware completed the operation behind our backs.
+                */
+               if (__intel_pageflip_stall_check(dev, crtc)) {
+                       DRM_DEBUG_DRIVER("flip queue: previous flip completed, continuing\n");
+                       page_flip_completed(intel_crtc);
+               } else {
+                       DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
+                       spin_unlock_irq(&dev->event_lock);
 
-               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
-               return -EBUSY;
+                       drm_crtc_vblank_put(crtc);
+                       kfree(work);
+                       return -EBUSY;
+               }
        }
        intel_crtc->unpin_work = work;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+       spin_unlock_irq(&dev->event_lock);
 
        if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
                flush_workqueue(dev_priv->wq);
@@ -9832,8 +9849,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
        work->pending_flip_obj = obj;
 
-       work->enable_stall_check = true;
-
        atomic_inc(&intel_crtc->unpin_work_count);
        intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 
@@ -9862,14 +9877,26 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        work->gtt_offset =
                i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
 
-       if (use_mmio_flip(ring, obj))
+       if (use_mmio_flip(ring, obj)) {
                ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring,
                                            page_flip_flags);
-       else
+               if (ret)
+                       goto cleanup_unpin;
+
+               work->flip_queued_seqno = obj->last_write_seqno;
+               work->flip_queued_ring = obj->ring;
+       } else {
                ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, ring,
-                               page_flip_flags);
-       if (ret)
-               goto cleanup_unpin;
+                                                  page_flip_flags);
+               if (ret)
+                       goto cleanup_unpin;
+
+               work->flip_queued_seqno = intel_ring_get_seqno(ring);
+               work->flip_queued_ring = ring;
+       }
+
+       work->flip_queued_vblank = drm_vblank_count(dev, intel_crtc->pipe);
+       work->enable_stall_check = true;
 
        i915_gem_track_fb(work->old_fb_obj, obj,
                          INTEL_FRONTBUFFER_PRIMARY(pipe));
@@ -9892,9 +9919,9 @@ cleanup_pending:
        mutex_unlock(&dev->struct_mutex);
 
 cleanup:
-       spin_lock_irqsave(&dev->event_lock, flags);
+       spin_lock_irq(&dev->event_lock);
        intel_crtc->unpin_work = NULL;
-       spin_unlock_irqrestore(&dev->event_lock, flags);
+       spin_unlock_irq(&dev->event_lock);
 
        drm_crtc_vblank_put(crtc);
 free_work:
@@ -9904,8 +9931,11 @@ free_work:
 out_hang:
                intel_crtc_wait_for_pending_flips(crtc);
                ret = intel_pipe_set_base(crtc, crtc->x, crtc->y, fb);
-               if (ret == 0 && event)
+               if (ret == 0 && event) {
+                       spin_lock_irq(&dev->event_lock);
                        drm_send_vblank_event(dev, pipe, event);
+                       spin_unlock_irq(&dev->event_lock);
+               }
        }
        return ret;
 }
@@ -11490,7 +11520,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
        val = I915_READ(PCH_DPLL(pll->id));
@@ -11624,89 +11654,37 @@ disable_unpin:
 }
 
 static int
-intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
-                            struct drm_framebuffer *fb, int crtc_x, int crtc_y,
-                            unsigned int crtc_w, unsigned int crtc_h,
-                            uint32_t src_x, uint32_t src_y,
-                            uint32_t src_w, uint32_t src_h)
+intel_check_primary_plane(struct drm_plane *plane,
+                         struct intel_plane_state *state)
+{
+       struct drm_crtc *crtc = state->crtc;
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_rect *dest = &state->dst;
+       struct drm_rect *src = &state->src;
+       const struct drm_rect *clip = &state->clip;
+
+       return drm_plane_helper_check_update(plane, crtc, fb,
+                                           src, dest, clip,
+                                           DRM_PLANE_HELPER_NO_SCALING,
+                                           DRM_PLANE_HELPER_NO_SCALING,
+                                           false, true, &state->visible);
+}
+
+static int
+intel_commit_primary_plane(struct drm_plane *plane,
+                          struct intel_plane_state *state)
 {
+       struct drm_crtc *crtc = state->crtc;
+       struct drm_framebuffer *fb = state->fb;
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
        struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb);
-       struct drm_rect dest = {
-               /* integer pixels */
-               .x1 = crtc_x,
-               .y1 = crtc_y,
-               .x2 = crtc_x + crtc_w,
-               .y2 = crtc_y + crtc_h,
-       };
-       struct drm_rect src = {
-               /* 16.16 fixed point */
-               .x1 = src_x,
-               .y1 = src_y,
-               .x2 = src_x + src_w,
-               .y2 = src_y + src_h,
-       };
-       const struct drm_rect clip = {
-               /* integer pixels */
-               .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
-               .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
-       };
-       const struct {
-               int crtc_x, crtc_y;
-               unsigned int crtc_w, crtc_h;
-               uint32_t src_x, src_y, src_w, src_h;
-       } orig = {
-               .crtc_x = crtc_x,
-               .crtc_y = crtc_y,
-               .crtc_w = crtc_w,
-               .crtc_h = crtc_h,
-               .src_x = src_x,
-               .src_y = src_y,
-               .src_w = src_w,
-               .src_h = src_h,
-       };
        struct intel_plane *intel_plane = to_intel_plane(plane);
-       bool visible;
+       struct drm_rect *src = &state->src;
        int ret;
 
-       ret = drm_plane_helper_check_update(plane, crtc, fb,
-                                           &src, &dest, &clip,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           false, true, &visible);
-
-       if (ret)
-               return ret;
-
-       /*
-        * If the CRTC isn't enabled, we're just pinning the framebuffer,
-        * updating the fb pointer, and returning without touching the
-        * hardware.  This allows us to later do a drmModeSetCrtc with fb=-1 to
-        * turn on the display with all planes setup as desired.
-        */
-       if (!crtc->enabled) {
-               mutex_lock(&dev->struct_mutex);
-
-               /*
-                * If we already called setplane while the crtc was disabled,
-                * we may have an fb pinned; unpin it.
-                */
-               if (plane->fb)
-                       intel_unpin_fb_obj(old_obj);
-
-               i915_gem_track_fb(old_obj, obj,
-                                 INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe));
-
-               /* Pin and return without programming hardware */
-               ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
-               mutex_unlock(&dev->struct_mutex);
-
-               return ret;
-       }
-
        intel_crtc_wait_for_pending_flips(crtc);
 
        /*
@@ -11715,7 +11693,7 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
         * happens if userspace explicitly disables the plane by passing fb=0
         * because plane->fb still gets set and pinned.
         */
-       if (!visible) {
+       if (!state->visible) {
                mutex_lock(&dev->struct_mutex);
 
                /*
@@ -11762,7 +11740,7 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
                                intel_disable_fbc(dev);
                        }
                }
-               ret = intel_pipe_set_base(crtc, src.x1, src.y1, fb);
+               ret = intel_pipe_set_base(crtc, src->x1, src->y1, fb);
                if (ret)
                        return ret;
 
@@ -11770,19 +11748,62 @@ intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
                        intel_enable_primary_hw_plane(plane, crtc);
        }
 
-       intel_plane->crtc_x = orig.crtc_x;
-       intel_plane->crtc_y = orig.crtc_y;
-       intel_plane->crtc_w = orig.crtc_w;
-       intel_plane->crtc_h = orig.crtc_h;
-       intel_plane->src_x = orig.src_x;
-       intel_plane->src_y = orig.src_y;
-       intel_plane->src_w = orig.src_w;
-       intel_plane->src_h = orig.src_h;
+       intel_plane->crtc_x = state->orig_dst.x1;
+       intel_plane->crtc_y = state->orig_dst.y1;
+       intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
+       intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
+       intel_plane->src_x = state->orig_src.x1;
+       intel_plane->src_y = state->orig_src.y1;
+       intel_plane->src_w = drm_rect_width(&state->orig_src);
+       intel_plane->src_h = drm_rect_height(&state->orig_src);
        intel_plane->obj = obj;
 
        return 0;
 }
 
+static int
+intel_primary_plane_setplane(struct drm_plane *plane, struct drm_crtc *crtc,
+                            struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+                            unsigned int crtc_w, unsigned int crtc_h,
+                            uint32_t src_x, uint32_t src_y,
+                            uint32_t src_w, uint32_t src_h)
+{
+       struct intel_plane_state state;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int ret;
+
+       state.crtc = crtc;
+       state.fb = fb;
+
+       /* sample coordinates in 16.16 fixed point */
+       state.src.x1 = src_x;
+       state.src.x2 = src_x + src_w;
+       state.src.y1 = src_y;
+       state.src.y2 = src_y + src_h;
+
+       /* integer pixels */
+       state.dst.x1 = crtc_x;
+       state.dst.x2 = crtc_x + crtc_w;
+       state.dst.y1 = crtc_y;
+       state.dst.y2 = crtc_y + crtc_h;
+
+       state.clip.x1 = 0;
+       state.clip.y1 = 0;
+       state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
+       state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
+
+       state.orig_src = state.src;
+       state.orig_dst = state.dst;
+
+       ret = intel_check_primary_plane(plane, &state);
+       if (ret)
+               return ret;
+
+       intel_commit_primary_plane(plane, &state);
+
+       return 0;
+}
+
 /* Common destruction function for both primary and cursor planes */
 static void intel_plane_destroy(struct drm_plane *plane)
 {
@@ -11857,51 +11878,41 @@ intel_cursor_plane_disable(struct drm_plane *plane)
 }
 
 static int
-intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
-                         struct drm_framebuffer *fb, int crtc_x, int crtc_y,
-                         unsigned int crtc_w, unsigned int crtc_h,
-                         uint32_t src_x, uint32_t src_y,
-                         uint32_t src_w, uint32_t src_h)
+intel_check_cursor_plane(struct drm_plane *plane,
+                        struct intel_plane_state *state)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-       struct drm_i915_gem_object *obj = intel_fb->obj;
-       struct drm_rect dest = {
-               /* integer pixels */
-               .x1 = crtc_x,
-               .y1 = crtc_y,
-               .x2 = crtc_x + crtc_w,
-               .y2 = crtc_y + crtc_h,
-       };
-       struct drm_rect src = {
-               /* 16.16 fixed point */
-               .x1 = src_x,
-               .y1 = src_y,
-               .x2 = src_x + src_w,
-               .y2 = src_y + src_h,
-       };
-       const struct drm_rect clip = {
-               /* integer pixels */
-               .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
-               .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
-       };
-       bool visible;
-       int ret;
+       struct drm_crtc *crtc = state->crtc;
+       struct drm_framebuffer *fb = state->fb;
+       struct drm_rect *dest = &state->dst;
+       struct drm_rect *src = &state->src;
+       const struct drm_rect *clip = &state->clip;
 
-       ret = drm_plane_helper_check_update(plane, crtc, fb,
-                                           &src, &dest, &clip,
+       return drm_plane_helper_check_update(plane, crtc, fb,
+                                           src, dest, clip,
                                            DRM_PLANE_HELPER_NO_SCALING,
                                            DRM_PLANE_HELPER_NO_SCALING,
-                                           true, true, &visible);
-       if (ret)
-               return ret;
+                                           true, true, &state->visible);
+}
 
-       crtc->cursor_x = crtc_x;
-       crtc->cursor_y = crtc_y;
+static int
+intel_commit_cursor_plane(struct drm_plane *plane,
+                         struct intel_plane_state *state)
+{
+       struct drm_crtc *crtc = state->crtc;
+       struct drm_framebuffer *fb = state->fb;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct drm_i915_gem_object *obj = intel_fb->obj;
+       int crtc_w, crtc_h;
+
+       crtc->cursor_x = state->orig_dst.x1;
+       crtc->cursor_y = state->orig_dst.y1;
        if (fb != crtc->cursor->fb) {
+               crtc_w = drm_rect_width(&state->orig_dst);
+               crtc_h = drm_rect_height(&state->orig_dst);
                return intel_crtc_cursor_set_obj(crtc, obj, crtc_w, crtc_h);
        } else {
-               intel_crtc_update_cursor(crtc, visible);
+               intel_crtc_update_cursor(crtc, state->visible);
 
                intel_frontbuffer_flip(crtc->dev,
                                       INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe));
@@ -11909,6 +11920,48 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
                return 0;
        }
 }
+
+static int
+intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+                         struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+                         unsigned int crtc_w, unsigned int crtc_h,
+                         uint32_t src_x, uint32_t src_y,
+                         uint32_t src_w, uint32_t src_h)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_plane_state state;
+       int ret;
+
+       state.crtc = crtc;
+       state.fb = fb;
+
+       /* sample coordinates in 16.16 fixed point */
+       state.src.x1 = src_x;
+       state.src.x2 = src_x + src_w;
+       state.src.y1 = src_y;
+       state.src.y2 = src_y + src_h;
+
+       /* integer pixels */
+       state.dst.x1 = crtc_x;
+       state.dst.x2 = crtc_x + crtc_w;
+       state.dst.y1 = crtc_y;
+       state.dst.y2 = crtc_y + crtc_h;
+
+       state.clip.x1 = 0;
+       state.clip.y1 = 0;
+       state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
+       state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
+
+       state.orig_src = state.src;
+       state.orig_dst = state.dst;
+
+       ret = intel_check_cursor_plane(plane, &state);
+       if (ret)
+               return ret;
+
+       return intel_commit_cursor_plane(plane, &state);
+}
+
 static const struct drm_plane_funcs intel_cursor_plane_funcs = {
        .update_plane = intel_cursor_plane_update,
        .disable_plane = intel_cursor_plane_disable,
@@ -12097,6 +12150,9 @@ static bool intel_crt_present(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       if (INTEL_INFO(dev)->gen >= 9)
+               return false;
+
        if (IS_ULT(dev))
                return false;
 
@@ -12440,8 +12496,12 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
                dev_priv->display.off = ironlake_crtc_off;
-               dev_priv->display.update_primary_plane =
-                       ironlake_update_primary_plane;
+               if (INTEL_INFO(dev)->gen >= 9)
+                       dev_priv->display.update_primary_plane =
+                               skylake_update_primary_plane;
+               else
+                       dev_priv->display.update_primary_plane =
+                               ironlake_update_primary_plane;
        } else if (HAS_PCH_SPLIT(dev)) {
                dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
                dev_priv->display.get_plane_config = ironlake_get_plane_config;
@@ -12516,7 +12576,7 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.write_eld = ironlake_write_eld;
                dev_priv->display.modeset_global_resources =
                        ivb_modeset_global_resources;
-       } else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
+       } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
                dev_priv->display.fdi_link_train = hsw_fdi_link_train;
                dev_priv->display.write_eld = haswell_write_eld;
                dev_priv->display.modeset_global_resources =
@@ -12525,6 +12585,10 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.modeset_global_resources =
                        valleyview_modeset_global_resources;
                dev_priv->display.write_eld = ironlake_write_eld;
+       } else if (INTEL_INFO(dev)->gen >= 9) {
+               dev_priv->display.write_eld = haswell_write_eld;
+               dev_priv->display.modeset_global_resources =
+                       haswell_modeset_global_resources;
        }
 
        /* Default just returns -ENODEV to indicate unsupported */
@@ -12554,6 +12618,8 @@ static void intel_init_display(struct drm_device *dev)
        }
 
        intel_panel_init_backlight_funcs(dev);
+
+       mutex_init(&dev_priv->pps_mutex);
 }
 
 /*
@@ -12684,6 +12750,9 @@ static struct intel_quirk intel_quirks[] = {
        /* Acer C720 and C720P Chromebooks (Celeron 2955U) have backlights */
        { 0x0a06, 0x1025, 0x0a11, quirk_backlight_present },
 
+       /* Acer C720 Chromebook (Core i3 4005U) */
+       { 0x0a16, 0x1025, 0x0a11, quirk_backlight_present },
+
        /* Toshiba CB35 Chromebook (Celeron 2955U) */
        { 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
 
@@ -12727,7 +12796,11 @@ static void i915_disable_vga(struct drm_device *dev)
        vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
        udelay(300);
 
-       I915_WRITE(vga_reg, VGA_DISP_DISABLE);
+       /*
+        * Fujitsu-Siemens Lifebook S6010 (830) has problems resuming
+        * from S3 without preserving (some of?) the other bits.
+        */
+       I915_WRITE(vga_reg, dev_priv->bios_vgacntr | VGA_DISP_DISABLE);
        POSTING_READ(vga_reg);
 }
 
@@ -12743,11 +12816,6 @@ void intel_modeset_init_hw(struct drm_device *dev)
        intel_enable_gt_powersave(dev);
 }
 
-void intel_modeset_suspend_hw(struct drm_device *dev)
-{
-       intel_suspend_hw(dev);
-}
-
 void intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -12816,6 +12884,8 @@ void intel_modeset_init(struct drm_device *dev)
 
        intel_shared_dpll_init(dev);
 
+       /* save the BIOS value before clobbering it */
+       dev_priv->bios_vgacntr = I915_READ(i915_vgacntrl_reg(dev));
        /* Just disable it once at startup */
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
@@ -12907,9 +12977,10 @@ 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 */
-       if (crtc->active)
+       if (crtc->active) {
+               update_scanline_offset(crtc);
                drm_vblank_on(dev, crtc->pipe);
-       else
+       else
                drm_vblank_off(dev, crtc->pipe);
 
        /* We need to sanitize the plane -> pipe mapping first because this will
@@ -12992,7 +13063,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                }
        }
 
-       if (crtc->active || IS_VALLEYVIEW(dev) || INTEL_INFO(dev)->gen < 5) {
+       if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
                /*
                 * We start out with underrun reporting disabled to avoid races.
                 * For correct bookkeeping mark this on active crtcs.
@@ -13008,8 +13079,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                 */
                crtc->cpu_fifo_underrun_disabled = true;
                crtc->pch_fifo_underrun_disabled = true;
-
-               update_scanline_offset(crtc);
        }
 }
 
@@ -13082,7 +13151,7 @@ void i915_redisable_vga(struct drm_device *dev)
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
         * the rest of the driver uses. */
-       if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_VGA))
+       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_VGA))
                return;
 
        i915_redisable_vga_power_on(dev);
@@ -13303,9 +13372,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
         * Too much stuff here (turning of rps, connectors, ...) would
         * experience fancy races otherwise.
         */
-       drm_irq_uninstall(dev);
-       intel_hpd_cancel_work(dev_priv);
-       dev_priv->pm._irqs_disabled = true;
+       intel_irq_uninstall(dev_priv);
 
        /*
         * Due to the hpd irq storm handling the hotplug work can re-arm the
@@ -13460,8 +13527,8 @@ intel_display_capture_error_state(struct drm_device *dev)
 
        for_each_pipe(dev_priv, i) {
                error->pipe[i].power_domain_on =
-                       intel_display_power_enabled_unlocked(dev_priv,
-                                                          POWER_DOMAIN_PIPE(i));
+                       __intel_display_power_is_enabled(dev_priv,
+                                                        POWER_DOMAIN_PIPE(i));
                if (!error->pipe[i].power_domain_on)
                        continue;
 
@@ -13496,7 +13563,7 @@ intel_display_capture_error_state(struct drm_device *dev)
                enum transcoder cpu_transcoder = transcoders[i];
 
                error->transcoder[i].power_domain_on =
-                       intel_display_power_enabled_unlocked(dev_priv,
+                       __intel_display_power_is_enabled(dev_priv,
                                POWER_DOMAIN_TRANSCODER(cpu_transcoder));
                if (!error->transcoder[i].power_domain_on)
                        continue;
@@ -13580,9 +13647,8 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
 
        for_each_intel_crtc(dev, crtc) {
                struct intel_unpin_work *work;
-               unsigned long irqflags;
 
-               spin_lock_irqsave(&dev->event_lock, irqflags);
+               spin_lock_irq(&dev->event_lock);
 
                work = crtc->unpin_work;
 
@@ -13592,6 +13658,6 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
                        work->event = NULL;
                }
 
-               spin_unlock_irqrestore(&dev->event_lock, irqflags);
+               spin_unlock_irq(&dev->event_lock);
        }
 }
This page took 0.066952 seconds and 5 git commands to generate.