drm/i915: check for strange pfit pipe assignemnt on ivb/hsw
[cascardo/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 2a9d067..a4b97ca 100644 (file)
@@ -59,24 +59,6 @@ typedef struct intel_limit intel_limit_t;
 struct intel_limit {
        intel_range_t   dot, vco, n, m, m1, m2, p, p1;
        intel_p2_t          p2;
-       /**
-        * find_pll() - Find the best values for the PLL
-        * @limit: limits for the PLL
-        * @crtc: current CRTC
-        * @target: target frequency in kHz
-        * @refclk: reference clock frequency in kHz
-        * @match_clock: if provided, @best_clock P divider must
-        *               match the P divider from @match_clock
-        *               used for LVDS downclocking
-        * @best_clock: best PLL values found
-        *
-        * Returns true on success, false on failure.
-        */
-       bool (*find_pll)(const intel_limit_t *limit,
-                        struct drm_crtc *crtc,
-                        int target, int refclk,
-                        intel_clock_t *match_clock,
-                        intel_clock_t *best_clock);
 };
 
 /* FDI */
@@ -92,20 +74,6 @@ intel_pch_rawclk(struct drm_device *dev)
        return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK;
 }
 
-static bool
-intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                   int target, int refclk, intel_clock_t *match_clock,
-                   intel_clock_t *best_clock);
-static bool
-intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                       int target, int refclk, intel_clock_t *match_clock,
-                       intel_clock_t *best_clock);
-
-static bool
-intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
-                       int target, int refclk, intel_clock_t *match_clock,
-                       intel_clock_t *best_clock);
-
 static inline u32 /* units of 100MHz */
 intel_fdi_link_freq(struct drm_device *dev)
 {
@@ -127,7 +95,6 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
        .p1 = { .min = 2, .max = 33 },
        .p2 = { .dot_limit = 165000,
                .p2_slow = 4, .p2_fast = 2 },
-       .find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i8xx_lvds = {
@@ -141,7 +108,6 @@ static const intel_limit_t intel_limits_i8xx_lvds = {
        .p1 = { .min = 1, .max = 6 },
        .p2 = { .dot_limit = 165000,
                .p2_slow = 14, .p2_fast = 7 },
-       .find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i9xx_sdvo = {
@@ -155,7 +121,6 @@ static const intel_limit_t intel_limits_i9xx_sdvo = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 200000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_i9xx_lvds = {
@@ -169,7 +134,6 @@ static const intel_limit_t intel_limits_i9xx_lvds = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 112000,
                .p2_slow = 14, .p2_fast = 7 },
-       .find_pll = intel_find_best_PLL,
 };
 
 
@@ -186,7 +150,6 @@ static const intel_limit_t intel_limits_g4x_sdvo = {
                .p2_slow = 10,
                .p2_fast = 10
        },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_g4x_hdmi = {
@@ -200,7 +163,6 @@ static const intel_limit_t intel_limits_g4x_hdmi = {
        .p1 = { .min = 1, .max = 8},
        .p2 = { .dot_limit = 165000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
@@ -215,7 +177,6 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
        .p2 = { .dot_limit = 0,
                .p2_slow = 14, .p2_fast = 14
        },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
@@ -230,7 +191,6 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
        .p2 = { .dot_limit = 0,
                .p2_slow = 7, .p2_fast = 7
        },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_pineview_sdvo = {
@@ -246,7 +206,6 @@ static const intel_limit_t intel_limits_pineview_sdvo = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 200000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_pineview_lvds = {
@@ -260,7 +219,6 @@ static const intel_limit_t intel_limits_pineview_lvds = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 112000,
                .p2_slow = 14, .p2_fast = 14 },
-       .find_pll = intel_find_best_PLL,
 };
 
 /* Ironlake / Sandybridge
@@ -279,7 +237,6 @@ static const intel_limit_t intel_limits_ironlake_dac = {
        .p1 = { .min = 1, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 10, .p2_fast = 5 },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_ironlake_single_lvds = {
@@ -293,7 +250,6 @@ static const intel_limit_t intel_limits_ironlake_single_lvds = {
        .p1 = { .min = 2, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 14, .p2_fast = 14 },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_ironlake_dual_lvds = {
@@ -307,7 +263,6 @@ static const intel_limit_t intel_limits_ironlake_dual_lvds = {
        .p1 = { .min = 2, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 7, .p2_fast = 7 },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 /* LVDS 100mhz refclk limits. */
@@ -322,7 +277,6 @@ static const intel_limit_t intel_limits_ironlake_single_lvds_100m = {
        .p1 = { .min = 2, .max = 8 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 14, .p2_fast = 14 },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
@@ -336,7 +290,6 @@ static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
        .p1 = { .min = 2, .max = 6 },
        .p2 = { .dot_limit = 225000,
                .p2_slow = 7, .p2_fast = 7 },
-       .find_pll = intel_g4x_find_best_PLL,
 };
 
 static const intel_limit_t intel_limits_vlv_dac = {
@@ -350,7 +303,6 @@ static const intel_limit_t intel_limits_vlv_dac = {
        .p1 = { .min = 1, .max = 3 },
        .p2 = { .dot_limit = 270000,
                .p2_slow = 2, .p2_fast = 20 },
-       .find_pll = intel_vlv_find_best_pll,
 };
 
 static const intel_limit_t intel_limits_vlv_hdmi = {
@@ -364,7 +316,6 @@ static const intel_limit_t intel_limits_vlv_hdmi = {
        .p1 = { .min = 2, .max = 3 },
        .p2 = { .dot_limit = 270000,
                .p2_slow = 2, .p2_fast = 20 },
-       .find_pll = intel_vlv_find_best_pll,
 };
 
 static const intel_limit_t intel_limits_vlv_dp = {
@@ -378,7 +329,6 @@ static const intel_limit_t intel_limits_vlv_dp = {
        .p1 = { .min = 1, .max = 3 },
        .p2 = { .dot_limit = 270000,
                .p2_slow = 2, .p2_fast = 20 },
-       .find_pll = intel_vlv_find_best_pll,
 };
 
 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,
@@ -475,12 +425,8 @@ static uint32_t i9xx_dpll_compute_m(struct dpll *dpll)
        return 5 * (dpll->m1 + 2) + (dpll->m2 + 2);
 }
 
-static void intel_clock(struct drm_device *dev, int refclk, intel_clock_t *clock)
+static void i9xx_clock(int refclk, intel_clock_t *clock)
 {
-       if (IS_PINEVIEW(dev)) {
-               pineview_clock(refclk, clock);
-               return;
-       }
        clock->m = i9xx_dpll_compute_m(clock);
        clock->p = clock->p1 * clock->p2;
        clock->vco = refclk * clock->m / (clock->n + 2);
@@ -538,10 +484,9 @@ static bool intel_PLL_is_valid(struct drm_device *dev,
 }
 
 static bool
-intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
+i9xx_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
                    int target, int refclk, intel_clock_t *match_clock,
                    intel_clock_t *best_clock)
-
 {
        struct drm_device *dev = crtc->dev;
        intel_clock_t clock;
@@ -570,8 +515,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
             clock.m1++) {
                for (clock.m2 = limit->m2.min;
                     clock.m2 <= limit->m2.max; clock.m2++) {
-                       /* m1 is always 0 in Pineview */
-                       if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev))
+                       if (clock.m2 >= clock.m1)
                                break;
                        for (clock.n = limit->n.min;
                             clock.n <= limit->n.max; clock.n++) {
@@ -579,7 +523,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                                        clock.p1 <= limit->p1.max; clock.p1++) {
                                        int this_err;
 
-                                       intel_clock(dev, refclk, &clock);
+                                       i9xx_clock(refclk, &clock);
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
@@ -601,9 +545,68 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 }
 
 static bool
-intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
-                       int target, int refclk, intel_clock_t *match_clock,
-                       intel_clock_t *best_clock)
+pnv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
+                  int target, int refclk, intel_clock_t *match_clock,
+                  intel_clock_t *best_clock)
+{
+       struct drm_device *dev = crtc->dev;
+       intel_clock_t clock;
+       int err = target;
+
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+               /*
+                * 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 (intel_is_dual_link_lvds(dev))
+                       clock.p2 = limit->p2.p2_fast;
+               else
+                       clock.p2 = limit->p2.p2_slow;
+       } else {
+               if (target < limit->p2.dot_limit)
+                       clock.p2 = limit->p2.p2_slow;
+               else
+                       clock.p2 = limit->p2.p2_fast;
+       }
+
+       memset(best_clock, 0, sizeof(*best_clock));
+
+       for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
+            clock.m1++) {
+               for (clock.m2 = limit->m2.min;
+                    clock.m2 <= limit->m2.max; clock.m2++) {
+                       for (clock.n = limit->n.min;
+                            clock.n <= limit->n.max; clock.n++) {
+                               for (clock.p1 = limit->p1.min;
+                                       clock.p1 <= limit->p1.max; clock.p1++) {
+                                       int this_err;
+
+                                       pineview_clock(refclk, &clock);
+                                       if (!intel_PLL_is_valid(dev, limit,
+                                                               &clock))
+                                               continue;
+                                       if (match_clock &&
+                                           clock.p != match_clock->p)
+                                               continue;
+
+                                       this_err = abs(clock.dot - target);
+                                       if (this_err < err) {
+                                               *best_clock = clock;
+                                               err = this_err;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return (err != target);
+}
+
+static bool
+g4x_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
+                  int target, int refclk, intel_clock_t *match_clock,
+                  intel_clock_t *best_clock)
 {
        struct drm_device *dev = crtc->dev;
        intel_clock_t clock;
@@ -638,7 +641,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                                     clock.p1 >= limit->p1.min; clock.p1--) {
                                        int this_err;
 
-                                       intel_clock(dev, refclk, &clock);
+                                       i9xx_clock(refclk, &clock);
                                        if (!intel_PLL_is_valid(dev, limit,
                                                                &clock))
                                                continue;
@@ -658,9 +661,9 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 }
 
 static bool
-intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,
-                       int target, int refclk, intel_clock_t *match_clock,
-                       intel_clock_t *best_clock)
+vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
+                  int target, int refclk, intel_clock_t *match_clock,
+                  intel_clock_t *best_clock)
 {
        u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2;
        u32 m, n, fastclk;
@@ -2212,7 +2215,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        crtc->y = y;
 
        if (old_fb) {
-               intel_wait_for_vblank(dev, intel_crtc->pipe);
+               if (intel_crtc->active && old_fb != fb)
+                       intel_wait_for_vblank(dev, intel_crtc->pipe);
                intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
        }
 
@@ -3242,6 +3246,42 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
        intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
+/* IPS only exists on ULT machines and is tied to pipe A. */
+static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
+{
+       return IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A;
+}
+
+static void hsw_enable_ips(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+       if (!crtc->config.ips_enabled)
+               return;
+
+       /* We can only enable IPS after we enable a plane and wait for a vblank.
+        * We guarantee that the plane is enabled by calling intel_enable_ips
+        * only after intel_enable_plane. And intel_enable_plane already waits
+        * for a vblank, so all we need to do here is to enable the IPS bit. */
+       assert_plane_enabled(dev_priv, crtc->plane);
+       I915_WRITE(IPS_CTL, IPS_ENABLE);
+}
+
+static void hsw_disable_ips(struct intel_crtc *crtc)
+{
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!crtc->config.ips_enabled)
+               return;
+
+       assert_plane_enabled(dev_priv, crtc->plane);
+       I915_WRITE(IPS_CTL, 0);
+
+       /* We need to wait for a vblank before we can disable the plane. */
+       intel_wait_for_vblank(dev, crtc->pipe);
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
@@ -3289,6 +3329,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
                          intel_crtc->config.has_pch_encoder);
        intel_enable_plane(dev_priv, plane, pipe);
 
+       hsw_enable_ips(intel_crtc);
+
        if (intel_crtc->config.has_pch_encoder)
                lpt_pch_enable(crtc);
 
@@ -3431,6 +3473,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
        if (dev_priv->cfb_plane == plane)
                intel_disable_fbc(dev);
 
+       hsw_disable_ips(intel_crtc);
+
        intel_disable_plane(dev_priv, plane, pipe);
 
        if (intel_crtc->config.has_pch_encoder)
@@ -3469,12 +3513,6 @@ static void ironlake_crtc_off(struct drm_crtc *crtc)
 
 static void haswell_crtc_off(struct drm_crtc *crtc)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       /* Stop saying we're using TRANSCODER_EDP because some other CRTC might
-        * start using it. */
-       intel_crtc->config.cpu_transcoder = (enum transcoder) intel_crtc->pipe;
-
        intel_ddi_put_crtc_pll(crtc);
 }
 
@@ -3529,18 +3567,12 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
        if (!crtc->config.gmch_pfit.control)
                return;
 
-       WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
-       assert_pipe_disabled(dev_priv, crtc->pipe);
-
        /*
-        * Enable automatic panel scaling so that non-native modes
-        * fill the screen.  The panel fitter should only be
-        * adjusted whilst the pipe is disabled, according to
-        * register description and PRM.
+        * The panel fitter should only be adjusted whilst the pipe is disabled,
+        * according to register description and PRM.
         */
-       DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
-                     pipe_config->gmch_pfit.control,
-                     pipe_config->gmch_pfit.pgm_ratios);
+       WARN_ON(I915_READ(PFIT_CONTROL) & PFIT_ENABLE);
+       assert_pipe_disabled(dev_priv, crtc->pipe);
 
        I915_WRITE(PFIT_PGM_RATIOS, pipe_config->gmch_pfit.pgm_ratios);
        I915_WRITE(PFIT_CONTROL, pipe_config->gmch_pfit.control);
@@ -3957,7 +3989,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc,
 {
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
-       int target_clock, lane, link_bw;
+       int lane, link_bw, fdi_dotclock;
        bool setup_ok, needs_recompute = false;
 
 retry:
@@ -3970,19 +4002,16 @@ retry:
         */
        link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
 
-       if (pipe_config->pixel_target_clock)
-               target_clock = pipe_config->pixel_target_clock;
-       else
-               target_clock = adjusted_mode->clock;
+       fdi_dotclock = adjusted_mode->clock;
+       if (pipe_config->pixel_multiplier > 1)
+               fdi_dotclock /= pipe_config->pixel_multiplier;
 
-       lane = ironlake_get_lanes_required(target_clock, link_bw,
+       lane = ironlake_get_lanes_required(fdi_dotclock, link_bw,
                                           pipe_config->pipe_bpp);
 
        pipe_config->fdi_lanes = lane;
 
-       if (pipe_config->pixel_multiplier > 1)
-               link_bw *= pipe_config->pixel_multiplier;
-       intel_link_compute_m_n(pipe_config->pipe_bpp, lane, target_clock,
+       intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
                               link_bw, &pipe_config->fdi_m_n);
 
        setup_ok = ironlake_check_fdi_lanes(intel_crtc->base.dev,
@@ -4003,11 +4032,20 @@ retry:
        return setup_ok ? 0 : -EINVAL;
 }
 
+static void hsw_compute_ips_config(struct intel_crtc *crtc,
+                                  struct intel_crtc_config *pipe_config)
+{
+       pipe_config->ips_enabled = i915_enable_ips &&
+                                  hsw_crtc_supports_ips(crtc) &&
+                                  pipe_config->pipe_bpp == 24;
+}
+
 static int intel_crtc_compute_config(struct drm_crtc *crtc,
                                     struct intel_crtc_config *pipe_config)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
        if (HAS_PCH_SPLIT(dev)) {
                /* FDI link clock is fixed at 2.7G */
@@ -4037,8 +4075,11 @@ static int intel_crtc_compute_config(struct drm_crtc *crtc,
                pipe_config->pipe_bpp = 8*3;
        }
 
+       if (IS_HASWELL(dev))
+               hsw_compute_ips_config(intel_crtc, pipe_config);
+
        if (pipe_config->has_pch_encoder)
-               return ironlake_fdi_compute_config(to_intel_crtc(crtc), pipe_config);
+               return ironlake_fdi_compute_config(intel_crtc, pipe_config);
 
        return 0;
 }
@@ -4311,8 +4352,6 @@ static void vlv_update_pll(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_display_mode *adjusted_mode =
-               &crtc->config.adjusted_mode;
        struct intel_encoder *encoder;
        int pipe = crtc->pipe;
        u32 dpll, mdiv;
@@ -4365,7 +4404,7 @@ static void vlv_update_pll(struct intel_crtc *crtc)
        vlv_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
 
        /* Set HBR and RBR LPF coefficients */
-       if (adjusted_mode->clock == 162000 ||
+       if (crtc->config.port_clock == 162000 ||
            intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_HDMI))
                vlv_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
                                 0x005f0021);
@@ -4538,7 +4577,6 @@ static void i9xx_update_pll(struct intel_crtc *crtc,
 }
 
 static void i8xx_update_pll(struct intel_crtc *crtc,
-                           struct drm_display_mode *adjusted_mode,
                            intel_clock_t *reduced_clock,
                            int num_connectors)
 {
@@ -4593,14 +4631,15 @@ static void i8xx_update_pll(struct intel_crtc *crtc,
        I915_WRITE(DPLL(pipe), dpll);
 }
 
-static void intel_set_pipe_timings(struct intel_crtc *intel_crtc,
-                                  struct drm_display_mode *mode,
-                                  struct drm_display_mode *adjusted_mode)
+static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
 {
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe = intel_crtc->pipe;
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
+       struct drm_display_mode *adjusted_mode =
+               &intel_crtc->config.adjusted_mode;
+       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end;
 
        /* We need to be careful not to changed the adjusted mode, for otherwise
@@ -4778,8 +4817,6 @@ 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);
-       struct drm_display_mode *adjusted_mode =
-               &intel_crtc->config.adjusted_mode;
        struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
@@ -4810,9 +4847,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
         * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
         */
        limit = intel_limit(crtc, refclk);
-       ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
-                            &clock);
-       if (!ok) {
+       ok = dev_priv->display.find_dpll(limit, crtc,
+                                        intel_crtc->config.port_clock,
+                                        refclk, NULL, &clock);
+       if (!ok && !intel_crtc->config.clock_set) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        }
@@ -4827,10 +4865,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                 * by using the FP0/FP1. In such case we will disable the LVDS
                 * downclock feature.
                */
-               has_reduced_clock = limit->find_pll(limit, crtc,
+               has_reduced_clock =
+                       dev_priv->display.find_dpll(limit, crtc,
                                                    dev_priv->lvds_downclock,
-                                                   refclk,
-                                                   &clock,
+                                                   refclk, &clock,
                                                    &reduced_clock);
        }
        /* Compat-code for transition, will disappear. */
@@ -4843,7 +4881,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        if (IS_GEN2(dev))
-               i8xx_update_pll(intel_crtc, adjusted_mode,
+               i8xx_update_pll(intel_crtc,
                                has_reduced_clock ? &reduced_clock : NULL,
                                num_connectors);
        else if (IS_VALLEYVIEW(dev))
@@ -4863,10 +4901,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                        dspcntr |= DISPPLANE_SEL_PIPE_B;
        }
 
-       DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe));
-       drm_mode_debug_printmodeline(mode);
-
-       intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+       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.
@@ -4925,6 +4960,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
+       pipe_config->cpu_transcoder = crtc->pipe;
+
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
                return false;
@@ -5419,7 +5456,6 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc)
 }
 
 static bool ironlake_compute_clocks(struct drm_crtc *crtc,
-                                   struct drm_display_mode *adjusted_mode,
                                    intel_clock_t *clock,
                                    bool *has_reduced_clock,
                                    intel_clock_t *reduced_clock)
@@ -5447,8 +5483,9 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
         * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
         */
        limit = intel_limit(crtc, refclk);
-       ret = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL,
-                             clock);
+       ret = dev_priv->display.find_dpll(limit, crtc,
+                                         to_intel_crtc(crtc)->config.port_clock,
+                                         refclk, NULL, clock);
        if (!ret)
                return false;
 
@@ -5459,11 +5496,11 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
                 * by using the FP0/FP1. In such case we will disable the LVDS
                 * downclock feature.
                */
-               *has_reduced_clock = limit->find_pll(limit, crtc,
-                                                    dev_priv->lvds_downclock,
-                                                    refclk,
-                                                    clock,
-                                                    reduced_clock);
+               *has_reduced_clock =
+                       dev_priv->display.find_dpll(limit, crtc,
+                                                   dev_priv->lvds_downclock,
+                                                   refclk, clock,
+                                                   reduced_clock);
        }
 
        return true;
@@ -5621,9 +5658,6 @@ static int ironlake_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);
-       struct drm_display_mode *adjusted_mode =
-               &intel_crtc->config.adjusted_mode;
-       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
        int num_connectors = 0;
@@ -5647,11 +5681,9 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
             "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
 
-       intel_crtc->config.cpu_transcoder = pipe;
-
-       ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock,
+       ok = ironlake_compute_clocks(crtc, &clock,
                                     &has_reduced_clock, &reduced_clock);
-       if (!ok) {
+       if (!ok && !intel_crtc->config.clock_set) {
                DRM_ERROR("Couldn't find PLL settings for mode!\n");
                return -EINVAL;
        }
@@ -5667,9 +5699,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        /* Ensure that the cursor is valid for the new mode before changing... */
        intel_crtc_update_cursor(crtc, true);
 
-       DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe));
-       drm_mode_debug_printmodeline(mode);
-
        /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
        if (intel_crtc->config.has_pch_encoder) {
                struct intel_pch_pll *pll;
@@ -5723,7 +5752,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
-       intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);
+       intel_set_pipe_timings(intel_crtc);
 
        if (intel_crtc->config.has_pch_encoder) {
                intel_cpu_transcoder_set_m_n(intel_crtc,
@@ -5774,6 +5803,14 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,
        if (tmp & PF_ENABLE) {
                pipe_config->pch_pfit.pos = I915_READ(PF_WIN_POS(crtc->pipe));
                pipe_config->pch_pfit.size = I915_READ(PF_WIN_SZ(crtc->pipe));
+
+               /* We currently do not free assignements of panel fitters on
+                * ivb/hsw (since we don't use the higher upscaling modes which
+                * differentiates them) so just WARN about this case for now. */
+               if (IS_GEN7(dev)) {
+                       WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) !=
+                               PF_PIPE_SEL_IVB(crtc->pipe));
+               }
        }
 }
 
@@ -5784,6 +5821,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t tmp;
 
+       pipe_config->cpu_transcoder = crtc->pipe;
+
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
                return false;
@@ -5809,23 +5848,13 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
 {
        bool enable = false;
        struct intel_crtc *crtc;
-       struct intel_encoder *encoder;
 
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
-               if (crtc->pipe != PIPE_A && crtc->base.enabled)
-                       enable = true;
-               /* XXX: Should check for edp transcoder here, but thanks to init
-                * sequence that's not yet available. Just in case desktop eDP
-                * on PORT D is possible on haswell, too. */
-               /* Even the eDP panel fitter is outside the always-on well. */
-               if (crtc->config.pch_pfit.size && crtc->base.enabled)
-                       enable = true;
-       }
+               if (!crtc->base.enabled)
+                       continue;
 
-       list_for_each_entry(encoder, &dev->mode_config.encoder_list,
-                           base.head) {
-               if (encoder->type != INTEL_OUTPUT_EDP &&
-                   encoder->connectors_active)
+               if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.size ||
+                   crtc->config.cpu_transcoder != TRANSCODER_EDP)
                        enable = true;
        }
 
@@ -5839,9 +5868,6 @@ static int haswell_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);
-       struct drm_display_mode *adjusted_mode =
-               &intel_crtc->config.adjusted_mode;
-       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
        int num_connectors = 0;
@@ -5860,38 +5886,21 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
                num_connectors++;
        }
 
-       if (is_cpu_edp)
-               intel_crtc->config.cpu_transcoder = TRANSCODER_EDP;
-       else
-               intel_crtc->config.cpu_transcoder = pipe;
-
-       /* We are not sure yet this won't happen. */
-       WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
-            INTEL_PCH_TYPE(dev));
-
        WARN(num_connectors != 1, "%d connectors attached to pipe %c\n",
             num_connectors, pipe_name(pipe));
 
-       WARN_ON(I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
-               (PIPECONF_ENABLE | I965_PIPECONF_ACTIVE));
-
-       WARN_ON(I915_READ(DSPCNTR(plane)) & DISPLAY_PLANE_ENABLE);
-
-       if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))
+       if (!intel_ddi_pll_mode_set(crtc))
                return -EINVAL;
 
        /* Ensure that the cursor is valid for the new mode before changing... */
        intel_crtc_update_cursor(crtc, true);
 
-       DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe_name(pipe));
-       drm_mode_debug_printmodeline(mode);
-
        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, mode, adjusted_mode);
+       intel_set_pipe_timings(intel_crtc);
 
        if (intel_crtc->config.has_pch_encoder) {
                intel_cpu_transcoder_set_m_n(intel_crtc,
@@ -5918,15 +5927,37 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       enum transcoder cpu_transcoder = crtc->config.cpu_transcoder;
        enum intel_display_power_domain pfit_domain;
        uint32_t tmp;
 
+       pipe_config->cpu_transcoder = crtc->pipe;
+       tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
+       if (tmp & TRANS_DDI_FUNC_ENABLE) {
+               enum pipe trans_edp_pipe;
+               switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
+               default:
+                       WARN(1, "unknown pipe linked to edp transcoder\n");
+               case TRANS_DDI_EDP_INPUT_A_ONOFF:
+               case TRANS_DDI_EDP_INPUT_A_ON:
+                       trans_edp_pipe = PIPE_A;
+                       break;
+               case TRANS_DDI_EDP_INPUT_B_ONOFF:
+                       trans_edp_pipe = PIPE_B;
+                       break;
+               case TRANS_DDI_EDP_INPUT_C_ONOFF:
+                       trans_edp_pipe = PIPE_C;
+                       break;
+               }
+
+               if (trans_edp_pipe == crtc->pipe)
+                       pipe_config->cpu_transcoder = TRANSCODER_EDP;
+       }
+
        if (!intel_display_power_enabled(dev,
-                       POWER_DOMAIN_TRANSCODER(cpu_transcoder)))
+                       POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
                return false;
 
-       tmp = I915_READ(PIPECONF(cpu_transcoder));
+       tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
        if (!(tmp & PIPECONF_ENABLE))
                return false;
 
@@ -5935,7 +5966,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
         * DDI E. So just check whether this pipe is wired to DDI E and whether
         * the PCH transcoder is on.
         */
-       tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+       tmp = I915_READ(TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder));
        if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(PORT_E) &&
            I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
                pipe_config->has_pch_encoder = true;
@@ -5953,6 +5984,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        if (intel_display_power_enabled(dev, pfit_domain))
                ironlake_get_pfit_config(crtc, pipe_config);
 
+       pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
+                                  (I915_READ(IPS_CTL) & IPS_ENABLE);
+
        return true;
 }
 
@@ -6257,8 +6291,10 @@ void intel_crtc_load_lut(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 palreg = PALETTE(intel_crtc->pipe);
+       enum pipe pipe = intel_crtc->pipe;
+       int palreg = PALETTE(pipe);
        int i;
+       bool reenable_ips = false;
 
        /* The clocks have to be on to load the palette. */
        if (!crtc->enabled || !intel_crtc->active)
@@ -6266,7 +6302,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 
        /* use legacy palette for Ironlake */
        if (HAS_PCH_SPLIT(dev))
-               palreg = LGC_PALETTE(intel_crtc->pipe);
+               palreg = LGC_PALETTE(pipe);
+
+       /* Workaround : Do not read or write the pipe palette/gamma data while
+        * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+        */
+       if (intel_crtc->config.ips_enabled &&
+           ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
+            GAMMA_MODE_MODE_SPLIT)) {
+               hsw_disable_ips(intel_crtc);
+               reenable_ips = true;
+       }
 
        for (i = 0; i < 256; i++) {
                I915_WRITE(palreg + 4 * i,
@@ -6274,6 +6320,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
                           (intel_crtc->lut_g[i] << 8) |
                           intel_crtc->lut_b[i]);
        }
+
+       if (reenable_ips)
+               hsw_enable_ips(intel_crtc);
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
@@ -6520,7 +6569,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        intel_crtc->cursor_width = width;
        intel_crtc->cursor_height = height;
 
-       intel_crtc_update_cursor(crtc, true);
+       intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
 
        return 0;
 fail_unpin:
@@ -6539,7 +6588,7 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
        intel_crtc->cursor_x = x;
        intel_crtc->cursor_y = y;
 
-       intel_crtc_update_cursor(crtc, true);
+       intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
 
        return 0;
 }
@@ -6860,8 +6909,10 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
                        return 0;
                }
 
-               /* XXX: Handle the 100Mhz refclk */
-               intel_clock(dev, 96000, &clock);
+               if (IS_PINEVIEW(dev))
+                       pineview_clock(96000, &clock);
+               else
+                       i9xx_clock(96000, &clock);
        } else {
                bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
 
@@ -6873,9 +6924,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
                        if ((dpll & PLL_REF_INPUT_MASK) ==
                            PLLB_REF_INPUT_SPREADSPECTRUMIN) {
                                /* XXX: might not be 66MHz */
-                               intel_clock(dev, 66000, &clock);
+                               i9xx_clock(66000, &clock);
                        } else
-                               intel_clock(dev, 48000, &clock);
+                               i9xx_clock(48000, &clock);
                } else {
                        if (dpll & PLL_P1_DIVIDE_BY_TWO)
                                clock.p1 = 2;
@@ -6888,7 +6939,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
                        else
                                clock.p2 = 2;
 
-                       intel_clock(dev, 48000, &clock);
+                       i9xx_clock(48000, &clock);
                }
        }
 
@@ -7053,6 +7104,8 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
                kfree(work);
        }
 
+       intel_crtc_cursor_set(crtc, NULL, 0, 0, 0);
+
        drm_crtc_cleanup(crtc);
 
        kfree(intel_crtc);
@@ -7600,13 +7653,39 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
        }
 }
 
+static void
+connected_sink_compute_bpp(struct intel_connector * connector,
+                          struct intel_crtc_config *pipe_config)
+{
+       int bpp = pipe_config->pipe_bpp;
+
+       DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n",
+               connector->base.base.id,
+               drm_get_connector_name(&connector->base));
+
+       /* Don't use an invalid EDID bpc value */
+       if (connector->base.display_info.bpc &&
+           connector->base.display_info.bpc * 3 < bpp) {
+               DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
+                             bpp, connector->base.display_info.bpc*3);
+               pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
+       }
+
+       /* Clamp bpp to 8 on screens without EDID 1.4 */
+       if (connector->base.display_info.bpc == 0 && bpp > 24) {
+               DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
+                             bpp);
+               pipe_config->pipe_bpp = 24;
+       }
+}
+
 static int
-pipe_config_set_bpp(struct drm_crtc *crtc,
-                   struct drm_framebuffer *fb,
-                   struct intel_crtc_config *pipe_config)
+compute_baseline_pipe_bpp(struct intel_crtc *crtc,
+                         struct drm_framebuffer *fb,
+                         struct intel_crtc_config *pipe_config)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_connector *connector;
+       struct drm_device *dev = crtc->base.dev;
+       struct intel_connector *connector;
        int bpp;
 
        switch (fb->pixel_format) {
@@ -7649,29 +7728,47 @@ pipe_config_set_bpp(struct drm_crtc *crtc,
 
        /* Clamp display bpp to EDID value */
        list_for_each_entry(connector, &dev->mode_config.connector_list,
-                           head) {
-               if (connector->encoder && connector->encoder->crtc != crtc)
+                           base.head) {
+               if (!connector->new_encoder ||
+                   connector->new_encoder->new_crtc != crtc)
                        continue;
 
-               /* Don't use an invalid EDID bpc value */
-               if (connector->display_info.bpc &&
-                   connector->display_info.bpc * 3 < bpp) {
-                       DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
-                                     bpp, connector->display_info.bpc*3);
-                       pipe_config->pipe_bpp = connector->display_info.bpc*3;
-               }
-
-               /* Clamp bpp to 8 on screens without EDID 1.4 */
-               if (connector->display_info.bpc == 0 && bpp > 24) {
-                       DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
-                                     bpp);
-                       pipe_config->pipe_bpp = 24;
-               }
+               connected_sink_compute_bpp(connector, pipe_config);
        }
 
        return bpp;
 }
 
+static void intel_dump_pipe_config(struct intel_crtc *crtc,
+                                  struct intel_crtc_config *pipe_config,
+                                  const char *context)
+{
+       DRM_DEBUG_KMS("[CRTC:%d]%s config for pipe %c\n", crtc->base.base.id,
+                     context, pipe_name(crtc->pipe));
+
+       DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder));
+       DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
+                     pipe_config->pipe_bpp, pipe_config->dither);
+       DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
+                     pipe_config->has_pch_encoder,
+                     pipe_config->fdi_lanes,
+                     pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n,
+                     pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n,
+                     pipe_config->fdi_m_n.tu);
+       DRM_DEBUG_KMS("requested mode:\n");
+       drm_mode_debug_printmodeline(&pipe_config->requested_mode);
+       DRM_DEBUG_KMS("adjusted mode:\n");
+       drm_mode_debug_printmodeline(&pipe_config->adjusted_mode);
+       DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
+                     pipe_config->gmch_pfit.control,
+                     pipe_config->gmch_pfit.pgm_ratios,
+                     pipe_config->gmch_pfit.lvds_border_bits);
+       DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
+                     pipe_config->pch_pfit.pos,
+                     pipe_config->pch_pfit.size);
+       DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
+}
+
 static struct intel_crtc_config *
 intel_modeset_pipe_config(struct drm_crtc *crtc,
                          struct drm_framebuffer *fb,
@@ -7690,12 +7787,21 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
 
        drm_mode_copy(&pipe_config->adjusted_mode, mode);
        drm_mode_copy(&pipe_config->requested_mode, mode);
-
-       plane_bpp = pipe_config_set_bpp(crtc, fb, pipe_config);
+       pipe_config->cpu_transcoder = to_intel_crtc(crtc)->pipe;
+
+       /* Compute a starting value for pipe_config->pipe_bpp taking the source
+        * plane pixel format and any sink constraints into account. Returns the
+        * source plane bpp so that dithering can be selected on mismatches
+        * after encoders and crtc also have had their say. */
+       plane_bpp = compute_baseline_pipe_bpp(to_intel_crtc(crtc),
+                                             fb, pipe_config);
        if (plane_bpp < 0)
                goto fail;
 
 encoder_retry:
+       /* Ensure the port clock default is reset when retrying. */
+       pipe_config->port_clock = 0;
+
        /* Pass our mode to the connectors and the CRTC to give them a chance to
         * adjust it according to limitations or connector properties, and also
         * a chance to reject the mode entirely.
@@ -7724,6 +7830,11 @@ encoder_retry:
                }
        }
 
+       /* Set default port clock if not overwritten by the encoder. Needs to be
+        * done afterwards in case the encoder adjusts the mode. */
+       if (!pipe_config->port_clock)
+               pipe_config->port_clock = pipe_config->adjusted_mode.clock;
+
        ret = intel_crtc_compute_config(crtc, pipe_config);
        if (ret < 0) {
                DRM_DEBUG_KMS("CRTC fixup failed\n");
@@ -7741,8 +7852,6 @@ encoder_retry:
                goto encoder_retry;
        }
 
-       DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
-
        pipe_config->dither = pipe_config->pipe_bpp != plane_bpp;
        DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
                      plane_bpp, pipe_config->pipe_bpp, pipe_config->dither);
@@ -7940,6 +8049,8 @@ intel_pipe_config_compare(struct drm_device *dev,
                return false; \
        }
 
+       PIPE_CONF_CHECK_I(cpu_transcoder);
+
        PIPE_CONF_CHECK_I(has_pch_encoder);
        PIPE_CONF_CHECK_I(fdi_lanes);
        PIPE_CONF_CHECK_I(fdi_m_n.gmch_m);
@@ -7985,6 +8096,8 @@ intel_pipe_config_compare(struct drm_device *dev,
        PIPE_CONF_CHECK_I(pch_pfit.pos);
        PIPE_CONF_CHECK_I(pch_pfit.size);
 
+       PIPE_CONF_CHECK_I(ips_enabled);
+
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_FLAGS
 
@@ -8091,16 +8204,20 @@ intel_modeset_check_state(struct drm_device *dev)
                     "crtc's computed enabled state doesn't match tracked enabled state "
                     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
 
-               pipe_config.cpu_transcoder = crtc->config.cpu_transcoder;
                active = dev_priv->display.get_pipe_config(crtc,
                                                           &pipe_config);
                WARN(crtc->active != active,
                     "crtc active state doesn't match with hw state "
                     "(expected %i, found %i)\n", crtc->active, active);
 
-               WARN(active &&
-                    !intel_pipe_config_compare(dev, &crtc->config, &pipe_config),
-                    "pipe state doesn't match!\n");
+               if (active &&
+                   !intel_pipe_config_compare(dev, &crtc->config, &pipe_config)) {
+                       WARN(1, "pipe state doesn't match!\n");
+                       intel_dump_pipe_config(crtc, &pipe_config,
+                                              "[hw state]");
+                       intel_dump_pipe_config(crtc, &crtc->config,
+                                              "[sw state]");
+               }
        }
 }
 
@@ -8140,6 +8257,8 @@ static int __intel_set_mode(struct drm_crtc *crtc,
 
                        goto out;
                }
+               intel_dump_pipe_config(to_intel_crtc(crtc), pipe_config,
+                                      "[modeset]");
        }
 
        for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
@@ -8154,12 +8273,10 @@ static int __intel_set_mode(struct drm_crtc *crtc,
         * to set it here already despite that we pass it down the callchain.
         */
        if (modeset_pipes) {
-               enum transcoder tmp = to_intel_crtc(crtc)->config.cpu_transcoder;
                crtc->mode = *mode;
                /* mode_set/enable/disable functions rely on a correct pipe
                 * config. */
                to_intel_crtc(crtc)->config = *pipe_config;
-               to_intel_crtc(crtc)->config.cpu_transcoder = tmp;
        }
 
        /* Only after disabling all output pipelines that will be changed can we
@@ -8478,12 +8595,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
                goto fail;
 
        if (config->mode_changed) {
-               if (set->mode) {
-                       DRM_DEBUG_KMS("attempting to set mode from"
-                                       " userspace\n");
-                       drm_mode_debug_printmodeline(set->mode);
-               }
-
                ret = intel_set_mode(set->crtc, set->mode,
                                     set->x, set->y, set->fb);
                if (ret) {
@@ -8570,7 +8681,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
        /* Swap pipes & planes for FBC on pre-965 */
        intel_crtc->pipe = pipe;
        intel_crtc->plane = pipe;
-       intel_crtc->config.cpu_transcoder = pipe;
        if (IS_MOBILE(dev) && IS_GEN3(dev)) {
                DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
                intel_crtc->plane = !pipe;
@@ -8910,6 +9020,15 @@ static void intel_init_display(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       if (HAS_PCH_SPLIT(dev) || IS_G4X(dev))
+               dev_priv->display.find_dpll = g4x_find_best_dpll;
+       else if (IS_VALLEYVIEW(dev))
+               dev_priv->display.find_dpll = vlv_find_best_dpll;
+       else if (IS_PINEVIEW(dev))
+               dev_priv->display.find_dpll = pnv_find_best_dpll;
+       else
+               dev_priv->display.find_dpll = i9xx_find_best_dpll;
+
        if (HAS_DDI(dev)) {
                dev_priv->display.get_pipe_config = haswell_get_pipe_config;
                dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;
@@ -9436,50 +9555,14 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
-       u32 tmp;
        struct drm_plane *plane;
        struct intel_crtc *crtc;
        struct intel_encoder *encoder;
        struct intel_connector *connector;
 
-       if (HAS_DDI(dev)) {
-               tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
-
-               if (tmp & TRANS_DDI_FUNC_ENABLE) {
-                       switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
-                       case TRANS_DDI_EDP_INPUT_A_ON:
-                       case TRANS_DDI_EDP_INPUT_A_ONOFF:
-                               pipe = PIPE_A;
-                               break;
-                       case TRANS_DDI_EDP_INPUT_B_ONOFF:
-                               pipe = PIPE_B;
-                               break;
-                       case TRANS_DDI_EDP_INPUT_C_ONOFF:
-                               pipe = PIPE_C;
-                               break;
-                       default:
-                               /* A bogus value has been programmed, disable
-                                * the transcoder */
-                               WARN(1, "Bogus eDP source %08x\n", tmp);
-                               intel_ddi_disable_transcoder_func(dev_priv,
-                                               TRANSCODER_EDP);
-                               goto setup_pipes;
-                       }
-
-                       crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
-                       crtc->config.cpu_transcoder = TRANSCODER_EDP;
-
-                       DRM_DEBUG_KMS("Pipe %c using transcoder EDP\n",
-                                     pipe_name(pipe));
-               }
-       }
-
-setup_pipes:
        list_for_each_entry(crtc, &dev->mode_config.crtc_list,
                            base.head) {
-               enum transcoder tmp = crtc->config.cpu_transcoder;
                memset(&crtc->config, 0, sizeof(crtc->config));
-               crtc->config.cpu_transcoder = tmp;
 
                crtc->active = dev_priv->display.get_pipe_config(crtc,
                                                                 &crtc->config);
@@ -9540,6 +9623,7 @@ setup_pipes:
        for_each_pipe(pipe) {
                crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
                intel_sanitize_crtc(crtc);
+               intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]");
        }
 
        if (force_restore) {