Merge drm/drm-next into drm-intel-next-queued
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / display / intel_display.c
index b18c5ac..19a4d81 100644 (file)
@@ -47,6 +47,7 @@
 #include "display/intel_ddi.h"
 #include "display/intel_dp.h"
 #include "display/intel_dp_mst.h"
+#include "display/intel_dpll_mgr.h"
 #include "display/intel_dsi.h"
 #include "display/intel_dvo.h"
 #include "display/intel_gmbus.h"
@@ -66,6 +67,7 @@
 #include "intel_bw.h"
 #include "intel_cdclk.h"
 #include "intel_color.h"
+#include "intel_csr.h"
 #include "intel_display_types.h"
 #include "intel_dp_link_training.h"
 #include "intel_fbc.h"
@@ -152,7 +154,7 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc,
 static int intel_framebuffer_init(struct intel_framebuffer *ifb,
                                  struct drm_i915_gem_object *obj,
                                  struct drm_mode_fb_cmd2 *mode_cmd);
-static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state);
+static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state);
 static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state);
 static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state,
                                         const struct intel_link_m_n *m_n,
@@ -1806,6 +1808,17 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc)
 static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       u32 mode_flags = crtc->mode_flags;
+
+       /*
+        * From Gen 11, In case of dsi cmd mode, frame counter wouldnt
+        * have updated at the beginning of TE, if we want to use
+        * the hw counter, then we would find it updated in only
+        * the next TE, hence switching to sw counter.
+        */
+       if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1))
+               return 0;
 
        /*
         * On i965gm the hardware frame counter reads
@@ -1988,13 +2001,17 @@ static int ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane)
        return ccs_plane - fb->format->num_planes / 2;
 }
 
-/* Return either the main plane's CCS or - if not a CCS FB - UV plane */
 int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
 {
+       struct drm_i915_private *i915 = to_i915(fb->dev);
+
        if (is_ccs_modifier(fb->modifier))
                return main_to_ccs_plane(fb, main_plane);
-
-       return 1;
+       else if (INTEL_GEN(i915) < 11 &&
+                intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
+               return 1;
+       else
+               return 0;
 }
 
 bool
@@ -2310,7 +2327,7 @@ err:
 
 void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags)
 {
-       i915_gem_object_lock(vma->obj);
+       i915_gem_object_lock(vma->obj, NULL);
        if (flags & PLANE_HAS_FENCE)
                i915_vma_unpin_fence(vma);
        i915_gem_object_unpin_from_display_plane(vma);
@@ -3432,6 +3449,14 @@ initial_plane_vma(struct drm_i915_private *i915,
        if (IS_ERR(obj))
                return NULL;
 
+       /*
+        * Mark it WT ahead of time to avoid changing the
+        * cache_level during fbdev initialization. The
+        * unbind there would get stuck waiting for rcu.
+        */
+       i915_gem_object_set_cache_coherency(obj, HAS_WT(i915) ?
+                                           I915_CACHE_WT : I915_CACHE_NONE);
+
        switch (plane_config->tiling) {
        case I915_TILING_NONE:
                break;
@@ -3450,7 +3475,7 @@ initial_plane_vma(struct drm_i915_private *i915,
        if (IS_ERR(vma))
                goto err_obj;
 
-       if (i915_ggtt_pin(vma, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base))
+       if (i915_ggtt_pin(vma, NULL, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base))
                goto err_obj;
 
        if (i915_gem_object_is_tiled(obj) &&
@@ -3761,6 +3786,44 @@ static int glk_max_plane_width(const struct drm_framebuffer *fb,
        }
 }
 
+static int icl_min_plane_width(const struct drm_framebuffer *fb)
+{
+       /* Wa_14011264657, Wa_14011050563: gen11+ */
+       switch (fb->format->format) {
+       case DRM_FORMAT_C8:
+               return 18;
+       case DRM_FORMAT_RGB565:
+               return 10;
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_XBGR8888:
+       case DRM_FORMAT_ARGB8888:
+       case DRM_FORMAT_ABGR8888:
+       case DRM_FORMAT_XRGB2101010:
+       case DRM_FORMAT_XBGR2101010:
+       case DRM_FORMAT_ARGB2101010:
+       case DRM_FORMAT_ABGR2101010:
+       case DRM_FORMAT_XVYU2101010:
+       case DRM_FORMAT_Y212:
+       case DRM_FORMAT_Y216:
+               return 6;
+       case DRM_FORMAT_NV12:
+               return 20;
+       case DRM_FORMAT_P010:
+       case DRM_FORMAT_P012:
+       case DRM_FORMAT_P016:
+               return 12;
+       case DRM_FORMAT_XRGB16161616F:
+       case DRM_FORMAT_XBGR16161616F:
+       case DRM_FORMAT_ARGB16161616F:
+       case DRM_FORMAT_ABGR16161616F:
+       case DRM_FORMAT_XVYU12_16161616:
+       case DRM_FORMAT_XVYU16161616:
+               return 4;
+       default:
+               return 1;
+       }
+}
+
 static int icl_max_plane_width(const struct drm_framebuffer *fb,
                               int color_plane,
                               unsigned int rotation)
@@ -3843,29 +3906,31 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
        int y = plane_state->uapi.src.y1 >> 16;
        int w = drm_rect_width(&plane_state->uapi.src) >> 16;
        int h = drm_rect_height(&plane_state->uapi.src) >> 16;
-       int max_width;
-       int max_height;
-       u32 alignment;
-       u32 offset;
+       int max_width, min_width, max_height;
+       u32 alignment, offset;
        int aux_plane = intel_main_to_aux_plane(fb, 0);
        u32 aux_offset = plane_state->color_plane[aux_plane].offset;
 
-       if (INTEL_GEN(dev_priv) >= 11)
+       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))
+               min_width = icl_min_plane_width(fb);
+       } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
                max_width = glk_max_plane_width(fb, 0, rotation);
-       else
+               min_width = 1;
+       } else {
                max_width = skl_max_plane_width(fb, 0, rotation);
+               min_width = 1;
+       }
 
        if (INTEL_GEN(dev_priv) >= 11)
                max_height = icl_max_plane_height();
        else
                max_height = skl_max_plane_height();
 
-       if (w > max_width || h > max_height) {
+       if (w > max_width || w < min_width || h > max_height) {
                drm_dbg_kms(&dev_priv->drm,
-                           "requested Y/RGB source size %dx%d too big (limit %dx%d)\n",
-                           w, h, max_width, max_height);
+                           "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n",
+                           w, h, min_width, max_width, max_height);
                return -EINVAL;
        }
 
@@ -3880,7 +3945,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
         * main surface offset, and it must be non-negative. Make
         * sure that is what we will get.
         */
-       if (offset > aux_offset)
+       if (aux_plane && offset > aux_offset)
                offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
                                                           offset, aux_offset & ~(alignment - 1));
 
@@ -3969,8 +4034,8 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
 
        if (is_ccs_modifier(fb->modifier)) {
                int ccs_plane = main_to_ccs_plane(fb, uv_plane);
-               int aux_offset = plane_state->color_plane[ccs_plane].offset;
-               int alignment = intel_surf_alignment(fb, uv_plane);
+               u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
+               u32 alignment = intel_surf_alignment(fb, uv_plane);
 
                if (offset > aux_offset)
                        offset = intel_plane_adjust_aligned_offset(&x, &y,
@@ -4051,8 +4116,7 @@ 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->hw.fb;
-       int ret;
-       bool needs_aux = false;
+       int ret, i;
 
        ret = intel_plane_compute_gtt(plane_state);
        if (ret)
@@ -4066,7 +4130,6 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
         * it.
         */
        if (is_ccs_modifier(fb->modifier)) {
-               needs_aux = true;
                ret = skl_check_ccs_aux_surface(plane_state);
                if (ret)
                        return ret;
@@ -4074,20 +4137,15 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
 
        if (intel_format_info_is_yuv_semiplanar(fb->format,
                                                fb->modifier)) {
-               needs_aux = true;
                ret = skl_check_nv12_aux_surface(plane_state);
                if (ret)
                        return ret;
        }
 
-       if (!needs_aux) {
-               int i;
-
-               for (i = 1; i < fb->format->num_planes; i++) {
-                       plane_state->color_plane[i].offset = ~0xfff;
-                       plane_state->color_plane[i].x = 0;
-                       plane_state->color_plane[i].y = 0;
-               }
+       for (i = fb->format->num_planes; i < ARRAY_SIZE(plane_state->color_plane); i++) {
+               plane_state->color_plane[i].offset = 0;
+               plane_state->color_plane[i].x = 0;
+               plane_state->color_plane[i].y = 0;
        }
 
        ret = skl_check_main_surface(plane_state);
@@ -4743,6 +4801,9 @@ u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
        struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
        u32 plane_ctl = 0;
 
+       if (crtc_state->uapi.async_flip)
+               plane_ctl |= PLANE_CTL_ASYNC_FLIP;
+
        if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return plane_ctl;
 
@@ -4980,18 +5041,14 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
                intel_pps_unlock_regs_wa(dev_priv);
                intel_modeset_init_hw(dev_priv);
                intel_init_clock_gating(dev_priv);
-
-               spin_lock_irq(&dev_priv->irq_lock);
-               if (dev_priv->display.hpd_irq_setup)
-                       dev_priv->display.hpd_irq_setup(dev_priv);
-               spin_unlock_irq(&dev_priv->irq_lock);
+               intel_hpd_init(dev_priv);
 
                ret = __intel_display_resume(dev, state, ctx);
                if (ret)
                        drm_err(&dev_priv->drm,
                                "Restoring old state failed with %i\n", ret);
 
-               intel_hpd_init(dev_priv);
+               intel_hpd_poll_disable(dev_priv);
        }
 
        drm_atomic_state_put(state);
@@ -6232,6 +6289,105 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
                skl_detach_scaler(crtc, i);
 }
 
+static int cnl_coef_tap(int i)
+{
+       return i % 7;
+}
+
+static u16 cnl_nearest_filter_coef(int t)
+{
+       return t == 3 ? 0x0800 : 0x3000;
+}
+
+/*
+ *  Theory behind setting nearest-neighbor integer scaling:
+ *
+ *  17 phase of 7 taps requires 119 coefficients in 60 dwords per set.
+ *  The letter represents the filter tap (D is the center tap) and the number
+ *  represents the coefficient set for a phase (0-16).
+ *
+ *         +------------+------------------------+------------------------+
+ *         |Index value | Data value coeffient 1 | Data value coeffient 2 |
+ *         +------------+------------------------+------------------------+
+ *         |   00h      |          B0            |          A0            |
+ *         +------------+------------------------+------------------------+
+ *         |   01h      |          D0            |          C0            |
+ *         +------------+------------------------+------------------------+
+ *         |   02h      |          F0            |          E0            |
+ *         +------------+------------------------+------------------------+
+ *         |   03h      |          A1            |          G0            |
+ *         +------------+------------------------+------------------------+
+ *         |   04h      |          C1            |          B1            |
+ *         +------------+------------------------+------------------------+
+ *         |   ...      |          ...           |          ...           |
+ *         +------------+------------------------+------------------------+
+ *         |   38h      |          B16           |          A16           |
+ *         +------------+------------------------+------------------------+
+ *         |   39h      |          D16           |          C16           |
+ *         +------------+------------------------+------------------------+
+ *         |   3Ah      |          F16           |          C16           |
+ *         +------------+------------------------+------------------------+
+ *         |   3Bh      |        Reserved        |          G16           |
+ *         +------------+------------------------+------------------------+
+ *
+ *  To enable nearest-neighbor scaling:  program scaler coefficents with
+ *  the center tap (Dxx) values set to 1 and all other values set to 0 as per
+ *  SCALER_COEFFICIENT_FORMAT
+ *
+ */
+
+static void cnl_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
+                                            enum pipe pipe, int id, int set)
+{
+       int i;
+
+       intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set),
+                         PS_COEE_INDEX_AUTO_INC);
+
+       for (i = 0; i < 17 * 7; i += 2) {
+               u32 tmp;
+               int t;
+
+               t = cnl_coef_tap(i);
+               tmp = cnl_nearest_filter_coef(t);
+
+               t = cnl_coef_tap(i + 1);
+               tmp |= cnl_nearest_filter_coef(t) << 16;
+
+               intel_de_write_fw(dev_priv, CNL_PS_COEF_DATA_SET(pipe, id, set),
+                                 tmp);
+       }
+
+       intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set), 0);
+}
+
+inline u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set)
+{
+       if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) {
+               return (PS_FILTER_PROGRAMMED |
+                       PS_Y_VERT_FILTER_SELECT(set) |
+                       PS_Y_HORZ_FILTER_SELECT(set) |
+                       PS_UV_VERT_FILTER_SELECT(set) |
+                       PS_UV_HORZ_FILTER_SELECT(set));
+       }
+
+       return PS_FILTER_MEDIUM;
+}
+
+void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
+                            int id, int set, enum drm_scaling_filter filter)
+{
+       switch (filter) {
+       case DRM_SCALING_FILTER_DEFAULT:
+               break;
+       case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
+               cnl_program_nearest_filter_coefs(dev_priv, pipe, id, set);
+               break;
+       default:
+               MISSING_CASE(filter);
+       }
+}
+
 static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -6252,6 +6408,7 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
        int hscale, vscale;
        unsigned long irqflags;
        int id;
+       u32 ps_ctrl;
 
        if (!crtc_state->pch_pfit.enabled)
                return;
@@ -6268,10 +6425,16 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
 
        id = scaler_state->scaler_id;
 
+       ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
+       ps_ctrl |=  PS_SCALER_EN | scaler_state->scalers[id].mode;
+
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
-       intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
-                         PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
+       skl_scaler_setup_filter(dev_priv, pipe, id, 0,
+                               crtc_state->hw.scaling_filter);
+
+       intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), ps_ctrl);
+
        intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, id),
                          PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase));
        intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, id),
@@ -6517,6 +6680,43 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
                icl_wa_scalerclkgating(dev_priv, pipe, false);
 }
 
+static void skl_disable_async_flip_wa(struct intel_atomic_state *state,
+                                     struct intel_crtc *crtc,
+                                     const struct intel_crtc_state *new_crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+       struct intel_plane *plane;
+       struct intel_plane_state *new_plane_state;
+       int i;
+
+       for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
+               u32 update_mask = new_crtc_state->update_planes;
+               u32 plane_ctl, surf_addr;
+               enum plane_id plane_id;
+               unsigned long irqflags;
+               enum pipe pipe;
+
+               if (crtc->pipe != plane->pipe ||
+                   !(update_mask & BIT(plane->id)))
+                       continue;
+
+               plane_id = plane->id;
+               pipe = plane->pipe;
+
+               spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+               plane_ctl = intel_de_read_fw(dev_priv, PLANE_CTL(pipe, plane_id));
+               surf_addr = intel_de_read_fw(dev_priv, PLANE_SURF(pipe, plane_id));
+
+               plane_ctl &= ~PLANE_CTL_ASYNC_FLIP;
+
+               intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl);
+               intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), surf_addr);
+               spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+       }
+
+       intel_wait_for_vblank(dev_priv, crtc->pipe);
+}
+
 static void intel_pre_plane_update(struct intel_atomic_state *state,
                                   struct intel_crtc *crtc)
 {
@@ -6602,6 +6802,15 @@ static void intel_pre_plane_update(struct intel_atomic_state *state,
         */
        if (IS_GEN(dev_priv, 2) && planes_disabling(old_crtc_state, new_crtc_state))
                intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
+
+       /*
+        * WA for platforms where async address update enable bit
+        * is double buffered and only latched at start of vblank.
+        */
+       if (old_crtc_state->uapi.async_flip &&
+           !new_crtc_state->uapi.async_flip &&
+           IS_GEN_RANGE(dev_priv, 9, 10))
+               skl_disable_async_flip_wa(state, crtc, new_crtc_state);
 }
 
 static void intel_crtc_disable_planes(struct intel_atomic_state *state,
@@ -6901,7 +7110,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state,
        if (intel_crtc_has_dp_encoder(new_crtc_state))
                intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(new_crtc_state);
+       intel_set_transcoder_timings(new_crtc_state);
        intel_set_pipe_src_size(new_crtc_state);
 
        if (new_crtc_state->has_pch_encoder)
@@ -7046,7 +7255,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state,
        intel_encoders_pre_enable(state, crtc);
 
        if (!transcoder_is_dsi(cpu_transcoder))
-               intel_set_pipe_timings(new_crtc_state);
+               intel_set_transcoder_timings(new_crtc_state);
 
        intel_set_pipe_src_size(new_crtc_state);
 
@@ -7232,7 +7441,7 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy)
                return false;
        else if (IS_ROCKETLAKE(dev_priv))
                return phy <= PHY_D;
-       else if (IS_ELKHARTLAKE(dev_priv))
+       else if (IS_JSL_EHL(dev_priv))
                return phy <= PHY_C;
        else if (INTEL_GEN(dev_priv) >= 11)
                return phy <= PHY_B;
@@ -7246,7 +7455,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
                return false;
        else if (INTEL_GEN(dev_priv) >= 12)
                return phy >= PHY_D && phy <= PHY_I;
-       else if (INTEL_GEN(dev_priv) >= 11 && !IS_ELKHARTLAKE(dev_priv))
+       else if (INTEL_GEN(dev_priv) >= 11 && !IS_JSL_EHL(dev_priv))
                return phy >= PHY_C && phy <= PHY_F;
        else
                return false;
@@ -7254,23 +7463,23 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy)
 
 enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port)
 {
-       if (IS_ROCKETLAKE(i915) && port >= PORT_D)
-               return (enum phy)port - 1;
-       else if (IS_ELKHARTLAKE(i915) && port == PORT_D)
+       if (IS_ROCKETLAKE(i915) && port >= PORT_TC1)
+               return PHY_C + port - PORT_TC1;
+       else if (IS_JSL_EHL(i915) && port == PORT_D)
                return PHY_A;
 
-       return (enum phy)port;
+       return PHY_A + port - PORT_A;
 }
 
 enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port)
 {
        if (!intel_phy_is_tc(dev_priv, intel_port_to_phy(dev_priv, port)))
-               return PORT_TC_NONE;
+               return TC_PORT_NONE;
 
        if (INTEL_GEN(dev_priv) >= 12)
-               return port - PORT_D;
-
-       return port - PORT_C;
+               return TC_PORT_1 + port - PORT_TC1;
+       else
+               return TC_PORT_1 + port - PORT_C;
 }
 
 enum intel_display_power_domain intel_port_to_power_domain(enum port port)
@@ -7290,6 +7499,10 @@ enum intel_display_power_domain intel_port_to_power_domain(enum port port)
                return POWER_DOMAIN_PORT_DDI_F_LANES;
        case PORT_G:
                return POWER_DOMAIN_PORT_DDI_G_LANES;
+       case PORT_H:
+               return POWER_DOMAIN_PORT_DDI_H_LANES;
+       case PORT_I:
+               return POWER_DOMAIN_PORT_DDI_I_LANES;
        default:
                MISSING_CASE(port);
                return POWER_DOMAIN_PORT_OTHER;
@@ -7315,6 +7528,10 @@ intel_aux_power_domain(struct intel_digital_port *dig_port)
                        return POWER_DOMAIN_AUX_F_TBT;
                case AUX_CH_G:
                        return POWER_DOMAIN_AUX_G_TBT;
+               case AUX_CH_H:
+                       return POWER_DOMAIN_AUX_H_TBT;
+               case AUX_CH_I:
+                       return POWER_DOMAIN_AUX_I_TBT;
                default:
                        MISSING_CASE(dig_port->aux_ch);
                        return POWER_DOMAIN_AUX_C_TBT;
@@ -7346,6 +7563,10 @@ intel_legacy_aux_to_power_domain(enum aux_ch aux_ch)
                return POWER_DOMAIN_AUX_F;
        case AUX_CH_G:
                return POWER_DOMAIN_AUX_G;
+       case AUX_CH_H:
+               return POWER_DOMAIN_AUX_H;
+       case AUX_CH_I:
+               return POWER_DOMAIN_AUX_I;
        default:
                MISSING_CASE(aux_ch);
                return POWER_DOMAIN_AUX_A;
@@ -7429,7 +7650,7 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state,
        if (intel_crtc_has_dp_encoder(new_crtc_state))
                intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(new_crtc_state);
+       intel_set_transcoder_timings(new_crtc_state);
        intel_set_pipe_src_size(new_crtc_state);
 
        if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
@@ -7497,7 +7718,7 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state,
        if (intel_crtc_has_dp_encoder(new_crtc_state))
                intel_dp_set_m_n(new_crtc_state, M1_N1);
 
-       intel_set_pipe_timings(new_crtc_state);
+       intel_set_transcoder_timings(new_crtc_state);
        intel_set_pipe_src_size(new_crtc_state);
 
        i9xx_set_pipeconf(new_crtc_state);
@@ -8114,7 +8335,7 @@ static void compute_m_n(unsigned int m, unsigned int n,
         * which the devices expect also in synchronous clock mode.
         */
        if (constant_n)
-               *ret_n = 0x8000;
+               *ret_n = DP_LINK_CONSTANT_N_VALUE;
        else
                *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
 
@@ -8751,7 +8972,7 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc,
        crtc_state->dpll_hw_state.dpll = dpll;
 }
 
-static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state)
+static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
@@ -8837,8 +9058,8 @@ static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state)
                return intel_de_read(dev_priv, PIPECONF(cpu_transcoder)) & PIPECONF_INTERLACE_MASK;
 }
 
-static void intel_get_pipe_timings(struct intel_crtc *crtc,
-                                  struct intel_crtc_state *pipe_config)
+static void intel_get_transcoder_timings(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);
@@ -9461,7 +9682,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        if (INTEL_GEN(dev_priv) < 4)
                pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
 
-       intel_get_pipe_timings(crtc, pipe_config);
+       intel_get_transcoder_timings(crtc, pipe_config);
        intel_get_pipe_src_size(crtc, pipe_config);
 
        i9xx_get_pfit_config(pipe_config);
@@ -10581,6 +10802,10 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
            val & PLANE_CTL_FLIP_HORIZONTAL)
                plane_config->rotation |= DRM_MODE_REFLECT_X;
 
+       /* 90/270 degree rotation would require extra work */
+       if (drm_rotation_90_or_270(plane_config->rotation))
+               goto error;
+
        base = intel_de_read(dev_priv, PLANE_SURF(pipe, plane_id)) & 0xfffff000;
        plane_config->base = base;
 
@@ -10742,7 +10967,7 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->pixel_multiplier = 1;
        }
 
-       intel_get_pipe_timings(crtc, pipe_config);
+       intel_get_transcoder_timings(crtc, pipe_config);
        intel_get_pipe_src_size(crtc, pipe_config);
 
        ilk_get_pfit_config(pipe_config);
@@ -10802,9 +11027,18 @@ static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port,
        u32 temp;
 
        if (intel_phy_is_combo(dev_priv, phy)) {
-               temp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0) &
-                       ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
-               id = temp >> ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy);
+               u32 mask, shift;
+
+               if (IS_ROCKETLAKE(dev_priv)) {
+                       mask = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
+                       shift = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy);
+               } else {
+                       mask = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
+                       shift = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy);
+               }
+
+               temp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0) & mask;
+               id = temp >> shift;
                port_dpll_id = ICL_PORT_DPLL_DEFAULT;
        } else if (intel_phy_is_tc(dev_priv, phy)) {
                u32 clk_sel = intel_de_read(dev_priv, DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK;
@@ -11150,7 +11384,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
        if (!transcoder_is_dsi(pipe_config->cpu_transcoder) ||
            INTEL_GEN(dev_priv) >= 11) {
                hsw_get_ddi_port_state(crtc, pipe_config);
-               intel_get_pipe_timings(crtc, pipe_config);
+               intel_get_transcoder_timings(crtc, pipe_config);
        }
 
        intel_get_pipe_src_size(crtc, pipe_config);
@@ -11166,18 +11400,6 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
        } else {
                pipe_config->output_format =
                        bdw_get_pipemisc_output_format(crtc);
-
-               /*
-                * Currently there is no interface defined to
-                * check user preference between RGB/YCBCR444
-                * or YCBCR420. So the only possible case for
-                * YCBCR444 usage is driving YCBCR420 output
-                * with LSPCON, when pipe is configured for
-                * YCBCR444 output and LSPCON takes care of
-                * downsampling it.
-                */
-               pipe_config->lspcon_downsampling =
-                       pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR444;
        }
 
        pipe_config->gamma_mode = intel_de_read(dev_priv,
@@ -11749,6 +11971,9 @@ static void i9xx_update_cursor(struct intel_plane *plane,
        if (INTEL_GEN(dev_priv) >= 9)
                skl_write_cursor_wm(plane, crtc_state);
 
+       if (!needs_modeset(crtc_state))
+               intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, 0);
+
        if (plane->cursor.base != base ||
            plane->cursor.size != fbc_ctl ||
            plane->cursor.cntl != cntl) {
@@ -12760,6 +12985,12 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
 
        }
 
+       if (!mode_changed) {
+               ret = intel_psr2_sel_fetch_update(state, crtc);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -13031,6 +13262,9 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                    transcoder_name(pipe_config->cpu_transcoder),
                    pipe_config->pipe_bpp, pipe_config->dither);
 
+       drm_dbg_kms(&dev_priv->drm, "MST master transcoder: %s\n",
+                   transcoder_name(pipe_config->mst_master_transcoder));
+
        drm_dbg_kms(&dev_priv->drm,
                    "port sync: master transcoder: %s, slave transcoder bitmask = 0x%x\n",
                    transcoder_name(pipe_config->master_transcoder),
@@ -13128,8 +13362,11 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config,
                            pipe_config->csc_mode, pipe_config->gamma_mode,
                            pipe_config->gamma_enable, pipe_config->csc_enable);
 
-       drm_dbg_kms(&dev_priv->drm, "MST master transcoder: %s\n",
-                   transcoder_name(pipe_config->mst_master_transcoder));
+       drm_dbg_kms(&dev_priv->drm, "degamma lut: %d entries, gamma lut: %d entries\n",
+                   pipe_config->hw.degamma_lut ?
+                   drm_color_lut_size(pipe_config->hw.degamma_lut) : 0,
+                   pipe_config->hw.gamma_lut ?
+                   drm_color_lut_size(pipe_config->hw.gamma_lut) : 0);
 
 dump_planes:
        if (!state)
@@ -13223,6 +13460,7 @@ intel_crtc_copy_uapi_to_hw_state(struct intel_crtc_state *crtc_state)
        crtc_state->hw.active = crtc_state->uapi.active;
        crtc_state->hw.mode = crtc_state->uapi.mode;
        crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode;
+       crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter;
        intel_crtc_copy_uapi_to_hw_state_nomodeset(crtc_state);
 }
 
@@ -13234,6 +13472,7 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
                    drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0);
 
        crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
+       crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
 
        /* copy color blobs to uapi */
        drm_property_replace_blob(&crtc_state->uapi.degamma_lut,
@@ -13418,12 +13657,6 @@ encoder_retry:
                    "hw max bpp: %i, pipe bpp: %i, dithering: %i\n",
                    base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
 
-       /*
-        * Make drm_calc_timestamping_constants in
-        * drm_atomic_helper_update_legacy_modeset_state() happy
-        */
-       pipe_config->uapi.adjusted_mode = pipe_config->hw.adjusted_mode;
-
        return 0;
 }
 
@@ -14244,7 +14477,6 @@ verify_crtc_state(struct intel_crtc *crtc,
        struct intel_encoder *encoder;
        struct intel_crtc_state *pipe_config = old_crtc_state;
        struct drm_atomic_state *state = old_crtc_state->uapi.state;
-       bool active;
 
        __drm_atomic_helper_crtc_destroy_state(&old_crtc_state->uapi);
        intel_crtc_free_hw_state(old_crtc_state);
@@ -14254,16 +14486,19 @@ verify_crtc_state(struct intel_crtc *crtc,
        drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s]\n", crtc->base.base.id,
                    crtc->base.name);
 
-       active = dev_priv->display.get_pipe_config(crtc, pipe_config);
+       pipe_config->hw.enable = new_crtc_state->hw.enable;
+
+       pipe_config->hw.active =
+               dev_priv->display.get_pipe_config(crtc, pipe_config);
 
        /* we keep both pipes enabled on 830 */
-       if (IS_I830(dev_priv))
-               active = new_crtc_state->hw.active;
+       if (IS_I830(dev_priv) && pipe_config->hw.active)
+               pipe_config->hw.active = new_crtc_state->hw.active;
 
-       I915_STATE_WARN(new_crtc_state->hw.active != active,
+       I915_STATE_WARN(new_crtc_state->hw.active != pipe_config->hw.active,
                        "crtc active state doesn't match with hw state "
                        "(expected %i, found %i)\n",
-                       new_crtc_state->hw.active, active);
+                       new_crtc_state->hw.active, pipe_config->hw.active);
 
        I915_STATE_WARN(crtc->active != new_crtc_state->hw.active,
                        "transitional active state does not match atomic hw state "
@@ -14272,6 +14507,7 @@ verify_crtc_state(struct intel_crtc *crtc,
 
        for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
                enum pipe pipe;
+               bool active;
 
                active = encoder->get_hw_state(encoder, &pipe);
                I915_STATE_WARN(active != new_crtc_state->hw.active,
@@ -14583,16 +14819,8 @@ u8 intel_calc_active_pipes(struct intel_atomic_state *state,
 static int intel_modeset_checks(struct intel_atomic_state *state)
 {
        struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       int ret;
 
        state->modeset = true;
-       state->active_pipes = intel_calc_active_pipes(state, dev_priv->active_pipes);
-
-       if (state->active_pipes != dev_priv->active_pipes) {
-               ret = _intel_atomic_lock_global_state(state);
-               if (ret)
-                       return ret;
-       }
 
        if (IS_HASWELL(dev_priv))
                return hsw_mode_set_planes_workaround(state);
@@ -14736,7 +14964,8 @@ static int intel_atomic_check_cdclk(struct intel_atomic_state *state,
                                    bool *need_cdclk_calc)
 {
        struct drm_i915_private *dev_priv = to_i915(state->base.dev);
-       struct intel_cdclk_state *new_cdclk_state;
+       const struct intel_cdclk_state *old_cdclk_state;
+       const struct intel_cdclk_state *new_cdclk_state;
        struct intel_plane_state *plane_state;
        struct intel_bw_state *new_bw_state;
        struct intel_plane *plane;
@@ -14755,9 +14984,11 @@ static int intel_atomic_check_cdclk(struct intel_atomic_state *state,
                        return ret;
        }
 
+       old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
        new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
 
-       if (new_cdclk_state && new_cdclk_state->force_min_cdclk_changed)
+       if (new_cdclk_state &&
+           old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk)
                *need_cdclk_calc = true;
 
        ret = dev_priv->display.bw_calc_min_cdclk(state);
@@ -14789,8 +15020,10 @@ static int intel_atomic_check_crtcs(struct intel_atomic_state *state)
        int i;
 
        for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
-               int ret = intel_crtc_atomic_check(state, crtc);
                struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+               int ret;
+
+               ret = intel_crtc_atomic_check(state, crtc);
                if (ret) {
                        drm_dbg_atomic(&i915->drm,
                                       "[CRTC:%d:%s] atomic driver check failed\n",
@@ -14819,6 +15052,139 @@ static bool intel_cpu_transcoders_need_modeset(struct intel_atomic_state *state,
        return false;
 }
 
+/**
+ * DOC: asynchronous flip implementation
+ *
+ * Asynchronous page flip is the implementation for the DRM_MODE_PAGE_FLIP_ASYNC
+ * flag. Currently async flip is only supported via the drmModePageFlip IOCTL.
+ * Correspondingly, support is currently added for primary plane only.
+ *
+ * Async flip can only change the plane surface address, so anything else
+ * changing is rejected from the intel_atomic_check_async() function.
+ * Once this check is cleared, flip done interrupt is enabled using
+ * the skl_enable_flip_done() function.
+ *
+ * As soon as the surface address register is written, flip done interrupt is
+ * generated and the requested events are sent to the usersapce in the interrupt
+ * handler itself. The timestamp and sequence sent during the flip done event
+ * correspond to the last vblank and have no relation to the actual time when
+ * the flip done event was sent.
+ */
+static int intel_atomic_check_async(struct intel_atomic_state *state)
+{
+       struct drm_i915_private *i915 = to_i915(state->base.dev);
+       const struct intel_crtc_state *old_crtc_state, *new_crtc_state;
+       const struct intel_plane_state *new_plane_state, *old_plane_state;
+       struct intel_crtc *crtc;
+       struct intel_plane *plane;
+       int i;
+
+       for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
+                                           new_crtc_state, i) {
+               if (needs_modeset(new_crtc_state)) {
+                       drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n");
+                       return -EINVAL;
+               }
+
+               if (!new_crtc_state->hw.active) {
+                       drm_dbg_kms(&i915->drm, "CRTC inactive\n");
+                       return -EINVAL;
+               }
+               if (old_crtc_state->active_planes != new_crtc_state->active_planes) {
+                       drm_dbg_kms(&i915->drm,
+                                   "Active planes cannot be changed during async flip\n");
+                       return -EINVAL;
+               }
+       }
+
+       for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state,
+                                            new_plane_state, i) {
+               /*
+                * TODO: Async flip is only supported through the page flip IOCTL
+                * as of now. So support currently added for primary plane only.
+                * Support for other planes on platforms on which supports
+                * this(vlv/chv and icl+) should be added when async flip is
+                * enabled in the atomic IOCTL path.
+                */
+               if (plane->id != PLANE_PRIMARY)
+                       return -EINVAL;
+
+               /*
+                * FIXME: This check is kept generic for all platforms.
+                * Need to verify this for all gen9 and gen10 platforms to enable
+                * this selectively if required.
+                */
+               switch (new_plane_state->hw.fb->modifier) {
+               case I915_FORMAT_MOD_X_TILED:
+               case I915_FORMAT_MOD_Y_TILED:
+               case I915_FORMAT_MOD_Yf_TILED:
+                       break;
+               default:
+                       drm_dbg_kms(&i915->drm,
+                                   "Linear memory/CCS does not support async flips\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->color_plane[0].stride !=
+                   new_plane_state->color_plane[0].stride) {
+                       drm_dbg_kms(&i915->drm, "Stride cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->hw.fb->modifier !=
+                   new_plane_state->hw.fb->modifier) {
+                       drm_dbg_kms(&i915->drm,
+                                   "Framebuffer modifiers cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->hw.fb->format !=
+                   new_plane_state->hw.fb->format) {
+                       drm_dbg_kms(&i915->drm,
+                                   "Framebuffer format cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->hw.rotation !=
+                   new_plane_state->hw.rotation) {
+                       drm_dbg_kms(&i915->drm, "Rotation cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (!drm_rect_equals(&old_plane_state->uapi.src, &new_plane_state->uapi.src) ||
+                   !drm_rect_equals(&old_plane_state->uapi.dst, &new_plane_state->uapi.dst)) {
+                       drm_dbg_kms(&i915->drm,
+                                   "Plane size/co-ordinates cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->hw.alpha != new_plane_state->hw.alpha) {
+                       drm_dbg_kms(&i915->drm, "Alpha value cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->hw.pixel_blend_mode !=
+                   new_plane_state->hw.pixel_blend_mode) {
+                       drm_dbg_kms(&i915->drm,
+                                   "Pixel blend mode cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->hw.color_encoding != new_plane_state->hw.color_encoding) {
+                       drm_dbg_kms(&i915->drm,
+                                   "Color encoding cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+
+               if (old_plane_state->hw.color_range != new_plane_state->hw.color_range) {
+                       drm_dbg_kms(&i915->drm, "Color range cannot be changed in async flip\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 /**
  * intel_atomic_check - validate state object
  * @dev: drm device
@@ -14987,6 +15353,12 @@ static int intel_atomic_check(struct drm_device *dev,
 
        for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
                                            new_crtc_state, i) {
+               if (new_crtc_state->uapi.async_flip) {
+                       ret = intel_atomic_check_async(state);
+                       if (ret)
+                               goto fail;
+               }
+
                if (!needs_modeset(new_crtc_state) &&
                    !new_crtc_state->update_pipe)
                        continue;
@@ -15134,6 +15506,8 @@ static void commit_pipe_config(struct intel_atomic_state *state,
 
                if (new_crtc_state->update_pipe)
                        intel_pipe_fastset(old_crtc_state, new_crtc_state);
+
+               intel_psr2_program_trans_man_trk_ctl(new_crtc_state);
        }
 
        if (dev_priv->display.atomic_update_watermarks)
@@ -15550,6 +15924,11 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
 
        intel_dbuf_pre_plane_update(state);
 
+       for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+               if (new_crtc_state->uapi.async_flip)
+                       skl_enable_flip_done(crtc);
+       }
+
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
        dev_priv->display.commit_modeset_enables(state);
 
@@ -15571,6 +15950,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
        drm_atomic_helper_wait_for_flip_done(dev, &state->base);
 
        for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
+               if (new_crtc_state->uapi.async_flip)
+                       skl_disable_flip_done(crtc);
+
                if (new_crtc_state->hw.active &&
                    !needs_modeset(new_crtc_state) &&
                    !new_crtc_state->preload_luts &&
@@ -15702,14 +16084,6 @@ static void intel_atomic_track_fbs(struct intel_atomic_state *state)
                                        plane->frontbuffer_bit);
 }
 
-static void assert_global_state_locked(struct drm_i915_private *dev_priv)
-{
-       struct intel_crtc *crtc;
-
-       for_each_intel_crtc(&dev_priv->drm, crtc)
-               drm_modeset_lock_assert_held(&crtc->base.mutex);
-}
-
 static int intel_atomic_commit(struct drm_device *dev,
                               struct drm_atomic_state *_state,
                               bool nonblock)
@@ -15785,12 +16159,6 @@ static int intel_atomic_commit(struct drm_device *dev,
        intel_shared_dpll_swap_state(state);
        intel_atomic_track_fbs(state);
 
-       if (state->global_state_changed) {
-               assert_global_state_locked(dev_priv);
-
-               dev_priv->active_pipes = state->active_pipes;
-       }
-
        drm_atomic_state_get(&state->base);
        INIT_WORK(&state->base.commit_work, intel_atomic_commit_work);
 
@@ -16699,6 +17067,11 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
                dev_priv->plane_to_crtc_mapping[i9xx_plane] = crtc;
        }
 
+       if (INTEL_GEN(dev_priv) >= 10)
+               drm_crtc_create_scaling_filter_property(&crtc->base,
+                                               BIT(DRM_SCALING_FILTER_DEFAULT) |
+                                               BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
+
        intel_color_init(crtc);
 
        intel_crtc_crc_init(crtc);
@@ -16837,25 +17210,25 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 
        intel_pps_init(dev_priv);
 
-       if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv))
+       if (!HAS_DISPLAY(dev_priv))
                return;
 
        if (IS_ROCKETLAKE(dev_priv)) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
-               intel_ddi_init(dev_priv, PORT_D);       /* DDI TC1 */
-               intel_ddi_init(dev_priv, PORT_E);       /* DDI TC2 */
+               intel_ddi_init(dev_priv, PORT_TC1);
+               intel_ddi_init(dev_priv, PORT_TC2);
        } else if (INTEL_GEN(dev_priv) >= 12) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
-               intel_ddi_init(dev_priv, PORT_D);
-               intel_ddi_init(dev_priv, PORT_E);
-               intel_ddi_init(dev_priv, PORT_F);
-               intel_ddi_init(dev_priv, PORT_G);
-               intel_ddi_init(dev_priv, PORT_H);
-               intel_ddi_init(dev_priv, PORT_I);
+               intel_ddi_init(dev_priv, PORT_TC1);
+               intel_ddi_init(dev_priv, PORT_TC2);
+               intel_ddi_init(dev_priv, PORT_TC3);
+               intel_ddi_init(dev_priv, PORT_TC4);
+               intel_ddi_init(dev_priv, PORT_TC5);
+               intel_ddi_init(dev_priv, PORT_TC6);
                icl_dsi_init(dev_priv);
-       } else if (IS_ELKHARTLAKE(dev_priv)) {
+       } else if (IS_JSL_EHL(dev_priv)) {
                intel_ddi_init(dev_priv, PORT_A);
                intel_ddi_init(dev_priv, PORT_B);
                intel_ddi_init(dev_priv, PORT_C);
@@ -17137,7 +17510,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
        if (!intel_fb->frontbuffer)
                return -ENOMEM;
 
-       i915_gem_object_lock(obj);
+       i915_gem_object_lock(obj, NULL);
        tiling = i915_gem_object_get_tiling(obj);
        stride = i915_gem_object_get_stride(obj);
        i915_gem_object_unlock(obj);
@@ -17690,6 +18063,8 @@ retry:
                }
 
                if (crtc_state->hw.active) {
+                       struct intel_encoder *encoder;
+
                        /*
                         * We've not yet detected sink capabilities
                         * (audio,infoframes,etc.) and thus we don't want to
@@ -17711,22 +18086,15 @@ retry:
                         */
                        crtc_state->uapi.color_mgmt_changed = true;
 
-                       /*
-                        * FIXME hack to force full modeset when DSC is being
-                        * used.
-                        *
-                        * As long as we do not have full state readout and
-                        * config comparison of crtc_state->dsc, we have no way
-                        * to ensure reliable fastset. Remove once we have
-                        * readout for DSC.
-                        */
-                       if (crtc_state->dsc.compression_enable) {
-                               ret = drm_atomic_add_affected_connectors(state,
-                                                                        &crtc->base);
-                               if (ret)
-                                       goto out;
-                               crtc_state->uapi.mode_changed = true;
-                               drm_dbg_kms(dev, "Force full modeset for DSC\n");
+                       for_each_intel_encoder_mask(dev, encoder,
+                                                   crtc_state->uapi.encoder_mask) {
+                               if (encoder->initial_fastset_check &&
+                                   !encoder->initial_fastset_check(encoder, crtc_state)) {
+                                       ret = drm_atomic_add_affected_connectors(state,
+                                                                                &crtc->base);
+                                       if (ret)
+                                               goto out;
+                               }
                        }
                }
        }
@@ -17765,6 +18133,9 @@ static void intel_mode_config_init(struct drm_i915_private *i915)
 
        mode_config->funcs = &intel_mode_funcs;
 
+       if (INTEL_GEN(i915) >= 9)
+               mode_config->async_page_flip = true;
+
        /*
         * Maximum framebuffer dimensions, chosen to match
         * the maximum render engine surface size on gen4+.
@@ -17823,6 +18194,27 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
 {
        int ret;
 
+       if (i915_inject_probe_failure(i915))
+               return -ENODEV;
+
+       if (HAS_DISPLAY(i915)) {
+               ret = drm_vblank_init(&i915->drm,
+                                     INTEL_NUM_PIPES(i915));
+               if (ret)
+                       return ret;
+       }
+
+       intel_bios_init(i915);
+
+       ret = intel_vga_register(i915);
+       if (ret)
+               goto cleanup_bios;
+
+       /* FIXME: completely on the wrong abstraction layer */
+       intel_power_domains_init_hw(i915, false);
+
+       intel_csr_ucode_init(i915);
+
        i915->modeset_wq = alloc_ordered_workqueue("i915_modeset", 0);
        i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI |
                                        WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE);
@@ -17831,15 +18223,15 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
 
        ret = intel_cdclk_init(i915);
        if (ret)
-               return ret;
+               goto cleanup_vga_client_pw_domain_csr;
 
        ret = intel_dbuf_init(i915);
        if (ret)
-               return ret;
+               goto cleanup_vga_client_pw_domain_csr;
 
        ret = intel_bw_init(i915);
        if (ret)
-               return ret;
+               goto cleanup_vga_client_pw_domain_csr;
 
        init_llist_head(&i915->atomic_helper.free_list);
        INIT_WORK(&i915->atomic_helper.free_work,
@@ -17850,10 +18242,19 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
        intel_fbc_init(i915);
 
        return 0;
+
+cleanup_vga_client_pw_domain_csr:
+       intel_csr_ucode_fini(i915);
+       intel_power_domains_driver_remove(i915);
+       intel_vga_unregister(i915);
+cleanup_bios:
+       intel_bios_driver_remove(i915);
+
+       return ret;
 }
 
-/* part #2: call after irq install */
-int intel_modeset_init(struct drm_i915_private *i915)
+/* part #2: call after irq install, but before gem init */
+int intel_modeset_init_nogem(struct drm_i915_private *i915)
 {
        struct drm_device *dev = &i915->drm;
        enum pipe pipe;
@@ -17870,7 +18271,7 @@ int intel_modeset_init(struct drm_i915_private *i915)
                    INTEL_NUM_PIPES(i915),
                    INTEL_NUM_PIPES(i915) > 1 ? "s" : "");
 
-       if (HAS_DISPLAY(i915) && INTEL_DISPLAY_ENABLED(i915)) {
+       if (HAS_DISPLAY(i915)) {
                for_each_pipe(i915, pipe) {
                        ret = intel_crtc_init(i915, pipe);
                        if (ret) {
@@ -17892,6 +18293,13 @@ int intel_modeset_init(struct drm_i915_private *i915)
        if (i915->max_cdclk_freq == 0)
                intel_update_max_cdclk(i915);
 
+       /*
+        * If the platform has HTI, we need to find out whether it has reserved
+        * any display resources before we create our display outputs.
+        */
+       if (INTEL_INFO(i915)->display.has_hti)
+               i915->hti_state = intel_de_read(i915, HDPORT_STATE);
+
        /* Just disable it once at startup */
        intel_vga_disable(i915);
        intel_setup_outputs(i915);
@@ -17945,6 +18353,31 @@ int intel_modeset_init(struct drm_i915_private *i915)
        return 0;
 }
 
+/* part #3: call after gem init */
+int intel_modeset_init(struct drm_i915_private *i915)
+{
+       int ret;
+
+       intel_overlay_setup(i915);
+
+       if (!HAS_DISPLAY(i915))
+               return 0;
+
+       ret = intel_fbdev_init(&i915->drm);
+       if (ret)
+               return ret;
+
+       /* Only enable hotplug handling once the fbdev is fully set up. */
+       intel_hpd_init(i915);
+       intel_hpd_poll_disable(i915);
+
+       intel_init_ipc(i915);
+
+       intel_psr_set_force_mode_changed(i915->psr.dp);
+
+       return 0;
+}
+
 void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
        struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
@@ -18403,6 +18836,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 
                        encoder->base.crtc = &crtc->base;
                        encoder->get_config(encoder, crtc_state);
+                       if (encoder->sync_state)
+                               encoder->sync_state(encoder, crtc_state);
                } else {
                        encoder->base.crtc = NULL;
                }
@@ -18573,6 +19008,15 @@ static void intel_early_display_was(struct drm_i915_private *dev_priv)
                intel_de_write(dev_priv, CHICKEN_PAR1_1,
                               intel_de_read(dev_priv, CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES);
        }
+
+       if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || IS_COMETLAKE(dev_priv)) {
+               /* Display WA #1142:kbl,cfl,cml */
+               intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
+                            KBL_ARB_FILL_SPARE_22, KBL_ARB_FILL_SPARE_22);
+               intel_de_rmw(dev_priv, CHICKEN_MISC_2,
+                            KBL_ARB_FILL_SPARE_13 | KBL_ARB_FILL_SPARE_14,
+                            KBL_ARB_FILL_SPARE_14);
+       }
 }
 
 static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv,
@@ -18829,6 +19273,18 @@ void intel_modeset_driver_remove_noirq(struct drm_i915_private *i915)
        intel_fbc_cleanup_cfb(i915);
 }
 
+/* part #3: call after gem init */
+void intel_modeset_driver_remove_nogem(struct drm_i915_private *i915)
+{
+       intel_csr_ucode_fini(i915);
+
+       intel_power_domains_driver_remove(i915);
+
+       intel_vga_unregister(i915);
+
+       intel_bios_driver_remove(i915);
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
 
 struct intel_display_error_state {
@@ -18889,7 +19345,7 @@ intel_display_capture_error_state(struct drm_i915_private *dev_priv)
 
        BUILD_BUG_ON(ARRAY_SIZE(transcoders) != ARRAY_SIZE(error->transcoder));
 
-       if (!HAS_DISPLAY(dev_priv) || !INTEL_DISPLAY_ENABLED(dev_priv))
+       if (!HAS_DISPLAY(dev_priv))
                return NULL;
 
        error = kzalloc(sizeof(*error), GFP_ATOMIC);