Merge tag 'drm-intel-next-2012-12-21' of git://people.freedesktop.org/~danvet/drm...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / gpu / drm / i915 / intel_display.c
index a9fb046b94a140ab169cbd2eb016922fc702dd98..8c36a11a9a57040bc93ae9fa4dc37cec7e18f84a 100644 (file)
@@ -416,13 +416,11 @@ static const intel_limit_t intel_limits_vlv_dp = {
 
 u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
 {
-       unsigned long flags;
-       u32 val = 0;
+       WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 
-       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
        if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
                DRM_ERROR("DPIO idle wait timed out\n");
-               goto out_unlock;
+               return 0;
        }
 
        I915_WRITE(DPIO_REG, reg);
@@ -430,24 +428,20 @@ u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)
                   DPIO_BYTE);
        if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
                DRM_ERROR("DPIO read wait timed out\n");
-               goto out_unlock;
+               return 0;
        }
-       val = I915_READ(DPIO_DATA);
 
-out_unlock:
-       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
-       return val;
+       return I915_READ(DPIO_DATA);
 }
 
 static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
                             u32 val)
 {
-       unsigned long flags;
+       WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 
-       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
        if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) {
                DRM_ERROR("DPIO idle wait timed out\n");
-               goto out_unlock;
+               return;
        }
 
        I915_WRITE(DPIO_DATA, val);
@@ -456,9 +450,6 @@ static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,
                   DPIO_BYTE);
        if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100))
                DRM_ERROR("DPIO write wait timed out\n");
-
-out_unlock:
-       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
 }
 
 static void vlv_init_dpio(struct drm_device *dev)
@@ -472,61 +463,14 @@ static void vlv_init_dpio(struct drm_device *dev)
        POSTING_READ(DPIO_CTL);
 }
 
-static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
-{
-       DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
-       return 1;
-}
-
-static const struct dmi_system_id intel_dual_link_lvds[] = {
-       {
-               .callback = intel_dual_link_lvds_callback,
-               .ident = "Apple MacBook Pro (Core i5/i7 Series)",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
-               },
-       },
-       { }     /* terminating entry */
-};
-
-static bool is_dual_link_lvds(struct drm_i915_private *dev_priv,
-                             unsigned int reg)
-{
-       unsigned int val;
-
-       /* use the module option value if specified */
-       if (i915_lvds_channel_mode > 0)
-               return i915_lvds_channel_mode == 2;
-
-       if (dmi_check_system(intel_dual_link_lvds))
-               return true;
-
-       if (dev_priv->lvds_val)
-               val = dev_priv->lvds_val;
-       else {
-               /* BIOS should set the proper LVDS register value at boot, but
-                * in reality, it doesn't set the value when the lid is closed;
-                * we need to check "the value to be set" in VBT when LVDS
-                * register is uninitialized.
-                */
-               val = I915_READ(reg);
-               if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
-                       val = dev_priv->bios_lvds_val;
-               dev_priv->lvds_val = val;
-       }
-       return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
-}
-
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
                                                int refclk)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        const intel_limit_t *limit;
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if (is_dual_link_lvds(dev_priv, PCH_LVDS)) {
+               if (intel_is_dual_link_lvds(dev)) {
                        /* LVDS dual channel */
                        if (refclk == 100000)
                                limit = &intel_limits_ironlake_dual_lvds_100m;
@@ -550,11 +494,10 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
 static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        const intel_limit_t *limit;
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if (is_dual_link_lvds(dev_priv, LVDS))
+               if (intel_is_dual_link_lvds(dev))
                        /* LVDS with dual channel */
                        limit = &intel_limits_g4x_dual_channel_lvds;
                else
@@ -686,19 +629,16 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        intel_clock_t clock;
        int err = target;
 
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
-           (I915_READ(LVDS)) != 0) {
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
                /*
-                * For LVDS, if the panel is on, just rely on its current
-                * settings for dual-channel.  We haven't figured out how to
-                * reliably set up different single/dual channel state, if we
-                * even can.
+                * For LVDS just rely on its current settings for dual-channel.
+                * We haven't figured out how to reliably set up different
+                * single/dual channel state, if we even can.
                 */
-               if (is_dual_link_lvds(dev_priv, LVDS))
+               if (intel_is_dual_link_lvds(dev))
                        clock.p2 = limit->p2.p2_fast;
                else
                        clock.p2 = limit->p2.p2_slow;
@@ -751,7 +691,6 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                        intel_clock_t *best_clock)
 {
        struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        intel_clock_t clock;
        int max_n;
        bool found;
@@ -766,8 +705,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                        lvds_reg = PCH_LVDS;
                else
                        lvds_reg = LVDS;
-               if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) ==
-                   LVDS_CLKB_POWER_UP)
+               if (intel_is_dual_link_lvds(dev))
                        clock.p2 = limit->p2.p2_fast;
                else
                        clock.p2 = limit->p2.p2_slow;
@@ -1047,6 +985,51 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
        }
 }
 
+/*
+ * ibx_digital_port_connected - is the specified port connected?
+ * @dev_priv: i915 private structure
+ * @port: the port to test
+ *
+ * Returns true if @port is connected, false otherwise.
+ */
+bool ibx_digital_port_connected(struct drm_i915_private *dev_priv,
+                               struct intel_digital_port *port)
+{
+       u32 bit;
+
+       if (HAS_PCH_IBX(dev_priv->dev)) {
+               switch(port->port) {
+               case PORT_B:
+                       bit = SDE_PORTB_HOTPLUG;
+                       break;
+               case PORT_C:
+                       bit = SDE_PORTC_HOTPLUG;
+                       break;
+               case PORT_D:
+                       bit = SDE_PORTD_HOTPLUG;
+                       break;
+               default:
+                       return true;
+               }
+       } else {
+               switch(port->port) {
+               case PORT_B:
+                       bit = SDE_PORTB_HOTPLUG_CPT;
+                       break;
+               case PORT_C:
+                       bit = SDE_PORTC_HOTPLUG_CPT;
+                       break;
+               case PORT_D:
+                       bit = SDE_PORTD_HOTPLUG_CPT;
+                       break;
+               default:
+                       return true;
+               }
+       }
+
+       return I915_READ(SDEISR) & bit;
+}
+
 static const char *state_string(bool enabled)
 {
        return enabled ? "on" : "off";
@@ -1125,8 +1108,8 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
 
-       if (IS_HASWELL(dev_priv->dev)) {
-               /* On Haswell, DDI is used instead of FDI_TX_CTL */
+       if (HAS_DDI(dev_priv->dev)) {
+               /* DDI does not have a specific FDI_TX register */
                reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
                val = I915_READ(reg);
                cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
@@ -1170,7 +1153,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
                return;
 
        /* On Haswell, DDI ports are responsible for the FDI PLL setup */
-       if (IS_HASWELL(dev_priv->dev))
+       if (HAS_DDI(dev_priv->dev))
                return;
 
        reg = FDI_TX_CTL(pipe);
@@ -1509,13 +1492,14 @@ static void
 intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
                enum intel_sbi_destination destination)
 {
-       unsigned long flags;
        u32 tmp;
 
-       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
-       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) {
+       WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
+
+       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
+                               100)) {
                DRM_ERROR("timeout waiting for SBI to become ready\n");
-               goto out_unlock;
+               return;
        }
 
        I915_WRITE(SBI_ADDR, (reg << 16));
@@ -1530,24 +1514,21 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
        if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
                                100)) {
                DRM_ERROR("timeout waiting for SBI to complete write transaction\n");
-               goto out_unlock;
+               return;
        }
-
-out_unlock:
-       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
 }
 
 static u32
 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
               enum intel_sbi_destination destination)
 {
-       unsigned long flags;
        u32 value = 0;
+       WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
 
-       spin_lock_irqsave(&dev_priv->dpio_lock, flags);
-       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) {
+       if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0,
+                               100)) {
                DRM_ERROR("timeout waiting for SBI to become ready\n");
-               goto out_unlock;
+               return 0;
        }
 
        I915_WRITE(SBI_ADDR, (reg << 16));
@@ -1561,14 +1542,10 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
        if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,
                                100)) {
                DRM_ERROR("timeout waiting for SBI to complete read transaction\n");
-               goto out_unlock;
+               return 0;
        }
 
-       value = I915_READ(SBI_DATA);
-
-out_unlock:
-       spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
-       return value;
+       return I915_READ(SBI_DATA);
 }
 
 /**
@@ -1700,8 +1677,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
                 * make the BPC in transcoder be consistent with
                 * that in pipeconf reg.
                 */
-               val &= ~PIPE_BPC_MASK;
-               val |= pipeconf_val & PIPE_BPC_MASK;
+               val &= ~PIPECONF_BPC_MASK;
+               val |= pipeconf_val & PIPECONF_BPC_MASK;
        }
 
        val &= ~TRANS_INTERLACE_MASK;
@@ -1728,7 +1705,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
        BUG_ON(dev_priv->info->gen < 5);
 
        /* FDI must be feeding us bits for PCH ports */
-       assert_fdi_tx_enabled(dev_priv, cpu_transcoder);
+       assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
        assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
 
        /* Workaround: set timing override bit. */
@@ -1816,11 +1793,11 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 {
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
-       enum transcoder pch_transcoder;
+       enum pipe pch_transcoder;
        int reg;
        u32 val;
 
-       if (IS_HASWELL(dev_priv->dev))
+       if (HAS_PCH_LPT(dev_priv->dev))
                pch_transcoder = TRANSCODER_A;
        else
                pch_transcoder = pipe;
@@ -1836,7 +1813,8 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
                if (pch_port) {
                        /* if driving the PCH, we need FDI enabled */
                        assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
-                       assert_fdi_tx_pll_enabled(dev_priv, cpu_transcoder);
+                       assert_fdi_tx_pll_enabled(dev_priv,
+                                                 (enum pipe) cpu_transcoder);
                }
                /* FIXME: assert CPU port conditions for SNB+ */
        }
@@ -2350,43 +2328,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        return 0;
 }
 
-static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 dpa_ctl;
-
-       DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock);
-       dpa_ctl = I915_READ(DP_A);
-       dpa_ctl &= ~DP_PLL_FREQ_MASK;
-
-       if (clock < 200000) {
-               u32 temp;
-               dpa_ctl |= DP_PLL_FREQ_160MHZ;
-               /* workaround for 160Mhz:
-                  1) program 0x4600c bits 15:0 = 0x8124
-                  2) program 0x46010 bit 0 = 1
-                  3) program 0x46034 bit 24 = 1
-                  4) program 0x64000 bit 14 = 1
-                  */
-               temp = I915_READ(0x4600c);
-               temp &= 0xffff0000;
-               I915_WRITE(0x4600c, temp | 0x8124);
-
-               temp = I915_READ(0x46010);
-               I915_WRITE(0x46010, temp | 1);
-
-               temp = I915_READ(0x46034);
-               I915_WRITE(0x46034, temp | (1 << 24));
-       } else {
-               dpa_ctl |= DP_PLL_FREQ_270MHZ;
-       }
-       I915_WRITE(DP_A, dpa_ctl);
-
-       POSTING_READ(DP_A);
-       udelay(500);
-}
-
 static void intel_fdi_normal_train(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -2815,7 +2756,7 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
        temp = I915_READ(reg);
        temp &= ~((0x7 << 19) | (0x7 << 16));
        temp |= (intel_crtc->fdi_lanes - 1) << 19;
-       temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+       temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
        I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);
 
        POSTING_READ(reg);
@@ -2828,18 +2769,14 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
        POSTING_READ(reg);
        udelay(200);
 
-       /* On Haswell, the PLL configuration for ports and pipes is handled
-        * separately, as part of DDI setup */
-       if (!IS_HASWELL(dev)) {
-               /* Enable CPU FDI TX PLL, always on for Ironlake */
-               reg = FDI_TX_CTL(pipe);
-               temp = I915_READ(reg);
-               if ((temp & FDI_TX_PLL_ENABLE) == 0) {
-                       I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE);
+       /* Enable CPU FDI TX PLL, always on for Ironlake */
+       reg = FDI_TX_CTL(pipe);
+       temp = I915_READ(reg);
+       if ((temp & FDI_TX_PLL_ENABLE) == 0) {
+               I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE);
 
-                       POSTING_READ(reg);
-                       udelay(100);
-               }
+               POSTING_READ(reg);
+               udelay(100);
        }
 }
 
@@ -2889,7 +2826,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
        reg = FDI_RX_CTL(pipe);
        temp = I915_READ(reg);
        temp &= ~(0x7 << 16);
-       temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+       temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
        I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
 
        POSTING_READ(reg);
@@ -2918,7 +2855,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)
        }
        /* BPC in FDI rx is consistent with that in PIPECONF */
        temp &= ~(0x07 << 16);
-       temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+       temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;
        I915_WRITE(reg, temp);
 
        POSTING_READ(reg);
@@ -2992,6 +2929,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
        u32 divsel, phaseinc, auxdiv, phasedir = 0;
        u32 temp;
 
+       mutex_lock(&dev_priv->dpio_lock);
+
        /* It is necessary to ungate the pixclk gate prior to programming
         * the divisors, and gate it back when it is done.
         */
@@ -3066,6 +3005,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)
        udelay(24);
 
        I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
+
+       mutex_unlock(&dev_priv->dpio_lock);
 }
 
 /*
@@ -3146,7 +3087,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
        if (HAS_PCH_CPT(dev) &&
            (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
             intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
-               u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
+               u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
                reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
                temp &= ~(TRANS_DP_PORT_SEL_MASK |
@@ -3623,7 +3564,7 @@ static void haswell_crtc_off(struct drm_crtc *crtc)
 
        /* Stop saying we're using TRANSCODER_EDP because some other CRTC might
         * start using it. */
-       intel_crtc->cpu_transcoder = intel_crtc->pipe;
+       intel_crtc->cpu_transcoder = (enum transcoder) intel_crtc->pipe;
 
        intel_ddi_put_crtc_pll(crtc);
 }
@@ -4012,16 +3953,8 @@ static int i830_get_display_clock_speed(struct drm_device *dev)
        return 133000;
 }
 
-struct fdi_m_n {
-       u32        tu;
-       u32        gmch_m;
-       u32        gmch_n;
-       u32        link_m;
-       u32        link_n;
-};
-
 static void
-fdi_reduce_ratio(u32 *num, u32 *den)
+intel_reduce_ratio(uint32_t *num, uint32_t *den)
 {
        while (*num > 0xffffff || *den > 0xffffff) {
                *num >>= 1;
@@ -4029,20 +3962,18 @@ fdi_reduce_ratio(u32 *num, u32 *den)
        }
 }
 
-static void
-ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock,
-                    int link_clock, struct fdi_m_n *m_n)
+void
+intel_link_compute_m_n(int bits_per_pixel, int nlanes,
+                      int pixel_clock, int link_clock,
+                      struct intel_link_m_n *m_n)
 {
-       m_n->tu = 64; /* default size */
-
-       /* BUG_ON(pixel_clock > INT_MAX / 36); */
+       m_n->tu = 64;
        m_n->gmch_m = bits_per_pixel * pixel_clock;
        m_n->gmch_n = link_clock * nlanes * 8;
-       fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
-
+       intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
        m_n->link_m = pixel_clock;
        m_n->link_n = link_clock;
-       fdi_reduce_ratio(&m_n->link_m, &m_n->link_n);
+       intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
 }
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
@@ -4289,51 +4220,6 @@ static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
        }
 }
 
-static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock,
-                             struct drm_display_mode *adjusted_mode)
-{
-       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;
-       u32 temp;
-
-       temp = I915_READ(LVDS);
-       temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-       if (pipe == 1) {
-               temp |= LVDS_PIPEB_SELECT;
-       } else {
-               temp &= ~LVDS_PIPEB_SELECT;
-       }
-       /* set the corresponsding LVDS_BORDER bit */
-       temp |= dev_priv->lvds_border_bits;
-       /* Set the B0-B3 data pairs corresponding to whether we're going to
-        * set the DPLLs for dual-channel mode or not.
-        */
-       if (clock->p2 == 7)
-               temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-       else
-               temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-
-       /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
-        * appropriately here, but we need to look more thoroughly into how
-        * panels behave in the two modes.
-        */
-       /* set the dithering flag on LVDS as needed */
-       if (INTEL_INFO(dev)->gen >= 4) {
-               if (dev_priv->lvds_dither)
-                       temp |= LVDS_ENABLE_DITHER;
-               else
-                       temp &= ~LVDS_ENABLE_DITHER;
-       }
-       temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
-       if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-               temp |= LVDS_HSYNC_POLARITY;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-               temp |= LVDS_VSYNC_POLARITY;
-       I915_WRITE(LVDS, temp);
-}
-
 static void vlv_update_pll(struct drm_crtc *crtc,
                           struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode,
@@ -4349,6 +4235,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,
        bool is_sdvo;
        u32 temp;
 
+       mutex_lock(&dev_priv->dpio_lock);
+
        is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
                intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
 
@@ -4432,6 +4320,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,
                        temp |= (1 << 21);
                intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp);
        }
+
+       mutex_unlock(&dev_priv->dpio_lock);
 }
 
 static void i9xx_update_pll(struct drm_crtc *crtc,
@@ -4443,6 +4333,7 @@ static void i9xx_update_pll(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;
        u32 dpll;
        bool is_sdvo;
@@ -4511,12 +4402,9 @@ static void i9xx_update_pll(struct drm_crtc *crtc,
        POSTING_READ(DPLL(pipe));
        udelay(150);
 
-       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
-        * This is an exception to the general rule that mode_set doesn't turn
-        * things on.
-        */
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-               intel_update_lvds(crtc, clock, adjusted_mode);
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               if (encoder->pre_pll_enable)
+                       encoder->pre_pll_enable(encoder);
 
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
@@ -4555,6 +4443,7 @@ static void i8xx_update_pll(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;
        u32 dpll;
 
@@ -4588,12 +4477,9 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
        POSTING_READ(DPLL(pipe));
        udelay(150);
 
-       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
-        * This is an exception to the general rule that mode_set doesn't turn
-        * things on.
-        */
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-               intel_update_lvds(crtc, clock, adjusted_mode);
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               if (encoder->pre_pll_enable)
+                       encoder->pre_pll_enable(encoder);
 
        I915_WRITE(DPLL(pipe), dpll);
 
@@ -4783,10 +4669,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        /* default to 8bpc */
-       pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN);
+       pipeconf &= ~(PIPECONF_BPC_MASK | PIPECONF_DITHER_EN);
        if (is_dp) {
                if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
-                       pipeconf |= PIPECONF_BPP_6 |
+                       pipeconf |= PIPECONF_6BPC |
                                    PIPECONF_DITHER_EN |
                                    PIPECONF_DITHER_TYPE_SP;
                }
@@ -4794,7 +4680,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 
        if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
                if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) {
-                       pipeconf |= PIPECONF_BPP_6 |
+                       pipeconf |= PIPECONF_6BPC |
                                        PIPECONF_ENABLE |
                                        I965_PIPECONF_ACTIVE;
                }
@@ -5177,19 +5063,19 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,
 
        val = I915_READ(PIPECONF(pipe));
 
-       val &= ~PIPE_BPC_MASK;
+       val &= ~PIPECONF_BPC_MASK;
        switch (intel_crtc->bpp) {
        case 18:
-               val |= PIPE_6BPC;
+               val |= PIPECONF_6BPC;
                break;
        case 24:
-               val |= PIPE_8BPC;
+               val |= PIPECONF_8BPC;
                break;
        case 30:
-               val |= PIPE_10BPC;
+               val |= PIPECONF_10BPC;
                break;
        case 36:
-               val |= PIPE_12BPC;
+               val |= PIPECONF_12BPC;
                break;
        default:
                /* Case prevented by intel_choose_pipe_bpp_dither. */
@@ -5400,7 +5286,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
        struct intel_encoder *intel_encoder, *edp_encoder = NULL;
-       struct fdi_m_n m_n = {0};
+       struct intel_link_m_n m_n = {0};
        int target_clock, pixel_multiplier, lane, link_bw;
        bool is_dp = false, is_cpu_edp = false;
 
@@ -5452,8 +5338,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,
 
        if (pixel_multiplier > 1)
                link_bw *= pixel_multiplier;
-       ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw,
-                            &m_n);
+       intel_link_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, &m_n);
 
        I915_WRITE(PIPE_DATA_M1(cpu_transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m);
        I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n);
@@ -5506,7 +5391,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        if (is_lvds) {
                if ((intel_panel_use_ssc(dev_priv) &&
                     dev_priv->lvds_ssc_freq == 100) ||
-                   (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP)
+                   intel_is_dual_link_lvds(dev))
                        factor = 25;
        } else if (is_sdvo && is_tv)
                factor = 20;
@@ -5581,7 +5466,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        bool ok, has_reduced_clock = false;
        bool is_lvds = false, is_dp = false, is_cpu_edp = false;
        struct intel_encoder *encoder;
-       u32 temp;
        int ret;
        bool dither, fdi_config_ok;
 
@@ -5645,54 +5529,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        } else
                intel_put_pch_pll(intel_crtc);
 
-       /* The LVDS pin pair needs to be on before the DPLLs are enabled.
-        * This is an exception to the general rule that mode_set doesn't turn
-        * things on.
-        */
-       if (is_lvds) {
-               temp = I915_READ(PCH_LVDS);
-               temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-               if (HAS_PCH_CPT(dev)) {
-                       temp &= ~PORT_TRANS_SEL_MASK;
-                       temp |= PORT_TRANS_SEL_CPT(pipe);
-               } else {
-                       if (pipe == 1)
-                               temp |= LVDS_PIPEB_SELECT;
-                       else
-                               temp &= ~LVDS_PIPEB_SELECT;
-               }
-
-               /* set the corresponsding LVDS_BORDER bit */
-               temp |= dev_priv->lvds_border_bits;
-               /* Set the B0-B3 data pairs corresponding to whether we're going to
-                * set the DPLLs for dual-channel mode or not.
-                */
-               if (clock.p2 == 7)
-                       temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-               else
-                       temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
-
-               /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
-                * appropriately here, but we need to look more thoroughly into how
-                * panels behave in the two modes.
-                */
-               temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
-               if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-                       temp |= LVDS_HSYNC_POLARITY;
-               if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-                       temp |= LVDS_VSYNC_POLARITY;
-               I915_WRITE(PCH_LVDS, temp);
-       }
-
-       if (is_dp && !is_cpu_edp) {
+       if (is_dp && !is_cpu_edp)
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
-       } else {
-               /* For non-DP output, clear any trans DP clock recovery setting.*/
-               I915_WRITE(TRANSDATA_M1(pipe), 0);
-               I915_WRITE(TRANSDATA_N1(pipe), 0);
-               I915_WRITE(TRANSDPLINK_M1(pipe), 0);
-               I915_WRITE(TRANSDPLINK_N1(pipe), 0);
-       }
+
+       for_each_encoder_on_crtc(dev, crtc, encoder)
+               if (encoder->pre_pll_enable)
+                       encoder->pre_pll_enable(encoder);
 
        if (intel_crtc->pch_pll) {
                I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
@@ -5727,9 +5569,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
        fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc);
 
-       if (is_cpu_edp)
-               ironlake_set_pll_edp(crtc, adjusted_mode->clock);
-
        ironlake_set_pipeconf(crtc, adjusted_mode, dither);
 
        intel_wait_for_vblank(dev, pipe);
@@ -5759,20 +5598,13 @@ static int haswell_crtc_mode_set(struct drm_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;
-       bool ok, has_reduced_clock = false;
-       bool is_lvds = false, is_dp = false, is_cpu_edp = false;
+       bool is_dp = false, is_cpu_edp = false;
        struct intel_encoder *encoder;
-       u32 temp;
        int ret;
        bool dither;
 
        for_each_encoder_on_crtc(dev, crtc, encoder) {
                switch (encoder->type) {
-               case INTEL_OUTPUT_LVDS:
-                       is_lvds = true;
-                       break;
                case INTEL_OUTPUT_DISPLAYPORT:
                        is_dp = true;
                        break;
@@ -5806,143 +5638,26 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
        if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
                return -EINVAL;
 
-       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
-               ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
-                                            &has_reduced_clock,
-                                            &reduced_clock);
-               if (!ok) {
-                       DRM_ERROR("Couldn't find PLL settings for mode!\n");
-                       return -EINVAL;
-               }
-       }
-
        /* Ensure that the cursor is valid for the new mode before changing... */
        intel_crtc_update_cursor(crtc, true);
 
        /* determine panel color depth */
        dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp,
                                              adjusted_mode);
-       if (is_lvds && dev_priv->lvds_dither)
-               dither = true;
 
        DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);
        drm_mode_debug_printmodeline(mode);
 
-       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
-               fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
-               if (has_reduced_clock)
-                       fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
-                             reduced_clock.m2;
-
-               dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock,
-                                            fp);
-
-               /* CPU eDP is the only output that doesn't need a PCH PLL of its
-                * own on pre-Haswell/LPT generation */
-               if (!is_cpu_edp) {
-                       struct intel_pch_pll *pll;
-
-                       pll = intel_get_pch_pll(intel_crtc, dpll, fp);
-                       if (pll == NULL) {
-                               DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n",
-                                                pipe);
-                               return -EINVAL;
-                       }
-               } else
-                       intel_put_pch_pll(intel_crtc);
-
-               /* The LVDS pin pair needs to be on before the DPLLs are
-                * enabled.  This is an exception to the general rule that
-                * mode_set doesn't turn things on.
-                */
-               if (is_lvds) {
-                       temp = I915_READ(PCH_LVDS);
-                       temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
-                       if (HAS_PCH_CPT(dev)) {
-                               temp &= ~PORT_TRANS_SEL_MASK;
-                               temp |= PORT_TRANS_SEL_CPT(pipe);
-                       } else {
-                               if (pipe == 1)
-                                       temp |= LVDS_PIPEB_SELECT;
-                               else
-                                       temp &= ~LVDS_PIPEB_SELECT;
-                       }
-
-                       /* set the corresponsding LVDS_BORDER bit */
-                       temp |= dev_priv->lvds_border_bits;
-                       /* Set the B0-B3 data pairs corresponding to whether
-                        * we're going to set the DPLLs for dual-channel mode or
-                        * not.
-                        */
-                       if (clock.p2 == 7)
-                               temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
-                       else
-                               temp &= ~(LVDS_B0B3_POWER_UP |
-                                         LVDS_CLKB_POWER_UP);
-
-                       /* It would be nice to set 24 vs 18-bit mode
-                        * (LVDS_A3_POWER_UP) appropriately here, but we need to
-                        * look more thoroughly into how panels behave in the
-                        * two modes.
-                        */
-                       temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
-                       if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
-                               temp |= LVDS_HSYNC_POLARITY;
-                       if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
-                               temp |= LVDS_VSYNC_POLARITY;
-                       I915_WRITE(PCH_LVDS, temp);
-               }
-       }
-
-       if (is_dp && !is_cpu_edp) {
+       if (is_dp && !is_cpu_edp)
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
-       } else {
-               if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
-                       /* For non-DP output, clear any trans DP clock recovery
-                        * setting.*/
-                       I915_WRITE(TRANSDATA_M1(pipe), 0);
-                       I915_WRITE(TRANSDATA_N1(pipe), 0);
-                       I915_WRITE(TRANSDPLINK_M1(pipe), 0);
-                       I915_WRITE(TRANSDPLINK_N1(pipe), 0);
-               }
-       }
 
        intel_crtc->lowfreq_avail = false;
-       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
-               if (intel_crtc->pch_pll) {
-                       I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
-
-                       /* Wait for the clocks to stabilize. */
-                       POSTING_READ(intel_crtc->pch_pll->pll_reg);
-                       udelay(150);
-
-                       /* The pixel multiplier can only be updated once the
-                        * DPLL is enabled and the clocks are stable.
-                        *
-                        * So write it again.
-                        */
-                       I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll);
-               }
-
-               if (intel_crtc->pch_pll) {
-                       if (is_lvds && has_reduced_clock && i915_powersave) {
-                               I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2);
-                               intel_crtc->lowfreq_avail = true;
-                       } else {
-                               I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp);
-                       }
-               }
-       }
 
        intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
 
        if (!is_dp || is_cpu_edp)
                ironlake_set_m_n(crtc, mode, adjusted_mode);
 
-       if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
-               if (is_cpu_edp)
-                       ironlake_set_pll_edp(crtc, adjusted_mode->clock);
-
        haswell_set_pipeconf(crtc, adjusted_mode, dither);
 
        /* Set up the display plane register */
@@ -6759,7 +6474,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
                return false;
        }
 
-       if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
+       if (intel_set_mode(crtc, mode, 0, 0, fb)) {
                DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
                if (old->release_fb)
                        old->release_fb->funcs->destroy(old->release_fb);
@@ -7109,8 +6824,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev,
 
        obj = work->old_fb_obj;
 
-       atomic_clear_mask(1 << intel_crtc->plane,
-                         &obj->pending_flip.counter);
        wake_up(&dev_priv->pending_flip_queue);
 
        queue_work(dev_priv->wq, &work->work);
@@ -7474,10 +7187,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
        work->enable_stall_check = true;
 
-       /* Block clients from rendering to the new back buffer until
-        * the flip occurs and the object is no longer visible.
-        */
-       atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
        atomic_inc(&intel_crtc->unpin_work_count);
 
        ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
@@ -7494,7 +7203,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 
 cleanup_pending:
        atomic_dec(&intel_crtc->unpin_work_count);
-       atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
        drm_gem_object_unreference(&work->old_fb_obj->base);
        drm_gem_object_unreference(&obj->base);
        mutex_unlock(&dev->struct_mutex);
@@ -7904,16 +7612,21 @@ intel_modeset_check_state(struct drm_device *dev)
        }
 }
 
-bool intel_set_mode(struct drm_crtc *crtc,
-                   struct drm_display_mode *mode,
-                   int x, int y, struct drm_framebuffer *fb)
+int intel_set_mode(struct drm_crtc *crtc,
+                  struct drm_display_mode *mode,
+                  int x, int y, struct drm_framebuffer *fb)
 {
        struct drm_device *dev = crtc->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
+       struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode;
        struct intel_crtc *intel_crtc;
        unsigned disable_pipes, prepare_pipes, modeset_pipes;
-       bool ret = true;
+       int ret = 0;
+
+       saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL);
+       if (!saved_mode)
+               return -ENOMEM;
+       saved_hwmode = saved_mode + 1;
 
        intel_modeset_affected_pipes(crtc, &modeset_pipes,
                                     &prepare_pipes, &disable_pipes);
@@ -7924,8 +7637,8 @@ bool intel_set_mode(struct drm_crtc *crtc,
        for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
                intel_crtc_disable(&intel_crtc->base);
 
-       saved_hwmode = crtc->hwmode;
-       saved_mode = crtc->mode;
+       *saved_hwmode = crtc->hwmode;
+       *saved_mode = crtc->mode;
 
        /* Hack: Because we don't (yet) support global modeset on multiple
         * crtcs, we don't keep track of the new mode for more than one crtc.
@@ -7936,7 +7649,8 @@ bool intel_set_mode(struct drm_crtc *crtc,
        if (modeset_pipes) {
                adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
                if (IS_ERR(adjusted_mode)) {
-                       return false;
+                       ret = PTR_ERR(adjusted_mode);
+                       goto out;
                }
        }
 
@@ -7962,11 +7676,11 @@ bool 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,
-                                          mode, adjusted_mode,
-                                          x, y, fb);
-               if (!ret)
-                   goto done;
+               ret = intel_crtc_mode_set(&intel_crtc->base,
+                                         mode, adjusted_mode,
+                                         x, y, fb);
+               if (ret)
+                       goto done;
        }
 
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
@@ -7987,16 +7701,23 @@ bool intel_set_mode(struct drm_crtc *crtc,
        /* FIXME: add subpixel order */
 done:
        drm_mode_destroy(dev, adjusted_mode);
-       if (!ret && crtc->enabled) {
-               crtc->hwmode = saved_hwmode;
-               crtc->mode = saved_mode;
+       if (ret && crtc->enabled) {
+               crtc->hwmode = *saved_hwmode;
+               crtc->mode = *saved_mode;
        } else {
                intel_modeset_check_state(dev);
        }
 
+out:
+       kfree(saved_mode);
        return ret;
 }
 
+void intel_crtc_restore_mode(struct drm_crtc *crtc)
+{
+       intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb);
+}
+
 #undef for_each_intel_crtc_masked
 
 static void intel_set_config_free(struct intel_set_config *config)
@@ -8262,11 +7983,11 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
                        drm_mode_debug_printmodeline(set->mode);
                }
 
-               if (!intel_set_mode(set->crtc, set->mode,
-                                   set->x, set->y, set->fb)) {
-                       DRM_ERROR("failed to set mode on [CRTC:%d]\n",
-                                 set->crtc->base.id);
-                       ret = -EINVAL;
+               ret = intel_set_mode(set->crtc, set->mode,
+                                    set->x, set->y, set->fb);
+               if (ret) {
+                       DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n",
+                                 set->crtc->base.id, ret);
                        goto fail;
                }
        } else if (config->fb_changed) {
@@ -8283,8 +8004,8 @@ fail:
 
        /* Try to restore the config */
        if (config->mode_changed &&
-           !intel_set_mode(save_set.crtc, save_set.mode,
-                           save_set.x, save_set.y, save_set.fb))
+           intel_set_mode(save_set.crtc, save_set.mode,
+                          save_set.x, save_set.y, save_set.fb))
                DRM_ERROR("failed to restore config after modeset failure\n");
 
 out_config:
@@ -8303,7 +8024,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
 
 static void intel_cpu_pll_init(struct drm_device *dev)
 {
-       if (IS_HASWELL(dev))
+       if (HAS_DDI(dev))
                intel_ddi_pll_init(dev);
 }
 
@@ -8439,11 +8160,10 @@ static void intel_setup_outputs(struct drm_device *dev)
                I915_WRITE(PFIT_CONTROL, 0);
        }
 
-       if (!(IS_HASWELL(dev) &&
-             (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)))
+       if (!(HAS_DDI(dev) && (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)))
                intel_crt_init(dev);
 
-       if (IS_HASWELL(dev)) {
+       if (HAS_DDI(dev)) {
                int found;
 
                /* Haswell uses DDI functions to detect digital outputs */
@@ -8686,7 +8406,7 @@ static void intel_init_display(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        /* We always want a DPMS function */
-       if (IS_HASWELL(dev)) {
+       if (HAS_DDI(dev)) {
                dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
                dev_priv->display.crtc_enable = haswell_crtc_enable;
                dev_priv->display.crtc_disable = haswell_crtc_disable;
@@ -8748,8 +8468,7 @@ static void intel_init_display(struct drm_device *dev)
                } else if (IS_HASWELL(dev)) {
                        dev_priv->display.fdi_link_train = hsw_fdi_link_train;
                        dev_priv->display.write_eld = haswell_write_eld;
-               } else
-                       dev_priv->display.update_wm = NULL;
+               }
        } else if (IS_G4X(dev)) {
                dev_priv->display.write_eld = g4x_write_eld;
        }
@@ -8982,6 +8701,9 @@ void intel_modeset_init(struct drm_device *dev)
        /* Just disable it once at startup */
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
+
+       /* Just in case the BIOS is doing something questionable. */
+       intel_disable_fbc(dev);
 }
 
 static void
@@ -9192,7 +8914,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
        struct intel_encoder *encoder;
        struct intel_connector *connector;
 
-       if (IS_HASWELL(dev)) {
+       if (HAS_DDI(dev)) {
                tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
 
                if (tmp & TRANS_DDI_FUNC_ENABLE) {
@@ -9233,7 +8955,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                              crtc->active ? "enabled" : "disabled");
        }
 
-       if (IS_HASWELL(dev))
+       if (HAS_DDI(dev))
                intel_ddi_setup_hw_pll_state(dev);
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list,
@@ -9284,9 +9006,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 
        if (force_restore) {
                for_each_pipe(pipe) {
-                       crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-                       intel_set_mode(&crtc->base, &crtc->base.mode,
-                                      crtc->base.x, crtc->base.y, crtc->base.fb);
+                       intel_crtc_restore_mode(dev_priv->pipe_to_crtc_mapping[pipe]);
                }
 
                i915_redisable_vga(dev);
@@ -9350,6 +9070,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
        flush_scheduled_work();
 
        drm_mode_config_cleanup(dev);
+
+       intel_cleanup_overlay(dev);
 }
 
 /*