drm/i915: Fix mmio vs. CS flip race on ILK+
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / i915 / intel_display.c
index 3a5b2ed53220d3a585bad81aee85878c9fd1259d..930746527e9d8c0e46a4ed0ce0e48aa0b7d8dbe2 100644 (file)
@@ -58,6 +58,15 @@ static int intel_framebuffer_init(struct drm_device *dev,
                                  struct intel_framebuffer *ifb,
                                  struct drm_mode_fb_cmd2 *mode_cmd,
                                  struct drm_i915_gem_object *obj);
+static void intel_dp_set_m_n(struct intel_crtc *crtc);
+static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
+static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
+static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
+                                        struct intel_link_m_n *m_n);
+static void ironlake_set_pipeconf(struct drm_crtc *crtc);
+static void haswell_set_pipeconf(struct drm_crtc *crtc);
+static void intel_set_pipe_csc(struct drm_crtc *crtc);
+static void vlv_prepare_pll(struct intel_crtc *crtc);
 
 typedef struct {
        int     min, max;
@@ -962,7 +971,7 @@ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
        u32 bit;
 
        if (HAS_PCH_IBX(dev_priv->dev)) {
-               switch(port->port) {
+               switch (port->port) {
                case PORT_B:
                        bit = SDE_PORTB_HOTPLUG;
                        break;
@@ -976,7 +985,7 @@ bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
                        return true;
                }
        } else {
-               switch(port->port) {
+               switch (port->port) {
                case PORT_B:
                        bit = SDE_PORTB_HOTPLUG_CPT;
                        break;
@@ -1181,10 +1190,8 @@ static void assert_cursor(struct drm_i915_private *dev_priv,
 
        if (IS_845G(dev) || IS_I865G(dev))
                cur_state = I915_READ(_CURACNTR) & CURSOR_ENABLE;
-       else if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev))
-               cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
        else
-               cur_state = I915_READ(CURCNTR_IVB(pipe)) & CURSOR_MODE;
+               cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
 
        WARN(cur_state != state,
             "cursor on pipe %c assertion failure (expected %s, current %s)\n",
@@ -1567,7 +1574,6 @@ static void chv_enable_pll(struct intel_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = crtc->pipe;
        enum dpio_channel port = vlv_pipe_to_channel(pipe);
-       int dpll = DPLL(crtc->pipe);
        u32 tmp;
 
        assert_pipe_disabled(dev_priv, crtc->pipe);
@@ -1587,19 +1593,15 @@ static void chv_enable_pll(struct intel_crtc *crtc)
        udelay(1);
 
        /* Enable PLL */
-       tmp = I915_READ(dpll);
-       tmp |= DPLL_VCO_ENABLE;
-       I915_WRITE(dpll, tmp);
+       I915_WRITE(DPLL(pipe), crtc->config.dpll_hw_state.dpll);
 
        /* Check PLL is locked */
-       if (wait_for(((I915_READ(dpll) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
+       if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
                DRM_ERROR("PLL %d failed to lock\n", pipe);
 
-       /* Deassert soft data lane reset*/
-       tmp = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port));
-       tmp |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), tmp);
-
+       /* not sure when this should be written */
+       I915_WRITE(DPLL_MD(pipe), crtc->config.dpll_hw_state.dpll_md);
+       POSTING_READ(DPLL_MD(pipe));
 
        mutex_unlock(&dev_priv->dpio_lock);
 }
@@ -1692,14 +1694,27 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 
 static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-       int dpll = DPLL(pipe);
+       enum dpio_channel port = vlv_pipe_to_channel(pipe);
        u32 val;
 
+       /* Make sure the pipe isn't still relying on us */
+       assert_pipe_disabled(dev_priv, pipe);
+
        /* Set PLL en = 0 */
-       val = I915_READ(dpll);
-       val &= ~DPLL_VCO_ENABLE;
-       I915_WRITE(dpll, val);
+       val = DPLL_SSC_REF_CLOCK_CHV;
+       if (pipe != PIPE_A)
+               val |= DPLL_INTEGRATED_CRI_CLK_VLV;
+       I915_WRITE(DPLL(pipe), val);
+       POSTING_READ(DPLL(pipe));
+
+       mutex_lock(&dev_priv->dpio_lock);
 
+       /* Disable 10bit clock to display controller */
+       val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
+       val &= ~DPIO_DCLKP_EN;
+       vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
+
+       mutex_unlock(&dev_priv->dpio_lock);
 }
 
 void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
@@ -1730,22 +1745,36 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
                     port_name(dport->port), I915_READ(dpll_reg));
 }
 
+static void intel_prepare_shared_dpll(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
+
+       WARN_ON(!pll->refcount);
+       if (pll->active == 0) {
+               DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
+               WARN_ON(pll->on);
+               assert_shared_dpll_disabled(dev_priv, pll);
+
+               pll->mode_set(dev_priv, pll);
+       }
+}
+
 /**
- * ironlake_enable_shared_dpll - enable PCH PLL
+ * intel_enable_shared_dpll - enable PCH PLL
  * @dev_priv: i915 private structure
  * @pipe: pipe PLL to enable
  *
  * The PCH PLL needs to be enabled before the PCH transcoder, since it
  * drives the transcoder clock.
  */
-static void ironlake_enable_shared_dpll(struct intel_crtc *crtc)
+static void intel_enable_shared_dpll(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 
-       /* PCH PLLs only available on ILK, SNB and IVB */
-       BUG_ON(INTEL_INFO(dev)->gen < 5);
        if (WARN_ON(pll == NULL))
                return;
 
@@ -2330,9 +2359,9 @@ static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
        }
 }
 
-static int i9xx_update_primary_plane(struct drm_crtc *crtc,
-                                    struct drm_framebuffer *fb,
-                                    int x, int y)
+static void i9xx_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;
@@ -2418,13 +2447,11 @@ static int i9xx_update_primary_plane(struct drm_crtc *crtc,
        } else
                I915_WRITE(DSPADDR(plane), i915_gem_obj_ggtt_offset(obj) + linear_offset);
        POSTING_READ(reg);
-
-       return 0;
 }
 
-static int ironlake_update_primary_plane(struct drm_crtc *crtc,
-                                        struct drm_framebuffer *fb,
-                                        int x, int y)
+static void ironlake_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;
@@ -2502,8 +2529,6 @@ static int ironlake_update_primary_plane(struct drm_crtc *crtc,
                I915_WRITE(DSPLINOFF(plane), linear_offset);
        }
        POSTING_READ(reg);
-
-       return 0;
 }
 
 /* Assume fb object is pinned & idle & fenced and just update base pointers */
@@ -2518,7 +2543,9 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                dev_priv->display.disable_fbc(dev);
        intel_increase_pllclock(crtc);
 
-       return dev_priv->display.update_primary_plane(crtc, fb, x, y);
+       dev_priv->display.update_primary_plane(crtc, fb, x, y);
+
+       return 0;
 }
 
 void intel_display_handle_reset(struct drm_device *dev)
@@ -2677,14 +2704,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                intel_crtc->config.pipe_src_h = adjusted_mode->crtc_vdisplay;
        }
 
-       ret = dev_priv->display.update_primary_plane(crtc, fb, x, y);
-       if (ret) {
-               mutex_lock(&dev->struct_mutex);
-               intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
-               mutex_unlock(&dev->struct_mutex);
-               DRM_ERROR("failed to update base address\n");
-               return ret;
-       }
+       dev_priv->display.update_primary_plane(crtc, fb, x, y);
 
        old_fb = crtc->primary->fb;
        crtc->primary->fb = fb;
@@ -3221,9 +3241,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
        udelay(100);
 
        /* Ironlake workaround, disable clock pointer after downing FDI */
-       if (HAS_PCH_IBX(dev)) {
+       if (HAS_PCH_IBX(dev))
                I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
-       }
 
        /* still set train pattern 1 */
        reg = FDI_TX_CTL(pipe);
@@ -3284,8 +3303,9 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 
        WARN_ON(waitqueue_active(&dev_priv->pending_flip_queue));
 
-       wait_event(dev_priv->pending_flip_queue,
-                  !intel_crtc_has_pending_flip(crtc));
+       WARN_ON(wait_event_timeout(dev_priv->pending_flip_queue,
+                                  !intel_crtc_has_pending_flip(crtc),
+                                  60*HZ) == 0);
 
        mutex_lock(&dev->struct_mutex);
        intel_finish_fb(crtc->primary->fb);
@@ -3498,7 +3518,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
         * Note that enable_shared_dpll tries to do the right thing, but
         * get_shared_dpll unconditionally resets the pll - we need that to have
         * the right LVDS enable sequence. */
-       ironlake_enable_shared_dpll(intel_crtc);
+       intel_enable_shared_dpll(intel_crtc);
 
        /* set transcoder timing, panel must allow it */
        assert_panel_unlocked(dev_priv, pipe);
@@ -3602,6 +3622,8 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
                DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
                              crtc->base.base.id, pll->name);
 
+               WARN_ON(pll->refcount);
+
                goto found;
        }
 
@@ -3635,20 +3657,13 @@ static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc)
        return NULL;
 
 found:
+       if (pll->refcount == 0)
+               pll->hw_state = crtc->config.dpll_hw_state;
+
        crtc->config.shared_dpll = i;
        DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
                         pipe_name(crtc->pipe));
 
-       if (pll->active == 0) {
-               memcpy(&pll->hw_state, &crtc->config.dpll_hw_state,
-                      sizeof(pll->hw_state));
-
-               DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
-               WARN_ON(pll->on);
-               assert_shared_dpll_disabled(dev_priv, pll);
-
-               pll->mode_set(dev_priv, pll);
-       }
        pll->refcount++;
 
        return pll;
@@ -3884,6 +3899,7 @@ static void intel_crtc_enable_planes(struct drm_crtc *crtc)
 
        mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
+       intel_edp_psr_update(dev);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -3916,12 +3932,35 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
+       enum plane plane = intel_crtc->plane;
 
        WARN_ON(!crtc->enabled);
 
        if (intel_crtc->active)
                return;
 
+       if (intel_crtc->config.has_pch_encoder)
+               intel_prepare_shared_dpll(intel_crtc);
+
+       if (intel_crtc->config.has_dp_encoder)
+               intel_dp_set_m_n(intel_crtc);
+
+       intel_set_pipe_timings(intel_crtc);
+
+       if (intel_crtc->config.has_pch_encoder) {
+               intel_cpu_transcoder_set_m_n(intel_crtc,
+                                            &intel_crtc->config.fdi_m_n);
+       }
+
+       ironlake_set_pipeconf(crtc);
+
+       /* Set up the display plane register */
+       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
+       POSTING_READ(DSPCNTR(plane));
+
+       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
+                                              crtc->x, crtc->y);
+
        intel_crtc->active = true;
 
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
@@ -4016,12 +4055,34 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_encoder *encoder;
        int pipe = intel_crtc->pipe;
+       enum plane plane = intel_crtc->plane;
 
        WARN_ON(!crtc->enabled);
 
        if (intel_crtc->active)
                return;
 
+       if (intel_crtc->config.has_dp_encoder)
+               intel_dp_set_m_n(intel_crtc);
+
+       intel_set_pipe_timings(intel_crtc);
+
+       if (intel_crtc->config.has_pch_encoder) {
+               intel_cpu_transcoder_set_m_n(intel_crtc,
+                                            &intel_crtc->config.fdi_m_n);
+       }
+
+       haswell_set_pipeconf(crtc);
+
+       intel_set_pipe_csc(crtc);
+
+       /* Set up the display plane register */
+       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
+       POSTING_READ(DSPCNTR(plane));
+
+       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
+                                              crtc->x, crtc->y);
+
        intel_crtc->active = true;
 
        intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
@@ -4140,6 +4201,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
        mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
+       intel_edp_psr_update(dev);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -4187,6 +4249,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
        mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
+       intel_edp_psr_update(dev);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -4498,16 +4561,45 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
 static void valleyview_crtc_enable(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_encoder *encoder;
        int pipe = intel_crtc->pipe;
+       int plane = intel_crtc->plane;
        bool is_dsi;
+       u32 dspcntr;
 
        WARN_ON(!crtc->enabled);
 
        if (intel_crtc->active)
                return;
 
+       vlv_prepare_pll(intel_crtc);
+
+       /* Set up the display plane register */
+       dspcntr = DISPPLANE_GAMMA_ENABLE;
+
+       if (intel_crtc->config.has_dp_encoder)
+               intel_dp_set_m_n(intel_crtc);
+
+       intel_set_pipe_timings(intel_crtc);
+
+       /* pipesrc and dspsize control the size that is scaled from,
+        * which should always be the user's requested size.
+        */
+       I915_WRITE(DSPSIZE(plane),
+                  ((intel_crtc->config.pipe_src_h - 1) << 16) |
+                  (intel_crtc->config.pipe_src_w - 1));
+       I915_WRITE(DSPPOS(plane), 0);
+
+       i9xx_set_pipeconf(intel_crtc);
+
+       I915_WRITE(DSPCNTR(plane), dspcntr);
+       POSTING_READ(DSPCNTR(plane));
+
+       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
+                                              crtc->x, crtc->y);
+
        intel_crtc->active = true;
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4541,18 +4633,61 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
        intel_crtc_enable_planes(crtc);
 }
 
+static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       I915_WRITE(FP0(crtc->pipe), crtc->config.dpll_hw_state.fp0);
+       I915_WRITE(FP1(crtc->pipe), crtc->config.dpll_hw_state.fp1);
+}
+
 static void i9xx_crtc_enable(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_encoder *encoder;
        int pipe = intel_crtc->pipe;
+       int plane = intel_crtc->plane;
+       u32 dspcntr;
 
        WARN_ON(!crtc->enabled);
 
        if (intel_crtc->active)
                return;
 
+       i9xx_set_pll_dividers(intel_crtc);
+
+       /* Set up the display plane register */
+       dspcntr = DISPPLANE_GAMMA_ENABLE;
+
+       if (pipe == 0)
+               dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
+       else
+               dspcntr |= DISPPLANE_SEL_PIPE_B;
+
+       if (intel_crtc->config.has_dp_encoder)
+               intel_dp_set_m_n(intel_crtc);
+
+       intel_set_pipe_timings(intel_crtc);
+
+       /* pipesrc and dspsize control the size that is scaled from,
+        * which should always be the user's requested size.
+        */
+       I915_WRITE(DSPSIZE(plane),
+                  ((intel_crtc->config.pipe_src_h - 1) << 16) |
+                  (intel_crtc->config.pipe_src_w - 1));
+       I915_WRITE(DSPPOS(plane), 0);
+
+       i9xx_set_pipeconf(intel_crtc);
+
+       I915_WRITE(DSPCNTR(plane), dspcntr);
+       POSTING_READ(DSPCNTR(plane));
+
+       dev_priv->display.update_primary_plane(crtc, crtc->primary->fb,
+                                              crtc->x, crtc->y);
+
        intel_crtc->active = true;
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4627,7 +4762,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
        intel_crtc->active = false;
        intel_update_watermarks(crtc);
 
+       mutex_lock(&dev->struct_mutex);
        intel_update_fbc(dev);
+       intel_edp_psr_update(dev);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -4690,13 +4828,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct drm_connector *connector;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
        /* crtc should still be enabled when we disable it. */
        WARN_ON(!crtc->enabled);
 
        dev_priv->display.crtc_disable(crtc);
-       intel_crtc->eld_vld = false;
        intel_crtc_update_sarea(crtc, false);
        dev_priv->display.off(crtc);
 
@@ -5164,8 +5300,6 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
                                     intel_clock_t *reduced_clock)
 {
        struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int pipe = crtc->pipe;
        u32 fp, fp2 = 0;
 
        if (IS_PINEVIEW(dev)) {
@@ -5178,17 +5312,14 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc,
                        fp2 = i9xx_dpll_compute_fp(reduced_clock);
        }
 
-       I915_WRITE(FP0(pipe), fp);
        crtc->config.dpll_hw_state.fp0 = fp;
 
        crtc->lowfreq_avail = false;
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
            reduced_clock && i915.powersave) {
-               I915_WRITE(FP1(pipe), fp2);
                crtc->config.dpll_hw_state.fp1 = fp2;
                crtc->lowfreq_avail = true;
        } else {
-               I915_WRITE(FP1(pipe), fp);
                crtc->config.dpll_hw_state.fp1 = fp;
        }
 }
@@ -5265,13 +5396,35 @@ static void intel_dp_set_m_n(struct intel_crtc *crtc)
 }
 
 static void vlv_update_pll(struct intel_crtc *crtc)
+{
+       u32 dpll, dpll_md;
+
+       /*
+        * Enable DPIO clock input. We should never disable the reference
+        * clock for pipe B, since VGA hotplug / manual detection depends
+        * on it.
+        */
+       dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
+               DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
+       /* We should never disable this, set it here for state tracking */
+       if (crtc->pipe == PIPE_B)
+               dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
+       dpll |= DPLL_VCO_ENABLE;
+       crtc->config.dpll_hw_state.dpll = dpll;
+
+       dpll_md = (crtc->config.pixel_multiplier - 1)
+               << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+       crtc->config.dpll_hw_state.dpll_md = dpll_md;
+}
+
+static void vlv_prepare_pll(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = crtc->pipe;
-       u32 dpll, mdiv;
+       u32 mdiv;
        u32 bestn, bestm1, bestm2, bestp1, bestp2;
-       u32 coreclk, reg_val, dpll_md;
+       u32 coreclk, reg_val;
 
        mutex_lock(&dev_priv->dpio_lock);
 
@@ -5284,7 +5437,7 @@ static void vlv_update_pll(struct intel_crtc *crtc)
        /* See eDP HDMI DPIO driver vbios notes doc */
 
        /* PLL B needs special handling */
-       if (pipe)
+       if (pipe == PIPE_B)
                vlv_pllb_recal_opamp(dev_priv, pipe);
 
        /* Set up Tx target for periodic Rcomp update */
@@ -5328,7 +5481,7 @@ static void vlv_update_pll(struct intel_crtc *crtc)
        if (intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_EDP) ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_DISPLAYPORT)) {
                /* Use SSC source */
-               if (!pipe)
+               if (pipe == PIPE_A)
                        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df40000);
                else
@@ -5336,7 +5489,7 @@ static void vlv_update_pll(struct intel_crtc *crtc)
                                         0x0df70000);
        } else { /* HDMI or VGA */
                /* Use bend source */
-               if (!pipe)
+               if (pipe == PIPE_A)
                        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW5(pipe),
                                         0x0df70000);
                else
@@ -5352,24 +5505,6 @@ static void vlv_update_pll(struct intel_crtc *crtc)
        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
 
        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
-
-       /*
-        * Enable DPIO clock input. We should never disable the reference
-        * clock for pipe B, since VGA hotplug / manual detection depends
-        * on it.
-        */
-       dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
-               DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
-       /* We should never disable this, set it here for state tracking */
-       if (pipe == PIPE_B)
-               dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
-       dpll |= DPLL_VCO_ENABLE;
-       crtc->config.dpll_hw_state.dpll = dpll;
-
-       dpll_md = (crtc->config.pixel_multiplier - 1)
-               << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-       crtc->config.dpll_hw_state.dpll_md = dpll_md;
-
        mutex_unlock(&dev_priv->dpio_lock);
 }
 
@@ -5380,11 +5515,18 @@ static void chv_update_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 val, loopfilter, intcoeff;
+       u32 loopfilter, intcoeff;
        u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
        int refclk;
 
-       mutex_lock(&dev_priv->dpio_lock);
+       crtc->config.dpll_hw_state.dpll = DPLL_SSC_REF_CLOCK_CHV |
+               DPLL_REFA_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
+               DPLL_VCO_ENABLE;
+       if (pipe != PIPE_A)
+               crtc->config.dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
+       crtc->config.dpll_hw_state.dpll_md =
+               (crtc->config.pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
 
        bestn = crtc->config.dpll.n;
        bestm2_frac = crtc->config.dpll.m2 & 0x3fffff;
@@ -5396,19 +5538,10 @@ static void chv_update_pll(struct intel_crtc *crtc)
        /*
         * Enable Refclk and SSC
         */
-       val = I915_READ(dpll_reg);
-       val |= (DPLL_SSC_REF_CLOCK_CHV | DPLL_REFA_CLK_ENABLE_VLV);
-       I915_WRITE(dpll_reg, val);
+       I915_WRITE(dpll_reg,
+                  crtc->config.dpll_hw_state.dpll & ~DPLL_VCO_ENABLE);
 
-       /* Propagate soft reset to data lane reset */
-       val = vlv_dpio_read(dev_priv, pipe, VLV_PCS_DW0(port));
-       val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-       vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), val);
-
-       /* Disable 10bit clock to display controller */
-       val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
-       val &= ~DPIO_DCLKP_EN;
-       vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
+       mutex_lock(&dev_priv->dpio_lock);
 
        /* p1 and p2 divider */
        vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port),
@@ -5767,16 +5900,12 @@ static int i9xx_crtc_mode_set(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);
-       int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
        int refclk, num_connectors = 0;
        intel_clock_t clock, reduced_clock;
-       u32 dspcntr;
        bool ok, has_reduced_clock = false;
        bool is_lvds = false, is_dsi = false;
        struct intel_encoder *encoder;
        const intel_limit_t *limit;
-       int ret;
 
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                switch (encoder->type) {
@@ -5792,7 +5921,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        if (is_dsi)
-               goto skip_dpll;
+               return 0;
 
        if (!intel_crtc->config.clock_set) {
                refclk = i9xx_get_refclk(crtc, num_connectors);
@@ -5844,41 +5973,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        } else {
                i9xx_update_pll(intel_crtc,
                                has_reduced_clock ? &reduced_clock : NULL,
-                                num_connectors);
-       }
-
-skip_dpll:
-       /* Set up the display plane register */
-       dspcntr = DISPPLANE_GAMMA_ENABLE;
-
-       if (!IS_VALLEYVIEW(dev)) {
-               if (pipe == 0)
-                       dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
-               else
-                       dspcntr |= DISPPLANE_SEL_PIPE_B;
+                               num_connectors);
        }
 
-       if (intel_crtc->config.has_dp_encoder)
-               intel_dp_set_m_n(intel_crtc);
-
-       intel_set_pipe_timings(intel_crtc);
-
-       /* pipesrc and dspsize control the size that is scaled from,
-        * which should always be the user's requested size.
-        */
-       I915_WRITE(DSPSIZE(plane),
-                  ((intel_crtc->config.pipe_src_h - 1) << 16) |
-                  (intel_crtc->config.pipe_src_w - 1));
-       I915_WRITE(DSPPOS(plane), 0);
-
-       i9xx_set_pipeconf(intel_crtc);
-
-       I915_WRITE(DSPCNTR(plane), dspcntr);
-       POSTING_READ(DSPCNTR(plane));
-
-       ret = intel_pipe_set_base(crtc, x, y, fb);
-
-       return ret;
+       return 0;
 }
 
 static void i9xx_get_pfit_config(struct intel_crtc *crtc,
@@ -6223,8 +6321,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                        if (intel_panel_use_ssc(dev_priv) && can_ssc) {
                                DRM_DEBUG_KMS("Using SSC on eDP\n");
                                val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
-                       }
-                       else
+                       } else
                                val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
                } else
                        val |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
@@ -6803,10 +6900,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                                  struct drm_framebuffer *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);
-       int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->plane;
        int num_connectors = 0;
        intel_clock_t clock, reduced_clock;
        u32 dpll = 0, fp = 0, fp2 = 0;
@@ -6814,7 +6908,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        bool is_lvds = false;
        struct intel_encoder *encoder;
        struct intel_shared_dpll *pll;
-       int ret;
 
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                switch (encoder->type) {
@@ -6864,36 +6957,18 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                pll = intel_get_shared_dpll(intel_crtc);
                if (pll == NULL) {
                        DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-                                        pipe_name(pipe));
+                                        pipe_name(intel_crtc->pipe));
                        return -EINVAL;
                }
        } else
                intel_put_shared_dpll(intel_crtc);
 
-       if (intel_crtc->config.has_dp_encoder)
-               intel_dp_set_m_n(intel_crtc);
-
        if (is_lvds && has_reduced_clock && i915.powersave)
                intel_crtc->lowfreq_avail = true;
        else
                intel_crtc->lowfreq_avail = false;
 
-       intel_set_pipe_timings(intel_crtc);
-
-       if (intel_crtc->config.has_pch_encoder) {
-               intel_cpu_transcoder_set_m_n(intel_crtc,
-                                            &intel_crtc->config.fdi_m_n);
-       }
-
-       ironlake_set_pipeconf(crtc);
-
-       /* Set up the display plane register */
-       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE);
-       POSTING_READ(DSPCNTR(plane));
-
-       ret = intel_pipe_set_base(crtc, x, y, fb);
-
-       return ret;
+       return 0;
 }
 
 static void intel_pch_transcoder_get_m_n(struct intel_crtc *crtc,
@@ -7359,39 +7434,15 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
                                 int x, int y,
                                 struct drm_framebuffer *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);
-       int plane = intel_crtc->plane;
-       int ret;
 
        if (!intel_ddi_pll_select(intel_crtc))
                return -EINVAL;
        intel_ddi_pll_enable(intel_crtc);
 
-       if (intel_crtc->config.has_dp_encoder)
-               intel_dp_set_m_n(intel_crtc);
-
        intel_crtc->lowfreq_avail = false;
 
-       intel_set_pipe_timings(intel_crtc);
-
-       if (intel_crtc->config.has_pch_encoder) {
-               intel_cpu_transcoder_set_m_n(intel_crtc,
-                                            &intel_crtc->config.fdi_m_n);
-       }
-
-       haswell_set_pipeconf(crtc);
-
-       intel_set_pipe_csc(crtc);
-
-       /* Set up the display plane register */
-       I915_WRITE(DSPCNTR(plane), DISPPLANE_GAMMA_ENABLE | DISPPLANE_PIPE_CSC_ENABLE);
-       POSTING_READ(DSPCNTR(plane));
-
-       ret = intel_pipe_set_base(crtc, x, y, fb);
-
-       return ret;
+       return 0;
 }
 
 static bool haswell_get_pipe_config(struct intel_crtc *crtc,
@@ -7471,40 +7522,6 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        return true;
 }
 
-static int intel_crtc_mode_set(struct drm_crtc *crtc,
-                              int x, int y,
-                              struct drm_framebuffer *fb)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_encoder *encoder;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
-       int pipe = intel_crtc->pipe;
-       int ret;
-
-       drm_vblank_pre_modeset(dev, pipe);
-
-       ret = dev_priv->display.crtc_mode_set(crtc, x, y, fb);
-
-       drm_vblank_post_modeset(dev, pipe);
-
-       if (ret != 0)
-               return ret;
-
-       for_each_encoder_on_crtc(dev, crtc, encoder) {
-               DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
-                       encoder->base.base.id,
-                       drm_get_encoder_name(&encoder->base),
-                       mode->base.id, mode->name);
-
-               if (encoder->mode_set)
-                       encoder->mode_set(encoder);
-       }
-
-       return 0;
-}
-
 static struct {
        int clock;
        u32 config;
@@ -7619,7 +7636,6 @@ static void haswell_write_eld(struct drm_connector *connector,
 {
        struct drm_i915_private *dev_priv = connector->dev->dev_private;
        uint8_t *eld = connector->eld;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t eldv;
        uint32_t i;
        int len;
@@ -7658,7 +7674,6 @@ static void haswell_write_eld(struct drm_connector *connector,
        DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe));
 
        eldv = AUDIO_ELD_VALID_A << (pipe * 4);
-       intel_crtc->eld_vld = true;
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
                DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
@@ -7899,7 +7914,7 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
 
        if (intel_crtc->cursor_visible != visible) {
                int16_t width = intel_crtc->cursor_width;
-               uint32_t cntl = I915_READ(CURCNTR_IVB(pipe));
+               uint32_t cntl = I915_READ(CURCNTR(pipe));
                if (base) {
                        cntl &= ~CURSOR_MODE;
                        cntl |= MCURSOR_GAMMA_ENABLE;
@@ -7925,14 +7940,14 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base)
                        cntl |= CURSOR_PIPE_CSC_ENABLE;
                        cntl &= ~CURSOR_TRICKLE_FEED_DISABLE;
                }
-               I915_WRITE(CURCNTR_IVB(pipe), cntl);
+               I915_WRITE(CURCNTR(pipe), cntl);
 
                intel_crtc->cursor_visible = visible;
        }
        /* and commit changes on next vblank */
-       POSTING_READ(CURCNTR_IVB(pipe));
-       I915_WRITE(CURBASE_IVB(pipe), base);
-       POSTING_READ(CURBASE_IVB(pipe));
+       POSTING_READ(CURCNTR(pipe));
+       I915_WRITE(CURBASE(pipe), base);
+       POSTING_READ(CURBASE(pipe));
 }
 
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
@@ -7979,16 +7994,14 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        if (!visible && !intel_crtc->cursor_visible)
                return;
 
-       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) {
-               I915_WRITE(CURPOS_IVB(pipe), pos);
+       I915_WRITE(CURPOS(pipe), pos);
+
+       if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev))
                ivb_update_cursor(crtc, base);
-       } else {
-               I915_WRITE(CURPOS(pipe), pos);
-               if (IS_845G(dev) || IS_I865G(dev))
-                       i845_update_cursor(crtc, base);
-               else
-                       i9xx_update_cursor(crtc, base);
-       }
+       else if (IS_845G(dev) || IS_I865G(dev))
+               i845_update_cursor(crtc, base);
+       else
+               i9xx_update_cursor(crtc, base);
 }
 
 static int intel_crtc_cursor_set(struct drm_crtc *crtc,
@@ -8833,6 +8846,48 @@ void intel_finish_page_flip_plane(struct drm_device *dev, int plane)
        do_intel_finish_page_flip(dev, crtc);
 }
 
+/* Is 'a' after or equal to 'b'? */
+static bool g4x_flip_count_after_eq(u32 a, u32 b)
+{
+       return !((a - b) & 0x80000000);
+}
+
+static bool page_flip_finished(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /*
+        * The relevant registers doen't exist on pre-ctg.
+        * As the flip done interrupt doesn't trigger for mmio
+        * flips on gmch platforms, a flip count check isn't
+        * really needed there. But since ctg has the registers,
+        * include it in the check anyway.
+        */
+       if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev))
+               return true;
+
+       /*
+        * A DSPSURFLIVE check isn't enough in case the mmio and CS flips
+        * used the same base address. In that case the mmio flip might
+        * have completed, but the CS hasn't even executed the flip yet.
+        *
+        * A flip count check isn't enough as the CS might have updated
+        * the base address just after start of vblank, but before we
+        * managed to process the interrupt. This means we'd complete the
+        * CS flip too soon.
+        *
+        * Combining both checks should get us a good enough result. It may
+        * still happen that the CS flip has been executed, but has not
+        * yet actually completed. But in case the base address is the same
+        * anyway, we don't really care.
+        */
+       return (I915_READ(DSPSURFLIVE(crtc->plane)) & ~0xfff) ==
+               crtc->unpin_work->gtt_offset &&
+               g4x_flip_count_after_eq(I915_READ(PIPE_FLIPCOUNT_GM45(crtc->pipe)),
+                                   crtc->unpin_work->flip_count);
+}
+
 void intel_prepare_page_flip(struct drm_device *dev, int plane)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -8845,12 +8900,12 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)
         * is also accompanied by a spurious intel_prepare_page_flip().
         */
        spin_lock_irqsave(&dev->event_lock, flags);
-       if (intel_crtc->unpin_work)
+       if (intel_crtc->unpin_work && page_flip_finished(intel_crtc))
                atomic_inc_not_zero(&intel_crtc->unpin_work->pending);
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
+static inline void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
 {
        /* Ensure that the work item is consistent when activating it ... */
        smp_wmb();
@@ -8875,6 +8930,9 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
        if (ret)
                goto err;
 
+       intel_crtc->unpin_work->gtt_offset =
+               i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
+
        ret = intel_ring_begin(ring, 6);
        if (ret)
                goto err_unpin;
@@ -8891,7 +8949,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,
        intel_ring_emit(ring, MI_DISPLAY_FLIP |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
        intel_ring_emit(ring, fb->pitches[0]);
-       intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
        intel_ring_emit(ring, 0); /* aux display base address, unused */
 
        intel_mark_page_flip_active(intel_crtc);
@@ -8920,6 +8978,9 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
        if (ret)
                goto err;
 
+       intel_crtc->unpin_work->gtt_offset =
+               i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
+
        ret = intel_ring_begin(ring, 6);
        if (ret)
                goto err_unpin;
@@ -8933,7 +8994,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev,
        intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
        intel_ring_emit(ring, fb->pitches[0]);
-       intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
        intel_ring_emit(ring, MI_NOOP);
 
        intel_mark_page_flip_active(intel_crtc);
@@ -8962,6 +9023,9 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
        if (ret)
                goto err;
 
+       intel_crtc->unpin_work->gtt_offset =
+               i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
+
        ret = intel_ring_begin(ring, 4);
        if (ret)
                goto err_unpin;
@@ -8973,8 +9037,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev,
        intel_ring_emit(ring, MI_DISPLAY_FLIP |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
        intel_ring_emit(ring, fb->pitches[0]);
-       intel_ring_emit(ring,
-                       (i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset) |
+       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset |
                        obj->tiling_mode);
 
        /* XXX Enabling the panel-fitter across page-flip is so far
@@ -9011,6 +9074,9 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
        if (ret)
                goto err;
 
+       intel_crtc->unpin_work->gtt_offset =
+               i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
+
        ret = intel_ring_begin(ring, 4);
        if (ret)
                goto err_unpin;
@@ -9018,7 +9084,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev,
        intel_ring_emit(ring, MI_DISPLAY_FLIP |
                        MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
        intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
-       intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
 
        /* Contrary to the suggestions in the documentation,
         * "Enable Panel Fitter" does not seem to be required when page
@@ -9060,7 +9126,10 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
        if (ret)
                goto err;
 
-       switch(intel_crtc->plane) {
+       intel_crtc->unpin_work->gtt_offset =
+               i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset;
+
+       switch (intel_crtc->plane) {
        case PLANE_A:
                plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A;
                break;
@@ -9137,7 +9206,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
 
        intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
        intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
-       intel_ring_emit(ring, i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
+       intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
        intel_ring_emit(ring, (MI_NOOP));
 
        intel_mark_page_flip_active(intel_crtc);
@@ -9235,6 +9304,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        atomic_inc(&intel_crtc->unpin_work_count);
        intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 
+       if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
+               work->flip_count = I915_READ(PIPE_FLIPCOUNT_GM45(intel_crtc->pipe)) + 1;
+
        ret = dev_priv->display.queue_flip(dev, crtc, fb, obj, page_flip_flags);
        if (ret)
                goto cleanup_pending;
@@ -9339,7 +9411,7 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 }
 
 static void
-connected_sink_compute_bpp(struct intel_connector * connector,
+connected_sink_compute_bpp(struct intel_connector *connector,
                           struct intel_crtc_config *pipe_config)
 {
        int bpp = pipe_config->pipe_bpp;
@@ -9894,6 +9966,8 @@ intel_pipe_config_compare(struct drm_device *dev,
            IS_VALLEYVIEW(dev))
                PIPE_CONF_CHECK_I(limited_color_range);
 
+       PIPE_CONF_CHECK_I(has_audio);
+
        PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags,
                              DRM_MODE_FLAG_INTERLACE);
 
@@ -10262,8 +10336,28 @@ static int __intel_set_mode(struct drm_crtc *crtc,
         * on the DPLL.
         */
        for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
-               ret = intel_crtc_mode_set(&intel_crtc->base,
-                                         x, y, fb);
+               struct drm_framebuffer *old_fb;
+
+               mutex_lock(&dev->struct_mutex);
+               ret = intel_pin_and_fence_fb_obj(dev,
+                                                to_intel_framebuffer(fb)->obj,
+                                                NULL);
+               if (ret != 0) {
+                       DRM_ERROR("pin & fence failed\n");
+                       mutex_unlock(&dev->struct_mutex);
+                       goto done;
+               }
+               old_fb = crtc->primary->fb;
+               if (old_fb)
+                       intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
+               mutex_unlock(&dev->struct_mutex);
+
+               crtc->primary->fb = fb;
+               crtc->x = x;
+               crtc->y = y;
+
+               ret = dev_priv->display.crtc_mode_set(&intel_crtc->base,
+                                                     x, y, fb);
                if (ret)
                        goto done;
        }
@@ -11024,6 +11118,15 @@ static void intel_setup_outputs(struct drm_device *dev)
                                intel_dp_init(dev, VLV_DISPLAY_BASE + DP_C, PORT_C);
                }
 
+               if (IS_CHERRYVIEW(dev)) {
+                       if (I915_READ(VLV_DISPLAY_BASE + CHV_HDMID) & SDVO_DETECTED) {
+                               intel_hdmi_init(dev, VLV_DISPLAY_BASE + CHV_HDMID,
+                                               PORT_D);
+                               if (I915_READ(VLV_DISPLAY_BASE + DP_D) & DP_DETECTED)
+                                       intel_dp_init(dev, VLV_DISPLAY_BASE + DP_D, PORT_D);
+                       }
+               }
+
                intel_dsi_init(dev);
        } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
                bool found = false;
@@ -12257,15 +12360,9 @@ intel_display_capture_error_state(struct drm_device *dev)
                if (!error->pipe[i].power_domain_on)
                        continue;
 
-               if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
-                       error->cursor[i].control = I915_READ(CURCNTR(i));
-                       error->cursor[i].position = I915_READ(CURPOS(i));
-                       error->cursor[i].base = I915_READ(CURBASE(i));
-               } else {
-                       error->cursor[i].control = I915_READ(CURCNTR_IVB(i));
-                       error->cursor[i].position = I915_READ(CURPOS_IVB(i));
-                       error->cursor[i].base = I915_READ(CURBASE_IVB(i));
-               }
+               error->cursor[i].control = I915_READ(CURCNTR(i));
+               error->cursor[i].position = I915_READ(CURPOS(i));
+               error->cursor[i].base = I915_READ(CURBASE(i));
 
                error->plane[i].control = I915_READ(DSPCNTR(i));
                error->plane[i].stride = I915_READ(DSPSTRIDE(i));