drm/i915: prefer 3-letter acronym for icelake
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / display / intel_ddi.c
index 0d6e494..7e8e20f 100644 (file)
@@ -34,6 +34,7 @@
 #include "intel_ddi.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_dp_mst.h"
 #include "intel_dp_link_training.h"
 #include "intel_dpio_phy.h"
 #include "intel_dsi.h"
@@ -593,7 +594,7 @@ struct tgl_dkl_phy_ddi_buf_trans {
        u32 dkl_de_emphasis_control;
 };
 
-static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_ddi_translations[] = {
+static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_dp_ddi_trans[] = {
                                /* VS   pre-emp Non-trans mV    Pre-emph dB */
        { 0x7, 0x0, 0x00 },     /* 0    0       400mV           0 dB */
        { 0x5, 0x0, 0x03 },     /* 0    1       400mV           3.5 dB */
@@ -607,6 +608,20 @@ static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_ddi_translations[] = {
        { 0x0, 0x0, 0x00 },     /* 3    0       1200mV          0 dB HDMI default */
 };
 
+static const struct tgl_dkl_phy_ddi_buf_trans tgl_dkl_phy_hdmi_ddi_trans[] = {
+                               /* HDMI Preset  VS      Pre-emph */
+       { 0x7, 0x0, 0x0 },      /* 1            400mV   0dB */
+       { 0x6, 0x0, 0x0 },      /* 2            500mV   0dB */
+       { 0x4, 0x0, 0x0 },      /* 3            650mV   0dB */
+       { 0x2, 0x0, 0x0 },      /* 4            800mV   0dB */
+       { 0x0, 0x0, 0x0 },      /* 5            1000mV  0dB */
+       { 0x0, 0x0, 0x5 },      /* 6            Full    -1.5 dB */
+       { 0x0, 0x0, 0x6 },      /* 7            Full    -1.8 dB */
+       { 0x0, 0x0, 0x7 },      /* 8            Full    -2 dB */
+       { 0x0, 0x0, 0x8 },      /* 9            Full    -2.5 dB */
+       { 0x0, 0x0, 0xA },      /* 10           Full    -3 dB */
+};
+
 static const struct ddi_buf_trans *
 bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
 {
@@ -888,17 +903,16 @@ icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, int type, int rate,
 
 static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
 {
+       struct ddi_vbt_port_info *port_info = &dev_priv->vbt.ddi_port_info[port];
        int n_entries, level, default_entry;
        enum phy phy = intel_port_to_phy(dev_priv, port);
 
-       level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
-
        if (INTEL_GEN(dev_priv) >= 12) {
                if (intel_phy_is_combo(dev_priv, phy))
                        icl_get_combo_buf_trans(dev_priv, INTEL_OUTPUT_HDMI,
                                                0, &n_entries);
                else
-                       n_entries = ARRAY_SIZE(tgl_dkl_phy_ddi_translations);
+                       n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans);
                default_entry = n_entries - 1;
        } else if (INTEL_GEN(dev_priv) == 11) {
                if (intel_phy_is_combo(dev_priv, phy))
@@ -927,12 +941,14 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por
                return 0;
        }
 
-       /* Choose a good default if VBT is badly populated */
-       if (level == HDMI_LEVEL_SHIFT_UNKNOWN || level >= n_entries)
-               level = default_entry;
-
        if (WARN_ON_ONCE(n_entries == 0))
                return 0;
+
+       if (port_info->hdmi_level_shift_set)
+               level = port_info->hdmi_level_shift;
+       else
+               level = default_entry;
+
        if (WARN_ON_ONCE(level >= n_entries))
                level = n_entries - 1;
 
@@ -1092,18 +1108,14 @@ static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
  * DDI A (which is used for eDP)
  */
 
-void hsw_fdi_link_train(struct intel_crtc *crtc,
+void hsw_fdi_link_train(struct intel_encoder *encoder,
                        const struct intel_crtc_state *crtc_state)
 {
-       struct drm_device *dev = crtc->base.dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_encoder *encoder;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        u32 temp, i, rx_ctl_val, ddi_pll_sel;
 
-       for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
-               WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG);
-               intel_prepare_dp_ddi_buffers(encoder, crtc_state);
-       }
+       intel_prepare_dp_ddi_buffers(encoder, crtc_state);
 
        /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
         * mode set "sequence for CRT port" document:
@@ -1528,7 +1540,7 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
        if (pipe_config->pixel_multiplier)
                dotclock /= pipe_config->pixel_multiplier;
 
-       pipe_config->base.adjusted_mode.crtc_clock = dotclock;
+       pipe_config->hw.adjusted_mode.crtc_clock = dotclock;
 }
 
 static void icl_ddi_clock_get(struct intel_encoder *encoder,
@@ -1744,7 +1756,7 @@ static void intel_ddi_clock_get(struct intel_encoder *encoder,
 void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
                          const struct drm_connector_state *conn_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        u32 temp;
@@ -1801,22 +1813,6 @@ void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
        I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp);
 }
 
-void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
-                                   bool state)
-{
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
-       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-       u32 temp;
-
-       temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
-       if (state == true)
-               temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
-       else
-               temp &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
-       I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
-}
-
 /*
  * Returns the TRANS_DDI_FUNC_CTL value based on CRTC state.
  *
@@ -1826,7 +1822,7 @@ void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,
 static u32
 intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
@@ -1858,9 +1854,9 @@ intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state)
                BUG();
        }
 
-       if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC)
+       if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC)
                temp |= TRANS_DDI_PVSYNC;
-       if (crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC)
+       if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC)
                temp |= TRANS_DDI_PHSYNC;
 
        if (cpu_transcoder == TRANSCODER_EDP) {
@@ -1904,8 +1900,13 @@ intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state)
                temp |= TRANS_DDI_MODE_SELECT_DP_MST;
                temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
 
-               if (INTEL_GEN(dev_priv) >= 12)
-                       temp |= TRANS_DDI_MST_TRANSPORT_SELECT(crtc_state->cpu_transcoder);
+               if (INTEL_GEN(dev_priv) >= 12) {
+                       enum transcoder master;
+
+                       master = crtc_state->mst_master_transcoder;
+                       WARN_ON(master == INVALID_TRANSCODER);
+                       temp |= TRANS_DDI_MST_TRANSPORT_SELECT(master);
+               }
        } else {
                temp |= TRANS_DDI_MODE_SELECT_DP_SST;
                temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
@@ -1916,12 +1917,14 @@ intel_ddi_transcoder_func_reg_val_get(const struct intel_crtc_state *crtc_state)
 
 void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        u32 temp;
 
        temp = intel_ddi_transcoder_func_reg_val_get(crtc_state);
+       if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
+               temp |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
        I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
 }
 
@@ -1932,7 +1935,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state)
 static void
 intel_ddi_config_transcoder_func(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
        u32 temp;
@@ -1944,20 +1947,21 @@ intel_ddi_config_transcoder_func(const struct intel_crtc_state *crtc_state)
 
 void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-       i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
-       u32 val = I915_READ(reg);
+       u32 val;
+
+       val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+       val &= ~TRANS_DDI_FUNC_ENABLE;
 
        if (INTEL_GEN(dev_priv) >= 12) {
-               val &= ~(TRANS_DDI_FUNC_ENABLE | TGL_TRANS_DDI_PORT_MASK |
-                        TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
+               if (!intel_dp_mst_is_master_trans(crtc_state))
+                       val &= ~TGL_TRANS_DDI_PORT_MASK;
        } else {
-               val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK |
-                        TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
+               val &= ~TRANS_DDI_PORT_MASK;
        }
-       I915_WRITE(reg, val);
+       I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), val);
 
        if (dev_priv->quirks & QUIRK_INCREASE_DDI_DISABLED_TIME &&
            intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
@@ -2242,7 +2246,7 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
 
 void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        struct intel_encoder *encoder = intel_ddi_get_crtc_encoder(crtc);
        enum port port = encoder->port;
@@ -2260,7 +2264,7 @@ void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state)
 
 void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
        enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
 
        if (cpu_transcoder != TRANSCODER_EDP) {
@@ -2371,7 +2375,7 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
                        icl_get_combo_buf_trans(dev_priv, encoder->type,
                                                intel_dp->link_rate, &n_entries);
                else
-                       n_entries = ARRAY_SIZE(tgl_dkl_phy_ddi_translations);
+                       n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans);
        } else if (INTEL_GEN(dev_priv) == 11) {
                if (intel_phy_is_combo(dev_priv, phy))
                        icl_get_combo_buf_trans(dev_priv, encoder->type,
@@ -2823,8 +2827,13 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder, int link_clock,
        const struct tgl_dkl_phy_ddi_buf_trans *ddi_translations;
        u32 n_entries, val, ln, dpcnt_mask, dpcnt_val;
 
-       n_entries = ARRAY_SIZE(tgl_dkl_phy_ddi_translations);
-       ddi_translations = tgl_dkl_phy_ddi_translations;
+       if (encoder->type == INTEL_OUTPUT_HDMI) {
+               n_entries = ARRAY_SIZE(tgl_dkl_phy_hdmi_ddi_trans);
+               ddi_translations = tgl_dkl_phy_hdmi_ddi_trans;
+       } else {
+               n_entries = ARRAY_SIZE(tgl_dkl_phy_dp_ddi_trans);
+               ddi_translations = tgl_dkl_phy_dp_ddi_trans;
+       }
 
        if (level >= n_entries)
                level = n_entries - 1;
@@ -2997,11 +3006,38 @@ static void icl_unmap_plls_to_ports(struct intel_encoder *encoder)
        mutex_unlock(&dev_priv->dpll_lock);
 }
 
+static void icl_sanitize_port_clk_off(struct drm_i915_private *dev_priv,
+                                     u32 port_mask, bool ddi_clk_needed)
+{
+       enum port port;
+       u32 val;
+
+       val = I915_READ(ICL_DPCLKA_CFGCR0);
+       for_each_port_masked(port, port_mask) {
+               enum phy phy = intel_port_to_phy(dev_priv, port);
+               bool ddi_clk_off = val & icl_dpclka_cfgcr0_clk_off(dev_priv,
+                                                                  phy);
+
+               if (ddi_clk_needed == !ddi_clk_off)
+                       continue;
+
+               /*
+                * Punt on the case now where clock is gated, but it would
+                * be needed by the port. Something else is really broken then.
+                */
+               if (WARN_ON(ddi_clk_needed))
+                       continue;
+
+               DRM_NOTE("PHY %c is disabled/in DSI mode with an ungated DDI clock, gate it\n",
+                        phy_name(phy));
+               val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
+               I915_WRITE(ICL_DPCLKA_CFGCR0, val);
+       }
+}
+
 void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       u32 val;
-       enum port port;
        u32 port_mask;
        bool ddi_clk_needed;
 
@@ -3050,29 +3086,7 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
                ddi_clk_needed = false;
        }
 
-       val = I915_READ(ICL_DPCLKA_CFGCR0);
-       for_each_port_masked(port, port_mask) {
-               enum phy phy = intel_port_to_phy(dev_priv, port);
-
-               bool ddi_clk_ungated = !(val &
-                                        icl_dpclka_cfgcr0_clk_off(dev_priv,
-                                                                  phy));
-
-               if (ddi_clk_needed == ddi_clk_ungated)
-                       continue;
-
-               /*
-                * Punt on the case now where clock is gated, but it would
-                * be needed by the port. Something else is really broken then.
-                */
-               if (WARN_ON(ddi_clk_needed))
-                       continue;
-
-               DRM_NOTE("PHY %c is disabled/in DSI mode with an ungated DDI clock, gate it\n",
-                        phy_name(port));
-               val |= icl_dpclka_cfgcr0_clk_off(dev_priv, phy);
-               I915_WRITE(ICL_DPCLKA_CFGCR0, val);
-       }
+       icl_sanitize_port_clk_off(dev_priv, port_mask, ddi_clk_needed);
 }
 
 static void intel_ddi_clk_select(struct intel_encoder *encoder,
@@ -3340,7 +3354,7 @@ static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
 static void
 tgl_clear_psr2_transcoder_exitline(const struct intel_crtc_state *cstate)
 {
-       struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev);
        u32 val;
 
        if (!cstate->dc3co_exitline)
@@ -3355,7 +3369,7 @@ static void
 tgl_set_psr2_transcoder_exitline(const struct intel_crtc_state *cstate)
 {
        u32 val, exit_scanlines;
-       struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev);
 
        if (!cstate->dc3co_exitline)
                return;
@@ -3373,8 +3387,8 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder,
                                              struct intel_crtc_state *cstate)
 {
        u32 exit_scanlines;
-       struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
-       u32 crtc_vdisplay = cstate->base.adjusted_mode.crtc_vdisplay;
+       struct drm_i915_private *dev_priv = to_i915(cstate->uapi.crtc->dev);
+       u32 crtc_vdisplay = cstate->hw.adjusted_mode.crtc_vdisplay;
 
        cstate->dc3co_exitline = 0;
 
@@ -3382,11 +3396,11 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder,
                return;
 
        /* B.Specs:49196 DC3CO only works with pipeA and DDIA.*/
-       if (to_intel_crtc(cstate->base.crtc)->pipe != PIPE_A ||
+       if (to_intel_crtc(cstate->uapi.crtc)->pipe != PIPE_A ||
            encoder->port != PORT_A)
                return;
 
-       if (!cstate->has_psr2 || !cstate->base.active)
+       if (!cstate->has_psr2 || !cstate->hw.active)
                return;
 
        /*
@@ -3394,7 +3408,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder,
         * PSR2 transcoder Early Exit scanlines = ROUNDUP(200 / line time) + 1
         */
        exit_scanlines =
-               intel_usecs_to_scanlines(&cstate->base.adjusted_mode, 200) + 1;
+               intel_usecs_to_scanlines(&cstate->hw.adjusted_mode, 200) + 1;
 
        if (WARN_ON(exit_scanlines > crtc_vdisplay))
                return;
@@ -3406,7 +3420,7 @@ static void tgl_dc3co_exitline_compute_config(struct intel_encoder *encoder,
 static void tgl_dc3co_exitline_get_config(struct intel_crtc_state *crtc_state)
 {
        u32 val;
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
 
        if (INTEL_GEN(dev_priv) < 12)
                return;
@@ -3436,47 +3450,86 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
        intel_dp->regs.dp_tp_ctl = TGL_DP_TP_CTL(transcoder);
        intel_dp->regs.dp_tp_status = TGL_DP_TP_STATUS(transcoder);
 
-       /* 1.a got on intel_atomic_commit_tail() */
+       /*
+        * 1. Enable Power Wells
+        *
+        * This was handled at the beginning of intel_atomic_commit_tail(),
+        * before we called down into this function.
+        */
 
-       /* 2. */
+       /* 2. Enable Panel Power if PPS is required */
        intel_edp_panel_on(intel_dp);
 
        /*
-        * 1.b, 3. and 4.a is done before tgl_ddi_pre_enable_dp() by:
-        * haswell_crtc_enable()->intel_encoders_pre_pll_enable() and
-        * haswell_crtc_enable()->intel_enable_shared_dpll()
+        * 3. For non-TBT Type-C ports, set FIA lane count
+        * (DFLEXDPSP.DPX4TXLATC)
+        *
+        * This was done before tgl_ddi_pre_enable_dp by
+        * hsw_crtc_enable()->intel_encoders_pre_pll_enable().
         */
 
-       /* 4.b */
+       /*
+        * 4. Enable the port PLL.
+        *
+        * The PLL enabling itself was already done before this function by
+        * hsw_crtc_enable()->intel_enable_shared_dpll().  We need only
+        * configure the PLL to port mapping here.
+        */
        intel_ddi_clk_select(encoder, crtc_state);
 
-       /* 5. */
+       /* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */
        if (!intel_phy_is_tc(dev_priv, phy) ||
            dig_port->tc_mode != TC_PORT_TBT_ALT)
                intel_display_power_get(dev_priv,
                                        dig_port->ddi_io_power_domain);
 
-       /* 6. */
+       /* 6. Program DP_MODE */
        icl_program_mg_dp_mode(dig_port, crtc_state);
 
        /*
-        * 7.a - Steps in this function should only be executed over MST
-        * master, what will be taken in care by MST hook
-        * intel_mst_pre_enable_dp()
+        * 7. The rest of the below are substeps under the bspec's "Enable and
+        * Train Display Port" step.  Note that steps that are specific to
+        * MST will be handled by intel_mst_pre_enable_dp() before/after it
+        * calls into this function.  Also intel_mst_pre_enable_dp() only calls
+        * us when active_mst_links==0, so any steps designated for "single
+        * stream or multi-stream master transcoder" can just be performed
+        * unconditionally here.
+        */
+
+       /*
+        * 7.a Configure Transcoder Clock Select to direct the Port clock to the
+        * Transcoder.
         */
        intel_ddi_enable_pipe_clock(crtc_state);
 
-       /* 7.b */
+       /*
+        * 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
+        * Transport Select
+        */
        intel_ddi_config_transcoder_func(crtc_state);
 
-       /* 7.d */
+       /*
+        * 7.c Configure & enable DP_TP_CTL with link training pattern 1
+        * selected
+        *
+        * This will be handled by the intel_dp_start_link_train() farther
+        * down this function.
+        */
+
+       /*
+        * 7.d Type C with DP alternate or fixed/legacy/static connection -
+        * Disable PHY clock gating per Type-C DDI Buffer page
+        */
        icl_phy_set_clock_gating(dig_port, false);
 
-       /* 7.e */
+       /* 7.e Configure voltage swing and related IO settings */
        tgl_ddi_vswing_sequence(encoder, crtc_state->port_clock, level,
                                encoder->type);
 
-       /* 7.f */
+       /*
+        * 7.f Combo PHY: Configure PORT_CL_DW10 Static Power Down to power up
+        * the used lanes of the DDI.
+        */
        if (intel_phy_is_combo(dev_priv, phy)) {
                bool lane_reversal =
                        dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
@@ -3486,7 +3539,14 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
                                               lane_reversal);
        }
 
-       /* 7.g */
+       /*
+        * 7.g Configure and enable DDI_BUF_CTL
+        * 7.h Wait for DDI_BUF_CTL DDI Idle Status = 0b (Not Idle), timeout
+        *     after 500 us.
+        *
+        * We only configure what the register value will be here.  Actual
+        * enabling happens during link training farther down.
+        */
        intel_ddi_init_dp_buf_reg(encoder);
 
        if (!is_mst)
@@ -3499,10 +3559,17 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
         * training
         */
        intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
-       /* 7.c, 7.h, 7.i, 7.j */
+
+       /*
+        * 7.i Follow DisplayPort specification training sequence (see notes for
+        *     failure handling)
+        * 7.j If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
+        *     Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
+        *     (timeout after 800 us)
+        */
        intel_dp_start_link_train(intel_dp);
 
-       /* 7.k */
+       /* 7.k Set DP_TP_CTL link training to Normal */
        if (!is_trans_port_sync_mode(crtc_state))
                intel_dp_stop_link_train(intel_dp);
 
@@ -3515,7 +3582,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_encoder *encoder,
         * so not enabling it for now.
         */
 
-       /* 7.l */
+       /* 7.l Configure and enable FEC if needed */
        intel_ddi_enable_fec(encoder, crtc_state);
        intel_dsc_enable(encoder, crtc_state);
 }
@@ -3658,7 +3725,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder,
                                 const struct intel_crtc_state *crtc_state,
                                 const struct drm_connector_state *conn_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum pipe pipe = crtc->pipe;
 
@@ -3742,17 +3809,36 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
                                          INTEL_OUTPUT_DP_MST);
        enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
 
-       if (!is_mst) {
-               intel_ddi_disable_pipe_clock(old_crtc_state);
-               /*
-                * Power down sink before disabling the port, otherwise we end
-                * up getting interrupts from the sink on detecting link loss.
-                */
-               intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
+       /*
+        * Power down sink before disabling the port, otherwise we end
+        * up getting interrupts from the sink on detecting link loss.
+        */
+       intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
+
+       if (INTEL_GEN(dev_priv) >= 12) {
+               if (is_mst) {
+                       enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
+                       u32 val;
+
+                       val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+                       val &= ~TGL_TRANS_DDI_PORT_MASK;
+                       I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), val);
+               }
+       } else {
+               if (!is_mst)
+                       intel_ddi_disable_pipe_clock(old_crtc_state);
        }
 
        intel_disable_ddi_buf(encoder, old_crtc_state);
 
+       /*
+        * From TGL spec: "If single stream or multi-stream master transcoder:
+        * Configure Transcoder Clock select to direct no clock to the
+        * transcoder"
+        */
+       if (INTEL_GEN(dev_priv) >= 12)
+               intel_ddi_disable_pipe_clock(old_crtc_state);
+
        intel_edp_panel_vdd_on(intel_dp);
        intel_edp_panel_off(intel_dp);
 
@@ -3788,11 +3874,49 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder,
        intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
 }
 
+static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       i915_reg_t reg;
+       u32 trans_ddi_func_ctl2_val;
+
+       if (old_crtc_state->master_transcoder == INVALID_TRANSCODER)
+               return;
+
+       DRM_DEBUG_KMS("Disabling Transcoder Port Sync on Slave Transcoder %s\n",
+                     transcoder_name(old_crtc_state->cpu_transcoder));
+
+       reg = TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder);
+       trans_ddi_func_ctl2_val = ~(PORT_SYNC_MODE_ENABLE |
+                                   PORT_SYNC_MODE_MASTER_SELECT_MASK);
+       I915_WRITE(reg, trans_ddi_func_ctl2_val);
+}
+
 static void intel_ddi_post_disable(struct intel_encoder *encoder,
                                   const struct intel_crtc_state *old_crtc_state,
                                   const struct drm_connector_state *old_conn_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
+       enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+       bool is_tc_port = intel_phy_is_tc(dev_priv, phy);
+
+       intel_crtc_vblank_off(old_crtc_state);
+
+       intel_disable_pipe(old_crtc_state);
+
+       if (INTEL_GEN(dev_priv) >= 11)
+               icl_disable_transcoder_port_sync(old_crtc_state);
+
+       intel_ddi_disable_transcoder_func(old_crtc_state);
+
+       intel_dsc_disable(old_crtc_state);
+
+       if (INTEL_GEN(dev_priv) >= 9)
+               skl_scaler_disable(old_crtc_state);
+       else
+               ironlake_pfit_disable(old_crtc_state);
 
        /*
         * When called from DP MST code:
@@ -3816,6 +3940,13 @@ static void intel_ddi_post_disable(struct intel_encoder *encoder,
 
        if (INTEL_GEN(dev_priv) >= 11)
                icl_unmap_plls_to_ports(encoder);
+
+       if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port)
+               intel_display_power_put_unchecked(dev_priv,
+                                                 intel_ddi_main_link_aux_domain(dig_port));
+
+       if (is_tc_port)
+               intel_tc_port_put_link(dig_port);
 }
 
 void intel_ddi_fdi_post_disable(struct intel_encoder *encoder,
@@ -3967,6 +4098,7 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED)
                intel_hdcp_enable(to_intel_connector(conn_state->connector),
+                                 crtc_state->cpu_transcoder,
                                  (u8)conn_state->hdcp_content_type);
 }
 
@@ -4070,7 +4202,9 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED ||
            content_protection_type_changed)
-               intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type);
+               intel_hdcp_enable(connector,
+                                 crtc_state->cpu_transcoder,
+                                 (u8)conn_state->hdcp_content_type);
 }
 
 static void
@@ -4085,7 +4219,7 @@ intel_ddi_update_prepare(struct intel_atomic_state *state,
        WARN_ON(crtc && crtc->active);
 
        intel_tc_port_get_link(enc_to_dig_port(&encoder->base), required_lanes);
-       if (crtc_state && crtc_state->base.active)
+       if (crtc_state && crtc_state->hw.active)
                intel_update_active_dpll(state, crtc, encoder);
 }
 
@@ -4125,61 +4259,44 @@ intel_ddi_pre_pll_enable(struct intel_encoder *encoder,
                                                crtc_state->lane_lat_optim_mask);
 }
 
-static void
-intel_ddi_post_pll_disable(struct intel_encoder *encoder,
-                          const struct intel_crtc_state *crtc_state,
-                          const struct drm_connector_state *conn_state)
-{
-       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
-       enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
-       bool is_tc_port = intel_phy_is_tc(dev_priv, phy);
-
-       if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port)
-               intel_display_power_put_unchecked(dev_priv,
-                                                 intel_ddi_main_link_aux_domain(dig_port));
-
-       if (is_tc_port)
-               intel_tc_port_put_link(dig_port);
-}
-
 static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        struct drm_i915_private *dev_priv =
                to_i915(intel_dig_port->base.base.dev);
        enum port port = intel_dig_port->base.port;
-       u32 val;
+       u32 dp_tp_ctl, ddi_buf_ctl;
        bool wait = false;
 
-       if (I915_READ(intel_dp->regs.dp_tp_ctl) & DP_TP_CTL_ENABLE) {
-               val = I915_READ(DDI_BUF_CTL(port));
-               if (val & DDI_BUF_CTL_ENABLE) {
-                       val &= ~DDI_BUF_CTL_ENABLE;
-                       I915_WRITE(DDI_BUF_CTL(port), val);
+       dp_tp_ctl = I915_READ(intel_dp->regs.dp_tp_ctl);
+
+       if (dp_tp_ctl & DP_TP_CTL_ENABLE) {
+               ddi_buf_ctl = I915_READ(DDI_BUF_CTL(port));
+               if (ddi_buf_ctl & DDI_BUF_CTL_ENABLE) {
+                       I915_WRITE(DDI_BUF_CTL(port),
+                                  ddi_buf_ctl & ~DDI_BUF_CTL_ENABLE);
                        wait = true;
                }
 
-               val = I915_READ(intel_dp->regs.dp_tp_ctl);
-               val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
-               val |= DP_TP_CTL_LINK_TRAIN_PAT1;
-               I915_WRITE(intel_dp->regs.dp_tp_ctl, val);
+               dp_tp_ctl &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
+               dp_tp_ctl |= DP_TP_CTL_LINK_TRAIN_PAT1;
+               I915_WRITE(intel_dp->regs.dp_tp_ctl, dp_tp_ctl);
                POSTING_READ(intel_dp->regs.dp_tp_ctl);
 
                if (wait)
                        intel_wait_ddi_buf_idle(dev_priv, port);
        }
 
-       val = DP_TP_CTL_ENABLE |
-             DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
+       dp_tp_ctl = DP_TP_CTL_ENABLE |
+                   DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE;
        if (intel_dp->link_mst)
-               val |= DP_TP_CTL_MODE_MST;
+               dp_tp_ctl |= DP_TP_CTL_MODE_MST;
        else {
-               val |= DP_TP_CTL_MODE_SST;
+               dp_tp_ctl |= DP_TP_CTL_MODE_SST;
                if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
-                       val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
+                       dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
        }
-       I915_WRITE(intel_dp->regs.dp_tp_ctl, val);
+       I915_WRITE(intel_dp->regs.dp_tp_ctl, dp_tp_ctl);
        POSTING_READ(intel_dp->regs.dp_tp_ctl);
 
        intel_dp->DP |= DDI_BUF_CTL_ENABLE;
@@ -4215,7 +4332,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
                          struct intel_crtc_state *pipe_config)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
+       struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->uapi.crtc);
        enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
        u32 temp, flags = 0;
 
@@ -4223,6 +4340,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
        if (WARN_ON(transcoder_is_dsi(cpu_transcoder)))
                return;
 
+       intel_dsc_get_config(encoder, pipe_config);
+
        temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
        if (temp & TRANS_DDI_PHSYNC)
                flags |= DRM_MODE_FLAG_PHSYNC;
@@ -4233,7 +4352,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
        else
                flags |= DRM_MODE_FLAG_NVSYNC;
 
-       pipe_config->base.adjusted_mode.flags |= flags;
+       pipe_config->hw.adjusted_mode.flags |= flags;
 
        switch (temp & TRANS_DDI_BPC_MASK) {
        case TRANS_DDI_BPC_6:
@@ -4304,6 +4423,11 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
                pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
                pipe_config->lane_count =
                        ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
+
+               if (INTEL_GEN(dev_priv) >= 12)
+                       pipe_config->mst_master_transcoder =
+                                       REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
+
                intel_dp_get_m_n(intel_crtc, pipe_config);
                break;
        default:
@@ -4382,7 +4506,7 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
                                    struct intel_crtc_state *pipe_config,
                                    struct drm_connector_state *conn_state)
 {
-       struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
+       struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        enum port port = encoder->port;
        int ret;
@@ -4516,7 +4640,7 @@ static int intel_hdmi_reset_link(struct intel_encoder *encoder,
 
        WARN_ON(!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI));
 
-       if (!crtc_state->base.active)
+       if (!crtc_state->hw.active)
                return 0;
 
        if (!crtc_state->hdmi_high_tmds_clock_ratio &&
@@ -4687,8 +4811,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        struct ddi_vbt_port_info *port_info =
                &dev_priv->vbt.ddi_port_info[port];
        struct intel_digital_port *intel_dig_port;
-       struct intel_encoder *intel_encoder;
-       struct drm_encoder *encoder;
+       struct intel_encoder *encoder;
        bool init_hdmi, init_dp, init_lspcon = false;
        enum phy phy = intel_port_to_phy(dev_priv, port);
 
@@ -4717,31 +4840,30 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        if (!intel_dig_port)
                return;
 
-       intel_encoder = &intel_dig_port->base;
-       encoder = &intel_encoder->base;
+       encoder = &intel_dig_port->base;
 
-       drm_encoder_init(&dev_priv->drm, encoder, &intel_ddi_funcs,
+       drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
                         DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port));
 
-       intel_encoder->hotplug = intel_ddi_hotplug;
-       intel_encoder->compute_output_type = intel_ddi_compute_output_type;
-       intel_encoder->compute_config = intel_ddi_compute_config;
-       intel_encoder->enable = intel_enable_ddi;
-       intel_encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
-       intel_encoder->post_pll_disable = intel_ddi_post_pll_disable;
-       intel_encoder->pre_enable = intel_ddi_pre_enable;
-       intel_encoder->disable = intel_disable_ddi;
-       intel_encoder->post_disable = intel_ddi_post_disable;
-       intel_encoder->update_pipe = intel_ddi_update_pipe;
-       intel_encoder->get_hw_state = intel_ddi_get_hw_state;
-       intel_encoder->get_config = intel_ddi_get_config;
-       intel_encoder->suspend = intel_dp_encoder_suspend;
-       intel_encoder->get_power_domains = intel_ddi_get_power_domains;
-       intel_encoder->type = INTEL_OUTPUT_DDI;
-       intel_encoder->power_domain = intel_port_to_power_domain(port);
-       intel_encoder->port = port;
-       intel_encoder->cloneable = 0;
-       intel_encoder->pipe_mask = ~0;
+       encoder->hotplug = intel_ddi_hotplug;
+       encoder->compute_output_type = intel_ddi_compute_output_type;
+       encoder->compute_config = intel_ddi_compute_config;
+       encoder->enable = intel_enable_ddi;
+       encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
+       encoder->pre_enable = intel_ddi_pre_enable;
+       encoder->disable = intel_disable_ddi;
+       encoder->post_disable = intel_ddi_post_disable;
+       encoder->update_pipe = intel_ddi_update_pipe;
+       encoder->get_hw_state = intel_ddi_get_hw_state;
+       encoder->get_config = intel_ddi_get_config;
+       encoder->suspend = intel_dp_encoder_suspend;
+       encoder->get_power_domains = intel_ddi_get_power_domains;
+
+       encoder->type = INTEL_OUTPUT_DDI;
+       encoder->power_domain = intel_port_to_power_domain(port);
+       encoder->port = port;
+       encoder->cloneable = 0;
+       encoder->pipe_mask = ~0;
 
        if (INTEL_GEN(dev_priv) >= 11)
                intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
@@ -4749,6 +4871,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        else
                intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
                        (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES);
+
        intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
        intel_dig_port->max_lanes = intel_ddi_max_lanes(intel_dig_port);
        intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port);
@@ -4759,8 +4882,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 
                intel_tc_port_init(intel_dig_port, is_legacy);
 
-               intel_encoder->update_prepare = intel_ddi_update_prepare;
-               intel_encoder->update_complete = intel_ddi_update_complete;
+               encoder->update_prepare = intel_ddi_update_prepare;
+               encoder->update_complete = intel_ddi_update_complete;
        }
 
        WARN_ON(port > PORT_I);
@@ -4776,7 +4899,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 
        /* In theory we don't need the encoder->type check, but leave it just in
         * case we have some really bad VBTs... */
-       if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
+       if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
                if (!intel_ddi_init_hdmi_connector(intel_dig_port))
                        goto err;
        }
@@ -4800,6 +4923,6 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
        return;
 
 err:
-       drm_encoder_cleanup(encoder);
+       drm_encoder_cleanup(&encoder->base);
        kfree(intel_dig_port);
 }