]> git.ipfire.org Git - thirdparty/kernel/stable.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: Bump gen7+ fb size limits to 16kx16k
[thirdparty/kernel/stable.git] / drivers / gpu / drm / i915 / intel_display.c
index 421aac80a83815b9c1cfa40a7142e171cfd8bcd5..d3b2f51e2dc2997c83c0f6a252a284b851bafbb7 100644 (file)
 #include "i915_drv.h"
 #include "i915_gem_clflush.h"
 #include "i915_trace.h"
+#include "intel_acpi.h"
+#include "intel_atomic.h"
+#include "intel_atomic_plane.h"
+#include "intel_color.h"
+#include "intel_cdclk.h"
+#include "intel_crt.h"
+#include "intel_ddi.h"
+#include "intel_dp.h"
 #include "intel_drv.h"
 #include "intel_dsi.h"
+#include "intel_dvo.h"
+#include "intel_fbc.h"
+#include "intel_fbdev.h"
+#include "intel_fifo_underrun.h"
 #include "intel_frontbuffer.h"
-
-#include "intel_drv.h"
-#include "intel_dsi.h"
-#include "intel_frontbuffer.h"
-
-#include "i915_drv.h"
-#include "i915_gem_clflush.h"
-#include "i915_reset.h"
-#include "i915_trace.h"
+#include "intel_gmbus.h"
+#include "intel_hdcp.h"
+#include "intel_hdmi.h"
+#include "intel_hotplug.h"
+#include "intel_lvds.h"
+#include "intel_overlay.h"
+#include "intel_pipe_crc.h"
+#include "intel_pm.h"
+#include "intel_psr.h"
+#include "intel_quirks.h"
+#include "intel_sdvo.h"
+#include "intel_sideband.h"
+#include "intel_sprite.h"
+#include "intel_tv.h"
+#include "intel_vdsc.h"
 
 /* Primary plane formats for gen <= 3 */
 static const u32 i8xx_primary_formats[] = {
@@ -110,13 +128,13 @@ static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_sta
 static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state);
 static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state);
 static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state);
-static void haswell_set_pipemisc(const struct intel_crtc_state *crtc_state);
+static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state);
 static void vlv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
 static void chv_prepare_pll(struct intel_crtc *crtc,
                            const struct intel_crtc_state *pipe_config);
-static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
-static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
+static void intel_begin_crtc_commit(struct intel_atomic_state *, struct intel_crtc *);
+static void intel_finish_crtc_commit(struct intel_atomic_state *, struct intel_crtc *);
 static void intel_crtc_init_scalers(struct intel_crtc *crtc,
                                    struct intel_crtc_state *crtc_state);
 static void skylake_pfit_enable(const struct intel_crtc_state *crtc_state);
@@ -143,10 +161,8 @@ int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
        int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
 
        /* Obtain SKU information */
-       mutex_lock(&dev_priv->sb_lock);
        hpll_freq = vlv_cck_read(dev_priv, CCK_FUSE_REG) &
                CCK_FUSE_HPLL_FREQ_MASK;
-       mutex_unlock(&dev_priv->sb_lock);
 
        return vco_freq[hpll_freq] * 1000;
 }
@@ -157,10 +173,7 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
        u32 val;
        int divider;
 
-       mutex_lock(&dev_priv->sb_lock);
        val = vlv_cck_read(dev_priv, reg);
-       mutex_unlock(&dev_priv->sb_lock);
-
        divider = val & CCK_FREQUENCY_VALUES;
 
        WARN((val & CCK_FREQUENCY_STATUS) !=
@@ -173,11 +186,18 @@ int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
 int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
                           const char *name, u32 reg)
 {
+       int hpll;
+
+       vlv_cck_get(dev_priv);
+
        if (dev_priv->hpll_freq == 0)
                dev_priv->hpll_freq = vlv_get_hpll_vco(dev_priv);
 
-       return vlv_get_cck_clock(dev_priv, name, reg,
-                                dev_priv->hpll_freq);
+       hpll = vlv_get_cck_clock(dev_priv, name, reg, dev_priv->hpll_freq);
+
+       vlv_cck_put(dev_priv);
+
+       return hpll;
 }
 
 static void intel_update_czclk(struct drm_i915_private *dev_priv)
@@ -466,11 +486,13 @@ static const struct intel_limit intel_limits_bxt = {
        .p2 = { .p2_slow = 1, .p2_fast = 20 },
 };
 
+/* WA Display #0827: Gen9:all */
 static void
-skl_wa_clkgate(struct drm_i915_private *dev_priv, int pipe, bool enable)
+skl_wa_827(struct drm_i915_private *dev_priv, int pipe, bool enable)
 {
        if (enable)
                I915_WRITE(CLKGATE_DIS_PSL(pipe),
+                          I915_READ(CLKGATE_DIS_PSL(pipe)) |
                           DUPS1_GATING_DIS | DUPS2_GATING_DIS);
        else
                I915_WRITE(CLKGATE_DIS_PSL(pipe),
@@ -478,6 +500,19 @@ skl_wa_clkgate(struct drm_i915_private *dev_priv, int pipe, bool enable)
                           ~(DUPS1_GATING_DIS | DUPS2_GATING_DIS));
 }
 
+/* Wa_2006604312:icl */
+static void
+icl_wa_scalerclkgating(struct drm_i915_private *dev_priv, enum pipe pipe,
+                      bool enable)
+{
+       if (enable)
+               I915_WRITE(CLKGATE_DIS_PSL(pipe),
+                          I915_READ(CLKGATE_DIS_PSL(pipe)) | DPFR_GATING_DIS);
+       else
+               I915_WRITE(CLKGATE_DIS_PSL(pipe),
+                          I915_READ(CLKGATE_DIS_PSL(pipe)) & ~DPFR_GATING_DIS);
+}
+
 static bool
 needs_modeset(const struct drm_crtc_state *state)
 {
@@ -540,7 +575,7 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock)
        clock->p = clock->p1 * clock->p2;
        if (WARN_ON(clock->n == 0 || clock->p == 0))
                return 0;
-       clock->vco = DIV_ROUND_CLOSEST_ULL((u64)refclk * clock->m,
+       clock->vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m),
                                           clock->n << 22);
        clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p);
 
@@ -595,7 +630,7 @@ i9xx_select_p2_div(const struct intel_limit *limit,
                   const struct intel_crtc_state *crtc_state,
                   int target)
 {
-       struct drm_device *dev = crtc_state->base.crtc->dev;
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
 
        if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
                /*
@@ -603,7 +638,7 @@ i9xx_select_p2_div(const struct intel_limit *limit,
                 * 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))
+               if (intel_is_dual_link_lvds(dev_priv))
                        return limit->p2.p2_fast;
                else
                        return limit->p2.p2_slow;
@@ -925,8 +960,8 @@ chv_find_best_dpll(const struct intel_limit *limit,
 
                        clock.p = clock.p1 * clock.p2;
 
-                       m2 = DIV_ROUND_CLOSEST_ULL(((u64)target * clock.p *
-                                       clock.n) << 22, refclk * clock.m1);
+                       m2 = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(target, clock.p * clock.n) << 22,
+                                                  refclk * clock.m1);
 
                        if (m2 > INT_MAX/clock.m1)
                                continue;
@@ -951,14 +986,15 @@ chv_find_best_dpll(const struct intel_limit *limit,
        return found;
 }
 
-bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
+bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state,
                        struct dpll *best_clock)
 {
        int refclk = 100000;
        const struct intel_limit *limit = &intel_limits_bxt;
 
        return chv_find_best_dpll(limit, crtc_state,
-                                 target_clock, refclk, NULL, best_clock);
+                                 crtc_state->port_clock, refclk,
+                                 NULL, best_clock);
 }
 
 bool intel_crtc_active(struct intel_crtc *crtc)
@@ -1039,7 +1075,7 @@ intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state)
                i915_reg_t reg = PIPECONF(cpu_transcoder);
 
                /* Wait for the Pipe State to go off */
-               if (intel_wait_for_register(dev_priv,
+               if (intel_wait_for_register(&dev_priv->uncore,
                                            reg, I965_PIPECONF_ACTIVE, 0,
                                            100))
                        WARN(1, "pipe_off wait timed out\n");
@@ -1068,9 +1104,9 @@ void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
        u32 val;
        bool cur_state;
 
-       mutex_lock(&dev_priv->sb_lock);
+       vlv_cck_get(dev_priv);
        val = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
-       mutex_unlock(&dev_priv->sb_lock);
+       vlv_cck_put(dev_priv);
 
        cur_state = val & DSI_PLL_VCO_EN;
        I915_STATE_WARN(cur_state != state,
@@ -1345,7 +1381,7 @@ static void _vlv_enable_pll(struct intel_crtc *crtc,
        POSTING_READ(DPLL(pipe));
        udelay(150);
 
-       if (intel_wait_for_register(dev_priv,
+       if (intel_wait_for_register(&dev_priv->uncore,
                                    DPLL(pipe),
                                    DPLL_LOCK_VLV,
                                    DPLL_LOCK_VLV,
@@ -1380,14 +1416,14 @@ static void _chv_enable_pll(struct intel_crtc *crtc,
        enum dpio_channel port = vlv_pipe_to_channel(pipe);
        u32 tmp;
 
-       mutex_lock(&dev_priv->sb_lock);
+       vlv_dpio_get(dev_priv);
 
        /* Enable back the 10bit clock to display controller */
        tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
        tmp |= DPIO_DCLKP_EN;
        vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), tmp);
 
-       mutex_unlock(&dev_priv->sb_lock);
+       vlv_dpio_put(dev_priv);
 
        /*
         * Need to wait > 100ns between dclkp clock enable bit and PLL enable.
@@ -1398,7 +1434,7 @@ static void _chv_enable_pll(struct intel_crtc *crtc,
        I915_WRITE(DPLL(pipe), pipe_config->dpll_hw_state.dpll);
 
        /* Check PLL is locked */
-       if (intel_wait_for_register(dev_priv,
+       if (intel_wait_for_register(&dev_priv->uncore,
                                    DPLL(pipe), DPLL_LOCK_VLV, DPLL_LOCK_VLV,
                                    1))
                DRM_ERROR("PLL %d failed to lock\n", pipe);
@@ -1441,17 +1477,12 @@ static void chv_enable_pll(struct intel_crtc *crtc,
        }
 }
 
-static int intel_num_dvo_pipes(struct drm_i915_private *dev_priv)
+static bool i9xx_has_pps(struct drm_i915_private *dev_priv)
 {
-       struct intel_crtc *crtc;
-       int count = 0;
-
-       for_each_intel_crtc(&dev_priv->drm, crtc) {
-               count += crtc->base.state->active &&
-                       intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO);
-       }
+       if (IS_I830(dev_priv))
+               return false;
 
-       return count;
+       return IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
 }
 
 static void i9xx_enable_pll(struct intel_crtc *crtc,
@@ -1465,29 +1496,15 @@ static void i9xx_enable_pll(struct intel_crtc *crtc,
        assert_pipe_disabled(dev_priv, crtc->pipe);
 
        /* PLL is protected by panel, make sure we can write it */
-       if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
+       if (i9xx_has_pps(dev_priv))
                assert_panel_unlocked(dev_priv, crtc->pipe);
 
-       /* Enable DVO 2x clock on both PLLs if necessary */
-       if (IS_I830(dev_priv) && intel_num_dvo_pipes(dev_priv) > 0) {
-               /*
-                * It appears to be important that we don't enable this
-                * for the current pipe before otherwise configuring the
-                * PLL. No idea how this should be handled if multiple
-                * DVO outputs are enabled simultaneosly.
-                */
-               dpll |= DPLL_DVO_2X_MODE;
-               I915_WRITE(DPLL(!crtc->pipe),
-                          I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
-       }
-
        /*
         * Apparently we need to have VGA mode enabled prior to changing
         * the P1/P2 dividers. Otherwise the DPLL will keep using the old
         * dividers, even though the register value does change.
         */
-       I915_WRITE(reg, 0);
-
+       I915_WRITE(reg, dpll & ~DPLL_VGA_MODE_DIS);
        I915_WRITE(reg, dpll);
 
        /* Wait for the clocks to stabilize. */
@@ -1520,16 +1537,6 @@ static void i9xx_disable_pll(const struct intel_crtc_state *crtc_state)
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
 
-       /* Disable DVO 2x clock on both PLLs if necessary */
-       if (IS_I830(dev_priv) &&
-           intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO) &&
-           !intel_num_dvo_pipes(dev_priv)) {
-               I915_WRITE(DPLL(PIPE_B),
-                          I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
-               I915_WRITE(DPLL(PIPE_A),
-                          I915_READ(DPLL(PIPE_A)) & ~DPLL_DVO_2X_MODE);
-       }
-
        /* Don't disable pipe or pipe PLLs if needed */
        if (IS_I830(dev_priv))
                return;
@@ -1573,14 +1580,14 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
        I915_WRITE(DPLL(pipe), val);
        POSTING_READ(DPLL(pipe));
 
-       mutex_lock(&dev_priv->sb_lock);
+       vlv_dpio_get(dev_priv);
 
        /* Disable 10bit clock to display controller */
        val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port));
        val &= ~DPIO_DCLKP_EN;
        vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
 
-       mutex_unlock(&dev_priv->sb_lock);
+       vlv_dpio_put(dev_priv);
 }
 
 void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
@@ -1608,7 +1615,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
                BUG();
        }
 
-       if (intel_wait_for_register(dev_priv,
+       if (intel_wait_for_register(&dev_priv->uncore,
                                    dpll_reg, port_mask, expected_mask,
                                    1000))
                WARN(1, "timed out waiting for port %c ready: got 0x%x, expected 0x%x\n",
@@ -1658,17 +1665,18 @@ static void ironlake_enable_pch_transcoder(const struct intel_crtc_state *crtc_s
        }
 
        val &= ~TRANS_INTERLACE_MASK;
-       if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
+       if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
                if (HAS_PCH_IBX(dev_priv) &&
                    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
                        val |= TRANS_LEGACY_INTERLACED_ILK;
                else
                        val |= TRANS_INTERLACED;
-       else
+       } else {
                val |= TRANS_PROGRESSIVE;
+       }
 
        I915_WRITE(reg, val | TRANS_ENABLE);
-       if (intel_wait_for_register(dev_priv,
+       if (intel_wait_for_register(&dev_priv->uncore,
                                    reg, TRANS_STATE_ENABLE, TRANS_STATE_ENABLE,
                                    100))
                DRM_ERROR("failed to enable transcoder %c\n", pipe_name(pipe));
@@ -1698,7 +1706,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
                val |= TRANS_PROGRESSIVE;
 
        I915_WRITE(LPT_TRANSCONF, val);
-       if (intel_wait_for_register(dev_priv,
+       if (intel_wait_for_register(&dev_priv->uncore,
                                    LPT_TRANSCONF,
                                    TRANS_STATE_ENABLE,
                                    TRANS_STATE_ENABLE,
@@ -1724,7 +1732,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
        val &= ~TRANS_ENABLE;
        I915_WRITE(reg, val);
        /* wait for PCH transcoder off, transcoder state */
-       if (intel_wait_for_register(dev_priv,
+       if (intel_wait_for_register(&dev_priv->uncore,
                                    reg, TRANS_STATE_ENABLE, 0,
                                    50))
                DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
@@ -1746,7 +1754,7 @@ void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
        val &= ~TRANS_ENABLE;
        I915_WRITE(LPT_TRANSCONF, val);
        /* wait for PCH transcoder off, transcoder state */
-       if (intel_wait_for_register(dev_priv,
+       if (intel_wait_for_register(&dev_priv->uncore,
                                    LPT_TRANSCONF, TRANS_STATE_ENABLE, 0,
                                    50))
                DRM_ERROR("Failed to disable PCH transcoder\n");
@@ -1830,6 +1838,8 @@ static void intel_enable_pipe(const struct intel_crtc_state *new_crtc_state)
                /* FIXME: assert CPU port conditions for SNB+ */
        }
 
+       trace_intel_pipe_enable(dev_priv, pipe);
+
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
        if (val & PIPECONF_ENABLE) {
@@ -1869,6 +1879,8 @@ static void intel_disable_pipe(const struct intel_crtc_state *old_crtc_state)
         */
        assert_planes_disabled(crtc);
 
+       trace_intel_pipe_disable(dev_priv, pipe);
+
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
        if ((val & PIPECONF_ENABLE) == 0)
@@ -1903,7 +1915,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
 
        switch (fb->modifier) {
        case DRM_FORMAT_MOD_LINEAR:
-               return cpp;
+               return intel_tile_size(dev_priv);
        case I915_FORMAT_MOD_X_TILED:
                if (IS_GEN(dev_priv, 2))
                        return 128;
@@ -1946,11 +1958,8 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
 static unsigned int
 intel_tile_height(const struct drm_framebuffer *fb, int color_plane)
 {
-       if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
-               return 1;
-       else
-               return intel_tile_size(to_i915(fb->dev)) /
-                       intel_tile_width_bytes(fb, color_plane);
+       return intel_tile_size(to_i915(fb->dev)) /
+               intel_tile_width_bytes(fb, color_plane);
 }
 
 /* Return the tile dimensions in pixel units */
@@ -1985,6 +1994,17 @@ unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info
        return size;
 }
 
+unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info)
+{
+       unsigned int size = 0;
+       int i;
+
+       for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++)
+               size += rem_info->plane[i].width * rem_info->plane[i].height;
+
+       return size;
+}
+
 static void
 intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
                        const struct drm_framebuffer *fb,
@@ -2054,7 +2074,9 @@ static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)
        struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 
-       return INTEL_GEN(dev_priv) < 4 || plane->has_fbc;
+       return INTEL_GEN(dev_priv) < 4 ||
+               (plane->has_fbc &&
+                plane_state->view.type == I915_GGTT_VIEW_NORMAL);
 }
 
 struct i915_vma *
@@ -2195,16 +2217,8 @@ void intel_add_fb_offsets(int *x, int *y,
                          int color_plane)
 
 {
-       const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb);
-       unsigned int rotation = state->base.rotation;
-
-       if (drm_rotation_90_or_270(rotation)) {
-               *x += intel_fb->rotated[color_plane].x;
-               *y += intel_fb->rotated[color_plane].y;
-       } else {
-               *x += intel_fb->normal[color_plane].x;
-               *y += intel_fb->normal[color_plane].y;
-       }
+       *x += state->color_plane[color_plane].x;
+       *y += state->color_plane[color_plane].y;
 }
 
 static u32 intel_adjust_tile_offset(int *x, int *y,
@@ -2484,6 +2498,134 @@ bool is_ccs_modifier(u64 modifier)
               modifier == I915_FORMAT_MOD_Yf_TILED_CCS;
 }
 
+u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
+                             u32 pixel_format, u64 modifier)
+{
+       struct intel_crtc *crtc;
+       struct intel_plane *plane;
+
+       /*
+        * We assume the primary plane for pipe A has
+        * the highest stride limits of them all.
+        */
+       crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
+       plane = to_intel_plane(crtc->base.primary);
+
+       return plane->max_stride(plane, pixel_format, modifier,
+                                DRM_MODE_ROTATE_0);
+}
+
+static
+u32 intel_fb_max_stride(struct drm_i915_private *dev_priv,
+                       u32 pixel_format, u64 modifier)
+{
+       /*
+        * Arbitrary limit for gen4+ chosen to match the
+        * render engine max stride.
+        *
+        * The new CCS hash mode makes remapping impossible
+        */
+       if (!is_ccs_modifier(modifier)) {
+               if (INTEL_GEN(dev_priv) >= 7)
+                       return 256*1024;
+               else if (INTEL_GEN(dev_priv) >= 4)
+                       return 128*1024;
+       }
+
+       return intel_plane_fb_max_stride(dev_priv, pixel_format, modifier);
+}
+
+static u32
+intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
+{
+       struct drm_i915_private *dev_priv = to_i915(fb->dev);
+
+       if (fb->modifier == DRM_FORMAT_MOD_LINEAR) {
+               u32 max_stride = intel_plane_fb_max_stride(dev_priv,
+                                                          fb->format->format,
+                                                          fb->modifier);
+
+               /*
+                * To make remapping with linear generally feasible
+                * we need the stride to be page aligned.
+                */
+               if (fb->pitches[color_plane] > max_stride)
+                       return intel_tile_size(dev_priv);
+               else
+                       return 64;
+       } else {
+               return intel_tile_width_bytes(fb, color_plane);
+       }
+}
+
+bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       int i;
+
+       /* We don't want to deal with remapping with cursors */
+       if (plane->id == PLANE_CURSOR)
+               return false;
+
+       /*
+        * The display engine limits already match/exceed the
+        * render engine limits, so not much point in remapping.
+        * Would also need to deal with the fence POT alignment
+        * and gen2 2KiB GTT tile size.
+        */
+       if (INTEL_GEN(dev_priv) < 4)
+               return false;
+
+       /*
+        * The new CCS hash mode isn't compatible with remapping as
+        * the virtual address of the pages affects the compressed data.
+        */
+       if (is_ccs_modifier(fb->modifier))
+               return false;
+
+       /* Linear needs a page aligned stride for remapping */
+       if (fb->modifier == DRM_FORMAT_MOD_LINEAR) {
+               unsigned int alignment = intel_tile_size(dev_priv) - 1;
+
+               for (i = 0; i < fb->format->num_planes; i++) {
+                       if (fb->pitches[i] & alignment)
+                               return false;
+               }
+       }
+
+       return true;
+}
+
+static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)
+{
+       struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       unsigned int rotation = plane_state->base.rotation;
+       u32 stride, max_stride;
+
+       /*
+        * No remapping for invisible planes since we don't have
+        * an actual source viewport to remap.
+        */
+       if (!plane_state->base.visible)
+               return false;
+
+       if (!intel_plane_can_remap(plane_state))
+               return false;
+
+       /*
+        * FIXME: aux plane limits on gen9+ are
+        * unclear in Bspec, for now no checking.
+        */
+       stride = intel_fb_pitch(fb, 0, rotation);
+       max_stride = plane->max_stride(plane, fb->format->format,
+                                      fb->modifier, rotation);
+
+       return stride > max_stride;
+}
+
 static int
 intel_fill_fb_info(struct drm_i915_private *dev_priv,
                   struct drm_framebuffer *fb)
@@ -2649,6 +2791,168 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
        return 0;
 }
 
+static void
+intel_plane_remap_gtt(struct intel_plane_state *plane_state)
+{
+       struct drm_i915_private *dev_priv =
+               to_i915(plane_state->base.plane->dev);
+       struct drm_framebuffer *fb = plane_state->base.fb;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct intel_rotation_info *info = &plane_state->view.rotated;
+       unsigned int rotation = plane_state->base.rotation;
+       int i, num_planes = fb->format->num_planes;
+       unsigned int tile_size = intel_tile_size(dev_priv);
+       unsigned int src_x, src_y;
+       unsigned int src_w, src_h;
+       u32 gtt_offset = 0;
+
+       memset(&plane_state->view, 0, sizeof(plane_state->view));
+       plane_state->view.type = drm_rotation_90_or_270(rotation) ?
+               I915_GGTT_VIEW_ROTATED : I915_GGTT_VIEW_REMAPPED;
+
+       src_x = plane_state->base.src.x1 >> 16;
+       src_y = plane_state->base.src.y1 >> 16;
+       src_w = drm_rect_width(&plane_state->base.src) >> 16;
+       src_h = drm_rect_height(&plane_state->base.src) >> 16;
+
+       WARN_ON(is_ccs_modifier(fb->modifier));
+
+       /* Make src coordinates relative to the viewport */
+       drm_rect_translate(&plane_state->base.src,
+                          -(src_x << 16), -(src_y << 16));
+
+       /* Rotate src coordinates to match rotated GTT view */
+       if (drm_rotation_90_or_270(rotation))
+               drm_rect_rotate(&plane_state->base.src,
+                               src_w << 16, src_h << 16,
+                               DRM_MODE_ROTATE_270);
+
+       for (i = 0; i < num_planes; i++) {
+               unsigned int hsub = i ? fb->format->hsub : 1;
+               unsigned int vsub = i ? fb->format->vsub : 1;
+               unsigned int cpp = fb->format->cpp[i];
+               unsigned int tile_width, tile_height;
+               unsigned int width, height;
+               unsigned int pitch_tiles;
+               unsigned int x, y;
+               u32 offset;
+
+               intel_tile_dims(fb, i, &tile_width, &tile_height);
+
+               x = src_x / hsub;
+               y = src_y / vsub;
+               width = src_w / hsub;
+               height = src_h / vsub;
+
+               /*
+                * First pixel of the src viewport from the
+                * start of the normal gtt mapping.
+                */
+               x += intel_fb->normal[i].x;
+               y += intel_fb->normal[i].y;
+
+               offset = intel_compute_aligned_offset(dev_priv, &x, &y,
+                                                     fb, i, fb->pitches[i],
+                                                     DRM_MODE_ROTATE_0, tile_size);
+               offset /= tile_size;
+
+               info->plane[i].offset = offset;
+               info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i],
+                                                    tile_width * cpp);
+               info->plane[i].width = DIV_ROUND_UP(x + width, tile_width);
+               info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
+
+               if (drm_rotation_90_or_270(rotation)) {
+                       struct drm_rect r;
+
+                       /* rotate the x/y offsets to match the GTT view */
+                       r.x1 = x;
+                       r.y1 = y;
+                       r.x2 = x + width;
+                       r.y2 = y + height;
+                       drm_rect_rotate(&r,
+                                       info->plane[i].width * tile_width,
+                                       info->plane[i].height * tile_height,
+                                       DRM_MODE_ROTATE_270);
+                       x = r.x1;
+                       y = r.y1;
+
+                       pitch_tiles = info->plane[i].height;
+                       plane_state->color_plane[i].stride = pitch_tiles * tile_height;
+
+                       /* rotate the tile dimensions to match the GTT view */
+                       swap(tile_width, tile_height);
+               } else {
+                       pitch_tiles = info->plane[i].width;
+                       plane_state->color_plane[i].stride = pitch_tiles * tile_width * cpp;
+               }
+
+               /*
+                * We only keep the x/y offsets, so push all of the
+                * gtt offset into the x/y offsets.
+                */
+               intel_adjust_tile_offset(&x, &y,
+                                        tile_width, tile_height,
+                                        tile_size, pitch_tiles,
+                                        gtt_offset * tile_size, 0);
+
+               gtt_offset += info->plane[i].width * info->plane[i].height;
+
+               plane_state->color_plane[i].offset = 0;
+               plane_state->color_plane[i].x = x;
+               plane_state->color_plane[i].y = y;
+       }
+}
+
+static int
+intel_plane_compute_gtt(struct intel_plane_state *plane_state)
+{
+       const struct intel_framebuffer *fb =
+               to_intel_framebuffer(plane_state->base.fb);
+       unsigned int rotation = plane_state->base.rotation;
+       int i, num_planes;
+
+       if (!fb)
+               return 0;
+
+       num_planes = fb->base.format->num_planes;
+
+       if (intel_plane_needs_remap(plane_state)) {
+               intel_plane_remap_gtt(plane_state);
+
+               /*
+                * Sometimes even remapping can't overcome
+                * the stride limitations :( Can happen with
+                * big plane sizes and suitably misaligned
+                * offsets.
+                */
+               return intel_plane_check_stride(plane_state);
+       }
+
+       intel_fill_fb_ggtt_view(&plane_state->view, &fb->base, rotation);
+
+       for (i = 0; i < num_planes; i++) {
+               plane_state->color_plane[i].stride = intel_fb_pitch(&fb->base, i, rotation);
+               plane_state->color_plane[i].offset = 0;
+
+               if (drm_rotation_90_or_270(rotation)) {
+                       plane_state->color_plane[i].x = fb->rotated[i].x;
+                       plane_state->color_plane[i].y = fb->rotated[i].y;
+               } else {
+                       plane_state->color_plane[i].x = fb->normal[i].x;
+                       plane_state->color_plane[i].y = fb->normal[i].y;
+               }
+       }
+
+       /* Rotate src coordinates to match rotated GTT view */
+       if (drm_rotation_90_or_270(rotation))
+               drm_rect_rotate(&plane_state->base.src,
+                               fb->base.width << 16, fb->base.height << 16,
+                               DRM_MODE_ROTATE_270);
+
+       return intel_plane_check_stride(plane_state);
+}
+
 static int i9xx_format_to_fourcc(int format)
 {
        switch (format) {
@@ -2677,6 +2981,24 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
                return DRM_FORMAT_RGB565;
        case PLANE_CTL_FORMAT_NV12:
                return DRM_FORMAT_NV12;
+       case PLANE_CTL_FORMAT_P010:
+               return DRM_FORMAT_P010;
+       case PLANE_CTL_FORMAT_P012:
+               return DRM_FORMAT_P012;
+       case PLANE_CTL_FORMAT_P016:
+               return DRM_FORMAT_P016;
+       case PLANE_CTL_FORMAT_Y210:
+               return DRM_FORMAT_Y210;
+       case PLANE_CTL_FORMAT_Y212:
+               return DRM_FORMAT_Y212;
+       case PLANE_CTL_FORMAT_Y216:
+               return DRM_FORMAT_Y216;
+       case PLANE_CTL_FORMAT_Y410:
+               return DRM_FORMAT_XVYU2101010;
+       case PLANE_CTL_FORMAT_Y412:
+               return DRM_FORMAT_XVYU12_16161616;
+       case PLANE_CTL_FORMAT_Y416:
+               return DRM_FORMAT_XVYU16161616;
        default:
        case PLANE_CTL_FORMAT_XRGB_8888:
                if (rgb_order) {
@@ -2695,6 +3017,18 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
                        return DRM_FORMAT_XBGR2101010;
                else
                        return DRM_FORMAT_XRGB2101010;
+       case PLANE_CTL_FORMAT_XRGB_16161616F:
+               if (rgb_order) {
+                       if (alpha)
+                               return DRM_FORMAT_ABGR16161616F;
+                       else
+                               return DRM_FORMAT_XBGR16161616F;
+               } else {
+                       if (alpha)
+                               return DRM_FORMAT_ARGB16161616F;
+                       else
+                               return DRM_FORMAT_XRGB16161616F;
+               }
        }
 }
 
@@ -2825,8 +3159,7 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
        if (plane->id == PLANE_PRIMARY)
                intel_pre_disable_primary_noatomic(&crtc->base);
 
-       trace_intel_disable_plane(&plane->base, crtc);
-       plane->disable_plane(plane, crtc_state);
+       intel_disable_plane(plane, crtc_state);
 }
 
 static void
@@ -2947,41 +3280,55 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb,
        switch (fb->modifier) {
        case DRM_FORMAT_MOD_LINEAR:
        case I915_FORMAT_MOD_X_TILED:
-               switch (cpp) {
-               case 8:
-                       return 4096;
-               case 4:
-               case 2:
-               case 1:
-                       return 8192;
-               default:
-                       MISSING_CASE(cpp);
-                       break;
-               }
-               break;
+               return 4096;
        case I915_FORMAT_MOD_Y_TILED_CCS:
        case I915_FORMAT_MOD_Yf_TILED_CCS:
                /* FIXME AUX plane? */
        case I915_FORMAT_MOD_Y_TILED:
        case I915_FORMAT_MOD_Yf_TILED:
-               switch (cpp) {
-               case 8:
+               if (cpp == 8)
                        return 2048;
-               case 4:
+               else
                        return 4096;
-               case 2:
-               case 1:
-                       return 8192;
-               default:
-                       MISSING_CASE(cpp);
-                       break;
-               }
-               break;
        default:
                MISSING_CASE(fb->modifier);
+               return 2048;
        }
+}
 
-       return 2048;
+static int glk_max_plane_width(const struct drm_framebuffer *fb,
+                              int color_plane,
+                              unsigned int rotation)
+{
+       int cpp = fb->format->cpp[color_plane];
+
+       switch (fb->modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               if (cpp == 8)
+                       return 4096;
+               else
+                       return 5120;
+       case I915_FORMAT_MOD_Y_TILED_CCS:
+       case I915_FORMAT_MOD_Yf_TILED_CCS:
+               /* FIXME AUX plane? */
+       case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_Yf_TILED:
+               if (cpp == 8)
+                       return 2048;
+               else
+                       return 5120;
+       default:
+               MISSING_CASE(fb->modifier);
+               return 2048;
+       }
+}
+
+static int icl_max_plane_width(const struct drm_framebuffer *fb,
+                              int color_plane,
+                              unsigned int rotation)
+{
+       return 5120;
 }
 
 static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
@@ -3024,16 +3371,24 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state
 
 static int skl_check_main_surface(struct intel_plane_state *plane_state)
 {
+       struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev);
        const struct drm_framebuffer *fb = plane_state->base.fb;
        unsigned int rotation = plane_state->base.rotation;
        int x = plane_state->base.src.x1 >> 16;
        int y = plane_state->base.src.y1 >> 16;
        int w = drm_rect_width(&plane_state->base.src) >> 16;
        int h = drm_rect_height(&plane_state->base.src) >> 16;
-       int max_width = skl_max_plane_width(fb, 0, rotation);
+       int max_width;
        int max_height = 4096;
        u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset;
 
+       if (INTEL_GEN(dev_priv) >= 11)
+               max_width = icl_max_plane_width(fb, 0, rotation);
+       else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               max_width = glk_max_plane_width(fb, 0, rotation);
+       else
+               max_width = skl_max_plane_width(fb, 0, rotation);
+
        if (w > max_width || h > max_height) {
                DRM_DEBUG_KMS("requested Y/RGB source size %dx%d too big (limit %dx%d)\n",
                              w, h, max_width, max_height);
@@ -3096,6 +3451,14 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
        plane_state->color_plane[0].x = x;
        plane_state->color_plane[0].y = y;
 
+       /*
+        * Put the final coordinates back so that the src
+        * coordinate checks will see the right values.
+        */
+       drm_rect_translate(&plane_state->base.src,
+                          (x << 16) - plane_state->base.src.x1,
+                          (y << 16) - plane_state->base.src.y1);
+
        return 0;
 }
 
@@ -3152,31 +3515,20 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
 int skl_check_plane_surface(struct intel_plane_state *plane_state)
 {
        const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
        int ret;
 
-       intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
-       plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
-       plane_state->color_plane[1].stride = intel_fb_pitch(fb, 1, rotation);
-
-       ret = intel_plane_check_stride(plane_state);
+       ret = intel_plane_compute_gtt(plane_state);
        if (ret)
                return ret;
 
        if (!plane_state->base.visible)
                return 0;
 
-       /* Rotate src coordinates to match rotated GTT view */
-       if (drm_rotation_90_or_270(rotation))
-               drm_rect_rotate(&plane_state->base.src,
-                               fb->width << 16, fb->height << 16,
-                               DRM_MODE_ROTATE_270);
-
        /*
         * Handle the AUX surface first since
         * the main surface setup depends on it.
         */
-       if (fb->format->format == DRM_FORMAT_NV12) {
+       if (is_planar_yuv_format(fb->format->format)) {
                ret = skl_check_nv12_aux_surface(plane_state);
                if (ret)
                        return ret;
@@ -3230,9 +3582,10 @@ static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 dspcntr = 0;
 
-       dspcntr |= DISPPLANE_GAMMA_ENABLE;
+       if (crtc_state->gamma_enable)
+               dspcntr |= DISPPLANE_GAMMA_ENABLE;
 
-       if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+       if (crtc_state->csc_enable)
                dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
 
        if (INTEL_GEN(dev_priv) < 5)
@@ -3300,20 +3653,20 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv =
                to_i915(plane_state->base.plane->dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
-       int src_x = plane_state->base.src.x1 >> 16;
-       int src_y = plane_state->base.src.y1 >> 16;
+       int src_x, src_y;
        u32 offset;
        int ret;
 
-       intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
-       plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
-
-       ret = intel_plane_check_stride(plane_state);
+       ret = intel_plane_compute_gtt(plane_state);
        if (ret)
                return ret;
 
+       if (!plane_state->base.visible)
+               return 0;
+
+       src_x = plane_state->base.src.x1 >> 16;
+       src_y = plane_state->base.src.y1 >> 16;
+
        intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
 
        if (INTEL_GEN(dev_priv) >= 4)
@@ -3322,8 +3675,17 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
        else
                offset = 0;
 
+       /*
+        * Put the final coordinates back so that the src
+        * coordinate checks will see the right values.
+        */
+       drm_rect_translate(&plane_state->base.src,
+                          (src_x << 16) - plane_state->base.src.x1,
+                          (src_y << 16) - plane_state->base.src.y1);
+
        /* HSW/BDW do this automagically in hardware */
        if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
+               unsigned int rotation = plane_state->base.rotation;
                int src_w = drm_rect_width(&plane_state->base.src) >> 16;
                int src_h = drm_rect_height(&plane_state->base.src) >> 16;
 
@@ -3360,6 +3722,10 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
+       ret = i9xx_check_plane_surface(plane_state);
+       if (ret)
+               return ret;
+
        if (!plane_state->base.visible)
                return 0;
 
@@ -3367,10 +3733,6 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
-       ret = i9xx_check_plane_surface(plane_state);
-       if (ret)
-               return ret;
-
        plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
 
        return 0;
@@ -3459,7 +3821,7 @@ static void i9xx_disable_plane(struct intel_plane *plane,
         *
         * On pre-g4x there is no way to gamma correct the
         * pipe bottom color but we'll keep on doing this
-        * anyway.
+        * anyway so that the crtc state readout works correctly.
         */
        dspcntr = i9xx_plane_ctl_crtc(crtc_state);
 
@@ -3509,15 +3871,6 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
        return ret;
 }
 
-static u32
-intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
-{
-       if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
-               return 64;
-       else
-               return intel_tile_width_bytes(fb, color_plane);
-}
-
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
 {
        struct drm_device *dev = intel_crtc->base.dev;
@@ -3590,6 +3943,12 @@ static u32 skl_plane_ctl_format(u32 pixel_format)
                return PLANE_CTL_FORMAT_XRGB_2101010;
        case DRM_FORMAT_XBGR2101010:
                return PLANE_CTL_ORDER_RGBX | PLANE_CTL_FORMAT_XRGB_2101010;
+       case DRM_FORMAT_XBGR16161616F:
+       case DRM_FORMAT_ABGR16161616F:
+               return PLANE_CTL_FORMAT_XRGB_16161616F | PLANE_CTL_ORDER_RGBX;
+       case DRM_FORMAT_XRGB16161616F:
+       case DRM_FORMAT_ARGB16161616F:
+               return PLANE_CTL_FORMAT_XRGB_16161616F;
        case DRM_FORMAT_YUYV:
                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_YUYV;
        case DRM_FORMAT_YVYU:
@@ -3600,6 +3959,24 @@ static u32 skl_plane_ctl_format(u32 pixel_format)
                return PLANE_CTL_FORMAT_YUV422 | PLANE_CTL_YUV422_VYUY;
        case DRM_FORMAT_NV12:
                return PLANE_CTL_FORMAT_NV12;
+       case DRM_FORMAT_P010:
+               return PLANE_CTL_FORMAT_P010;
+       case DRM_FORMAT_P012:
+               return PLANE_CTL_FORMAT_P012;
+       case DRM_FORMAT_P016:
+               return PLANE_CTL_FORMAT_P016;
+       case DRM_FORMAT_Y210:
+               return PLANE_CTL_FORMAT_Y210;
+       case DRM_FORMAT_Y212:
+               return PLANE_CTL_FORMAT_Y212;
+       case DRM_FORMAT_Y216:
+               return PLANE_CTL_FORMAT_Y216;
+       case DRM_FORMAT_XVYU2101010:
+               return PLANE_CTL_FORMAT_Y410;
+       case DRM_FORMAT_XVYU12_16161616:
+               return PLANE_CTL_FORMAT_Y412;
+       case DRM_FORMAT_XVYU16161616:
+               return PLANE_CTL_FORMAT_Y416;
        default:
                MISSING_CASE(pixel_format);
        }
@@ -3710,8 +4087,11 @@ u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return plane_ctl;
 
-       plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
-       plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
+       if (crtc_state->gamma_enable)
+               plane_ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE;
+
+       if (crtc_state->csc_enable)
+               plane_ctl |= PLANE_CTL_PIPE_CSC_ENABLE;
 
        return plane_ctl;
 }
@@ -3763,8 +4143,11 @@ u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
        if (INTEL_GEN(dev_priv) >= 11)
                return plane_color_ctl;
 
-       plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
-       plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
+       if (crtc_state->gamma_enable)
+               plane_color_ctl |= PLANE_COLOR_PIPE_GAMMA_ENABLE;
+
+       if (crtc_state->csc_enable)
+               plane_color_ctl |= PLANE_COLOR_PIPE_CSC_ENABLE;
 
        return plane_color_ctl;
 }
@@ -3772,6 +4155,8 @@ u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state)
 u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
                        const struct intel_plane_state *plane_state)
 {
+       struct drm_i915_private *dev_priv =
+               to_i915(plane_state->base.plane->dev);
        const struct drm_framebuffer *fb = plane_state->base.fb;
        struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
        u32 plane_color_ctl = 0;
@@ -3779,7 +4164,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
        plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE;
        plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state);
 
-       if (fb->format->is_yuv && !icl_is_hdr_plane(plane)) {
+       if (fb->format->is_yuv && !icl_is_hdr_plane(dev_priv, plane->id)) {
                if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
                        plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
                else
@@ -3921,9 +4306,6 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                 * The display has been reset as well,
                 * so need a full re-initialization.
                 */
-               intel_runtime_pm_disable_interrupts(dev_priv);
-               intel_runtime_pm_enable_interrupts(dev_priv);
-
                intel_pps_unlock_regs_wa(dev_priv);
                intel_modeset_init_hw(dev);
                intel_init_clock_gating(dev_priv);
@@ -3963,13 +4345,13 @@ static void icl_set_pipe_chicken(struct intel_crtc *crtc)
         * and rounding for per-pixel values 00 and 0xff
         */
        tmp |= PER_PIXEL_ALPHA_BYPASS_EN;
-
        /*
-        * W/A for underruns with linear/X-tiled with
-        * WM1+ disabled.
+        * Display WA # 1605353570: icl
+        * Set the pixel rounding bit to 1 for allowing
+        * passthrough of Frame buffer pixels unmodified
+        * across pipe
         */
-       tmp |= PM_FILL_MAINTAIN_DBUF_FULLNESS;
-
+       tmp |= PIXEL_ROUNDING_TRUNC_FB_PASSTHRU;
        I915_WRITE(PIPE_CHICKEN(pipe), tmp);
 }
 
@@ -4008,16 +4390,6 @@ static void intel_update_pipe_config(const struct intel_crtc_state *old_crtc_sta
                        ironlake_pfit_disable(old_crtc_state);
        }
 
-       /*
-        * We don't (yet) allow userspace to control the pipe background color,
-        * so force it to black, but apply pipe gamma and CSC so that its
-        * handling will match how we program our planes.
-        */
-       if (INTEL_GEN(dev_priv) >= 9)
-               I915_WRITE(SKL_BOTTOM_COLOR(crtc->pipe),
-                          SKL_BOTTOM_COLOR_GAMMA_ENABLE |
-                          SKL_BOTTOM_COLOR_CSC_ENABLE);
-
        if (INTEL_GEN(dev_priv) >= 11)
                icl_set_pipe_chicken(crtc);
 }
@@ -4978,6 +5350,21 @@ u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
        return ((phase >> 2) & PS_PHASE_MASK) | trip;
 }
 
+#define SKL_MIN_SRC_W 8
+#define SKL_MAX_SRC_W 4096
+#define SKL_MIN_SRC_H 8
+#define SKL_MAX_SRC_H 4096
+#define SKL_MIN_DST_W 8
+#define SKL_MAX_DST_W 4096
+#define SKL_MIN_DST_H 8
+#define SKL_MAX_DST_H 4096
+#define ICL_MAX_SRC_W 5120
+#define ICL_MAX_SRC_H 4096
+#define ICL_MAX_DST_W 5120
+#define ICL_MAX_DST_H 4096
+#define SKL_MIN_YUV_420_SRC_W 16
+#define SKL_MIN_YUV_420_SRC_H 16
+
 static int
 skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
                  unsigned int scaler_user, int *scaler_id,
@@ -5036,19 +5423,19 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
                return 0;
        }
 
-       if (format && format->format == DRM_FORMAT_NV12 &&
+       if (format && is_planar_yuv_format(format->format) &&
            (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) {
-               DRM_DEBUG_KMS("NV12: src dimensions not met\n");
+               DRM_DEBUG_KMS("Planar YUV: src dimensions not met\n");
                return -EINVAL;
        }
 
        /* range checks */
        if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H ||
            dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H ||
-           (IS_GEN(dev_priv, 11) &&
+           (INTEL_GEN(dev_priv) >= 11 &&
             (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H ||
              dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) ||
-           (!IS_GEN(dev_priv, 11) &&
+           (INTEL_GEN(dev_priv) < 11 &&
             (src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H ||
              dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) {
                DRM_DEBUG_KMS("scaler_user index %u.%u: src %ux%u dst %ux%u "
@@ -5105,14 +5492,15 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
 {
        struct intel_plane *intel_plane =
                to_intel_plane(plane_state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
        struct drm_framebuffer *fb = plane_state->base.fb;
        int ret;
        bool force_detach = !fb || !plane_state->base.visible;
        bool need_scaler = false;
 
        /* Pre-gen11 and SDR planes always need a scaler for planar formats. */
-       if (!icl_is_hdr_plane(intel_plane) &&
-           fb && fb->format->format == DRM_FORMAT_NV12)
+       if (!icl_is_hdr_plane(dev_priv, intel_plane->id) &&
+           fb && is_planar_yuv_format(fb->format->format))
                need_scaler = true;
 
        ret = skl_update_scaler(crtc_state, force_detach,
@@ -5144,11 +5532,24 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
        case DRM_FORMAT_ARGB8888:
        case DRM_FORMAT_XRGB2101010:
        case DRM_FORMAT_XBGR2101010:
+       case DRM_FORMAT_XBGR16161616F:
+       case DRM_FORMAT_ABGR16161616F:
+       case DRM_FORMAT_XRGB16161616F:
+       case DRM_FORMAT_ARGB16161616F:
        case DRM_FORMAT_YUYV:
        case DRM_FORMAT_YVYU:
        case DRM_FORMAT_UYVY:
        case DRM_FORMAT_VYUY:
        case DRM_FORMAT_NV12:
+       case DRM_FORMAT_P010:
+       case DRM_FORMAT_P012:
+       case DRM_FORMAT_P016:
+       case DRM_FORMAT_Y210:
+       case DRM_FORMAT_Y212:
+       case DRM_FORMAT_Y216:
+       case DRM_FORMAT_XVYU2101010:
+       case DRM_FORMAT_XVYU12_16161616:
+       case DRM_FORMAT_XVYU16161616:
                break;
        default:
                DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n",
@@ -5243,10 +5644,8 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state)
        WARN_ON(!(crtc_state->active_planes & ~BIT(PLANE_CURSOR)));
 
        if (IS_BROADWELL(dev_priv)) {
-               mutex_lock(&dev_priv->pcu_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL,
                                                IPS_ENABLE | IPS_PCODE_CONTROL));
-               mutex_unlock(&dev_priv->pcu_lock);
                /* Quoting Art Runyan: "its not safe to expect any particular
                 * value in IPS_CTL bit 31 after enabling IPS through the
                 * mailbox." Moreover, the mailbox may return a bogus state,
@@ -5259,7 +5658,7 @@ void hsw_enable_ips(const struct intel_crtc_state *crtc_state)
                 * and don't wait for vblanks until the end of crtc_enable, then
                 * the HW state readout code will complain that the expected
                 * IPS_CTL value is not the one we read. */
-               if (intel_wait_for_register(dev_priv,
+               if (intel_wait_for_register(&dev_priv->uncore,
                                            IPS_CTL, IPS_ENABLE, IPS_ENABLE,
                                            50))
                        DRM_ERROR("Timed out waiting for IPS enable\n");
@@ -5276,15 +5675,13 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state)
                return;
 
        if (IS_BROADWELL(dev_priv)) {
-               mutex_lock(&dev_priv->pcu_lock);
                WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
-               mutex_unlock(&dev_priv->pcu_lock);
                /*
                 * Wait for PCODE to finish disabling IPS. The BSpec specified
                 * 42ms timeout value leads to occasional timeouts so use 100ms
                 * instead.
                 */
-               if (intel_wait_for_register(dev_priv,
+               if (intel_wait_for_register(&dev_priv->uncore,
                                            IPS_CTL, IPS_ENABLE, 0,
                                            100))
                        DRM_ERROR("Timed out waiting for IPS disable\n");
@@ -5454,6 +5851,16 @@ static bool needs_nv12_wa(struct drm_i915_private *dev_priv,
        return false;
 }
 
+static bool needs_scalerclk_wa(struct drm_i915_private *dev_priv,
+                              const struct intel_crtc_state *crtc_state)
+{
+       /* Wa_2006604312:icl */
+       if (crtc_state->scaler_state.scaler_users > 0 && IS_ICELAKE(dev_priv))
+               return true;
+
+       return false;
+}
+
 static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
@@ -5487,11 +5894,13 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
                        intel_post_enable_primary(&crtc->base, pipe_config);
        }
 
-       /* Display WA 827 */
        if (needs_nv12_wa(dev_priv, old_crtc_state) &&
-           !needs_nv12_wa(dev_priv, pipe_config)) {
-               skl_wa_clkgate(dev_priv, crtc->pipe, false);
-       }
+           !needs_nv12_wa(dev_priv, pipe_config))
+               skl_wa_827(dev_priv, crtc->pipe, false);
+
+       if (needs_scalerclk_wa(dev_priv, old_crtc_state) &&
+           !needs_scalerclk_wa(dev_priv, pipe_config))
+               icl_wa_scalerclkgating(dev_priv, crtc->pipe, false);
 }
 
 static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
@@ -5528,9 +5937,13 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
 
        /* Display WA 827 */
        if (!needs_nv12_wa(dev_priv, old_crtc_state) &&
-           needs_nv12_wa(dev_priv, pipe_config)) {
-               skl_wa_clkgate(dev_priv, crtc->pipe, true);
-       }
+           needs_nv12_wa(dev_priv, pipe_config))
+               skl_wa_827(dev_priv, crtc->pipe, true);
+
+       /* Wa_2006604312:icl */
+       if (!needs_scalerclk_wa(dev_priv, old_crtc_state) &&
+           needs_scalerclk_wa(dev_priv, pipe_config))
+               icl_wa_scalerclkgating(dev_priv, crtc->pipe, true);
 
        /*
         * Vblank time updates from the shadow to live plane control register
@@ -5603,7 +6016,7 @@ static void intel_crtc_disable_planes(struct intel_atomic_state *state,
                    !(update_mask & BIT(plane->id)))
                        continue;
 
-               plane->disable_plane(plane, new_crtc_state);
+               intel_disable_plane(plane, new_crtc_state);
 
                if (old_plane_state->base.visible)
                        fb_bits |= plane->frontbuffer_bit;
@@ -5754,6 +6167,14 @@ static void intel_encoders_update_pipe(struct drm_crtc *crtc,
        }
 }
 
+static void intel_disable_primary_plane(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+
+       plane->disable_plane(plane, crtc_state);
+}
+
 static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
                                 struct drm_atomic_state *old_state)
 {
@@ -5819,6 +6240,8 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config,
         */
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
+       /* update DSPCNTR to configure gamma for pipe bottom color */
+       intel_disable_primary_plane(pipe_config);
 
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state, pipe_config);
@@ -5926,7 +6349,8 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
        if (!transcoder_is_dsi(cpu_transcoder))
                haswell_set_pipeconf(pipe_config);
 
-       haswell_set_pipemisc(pipe_config);
+       if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
+               bdw_set_pipemisc(pipe_config);
 
        intel_crtc->active = true;
 
@@ -5947,6 +6371,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
         */
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
+       /* update DSPCNTR to configure gamma/csc for pipe bottom color */
+       if (INTEL_GEN(dev_priv) < 9)
+               intel_disable_primary_plane(pipe_config);
 
        if (INTEL_GEN(dev_priv) >= 11)
                icl_set_pipe_chicken(intel_crtc);
@@ -6127,7 +6554,10 @@ bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port)
        if (port == PORT_NONE)
                return false;
 
-       if (IS_ICELAKE(dev_priv))
+       if (IS_ELKHARTLAKE(dev_priv))
+               return port <= PORT_C;
+
+       if (INTEL_GEN(dev_priv) >= 11)
                return port <= PORT_B;
 
        return false;
@@ -6135,7 +6565,7 @@ bool intel_port_is_combophy(struct drm_i915_private *dev_priv, enum port port)
 
 bool intel_port_is_tc(struct drm_i915_private *dev_priv, enum port port)
 {
-       if (IS_ICELAKE(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 11 && !IS_ELKHARTLAKE(dev_priv))
                return port >= PORT_C && port <= PORT_F;
 
        return false;
@@ -6222,7 +6652,7 @@ static u64 get_crtc_power_domains(struct drm_crtc *crtc,
                mask |= BIT_ULL(POWER_DOMAIN_AUDIO);
 
        if (crtc_state->shared_dpll)
-               mask |= BIT_ULL(POWER_DOMAIN_PLLS);
+               mask |= BIT_ULL(POWER_DOMAIN_DISPLAY_CORE);
 
        return mask;
 }
@@ -6304,6 +6734,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
 
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
+       /* update DSPCNTR to configure gamma for pipe bottom color */
+       intel_disable_primary_plane(pipe_config);
 
        dev_priv->display.initial_watermarks(old_intel_state,
                                             pipe_config);
@@ -6361,6 +6793,8 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
 
        intel_color_load_luts(pipe_config);
        intel_color_commit(pipe_config);
+       /* update DSPCNTR to configure gamma for pipe bottom color */
+       intel_disable_primary_plane(pipe_config);
 
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state,
@@ -6743,7 +7177,13 @@ static bool hsw_compute_ips_config(struct intel_crtc_state *crtc_state)
        if (!hsw_crtc_state_ips_capable(crtc_state))
                return false;
 
-       if (crtc_state->ips_force_disable)
+       /*
+        * When IPS gets enabled, the pipe CRC changes. Since IPS gets
+        * enabled and disabled dynamically based on package C states,
+        * user space can't make reliable use of the CRCs, so let's just
+        * completely disable it.
+        */
+       if (crtc_state->crc_enabled)
                return false;
 
        /* IPS should be fine as long as at least one plane is enabled. */
@@ -6795,7 +7235,7 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config)
                if (WARN_ON(!pfit_w || !pfit_h))
                        return pixel_rate;
 
-               pixel_rate = div_u64((u64)pixel_rate * pipe_w * pipe_h,
+               pixel_rate = div_u64(mul_u32_u32(pixel_rate, pipe_w * pipe_h),
                                     pfit_w * pfit_h);
        }
 
@@ -6818,8 +7258,7 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
 static int intel_crtc_compute_config(struct intel_crtc *crtc,
                                     struct intel_crtc_state *pipe_config)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
        int clock_limit = dev_priv->max_dotclk_freq;
 
@@ -6869,7 +7308,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
                }
 
                if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) &&
-                   intel_is_dual_link_lvds(dev)) {
+                   intel_is_dual_link_lvds(dev_priv)) {
                        DRM_DEBUG_KMS("Odd pipe source width not supported with dual link LVDS\n");
                        return -EINVAL;
                }
@@ -6916,7 +7355,7 @@ static void compute_m_n(unsigned int m, unsigned int n,
        else
                *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
 
-       *ret_m = div_u64((u64)m * *ret_n, n);
+       *ret_m = div_u64(mul_u32_u32(m, *ret_n), n);
        intel_reduce_m_n_ratio(ret_m, ret_n);
 }
 
@@ -7149,7 +7588,7 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
        if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
                return;
 
-       mutex_lock(&dev_priv->sb_lock);
+       vlv_dpio_get(dev_priv);
 
        bestn = pipe_config->dpll.n;
        bestm1 = pipe_config->dpll.m1;
@@ -7226,7 +7665,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW7(pipe), coreclk);
 
        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW11(pipe), 0x87871000);
-       mutex_unlock(&dev_priv->sb_lock);
+
+       vlv_dpio_put(dev_priv);
 }
 
 static void chv_prepare_pll(struct intel_crtc *crtc,
@@ -7259,7 +7699,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
        dpio_val = 0;
        loopfilter = 0;
 
-       mutex_lock(&dev_priv->sb_lock);
+       vlv_dpio_get(dev_priv);
 
        /* p1 and p2 divider */
        vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW13(port),
@@ -7331,7 +7771,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
                        vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW14(port)) |
                        DPIO_AFC_RECAL);
 
-       mutex_unlock(&dev_priv->sb_lock);
+       vlv_dpio_put(dev_priv);
 }
 
 /**
@@ -7486,7 +7926,19 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,
                        dpll |= PLL_P2_DIVIDE_BY_4;
        }
 
-       if (!IS_I830(dev_priv) &&
+       /*
+        * Bspec:
+        * "[Almador Errata}: For the correct operation of the muxed DVO pins
+        *  (GDEVSELB/I2Cdata, GIRDBY/I2CClk) and (GFRAMEB/DVI_Data,
+        *  GTRDYB/DVI_Clk): Bit 31 (DPLL VCO Enable) and Bit 30 (2X Clock
+        *  Enable) must be set to “1” in both the DPLL A Control Register
+        *  (06014h-06017h) and DPLL B Control Register (06018h-0601Bh)."
+        *
+        * For simplicity We simply keep both bits always enabled in
+        * both DPLLS. The spec says we should disable the DVO 2X clock
+        * when not needed, but this seems to work fine in practice.
+        */
+       if (IS_I830(dev_priv) ||
            intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
                dpll |= DPLL_DVO_2X_MODE;
 
@@ -7587,9 +8039,14 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
        tmp = I915_READ(HTOTAL(cpu_transcoder));
        pipe_config->base.adjusted_mode.crtc_hdisplay = (tmp & 0xffff) + 1;
        pipe_config->base.adjusted_mode.crtc_htotal = ((tmp >> 16) & 0xffff) + 1;
-       tmp = I915_READ(HBLANK(cpu_transcoder));
-       pipe_config->base.adjusted_mode.crtc_hblank_start = (tmp & 0xffff) + 1;
-       pipe_config->base.adjusted_mode.crtc_hblank_end = ((tmp >> 16) & 0xffff) + 1;
+
+       if (!transcoder_is_dsi(cpu_transcoder)) {
+               tmp = I915_READ(HBLANK(cpu_transcoder));
+               pipe_config->base.adjusted_mode.crtc_hblank_start =
+                                                       (tmp & 0xffff) + 1;
+               pipe_config->base.adjusted_mode.crtc_hblank_end =
+                                               ((tmp >> 16) & 0xffff) + 1;
+       }
        tmp = I915_READ(HSYNC(cpu_transcoder));
        pipe_config->base.adjusted_mode.crtc_hsync_start = (tmp & 0xffff) + 1;
        pipe_config->base.adjusted_mode.crtc_hsync_end = ((tmp >> 16) & 0xffff) + 1;
@@ -7597,9 +8054,14 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
        tmp = I915_READ(VTOTAL(cpu_transcoder));
        pipe_config->base.adjusted_mode.crtc_vdisplay = (tmp & 0xffff) + 1;
        pipe_config->base.adjusted_mode.crtc_vtotal = ((tmp >> 16) & 0xffff) + 1;
-       tmp = I915_READ(VBLANK(cpu_transcoder));
-       pipe_config->base.adjusted_mode.crtc_vblank_start = (tmp & 0xffff) + 1;
-       pipe_config->base.adjusted_mode.crtc_vblank_end = ((tmp >> 16) & 0xffff) + 1;
+
+       if (!transcoder_is_dsi(cpu_transcoder)) {
+               tmp = I915_READ(VBLANK(cpu_transcoder));
+               pipe_config->base.adjusted_mode.crtc_vblank_start =
+                                                       (tmp & 0xffff) + 1;
+               pipe_config->base.adjusted_mode.crtc_vblank_end =
+                                               ((tmp >> 16) & 0xffff) + 1;
+       }
        tmp = I915_READ(VSYNC(cpu_transcoder));
        pipe_config->base.adjusted_mode.crtc_vsync_start = (tmp & 0xffff) + 1;
        pipe_config->base.adjusted_mode.crtc_vsync_end = ((tmp >> 16) & 0xffff) + 1;
@@ -7694,13 +8156,16 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state)
                        pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
                else
                        pipeconf |= PIPECONF_INTERLACE_W_SYNC_SHIFT;
-       } else
+       } else {
                pipeconf |= PIPECONF_PROGRESSIVE;
+       }
 
        if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
             crtc_state->limited_color_range)
                pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
 
+       pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
+
        I915_WRITE(PIPECONF(crtc->pipe), pipeconf);
        POSTING_READ(PIPECONF(crtc->pipe));
 }
@@ -7744,8 +8209,7 @@ static int i8xx_crtc_compute_clock(struct intel_crtc *crtc,
 static int g4x_crtc_compute_clock(struct intel_crtc *crtc,
                                  struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct intel_limit *limit;
        int refclk = 96000;
 
@@ -7758,7 +8222,7 @@ static int g4x_crtc_compute_clock(struct intel_crtc *crtc,
                        DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
                }
 
-               if (intel_is_dual_link_lvds(dev))
+               if (intel_is_dual_link_lvds(dev_priv))
                        limit = &intel_limits_g4x_dual_channel_lvds;
                else
                        limit = &intel_limits_g4x_single_channel_lvds;
@@ -7894,14 +8358,22 @@ static int vlv_crtc_compute_clock(struct intel_crtc *crtc,
        return 0;
 }
 
+static bool i9xx_has_pfit(struct drm_i915_private *dev_priv)
+{
+       if (IS_I830(dev_priv))
+               return false;
+
+       return INTEL_GEN(dev_priv) >= 4 ||
+               IS_PINEVIEW(dev_priv) || IS_MOBILE(dev_priv);
+}
+
 static void i9xx_get_pfit_config(struct intel_crtc *crtc,
                                 struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 tmp;
 
-       if (INTEL_GEN(dev_priv) <= 3 &&
-           (IS_I830(dev_priv) || !IS_MOBILE(dev_priv)))
+       if (!i9xx_has_pfit(dev_priv))
                return;
 
        tmp = I915_READ(PFIT_CONTROL);
@@ -7935,9 +8407,9 @@ static void vlv_crtc_clock_get(struct intel_crtc *crtc,
        if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
                return;
 
-       mutex_lock(&dev_priv->sb_lock);
+       vlv_dpio_get(dev_priv);
        mdiv = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW3(pipe));
-       mutex_unlock(&dev_priv->sb_lock);
+       vlv_dpio_put(dev_priv);
 
        clock.m1 = (mdiv >> DPIO_M1DIV_SHIFT) & 7;
        clock.m2 = mdiv & DPIO_M2DIV_MASK;
@@ -8046,13 +8518,13 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc,
        if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
                return;
 
-       mutex_lock(&dev_priv->sb_lock);
+       vlv_dpio_get(dev_priv);
        cmn_dw13 = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW13(port));
        pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port));
        pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port));
        pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port));
        pll_dw3 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
-       mutex_unlock(&dev_priv->sb_lock);
+       vlv_dpio_put(dev_priv);
 
        clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0;
        clock.m2 = (pll_dw0 & 0xff) << 22;
@@ -8108,6 +8580,24 @@ static void intel_get_crtc_ycbcr_config(struct intel_crtc *crtc,
        pipe_config->output_format = output;
 }
 
+static void i9xx_get_pipe_color_config(struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+       u32 tmp;
+
+       tmp = I915_READ(DSPCNTR(i9xx_plane));
+
+       if (tmp & DISPPLANE_GAMMA_ENABLE)
+               crtc_state->gamma_enable = true;
+
+       if (!HAS_GMCH(dev_priv) &&
+           tmp & DISPPLANE_PIPE_CSC_ENABLE)
+               crtc_state->csc_enable = true;
+}
+
 static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                                 struct intel_crtc_state *pipe_config)
 {
@@ -8153,6 +8643,14 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
            (tmp & PIPECONF_COLOR_RANGE_SELECT))
                pipe_config->limited_color_range = true;
 
+       pipe_config->gamma_mode = (tmp & PIPECONF_GAMMA_MODE_MASK_I9XX) >>
+               PIPECONF_GAMMA_MODE_SHIFT;
+
+       if (IS_CHERRYVIEW(dev_priv))
+               pipe_config->cgm_mode = I915_READ(CGM_PIPE_MODE(crtc->pipe));
+
+       i9xx_get_pipe_color_config(pipe_config);
+
        if (INTEL_GEN(dev_priv) < 4)
                pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
 
@@ -8185,14 +8683,6 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        }
        pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
        if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
-               /*
-                * DPLL_DVO_2X_MODE must be enabled for both DPLLs
-                * on 830. Filter it out here so that we don't
-                * report errors due to that.
-                */
-               if (IS_I830(dev_priv))
-                       pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE;
-
                pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe));
                pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(crtc->pipe));
        } else {
@@ -8534,7 +9024,7 @@ static void lpt_enable_clkout_dp(struct drm_i915_private *dev_priv,
 }
 
 /* Sequence to disable CLKOUT_DP */
-static void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
+void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv)
 {
        u32 reg, tmp;
 
@@ -8692,6 +9182,8 @@ static void ironlake_set_pipeconf(const struct intel_crtc_state *crtc_state)
        if (crtc_state->limited_color_range)
                val |= PIPECONF_COLOR_RANGE_SELECT;
 
+       val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode);
+
        I915_WRITE(PIPECONF(pipe), val);
        POSTING_READ(PIPECONF(pipe));
 }
@@ -8715,44 +9207,68 @@ static void haswell_set_pipeconf(const struct intel_crtc_state *crtc_state)
        POSTING_READ(PIPECONF(cpu_transcoder));
 }
 
-static void haswell_set_pipemisc(const struct intel_crtc_state *crtc_state)
+static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
-       struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       u32 val = 0;
 
-       if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) {
-               u32 val = 0;
+       switch (crtc_state->pipe_bpp) {
+       case 18:
+               val |= PIPEMISC_DITHER_6_BPC;
+               break;
+       case 24:
+               val |= PIPEMISC_DITHER_8_BPC;
+               break;
+       case 30:
+               val |= PIPEMISC_DITHER_10_BPC;
+               break;
+       case 36:
+               val |= PIPEMISC_DITHER_12_BPC;
+               break;
+       default:
+               MISSING_CASE(crtc_state->pipe_bpp);
+               break;
+       }
 
-               switch (crtc_state->pipe_bpp) {
-               case 18:
-                       val |= PIPEMISC_DITHER_6_BPC;
-                       break;
-               case 24:
-                       val |= PIPEMISC_DITHER_8_BPC;
-                       break;
-               case 30:
-                       val |= PIPEMISC_DITHER_10_BPC;
-                       break;
-               case 36:
-                       val |= PIPEMISC_DITHER_12_BPC;
-                       break;
-               default:
-                       /* Case prevented by pipe_config_set_bpp. */
-                       BUG();
-               }
+       if (crtc_state->dither)
+               val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
+
+       if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
+           crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
+               val |= PIPEMISC_OUTPUT_COLORSPACE_YUV;
 
-               if (crtc_state->dither)
-                       val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
+       if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
+               val |= PIPEMISC_YUV420_ENABLE |
+                       PIPEMISC_YUV420_MODE_FULL_BLEND;
 
-               if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
-                   crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
-                       val |= PIPEMISC_OUTPUT_COLORSPACE_YUV;
+       if (INTEL_GEN(dev_priv) >= 11 &&
+           (crtc_state->active_planes & ~(icl_hdr_plane_mask() |
+                                          BIT(PLANE_CURSOR))) == 0)
+               val |= PIPEMISC_HDR_MODE_PRECISION;
 
-               if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
-                       val |= PIPEMISC_YUV420_ENABLE |
-                               PIPEMISC_YUV420_MODE_FULL_BLEND;
+       I915_WRITE(PIPEMISC(crtc->pipe), val);
+}
 
-               I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
+int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       u32 tmp;
+
+       tmp = I915_READ(PIPEMISC(crtc->pipe));
+
+       switch (tmp & PIPEMISC_DITHER_BPC_MASK) {
+       case PIPEMISC_DITHER_6_BPC:
+               return 18;
+       case PIPEMISC_DITHER_8_BPC:
+               return 24;
+       case PIPEMISC_DITHER_10_BPC:
+               return 30;
+       case PIPEMISC_DITHER_12_BPC:
+               return 36;
+       default:
+               MISSING_CASE(tmp);
+               return 0;
        }
 }
 
@@ -8772,13 +9288,11 @@ static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor)
        return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
 }
 
-static void ironlake_compute_dpll(struct intel_crtc *intel_crtc,
+static void ironlake_compute_dpll(struct intel_crtc *crtc,
                                  struct intel_crtc_state *crtc_state,
                                  struct dpll *reduced_clock)
 {
-       struct drm_crtc *crtc = &intel_crtc->base;
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 dpll, fp, fp2;
        int factor;
 
@@ -8787,10 +9301,12 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc,
        if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
                if ((intel_panel_use_ssc(dev_priv) &&
                     dev_priv->vbt.lvds_ssc_freq == 100000) ||
-                   (HAS_PCH_IBX(dev_priv) && intel_is_dual_link_lvds(dev)))
+                   (HAS_PCH_IBX(dev_priv) &&
+                    intel_is_dual_link_lvds(dev_priv)))
                        factor = 25;
-       } else if (crtc_state->sdvo_tv_clock)
+       } else if (crtc_state->sdvo_tv_clock) {
                factor = 20;
+       }
 
        fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
 
@@ -8877,8 +9393,7 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc,
 static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
                                       struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct intel_limit *limit;
        int refclk = 120000;
 
@@ -8896,7 +9411,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
                        refclk = dev_priv->vbt.lvds_ssc_freq;
                }
 
-               if (intel_is_dual_link_lvds(dev)) {
+               if (intel_is_dual_link_lvds(dev_priv)) {
                        if (refclk == 100000)
                                limit = &intel_limits_ironlake_dual_lvds_100m;
                        else
@@ -8920,7 +9435,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
 
        ironlake_compute_dpll(crtc, crtc_state, NULL);
 
-       if (!intel_get_shared_dpll(crtc, crtc_state, NULL)) {
+       if (!intel_get_shared_dpll(crtc_state, NULL)) {
                DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
                              pipe_name(crtc->pipe));
                return -EINVAL;
@@ -9226,6 +9741,13 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
        if (tmp & PIPECONF_COLOR_RANGE_SELECT)
                pipe_config->limited_color_range = true;
 
+       pipe_config->gamma_mode = (tmp & PIPECONF_GAMMA_MODE_MASK_ILK) >>
+               PIPECONF_GAMMA_MODE_SHIFT;
+
+       pipe_config->csc_mode = I915_READ(PIPE_CSC_MODE(crtc->pipe));
+
+       i9xx_get_pipe_color_config(pipe_config);
+
        if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
                struct intel_shared_dpll *pll;
                enum intel_dpll_id pll_id;
@@ -9281,227 +9803,6 @@ out:
 
        return ret;
 }
-
-static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
-{
-       struct drm_device *dev = &dev_priv->drm;
-       struct intel_crtc *crtc;
-
-       for_each_intel_crtc(dev, crtc)
-               I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n",
-                    pipe_name(crtc->pipe));
-
-       I915_STATE_WARN(I915_READ(HSW_PWR_WELL_CTL2),
-                       "Display power well on\n");
-       I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
-       I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
-       I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
-       I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
-       I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
-            "CPU PWM1 enabled\n");
-       if (IS_HASWELL(dev_priv))
-               I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
-                    "CPU PWM2 enabled\n");
-       I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
-            "PCH PWM1 enabled\n");
-       I915_STATE_WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
-            "Utility pin enabled\n");
-       I915_STATE_WARN(I915_READ(PCH_GTC_CTL) & PCH_GTC_ENABLE, "PCH GTC enabled\n");
-
-       /*
-        * In theory we can still leave IRQs enabled, as long as only the HPD
-        * interrupts remain enabled. We used to check for that, but since it's
-        * gen-specific and since we only disable LCPLL after we fully disable
-        * the interrupts, the check below should be enough.
-        */
-       I915_STATE_WARN(intel_irqs_enabled(dev_priv), "IRQs enabled\n");
-}
-
-static u32 hsw_read_dcomp(struct drm_i915_private *dev_priv)
-{
-       if (IS_HASWELL(dev_priv))
-               return I915_READ(D_COMP_HSW);
-       else
-               return I915_READ(D_COMP_BDW);
-}
-
-static void hsw_write_dcomp(struct drm_i915_private *dev_priv, u32 val)
-{
-       if (IS_HASWELL(dev_priv)) {
-               mutex_lock(&dev_priv->pcu_lock);
-               if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
-                                           val))
-                       DRM_DEBUG_KMS("Failed to write to D_COMP\n");
-               mutex_unlock(&dev_priv->pcu_lock);
-       } else {
-               I915_WRITE(D_COMP_BDW, val);
-               POSTING_READ(D_COMP_BDW);
-       }
-}
-
-/*
- * This function implements pieces of two sequences from BSpec:
- * - Sequence for display software to disable LCPLL
- * - Sequence for display software to allow package C8+
- * The steps implemented here are just the steps that actually touch the LCPLL
- * register. Callers should take care of disabling all the display engine
- * functions, doing the mode unset, fixing interrupts, etc.
- */
-static void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
-                             bool switch_to_fclk, bool allow_power_down)
-{
-       u32 val;
-
-       assert_can_disable_lcpll(dev_priv);
-
-       val = I915_READ(LCPLL_CTL);
-
-       if (switch_to_fclk) {
-               val |= LCPLL_CD_SOURCE_FCLK;
-               I915_WRITE(LCPLL_CTL, val);
-
-               if (wait_for_us(I915_READ(LCPLL_CTL) &
-                               LCPLL_CD_SOURCE_FCLK_DONE, 1))
-                       DRM_ERROR("Switching to FCLK failed\n");
-
-               val = I915_READ(LCPLL_CTL);
-       }
-
-       val |= LCPLL_PLL_DISABLE;
-       I915_WRITE(LCPLL_CTL, val);
-       POSTING_READ(LCPLL_CTL);
-
-       if (intel_wait_for_register(dev_priv, LCPLL_CTL, LCPLL_PLL_LOCK, 0, 1))
-               DRM_ERROR("LCPLL still locked\n");
-
-       val = hsw_read_dcomp(dev_priv);
-       val |= D_COMP_COMP_DISABLE;
-       hsw_write_dcomp(dev_priv, val);
-       ndelay(100);
-
-       if (wait_for((hsw_read_dcomp(dev_priv) & D_COMP_RCOMP_IN_PROGRESS) == 0,
-                    1))
-               DRM_ERROR("D_COMP RCOMP still in progress\n");
-
-       if (allow_power_down) {
-               val = I915_READ(LCPLL_CTL);
-               val |= LCPLL_POWER_DOWN_ALLOW;
-               I915_WRITE(LCPLL_CTL, val);
-               POSTING_READ(LCPLL_CTL);
-       }
-}
-
-/*
- * Fully restores LCPLL, disallowing power down and switching back to LCPLL
- * source.
- */
-static void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
-{
-       u32 val;
-
-       val = I915_READ(LCPLL_CTL);
-
-       if ((val & (LCPLL_PLL_LOCK | LCPLL_PLL_DISABLE | LCPLL_CD_SOURCE_FCLK |
-                   LCPLL_POWER_DOWN_ALLOW)) == LCPLL_PLL_LOCK)
-               return;
-
-       /*
-        * Make sure we're not on PC8 state before disabling PC8, otherwise
-        * we'll hang the machine. To prevent PC8 state, just enable force_wake.
-        */
-       intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
-
-       if (val & LCPLL_POWER_DOWN_ALLOW) {
-               val &= ~LCPLL_POWER_DOWN_ALLOW;
-               I915_WRITE(LCPLL_CTL, val);
-               POSTING_READ(LCPLL_CTL);
-       }
-
-       val = hsw_read_dcomp(dev_priv);
-       val |= D_COMP_COMP_FORCE;
-       val &= ~D_COMP_COMP_DISABLE;
-       hsw_write_dcomp(dev_priv, val);
-
-       val = I915_READ(LCPLL_CTL);
-       val &= ~LCPLL_PLL_DISABLE;
-       I915_WRITE(LCPLL_CTL, val);
-
-       if (intel_wait_for_register(dev_priv,
-                                   LCPLL_CTL, LCPLL_PLL_LOCK, LCPLL_PLL_LOCK,
-                                   5))
-               DRM_ERROR("LCPLL not locked yet\n");
-
-       if (val & LCPLL_CD_SOURCE_FCLK) {
-               val = I915_READ(LCPLL_CTL);
-               val &= ~LCPLL_CD_SOURCE_FCLK;
-               I915_WRITE(LCPLL_CTL, val);
-
-               if (wait_for_us((I915_READ(LCPLL_CTL) &
-                                LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
-                       DRM_ERROR("Switching back to LCPLL failed\n");
-       }
-
-       intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-
-       intel_update_cdclk(dev_priv);
-       intel_dump_cdclk_state(&dev_priv->cdclk.hw, "Current CDCLK");
-}
-
-/*
- * Package states C8 and deeper are really deep PC states that can only be
- * reached when all the devices on the system allow it, so even if the graphics
- * device allows PC8+, it doesn't mean the system will actually get to these
- * states. Our driver only allows PC8+ when going into runtime PM.
- *
- * The requirements for PC8+ are that all the outputs are disabled, the power
- * well is disabled and most interrupts are disabled, and these are also
- * requirements for runtime PM. When these conditions are met, we manually do
- * the other conditions: disable the interrupts, clocks and switch LCPLL refclk
- * to Fclk. If we're in PC8+ and we get an non-hotplug interrupt, we can hard
- * hang the machine.
- *
- * When we really reach PC8 or deeper states (not just when we allow it) we lose
- * the state of some registers, so when we come back from PC8+ we need to
- * restore this state. We don't get into PC8+ if we're not in RC6, so we don't
- * need to take care of the registers kept by RC6. Notice that this happens even
- * if we don't put the device in PCI D3 state (which is what currently happens
- * because of the runtime PM support).
- *
- * For more, read "Display Sequences for Package C8" on the hardware
- * documentation.
- */
-void hsw_enable_pc8(struct drm_i915_private *dev_priv)
-{
-       u32 val;
-
-       DRM_DEBUG_KMS("Enabling package C8+\n");
-
-       if (HAS_PCH_LPT_LP(dev_priv)) {
-               val = I915_READ(SOUTH_DSPCLK_GATE_D);
-               val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
-               I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
-       }
-
-       lpt_disable_clkout_dp(dev_priv);
-       hsw_disable_lcpll(dev_priv, true, true);
-}
-
-void hsw_disable_pc8(struct drm_i915_private *dev_priv)
-{
-       u32 val;
-
-       DRM_DEBUG_KMS("Disabling package C8+\n");
-
-       hsw_restore_lcpll(dev_priv);
-       lpt_init_pch_refclk(dev_priv);
-
-       if (HAS_PCH_LPT_LP(dev_priv)) {
-               val = I915_READ(SOUTH_DSPCLK_GATE_D);
-               val |= PCH_LP_PARTITION_LEVEL_DISABLE;
-               I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
-       }
-}
-
 static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
                                      struct intel_crtc_state *crtc_state)
 {
@@ -9510,11 +9811,11 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
                to_intel_atomic_state(crtc_state->base.state);
 
        if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) ||
-           IS_ICELAKE(dev_priv)) {
+           INTEL_GEN(dev_priv) >= 11) {
                struct intel_encoder *encoder =
                        intel_get_crtc_new_encoder(state, crtc_state);
 
-               if (!intel_get_shared_dpll(crtc, crtc_state, encoder)) {
+               if (!intel_get_shared_dpll(crtc_state, encoder)) {
                        DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
                                      pipe_name(crtc->pipe));
                        return -EINVAL;
@@ -9552,9 +9853,6 @@ static void icelake_get_ddi_pll(struct drm_i915_private *dev_priv,
                temp = I915_READ(DPCLKA_CFGCR0_ICL) &
                       DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
                id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port);
-
-               if (WARN_ON(!intel_dpll_is_combophy(id)))
-                       return;
        } else if (intel_port_is_tc(dev_priv, port)) {
                id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv, port));
        } else {
@@ -9643,20 +9941,25 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
 
 static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
                                     struct intel_crtc_state *pipe_config,
-                                    u64 *power_domain_mask)
+                                    u64 *power_domain_mask,
+                                    intel_wakeref_t *wakerefs)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum intel_display_power_domain power_domain;
-       unsigned long panel_transcoder_mask = BIT(TRANSCODER_EDP);
+       unsigned long panel_transcoder_mask = 0;
        unsigned long enabled_panel_transcoders = 0;
        enum transcoder panel_transcoder;
+       intel_wakeref_t wf;
        u32 tmp;
 
-       if (IS_ICELAKE(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 11)
                panel_transcoder_mask |=
                        BIT(TRANSCODER_DSI_0) | BIT(TRANSCODER_DSI_1);
 
+       if (HAS_TRANSCODER_EDP(dev_priv))
+               panel_transcoder_mask |= BIT(TRANSCODER_EDP);
+
        /*
         * The pipe->transcoder mapping is fixed with the exception of the eDP
         * and DSI transcoders handled below.
@@ -9670,6 +9973,7 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
        for_each_set_bit(panel_transcoder,
                         &panel_transcoder_mask,
                         ARRAY_SIZE(INTEL_INFO(dev_priv)->trans_offsets)) {
+               bool force_thru = false;
                enum pipe trans_pipe;
 
                tmp = I915_READ(TRANS_DDI_FUNC_CTL(panel_transcoder));
@@ -9691,6 +9995,8 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
                             transcoder_name(panel_transcoder));
                        /* fall through */
                case TRANS_DDI_EDP_INPUT_A_ONOFF:
+                       force_thru = true;
+                       /* fall through */
                case TRANS_DDI_EDP_INPUT_A_ON:
                        trans_pipe = PIPE_A;
                        break;
@@ -9702,8 +10008,10 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
                        break;
                }
 
-               if (trans_pipe == crtc->pipe)
+               if (trans_pipe == crtc->pipe) {
                        pipe_config->cpu_transcoder = panel_transcoder;
+                       pipe_config->pch_pfit.force_thru = force_thru;
+               }
        }
 
        /*
@@ -9713,10 +10021,13 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
                enabled_panel_transcoders != BIT(TRANSCODER_EDP));
 
        power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+
+       wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wf)
                return false;
 
-       WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+       wakerefs[power_domain] = wf;
        *power_domain_mask |= BIT_ULL(power_domain);
 
        tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
@@ -9726,13 +10037,15 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
 
 static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
                                         struct intel_crtc_state *pipe_config,
-                                        u64 *power_domain_mask)
+                                        u64 *power_domain_mask,
+                                        intel_wakeref_t *wakerefs)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum intel_display_power_domain power_domain;
-       enum port port;
        enum transcoder cpu_transcoder;
+       intel_wakeref_t wf;
+       enum port port;
        u32 tmp;
 
        for_each_port_masked(port, BIT(PORT_A) | BIT(PORT_C)) {
@@ -9742,10 +10055,13 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
                        cpu_transcoder = TRANSCODER_DSI_C;
 
                power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
-               if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+
+               wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+               if (!wf)
                        continue;
 
-               WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
+               wakerefs[power_domain] = wf;
                *power_domain_mask |= BIT_ULL(power_domain);
 
                /*
@@ -9786,7 +10102,7 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
 
        port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
 
-       if (IS_ICELAKE(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 11)
                icelake_get_ddi_pll(dev_priv, port, pipe_config);
        else if (IS_CANNONLAKE(dev_priv))
                cannonlake_get_ddi_pll(dev_priv, port, pipe_config);
@@ -9824,6 +10140,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                                    struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       intel_wakeref_t wakerefs[POWER_DOMAIN_NUM], wf;
        enum intel_display_power_domain power_domain;
        u64 power_domain_mask;
        bool active;
@@ -9831,16 +10148,21 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        intel_crtc_init_scalers(crtc, pipe_config);
 
        power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+       wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (!wf)
                return false;
+
+       wakerefs[power_domain] = wf;
        power_domain_mask = BIT_ULL(power_domain);
 
        pipe_config->shared_dpll = NULL;
 
-       active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_mask);
+       active = hsw_get_transcoder_state(crtc, pipe_config,
+                                         &power_domain_mask, wakerefs);
 
        if (IS_GEN9_LP(dev_priv) &&
-           bxt_get_dsi_transcoder_state(crtc, pipe_config, &power_domain_mask)) {
+           bxt_get_dsi_transcoder_state(crtc, pipe_config,
+                                        &power_domain_mask, wakerefs)) {
                WARN_ON(active);
                active = true;
        }
@@ -9849,7 +10171,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                goto out;
 
        if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
-           IS_ICELAKE(dev_priv)) {
+           INTEL_GEN(dev_priv) >= 11) {
                haswell_get_ddi_port_state(crtc, pipe_config);
                intel_get_pipe_timings(crtc, pipe_config);
        }
@@ -9857,12 +10179,28 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        intel_get_pipe_src_size(crtc, pipe_config);
        intel_get_crtc_ycbcr_config(crtc, pipe_config);
 
-       pipe_config->gamma_mode =
-               I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
+       pipe_config->gamma_mode = I915_READ(GAMMA_MODE(crtc->pipe));
+
+       pipe_config->csc_mode = I915_READ(PIPE_CSC_MODE(crtc->pipe));
+
+       if (INTEL_GEN(dev_priv) >= 9) {
+               u32 tmp = I915_READ(SKL_BOTTOM_COLOR(crtc->pipe));
+
+               if (tmp & SKL_BOTTOM_COLOR_GAMMA_ENABLE)
+                       pipe_config->gamma_enable = true;
+
+               if (tmp & SKL_BOTTOM_COLOR_CSC_ENABLE)
+                       pipe_config->csc_enable = true;
+       } else {
+               i9xx_get_pipe_color_config(pipe_config);
+       }
 
        power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
-       if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
-               WARN_ON(power_domain_mask & BIT_ULL(power_domain));
+       WARN_ON(power_domain_mask & BIT_ULL(power_domain));
+
+       wf = intel_display_power_get_if_enabled(dev_priv, power_domain);
+       if (wf) {
+               wakerefs[power_domain] = wf;
                power_domain_mask |= BIT_ULL(power_domain);
 
                if (INTEL_GEN(dev_priv) >= 9)
@@ -9894,7 +10232,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
 out:
        for_each_power_domain(power_domain, power_domain_mask)
-               intel_display_power_put_unchecked(dev_priv, power_domain);
+               intel_display_power_put(dev_priv,
+                                       power_domain, wakerefs[power_domain]);
 
        return active;
 }
@@ -9957,19 +10296,17 @@ static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
 
 static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-       unsigned int rotation = plane_state->base.rotation;
        int src_x, src_y;
        u32 offset;
        int ret;
 
-       intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
-       plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
-
-       ret = intel_plane_check_stride(plane_state);
+       ret = intel_plane_compute_gtt(plane_state);
        if (ret)
                return ret;
 
+       if (!plane_state->base.visible)
+               return 0;
+
        src_x = plane_state->base.src_x >> 16;
        src_y = plane_state->base.src_y >> 16;
 
@@ -10006,6 +10343,10 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
+       ret = intel_cursor_check_surface(plane_state);
+       if (ret)
+               return ret;
+
        if (!plane_state->base.visible)
                return 0;
 
@@ -10013,10 +10354,6 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
-       ret = intel_cursor_check_surface(plane_state);
-       if (ret)
-               return ret;
-
        return 0;
 }
 
@@ -10030,7 +10367,12 @@ i845_cursor_max_stride(struct intel_plane *plane,
 
 static u32 i845_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
 {
-       return CURSOR_GAMMA_ENABLE;
+       u32 cntl = 0;
+
+       if (crtc_state->gamma_enable)
+               cntl |= CURSOR_GAMMA_ENABLE;
+
+       return cntl;
 }
 
 static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
@@ -10184,9 +10526,10 @@ static u32 i9xx_cursor_ctl_crtc(const struct intel_crtc_state *crtc_state)
        if (INTEL_GEN(dev_priv) >= 11)
                return cntl;
 
-       cntl |= MCURSOR_GAMMA_ENABLE;
+       if (crtc_state->gamma_enable)
+               cntl = MCURSOR_GAMMA_ENABLE;
 
-       if (HAS_DDI(dev_priv))
+       if (crtc_state->csc_enable)
                cntl |= MCURSOR_PIPE_CSC_ENABLE;
 
        if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
@@ -11134,7 +11477,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
                }
 
                if (!linked_state) {
-                       DRM_DEBUG_KMS("Need %d free Y planes for NV12\n",
+                       DRM_DEBUG_KMS("Need %d free Y planes for planar YUV\n",
                                      hweight8(crtc_state->nv12_planes));
 
                        return -EINVAL;
@@ -11175,16 +11518,11 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
                        return ret;
        }
 
-       if (mode_changed || crtc_state->color_mgmt_changed) {
+       if (mode_changed || pipe_config->update_pipe ||
+           crtc_state->color_mgmt_changed) {
                ret = intel_color_check(pipe_config);
                if (ret)
                        return ret;
-
-               /*
-                * Changing color management on Intel hardware is
-                * handled as part of planes update.
-                */
-               crtc_state->planes_changed = true;
        }
 
        ret = 0;
@@ -11355,6 +11693,16 @@ intel_dump_m_n_config(struct intel_crtc_state *pipe_config, char *id,
                      m_n->link_m, m_n->link_n, m_n->tu);
 }
 
+static void
+intel_dump_infoframe(struct drm_i915_private *dev_priv,
+                    const union hdmi_infoframe *frame)
+{
+       if ((drm_debug & DRM_UT_KMS) == 0)
+               return;
+
+       hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, frame);
+}
+
 #define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x
 
 static const char * const output_type_str[] = {
@@ -11458,6 +11806,22 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
        DRM_DEBUG_KMS("audio: %i, infoframes: %i\n",
                      pipe_config->has_audio, pipe_config->has_infoframe);
 
+       DRM_DEBUG_KMS("infoframes enabled: 0x%x\n",
+                     pipe_config->infoframes.enable);
+
+       if (pipe_config->infoframes.enable &
+           intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL))
+               DRM_DEBUG_KMS("GCP: 0x%x\n", pipe_config->infoframes.gcp);
+       if (pipe_config->infoframes.enable &
+           intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI))
+               intel_dump_infoframe(dev_priv, &pipe_config->infoframes.avi);
+       if (pipe_config->infoframes.enable &
+           intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_SPD))
+               intel_dump_infoframe(dev_priv, &pipe_config->infoframes.spd);
+       if (pipe_config->infoframes.enable &
+           intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_VENDOR))
+               intel_dump_infoframe(dev_priv, &pipe_config->infoframes.hdmi);
+
        DRM_DEBUG_KMS("requested mode:\n");
        drm_mode_debug_printmodeline(&pipe_config->base.mode);
        DRM_DEBUG_KMS("adjusted mode:\n");
@@ -11480,10 +11844,11 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                              pipe_config->gmch_pfit.pgm_ratios,
                              pipe_config->gmch_pfit.lvds_border_bits);
        else
-               DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
+               DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s, force thru: %s\n",
                              pipe_config->pch_pfit.pos,
                              pipe_config->pch_pfit.size,
-                             enableddisabled(pipe_config->pch_pfit.enabled));
+                             enableddisabled(pipe_config->pch_pfit.enabled),
+                             yesno(pipe_config->pch_pfit.force_thru));
 
        DRM_DEBUG_KMS("ips: %i, double wide: %i\n",
                      pipe_config->ips_enabled, pipe_config->double_wide);
@@ -11605,8 +11970,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
        saved_state->scaler_state = crtc_state->scaler_state;
        saved_state->shared_dpll = crtc_state->shared_dpll;
        saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
-       saved_state->pch_pfit.force_thru = crtc_state->pch_pfit.force_thru;
-       saved_state->ips_force_disable = crtc_state->ips_force_disable;
+       saved_state->crc_enabled = crtc_state->crc_enabled;
        if (IS_G4X(dev_priv) ||
            IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                saved_state->wm = crtc_state->wm;
@@ -11825,6 +12189,37 @@ intel_compare_link_m_n(const struct intel_link_m_n *m_n,
        return false;
 }
 
+static bool
+intel_compare_infoframe(const union hdmi_infoframe *a,
+                       const union hdmi_infoframe *b)
+{
+       return memcmp(a, b, sizeof(*a)) == 0;
+}
+
+static void
+pipe_config_infoframe_err(struct drm_i915_private *dev_priv,
+                         bool adjust, const char *name,
+                         const union hdmi_infoframe *a,
+                         const union hdmi_infoframe *b)
+{
+       if (adjust) {
+               if ((drm_debug & DRM_UT_KMS) == 0)
+                       return;
+
+               drm_dbg(DRM_UT_KMS, "mismatch in %s infoframe", name);
+               drm_dbg(DRM_UT_KMS, "expected:");
+               hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, a);
+               drm_dbg(DRM_UT_KMS, "found");
+               hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, b);
+       } else {
+               drm_err("mismatch in %s infoframe", name);
+               drm_err("expected:");
+               hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, a);
+               drm_err("found");
+               hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, b);
+       }
+}
+
 static void __printf(3, 4)
 pipe_config_err(bool adjust, const char *name, const char *format, ...)
 {
@@ -12008,7 +12403,17 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
        } \
 } while (0)
 
-#define PIPE_CONF_QUIRK(quirk) \
+#define PIPE_CONF_CHECK_INFOFRAME(name) do { \
+       if (!intel_compare_infoframe(&current_config->infoframes.name, \
+                                    &pipe_config->infoframes.name)) { \
+               pipe_config_infoframe_err(dev_priv, adjust, __stringify(name), \
+                                         &current_config->infoframes.name, \
+                                         &pipe_config->infoframes.name); \
+               ret = false; \
+       } \
+} while (0)
+
+#define PIPE_CONF_QUIRK(quirk) \
        ((current_config->quirks | pipe_config->quirks) & (quirk))
 
        PIPE_CONF_CHECK_I(cpu_transcoder);
@@ -12077,6 +12482,12 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
                PIPE_CONF_CHECK_X(gmch_pfit.pgm_ratios);
        PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits);
 
+       /*
+        * Changing the EDP transcoder input mux
+        * (A_ONOFF vs. A_ON) requires a full modeset.
+        */
+       PIPE_CONF_CHECK_BOOL(pch_pfit.force_thru);
+
        if (!adjust) {
                PIPE_CONF_CHECK_I(pipe_src_w);
                PIPE_CONF_CHECK_I(pipe_src_h);
@@ -12089,6 +12500,14 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 
                PIPE_CONF_CHECK_I(scaler_state.scaler_id);
                PIPE_CONF_CHECK_CLOCK_FUZZY(pixel_rate);
+
+               PIPE_CONF_CHECK_X(gamma_mode);
+               if (IS_CHERRYVIEW(dev_priv))
+                       PIPE_CONF_CHECK_X(cgm_mode);
+               else
+                       PIPE_CONF_CHECK_X(csc_mode);
+               PIPE_CONF_CHECK_BOOL(gamma_enable);
+               PIPE_CONF_CHECK_BOOL(csc_enable);
        }
 
        PIPE_CONF_CHECK_BOOL(double_wide);
@@ -12137,6 +12556,12 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 
        PIPE_CONF_CHECK_I(min_voltage_level);
 
+       PIPE_CONF_CHECK_X(infoframes.enable);
+       PIPE_CONF_CHECK_X(infoframes.gcp);
+       PIPE_CONF_CHECK_INFOFRAME(avi);
+       PIPE_CONF_CHECK_INFOFRAME(spd);
+       PIPE_CONF_CHECK_INFOFRAME(hdmi);
+
 #undef PIPE_CONF_CHECK_X
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_BOOL
@@ -12171,12 +12596,15 @@ static void verify_wm_state(struct drm_crtc *crtc,
                            struct drm_crtc_state *new_state)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc->dev);
-       struct skl_ddb_allocation hw_ddb, *sw_ddb;
-       struct skl_pipe_wm hw_wm, *sw_wm;
-       struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
+       struct skl_hw_state {
+               struct skl_ddb_entry ddb_y[I915_MAX_PLANES];
+               struct skl_ddb_entry ddb_uv[I915_MAX_PLANES];
+               struct skl_ddb_allocation ddb;
+               struct skl_pipe_wm wm;
+       } *hw;
+       struct skl_ddb_allocation *sw_ddb;
+       struct skl_pipe_wm *sw_wm;
        struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
-       struct skl_ddb_entry hw_ddb_y[I915_MAX_PLANES];
-       struct skl_ddb_entry hw_ddb_uv[I915_MAX_PLANES];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        const enum pipe pipe = intel_crtc->pipe;
        int plane, level, max_level = ilk_wm_max_level(dev_priv);
@@ -12184,22 +12612,29 @@ static void verify_wm_state(struct drm_crtc *crtc,
        if (INTEL_GEN(dev_priv) < 9 || !new_state->active)
                return;
 
-       skl_pipe_wm_get_hw_state(intel_crtc, &hw_wm);
+       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       if (!hw)
+               return;
+
+       skl_pipe_wm_get_hw_state(intel_crtc, &hw->wm);
        sw_wm = &to_intel_crtc_state(new_state)->wm.skl.optimal;
 
-       skl_pipe_ddb_get_hw_state(intel_crtc, hw_ddb_y, hw_ddb_uv);
+       skl_pipe_ddb_get_hw_state(intel_crtc, hw->ddb_y, hw->ddb_uv);
 
-       skl_ddb_get_hw_state(dev_priv, &hw_ddb);
+       skl_ddb_get_hw_state(dev_priv, &hw->ddb);
        sw_ddb = &dev_priv->wm.skl_hw.ddb;
 
-       if (INTEL_GEN(dev_priv) >= 11)
-               if (hw_ddb.enabled_slices != sw_ddb->enabled_slices)
-                       DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
-                                 sw_ddb->enabled_slices,
-                                 hw_ddb.enabled_slices);
+       if (INTEL_GEN(dev_priv) >= 11 &&
+           hw->ddb.enabled_slices != sw_ddb->enabled_slices)
+               DRM_ERROR("mismatch in DBUF Slices (expected %u, got %u)\n",
+                         sw_ddb->enabled_slices,
+                         hw->ddb.enabled_slices);
+
        /* planes */
        for_each_universal_plane(dev_priv, pipe, plane) {
-               hw_plane_wm = &hw_wm.planes[plane];
+               struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
+
+               hw_plane_wm = &hw->wm.planes[plane];
                sw_plane_wm = &sw_wm->planes[plane];
 
                /* Watermarks */
@@ -12231,7 +12666,7 @@ static void verify_wm_state(struct drm_crtc *crtc,
                }
 
                /* DDB */
-               hw_ddb_entry = &hw_ddb_y[plane];
+               hw_ddb_entry = &hw->ddb_y[plane];
                sw_ddb_entry = &to_intel_crtc_state(new_state)->wm.skl.plane_ddb_y[plane];
 
                if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
@@ -12249,7 +12684,9 @@ static void verify_wm_state(struct drm_crtc *crtc,
         * once the plane becomes visible, we can skip this check
         */
        if (1) {
-               hw_plane_wm = &hw_wm.planes[PLANE_CURSOR];
+               struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
+
+               hw_plane_wm = &hw->wm.planes[PLANE_CURSOR];
                sw_plane_wm = &sw_wm->planes[PLANE_CURSOR];
 
                /* Watermarks */
@@ -12281,7 +12718,7 @@ static void verify_wm_state(struct drm_crtc *crtc,
                }
 
                /* DDB */
-               hw_ddb_entry = &hw_ddb_y[PLANE_CURSOR];
+               hw_ddb_entry = &hw->ddb_y[PLANE_CURSOR];
                sw_ddb_entry = &to_intel_crtc_state(new_state)->wm.skl.plane_ddb_y[PLANE_CURSOR];
 
                if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
@@ -12291,6 +12728,8 @@ static void verify_wm_state(struct drm_crtc *crtc,
                                  hw_ddb_entry->start, hw_ddb_entry->end);
                }
        }
+
+       kfree(hw);
 }
 
 static void
@@ -12447,7 +12886,8 @@ intel_verify_planes(struct intel_atomic_state *state)
 
        for_each_new_intel_plane_in_state(state, plane,
                                          plane_state, i)
-               assert_plane(plane, plane_state->base.visible);
+               assert_plane(plane, plane_state->slave ||
+                            plane_state->base.visible);
 }
 
 static void
@@ -12769,10 +13209,16 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                return -EINVAL;
        }
 
+       /* keep the current setting */
+       if (!intel_state->cdclk.force_min_cdclk_changed)
+               intel_state->cdclk.force_min_cdclk =
+                       dev_priv->cdclk.force_min_cdclk;
+
        intel_state->modeset = true;
        intel_state->active_crtcs = dev_priv->active_crtcs;
        intel_state->cdclk.logical = dev_priv->cdclk.logical;
        intel_state->cdclk.actual = dev_priv->cdclk.actual;
+       intel_state->cdclk.pipe = INVALID_PIPE;
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                if (new_crtc_state->active)
@@ -12792,6 +13238,8 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
         * adjusted_mode bits in the crtc directly.
         */
        if (dev_priv->display.modeset_calc_cdclk) {
+               enum pipe pipe;
+
                ret = dev_priv->display.modeset_calc_cdclk(state);
                if (ret < 0)
                        return ret;
@@ -12808,12 +13256,36 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                                return ret;
                }
 
+               if (is_power_of_2(intel_state->active_crtcs)) {
+                       struct drm_crtc *crtc;
+                       struct drm_crtc_state *crtc_state;
+
+                       pipe = ilog2(intel_state->active_crtcs);
+                       crtc = &intel_get_crtc_for_pipe(dev_priv, pipe)->base;
+                       crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+                       if (crtc_state && needs_modeset(crtc_state))
+                               pipe = INVALID_PIPE;
+               } else {
+                       pipe = INVALID_PIPE;
+               }
+
                /* All pipes must be switched off while we change the cdclk. */
-               if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual,
-                                             &intel_state->cdclk.actual)) {
+               if (pipe != INVALID_PIPE &&
+                   intel_cdclk_needs_cd2x_update(dev_priv,
+                                                 &dev_priv->cdclk.actual,
+                                                 &intel_state->cdclk.actual)) {
+                       ret = intel_lock_all_pipes(state);
+                       if (ret < 0)
+                               return ret;
+
+                       intel_state->cdclk.pipe = pipe;
+               } else if (intel_cdclk_needs_modeset(&dev_priv->cdclk.actual,
+                                                    &intel_state->cdclk.actual)) {
                        ret = intel_modeset_all_pipes(state);
                        if (ret < 0)
                                return ret;
+
+                       intel_state->cdclk.pipe = INVALID_PIPE;
                }
 
                DRM_DEBUG_KMS("New cdclk calculated to be logical %u kHz, actual %u kHz\n",
@@ -12822,8 +13294,6 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
                DRM_DEBUG_KMS("New voltage level calculated to be logical %u, actual %u\n",
                              intel_state->cdclk.logical.voltage_level,
                              intel_state->cdclk.actual.voltage_level);
-       } else {
-               to_intel_atomic_state(state)->cdclk.logical = dev_priv->cdclk.logical;
        }
 
        intel_modeset_clear_plls(state);
@@ -12864,7 +13334,7 @@ static int intel_atomic_check(struct drm_device *dev,
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *crtc_state;
        int ret, i;
-       bool any_ms = false;
+       bool any_ms = intel_state->cdclk.force_min_cdclk_changed;
 
        /* Catch I915_MODE_FLAG_INHERITED */
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
@@ -12989,14 +13459,14 @@ static void intel_update_crtc(struct drm_crtc *crtc,
        else if (new_plane_state)
                intel_fbc_enable(intel_crtc, pipe_config, new_plane_state);
 
-       intel_begin_crtc_commit(crtc, old_crtc_state);
+       intel_begin_crtc_commit(to_intel_atomic_state(state), intel_crtc);
 
        if (INTEL_GEN(dev_priv) >= 9)
                skl_update_planes_on_crtc(to_intel_atomic_state(state), intel_crtc);
        else
                i9xx_update_planes_on_crtc(to_intel_atomic_state(state), intel_crtc);
 
-       intel_finish_crtc_commit(crtc, old_crtc_state);
+       intel_finish_crtc_commit(to_intel_atomic_state(state), intel_crtc);
 }
 
 static void intel_update_crtcs(struct drm_atomic_state *state)
@@ -13224,7 +13694,10 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        if (intel_state->modeset) {
                drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
-               intel_set_cdclk(dev_priv, &dev_priv->cdclk.actual);
+               intel_set_cdclk_pre_plane_update(dev_priv,
+                                                &intel_state->cdclk.actual,
+                                                &dev_priv->cdclk.actual,
+                                                intel_state->cdclk.pipe);
 
                /*
                 * SKL workaround: bspec recommends we disable the SAGV when we
@@ -13253,6 +13726,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
        dev_priv->display.update_crtcs(state);
 
+       if (intel_state->modeset)
+               intel_set_cdclk_post_plane_update(dev_priv,
+                                                 &intel_state->cdclk.actual,
+                                                 &dev_priv->cdclk.actual,
+                                                 intel_state->cdclk.pipe);
+
        /* FIXME: We should call drm_atomic_helper_commit_hw_done() here
         * already, but still need the state for the delayed optimization. To
         * fix this:
@@ -13313,7 +13792,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
                 * so enable debugging for the next modeset - and hope we catch
                 * the culprit.
                 */
-               intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
+               intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
                intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);
        }
 
@@ -13454,8 +13933,10 @@ static int intel_atomic_commit(struct drm_device *dev,
                       intel_state->min_voltage_level,
                       sizeof(intel_state->min_voltage_level));
                dev_priv->active_crtcs = intel_state->active_crtcs;
-               dev_priv->cdclk.logical = intel_state->cdclk.logical;
-               dev_priv->cdclk.actual = intel_state->cdclk.actual;
+               dev_priv->cdclk.force_min_cdclk =
+                       intel_state->cdclk.force_min_cdclk;
+
+               intel_cdclk_swap_state(intel_state);
        }
 
        drm_atomic_state_get(state);
@@ -13506,7 +13987,7 @@ static int do_rps_boost(struct wait_queue_entry *_wait,
         * vblank without our intervention, so leave RPS alone.
         */
        if (!i915_request_started(rq))
-               gen6_rps_boost(rq, NULL);
+               gen6_rps_boost(rq);
        i915_request_put(rq);
 
        drm_crtc_vblank_put(wait->crtc);
@@ -13767,7 +14248,7 @@ skl_max_scale(const struct intel_crtc_state *crtc_state,
         *            or
         *    cdclk/crtc_clock
         */
-       mult = pixel_format == DRM_FORMAT_NV12 ? 2 : 3;
+       mult = is_planar_yuv_format(pixel_format) ? 2 : 3;
        tmpclk1 = (1 << 16) * mult - 1;
        tmpclk2 = (1 << 8) * ((max_dotclk << 8) / crtc_clock);
        max_scale = min(tmpclk1, tmpclk2);
@@ -13775,39 +14256,38 @@ skl_max_scale(const struct intel_crtc_state *crtc_state,
        return max_scale;
 }
 
-static void intel_begin_crtc_commit(struct drm_crtc *crtc,
-                                   struct drm_crtc_state *old_crtc_state)
+static void intel_begin_crtc_commit(struct intel_atomic_state *state,
+                                   struct intel_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_crtc_state *old_intel_cstate =
-               to_intel_crtc_state(old_crtc_state);
-       struct intel_atomic_state *old_intel_state =
-               to_intel_atomic_state(old_crtc_state->state);
-       struct intel_crtc_state *intel_cstate =
-               intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc);
-       bool modeset = needs_modeset(&intel_cstate->base);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
+       struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       bool modeset = needs_modeset(&new_crtc_state->base);
 
        /* Perform vblank evasion around commit operation */
-       intel_pipe_update_start(intel_cstate);
+       intel_pipe_update_start(new_crtc_state);
 
        if (modeset)
                goto out;
 
-       if (intel_cstate->base.color_mgmt_changed ||
-           intel_cstate->update_pipe)
-               intel_color_commit(intel_cstate);
+       if (new_crtc_state->base.color_mgmt_changed ||
+           new_crtc_state->update_pipe)
+               intel_color_commit(new_crtc_state);
 
-       if (intel_cstate->update_pipe)
-               intel_update_pipe_config(old_intel_cstate, intel_cstate);
+       if (new_crtc_state->update_pipe)
+               intel_update_pipe_config(old_crtc_state, new_crtc_state);
        else if (INTEL_GEN(dev_priv) >= 9)
-               skl_detach_scalers(intel_cstate);
+               skl_detach_scalers(new_crtc_state);
+
+       if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
+               bdw_set_pipemisc(new_crtc_state);
 
 out:
        if (dev_priv->display.atomic_update_watermarks)
-               dev_priv->display.atomic_update_watermarks(old_intel_state,
-                                                          intel_cstate);
+               dev_priv->display.atomic_update_watermarks(state,
+                                                          new_crtc_state);
 }
 
 void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
@@ -13826,21 +14306,20 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
        }
 }
 
-static void intel_finish_crtc_commit(struct drm_crtc *crtc,
-                                    struct drm_crtc_state *old_crtc_state)
+static void intel_finish_crtc_commit(struct intel_atomic_state *state,
+                                    struct intel_crtc *crtc)
 {
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_atomic_state *old_intel_state =
-               to_intel_atomic_state(old_crtc_state->state);
+       struct intel_crtc_state *old_crtc_state =
+               intel_atomic_get_old_crtc_state(state, crtc);
        struct intel_crtc_state *new_crtc_state =
-               intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc);
+               intel_atomic_get_new_crtc_state(state, crtc);
 
        intel_pipe_update_end(new_crtc_state);
 
        if (new_crtc_state->update_pipe &&
            !needs_modeset(&new_crtc_state->base) &&
-           old_crtc_state->mode.private_flags & I915_MODE_FLAG_INHERITED)
-               intel_crtc_arm_fifo_underrun(intel_crtc, new_crtc_state);
+           old_crtc_state->base.mode.private_flags & I915_MODE_FLAG_INHERITED)
+               intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);
 }
 
 /**
@@ -14039,14 +14518,11 @@ intel_legacy_cursor_update(struct drm_plane *plane,
         */
        crtc_state->active_planes = new_crtc_state->active_planes;
 
-       if (plane->state->visible) {
-               trace_intel_update_plane(plane, to_intel_crtc(crtc));
-               intel_plane->update_plane(intel_plane, crtc_state,
-                                         to_intel_plane_state(plane->state));
-       } else {
-               trace_intel_disable_plane(plane, to_intel_crtc(crtc));
-               intel_plane->disable_plane(intel_plane, crtc_state);
-       }
+       if (plane->state->visible)
+               intel_update_plane(intel_plane, crtc_state,
+                                  to_intel_plane_state(plane->state));
+       else
+               intel_disable_plane(intel_plane, crtc_state);
 
        intel_plane_unpin_fb(to_intel_plane_state(old_plane_state));
 
@@ -14496,7 +14972,12 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
        if (!HAS_DISPLAY(dev_priv))
                return;
 
-       if (IS_ICELAKE(dev_priv)) {
+       if (IS_ELKHARTLAKE(dev_priv)) {
+               intel_ddi_init(dev_priv, PORT_A);
+               intel_ddi_init(dev_priv, PORT_B);
+               intel_ddi_init(dev_priv, PORT_C);
+               icl_dsi_init(dev_priv);
+       } else if (INTEL_GEN(dev_priv) >= 11) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
                intel_ddi_init(dev_priv, PORT_C);
@@ -14758,31 +15239,13 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
        .dirty = intel_user_framebuffer_dirty,
 };
 
-static
-u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv,
-                        u32 pixel_format, u64 fb_modifier)
-{
-       struct intel_crtc *crtc;
-       struct intel_plane *plane;
-
-       /*
-        * We assume the primary plane for pipe A has
-        * the highest stride limits of them all.
-        */
-       crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
-       plane = to_intel_plane(crtc->base.primary);
-
-       return plane->max_stride(plane, pixel_format, fb_modifier,
-                                DRM_MODE_ROTATE_0);
-}
-
 static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
                                  struct drm_i915_gem_object *obj,
                                  struct drm_mode_fb_cmd2 *mode_cmd)
 {
        struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
        struct drm_framebuffer *fb = &intel_fb->base;
-       u32 pitch_limit;
+       u32 max_stride;
        unsigned int tiling, stride;
        int ret = -EINVAL;
        int i;
@@ -14834,13 +15297,13 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
                goto err;
        }
 
-       pitch_limit = intel_fb_pitch_limit(dev_priv, mode_cmd->pixel_format,
-                                          mode_cmd->modifier[0]);
-       if (mode_cmd->pitches[0] > pitch_limit) {
+       max_stride = intel_fb_max_stride(dev_priv, mode_cmd->pixel_format,
+                                        mode_cmd->modifier[0]);
+       if (mode_cmd->pitches[0] > max_stride) {
                DRM_DEBUG_KMS("%s pitch (%u) must be at most %d\n",
                              mode_cmd->modifier[0] != DRM_FORMAT_MOD_LINEAR ?
                              "tiled" : "linear",
-                             mode_cmd->pitches[0], pitch_limit);
+                             mode_cmd->pitches[0], max_stride);
                goto err;
        }
 
@@ -15117,6 +15580,16 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
                dev_priv->display.update_crtcs = intel_update_crtcs;
 }
 
+static i915_reg_t i915_vgacntrl_reg(struct drm_i915_private *dev_priv)
+{
+       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+               return VLV_VGACNTRL;
+       else if (INTEL_GEN(dev_priv) >= 5)
+               return CPU_VGACNTRL;
+       else
+               return VGACNTRL;
+}
+
 /* Disable the VGA plane that we never use */
 static void i915_disable_vga(struct drm_i915_private *dev_priv)
 {
@@ -15354,16 +15827,22 @@ int intel_modeset_init(struct drm_device *dev)
                }
        }
 
-       /* maximum framebuffer dimensions */
-       if (IS_GEN(dev_priv, 2)) {
-               dev->mode_config.max_width = 2048;
-               dev->mode_config.max_height = 2048;
+       /*
+        * Maximum framebuffer dimensions, chosen to match
+        * the maximum render engine surface size on gen4+.
+        */
+       if (INTEL_GEN(dev_priv) >= 7) {
+               dev->mode_config.max_width = 16384;
+               dev->mode_config.max_height = 16384;
+       } else if (INTEL_GEN(dev_priv) >= 4) {
+               dev->mode_config.max_width = 8192;
+               dev->mode_config.max_height = 8192;
        } else if (IS_GEN(dev_priv, 3)) {
                dev->mode_config.max_width = 4096;
                dev->mode_config.max_height = 4096;
        } else {
-               dev->mode_config.max_width = 8192;
-               dev->mode_config.max_height = 8192;
+               dev->mode_config.max_width = 2048;
+               dev->mode_config.max_height = 2048;
        }
 
        if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
@@ -15397,6 +15876,8 @@ int intel_modeset_init(struct drm_device *dev)
        intel_update_czclk(dev_priv);
        intel_modeset_init_hw(dev);
 
+       intel_hdcp_component_init(dev_priv);
+
        if (dev_priv->max_cdclk_freq == 0)
                intel_update_max_cdclk(dev_priv);
 
@@ -15472,7 +15953,7 @@ void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
                      pipe_name(pipe), clock.vco, clock.dot);
 
        fp = i9xx_dpll_compute_fp(&clock);
-       dpll = (I915_READ(DPLL(pipe)) & DPLL_DVO_2X_MODE) |
+       dpll = DPLL_DVO_2X_MODE |
                DPLL_VGA_MODE_DIS |
                ((clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT) |
                PLL_P2_DIVIDE_BY_4 |
@@ -16254,11 +16735,13 @@ void intel_modeset_cleanup(struct drm_device *dev)
        /* flush any delayed tasks or pending work */
        flush_scheduled_work();
 
+       intel_hdcp_component_fini(dev_priv);
+
        drm_mode_config_cleanup(dev);
 
        intel_overlay_cleanup(dev_priv);
 
-       intel_teardown_gmbus(dev_priv);
+       intel_gmbus_teardown(dev_priv);
 
        destroy_workqueue(dev_priv->modeset_wq);
 
@@ -16300,8 +16783,6 @@ struct intel_display_error_state {
 
        u32 power_well_driver;
 
-       int num_transcoders;
-
        struct intel_cursor_error_state {
                u32 control;
                u32 position;
@@ -16326,6 +16807,7 @@ struct intel_display_error_state {
        } plane[I915_MAX_PIPES];
 
        struct intel_transcoder_error_state {
+               bool available;
                bool power_domain_on;
                enum transcoder cpu_transcoder;
 
@@ -16352,6 +16834,8 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
        };
        int i;
 
+       BUILD_BUG_ON(ARRAY_SIZE(transcoders) != ARRAY_SIZE(error->transcoder));
+
        if (!HAS_DISPLAY(dev_priv))
                return NULL;
 
@@ -16392,14 +16876,13 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
                        error->pipe[i].stat = I915_READ(PIPESTAT(i));
        }
 
-       /* Note: this does not include DSI transcoders. */
-       error->num_transcoders = INTEL_INFO(dev_priv)->num_pipes;
-       if (HAS_DDI(dev_priv))
-               error->num_transcoders++; /* Account for eDP. */
-
-       for (i = 0; i < error->num_transcoders; i++) {
+       for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
                enum transcoder cpu_transcoder = transcoders[i];
 
+               if (!INTEL_INFO(dev_priv)->trans_offsets[cpu_transcoder])
+                       continue;
+
+               error->transcoder[i].available = true;
                error->transcoder[i].power_domain_on =
                        __intel_display_power_is_enabled(dev_priv,
                                POWER_DOMAIN_TRANSCODER(cpu_transcoder));
@@ -16463,7 +16946,10 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
                err_printf(m, "  BASE: %08x\n", error->cursor[i].base);
        }
 
-       for (i = 0; i < error->num_transcoders; i++) {
+       for (i = 0; i < ARRAY_SIZE(error->transcoder); i++) {
+               if (!error->transcoder[i].available)
+                       continue;
+
                err_printf(m, "CPU transcoder: %s\n",
                           transcoder_name(error->transcoder[i].cpu_transcoder));
                err_printf(m, "  Power: %s\n",