diff mbox

[7/8] drm/i915/icl: Implement voltage swing programming sequence for Combo PHY DDI

Message ID 20180328215803.13835-8-paulo.r.zanoni@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zanoni, Paulo R March 28, 2018, 9:58 p.m. UTC
From: Manasi Navare <manasi.d.navare@intel.com>

This is an important part of the DDI initalization as well as
for changing the voltage during DisplayPort link training.

The Voltage swing seqeuence is similar to Cannonlake.
However it has different register definitions and hence
it makes sense to create a separate vswing sequence and
program functions for ICL to leave room for more changes
in case the Bspec changes later and deviates from CNL sequence.

v2:
Use ~TAP3_DISABLE for enbaling that bit (Jani Nikula)

v3:
* Use dw4_scaling column for PORT_TX_DW4 values (Rodrigo)

v4:
* Call it combo_vswing, use switch statement (Paulo)

v5 (from Paulo):
* Fix a typo.
* s/rate < 600000/rate <= 600000/.
* Don't remove blank lines that should be there.

v6:
* Rebased by Rodrigo on top of Cannonlake changes
  where non vswing sequences are not aligned with iboost
  anymore.

v7: Another rebase after an upstream rework.

v8 (from Paulo):
* Adjust the code to the upstream output type changes.
* Squash the patch that moved some functions up.
* Merge both get_combo_buf_trans functions in order to simplify the
  code.
* Change the changelog format.

v9 (from Paulo):
* Use RTERM_SELECT instead of SCALING_MODE_SEL.
* Adjust the output type handling according to how the other platforms
  do it now.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: James Ausmus <james.ausmus@intel.com>
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c | 191 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 188 insertions(+), 3 deletions(-)

Comments

kernel test robot March 31, 2018, 9:53 a.m. UTC | #1
Hi Manasi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20180329]
[cannot apply to v4.16-rc7]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Paulo-Zanoni/ICL-PLLs-DP-HDMI-and-misc-display-v2/20180330-131619
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: i386-randconfig-h0-03311214 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

                    ^
   In file included from include/linux/list.h:9:0,
                    from include/linux/kobject.h:19,
                    from include/linux/device.h:16,
                    from include/linux/i2c.h:30,
                    from include/drm/drm_scdc_helper.h:27,
                    from drivers/gpu//drm/i915/intel_ddi.c:28:
   drivers/gpu//drm/i915/intel_ddi.c:784:28: error: 'icl_combo_phy_ddi_translations_dp_hdmi_1_05V' undeclared (first use in this function)
       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
                               ^
   include/linux/kernel.h:71:33: note: in definition of macro 'ARRAY_SIZE'
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                                    ^
   In file included from include/linux/kernel.h:15:0,
                    from include/linux/list.h:9,
                    from include/linux/kobject.h:19,
                    from include/linux/device.h:16,
                    from include/linux/i2c.h:30,
                    from include/drm/drm_scdc_helper.h:27,
                    from drivers/gpu//drm/i915/intel_ddi.c:28:
   include/linux/build_bug.h:29:45: error: bit-field '<anonymous>' width not an integer constant
    #define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
                                                ^
   include/linux/compiler-gcc.h:65:28: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
    #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
                               ^
   include/linux/kernel.h:71:59: note: in expansion of macro '__must_be_array'
    #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                                                              ^
   drivers/gpu//drm/i915/intel_ddi.c:784:17: note: in expansion of macro 'ARRAY_SIZE'
       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
                    ^
   drivers/gpu//drm/i915/intel_ddi.c: In function 'icl_pll_to_ddi_pll_sel':
   drivers/gpu//drm/i915/intel_ddi.c:939:35: error: 'const struct intel_shared_dpll' has no member named 'info'
     const enum intel_dpll_id id = pll->info->id;
                                      ^
   drivers/gpu//drm/i915/intel_ddi.c: In function 'icl_ddi_combo_vswing_program':
   drivers/gpu//drm/i915/intel_ddi.c:2142:2: error: implicit declaration of function 'ICL_PORT_TX_DW5_LN0' [-Werror=implicit-function-declaration]
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2142:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2142:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2145:2: error: implicit declaration of function 'ICL_PORT_TX_DW5_GRP' [-Werror=implicit-function-declaration]
     I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2145:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2145:2: note: expected 'i915_reg_t' but argument is of type 'int'
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2148:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2148:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2153:10: error: 'TAP2_DISABLE' undeclared (first use in this function)
      val |= TAP2_DISABLE;
             ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2159:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2159:2: note: expected 'i915_reg_t' but argument is of type 'int'
   drivers/gpu//drm/i915/intel_ddi.c:2162:2: error: implicit declaration of function 'ICL_PORT_TX_DW2_LN0' [-Werror=implicit-function-declaration]
     val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2162:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2162:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2165:2: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
     val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
     ^
   In file included from drivers/gpu//drm/i915/i915_drv.h:56:0,
                    from drivers/gpu//drm/i915/intel_ddi.c:29:
>> drivers/gpu//drm/i915/intel_ddi.c:2165:41: error: dereferencing pointer to incomplete type
     val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
                                            ^
   drivers/gpu//drm/i915/i915_reg.h:1991:33: note: in definition of macro 'SWING_SEL_UPPER'
    #define   SWING_SEL_UPPER(x)  ((x >> 3) << 15)
                                    ^
   drivers/gpu//drm/i915/intel_ddi.c:2166:2: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
     val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
     ^
   In file included from drivers/gpu//drm/i915/i915_drv.h:56:0,
                    from drivers/gpu//drm/i915/intel_ddi.c:29:
   drivers/gpu//drm/i915/intel_ddi.c:2166:41: error: dereferencing pointer to incomplete type
     val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
                                            ^
   drivers/gpu//drm/i915/i915_reg.h:1993:33: note: in definition of macro 'SWING_SEL_LOWER'
    #define   SWING_SEL_LOWER(x)  ((x & 0x7) << 11)
                                    ^
   drivers/gpu//drm/i915/intel_ddi.c:2168:2: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
     val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
     ^
   In file included from drivers/gpu//drm/i915/i915_drv.h:56:0,
                    from drivers/gpu//drm/i915/intel_ddi.c:29:
   drivers/gpu//drm/i915/intel_ddi.c:2168:38: error: dereferencing pointer to incomplete type
     val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
                                         ^
   drivers/gpu//drm/i915/i915_reg.h:1995:30: note: in definition of macro 'RCOMP_SCALAR'
    #define   RCOMP_SCALAR(x)  ((x) << 0)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2169:2: error: implicit declaration of function 'ICL_PORT_TX_DW2_GRP' [-Werror=implicit-function-declaration]
     I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2169:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2169:2: note: expected 'i915_reg_t' but argument is of type 'int'
   drivers/gpu//drm/i915/intel_ddi.c:2174:3: error: implicit declaration of function 'ICL_PORT_TX_DW4_LN' [-Werror=implicit-function-declaration]
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
      ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2174:9: note: in expansion of macro 'I915_READ'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
            ^
   drivers/gpu//drm/i915/intel_ddi.c:2174:3: note: expected 'i915_reg_t' but argument is of type 'int'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
      ^
   drivers/gpu//drm/i915/intel_ddi.c:2177:3: error: invalid use of undefined type 'struct icl_combo_phy_ddi_buf_trans'
      val |= ddi_translations[level].dw4_scaling;
      ^
   drivers/gpu//drm/i915/intel_ddi.c:2177:26: error: dereferencing pointer to incomplete type
      val |= ddi_translations[level].dw4_scaling;
                             ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2178:3: note: in expansion of macro 'I915_WRITE'
      I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
      ^
   drivers/gpu//drm/i915/intel_ddi.c:2178:3: note: expected 'i915_reg_t' but argument is of type 'int'
   drivers/gpu//drm/i915/intel_ddi.c: In function 'icl_combo_phy_ddi_vswing_sequence':
   drivers/gpu//drm/i915/intel_ddi.c:2208:2: error: implicit declaration of function 'ICL_PORT_PCS_DW1_LN0' [-Werror=implicit-function-declaration]
     val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2208:8: note: in expansion of macro 'I915_READ'
     val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
           ^
   drivers/gpu//drm/i915/intel_ddi.c:2208:2: note: expected 'i915_reg_t' but argument is of type 'int'
     val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2213:2: error: implicit declaration of function 'ICL_PORT_PCS_DW1_GRP' [-Werror=implicit-function-declaration]
     I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val);
     ^
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3858:30: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_writel'
    #define I915_WRITE(reg, val) dev_priv->uncore.funcs.mmio_writel(dev_priv, (reg), (val), true)
                                 ^
   drivers/gpu//drm/i915/intel_ddi.c:2213:2: note: in expansion of macro 'I915_WRITE'
     I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val);
     ^
   drivers/gpu//drm/i915/intel_ddi.c:2213:2: note: expected 'i915_reg_t' but argument is of type 'int'
   In file included from drivers/gpu//drm/i915/intel_ddi.c:29:0:
   drivers/gpu//drm/i915/i915_drv.h:3857:25: error: incompatible type for argument 2 of 'dev_priv->uncore.funcs.mmio_readl'
    #define I915_READ(reg)  dev_priv->uncore.funcs.mmio_readl(dev_priv, (reg), true)
                            ^
   drivers/gpu//drm/i915/intel_ddi.c:2223:9: note: in expansion of macro 'I915_READ'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
            ^
   drivers/gpu//drm/i915/intel_ddi.c:2223:3: note: expected 'i915_reg_t' but argument is of type 'int'
      val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
      ^

vim +2165 drivers/gpu//drm/i915/intel_ddi.c

  2123	
  2124	static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
  2125						 u32 level, enum port port, int type)
  2126	{
  2127		const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
  2128		u32 n_entries, val;
  2129		int ln;
  2130	
  2131		ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
  2132							   &n_entries);
  2133		if (!ddi_translations)
  2134			return;
  2135	
  2136		if (level >= n_entries) {
  2137			DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1);
  2138			level = n_entries - 1;
  2139		}
  2140	
  2141		/* Set PORT_TX_DW5 Scaling Mode Sel to 110b. */
  2142		val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
  2143		val &= ~RTERM_SELECT_MASK;
  2144		val |= RTERM_SELECT(0x6);
  2145		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
  2146	
  2147		/* Program PORT_TX_DW5 */
  2148		val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
  2149		/* Set DisableTap2 and DisableTap3 if MIPI DSI
  2150		 * Clear DisableTap2 and DisableTap3 for all other Ports
  2151		 */
  2152		if (type == INTEL_OUTPUT_DSI) {
  2153			val |= TAP2_DISABLE;
  2154			val |= TAP3_DISABLE;
  2155		} else {
  2156			val &= ~TAP2_DISABLE;
  2157			val &= ~TAP3_DISABLE;
  2158		}
  2159		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
  2160	
  2161		/* Program PORT_TX_DW2 */
> 2162		val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
  2163		val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
  2164			 RCOMP_SCALAR_MASK);
> 2165		val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
  2166		val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
  2167		/* Program Rcomp scalar for every table entry */
  2168		val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
  2169		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
  2170	
  2171		/* Program PORT_TX_DW4 */
  2172		/* We cannot write to GRP. It would overwrite individual loadgen. */
  2173		for (ln = 0; ln <= 3; ln++) {
  2174			val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
  2175			val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
  2176				 CURSOR_COEFF_MASK);
  2177			val |= ddi_translations[level].dw4_scaling;
  2178			I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
  2179		}
  2180	}
  2181	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 10223ffcceab..bfe3e10e080d 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -870,6 +870,45 @@  cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
 	}
 }
 
+static const struct icl_combo_phy_ddi_buf_trans *
+icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
+			int type, int *n_entries)
+{
+	u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
+
+	if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+		switch (voltage) {
+		case VOLTAGE_INFO_0_85V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
+			return icl_combo_phy_ddi_translations_edp_0_85V;
+		case VOLTAGE_INFO_0_95V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
+			return icl_combo_phy_ddi_translations_edp_0_95V;
+		case VOLTAGE_INFO_1_05V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
+			return icl_combo_phy_ddi_translations_edp_1_05V;
+		default:
+			MISSING_CASE(voltage);
+			return NULL;
+		}
+	} else {
+		switch (voltage) {
+		case VOLTAGE_INFO_0_85V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
+			return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
+		case VOLTAGE_INFO_0_95V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
+			return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
+		case VOLTAGE_INFO_1_05V:
+			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
+			return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
+		default:
+			MISSING_CASE(voltage);
+			return NULL;
+		}
+	}
+}
+
 static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
 {
 	int n_entries, level, default_entry;
@@ -2201,6 +2240,146 @@  static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
 	I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val);
 }
 
+static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
+					 u32 level, enum port port, int type)
+{
+	const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
+	u32 n_entries, val;
+	int ln;
+
+	ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
+						   &n_entries);
+	if (!ddi_translations)
+		return;
+
+	if (level >= n_entries) {
+		DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1);
+		level = n_entries - 1;
+	}
+
+	/* Set PORT_TX_DW5 Scaling Mode Sel to 110b. */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	val &= ~RTERM_SELECT_MASK;
+	val |= RTERM_SELECT(0x6);
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+
+	/* Program PORT_TX_DW5 */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	/* Set DisableTap2 and DisableTap3 if MIPI DSI
+	 * Clear DisableTap2 and DisableTap3 for all other Ports
+	 */
+	if (type == INTEL_OUTPUT_DSI) {
+		val |= TAP2_DISABLE;
+		val |= TAP3_DISABLE;
+	} else {
+		val &= ~TAP2_DISABLE;
+		val &= ~TAP3_DISABLE;
+	}
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+
+	/* Program PORT_TX_DW2 */
+	val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
+	val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
+		 RCOMP_SCALAR_MASK);
+	val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
+	val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
+	/* Program Rcomp scalar for every table entry */
+	val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
+	I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
+
+	/* Program PORT_TX_DW4 */
+	/* We cannot write to GRP. It would overwrite individual loadgen. */
+	for (ln = 0; ln <= 3; ln++) {
+		val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
+		val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
+			 CURSOR_COEFF_MASK);
+		val |= ddi_translations[level].dw4_scaling;
+		I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
+	}
+}
+
+static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
+					      u32 level,
+					      enum intel_output_type type)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum port port = encoder->port;
+	int width = 0;
+	int rate = 0;
+	u32 val;
+	int ln = 0;
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		width = 4;
+		/* Rate is always < than 6GHz for HDMI */
+	} else {
+		struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+		width = intel_dp->lane_count;
+		rate = intel_dp->link_rate;
+	}
+
+	/*
+	 * 1. If port type is eDP or DP,
+	 * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
+	 * else clear to 0b.
+	 */
+	val = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
+	if (type == INTEL_OUTPUT_HDMI)
+		val &= ~COMMON_KEEPER_EN;
+	else
+		val |= COMMON_KEEPER_EN;
+	I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), val);
+
+	/* 2. Program loadgen select */
+	/*
+	 * Program PORT_TX_DW4_LN depending on Bit rate and used lanes
+	 * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
+	 * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
+	 * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
+	 */
+	for (ln = 0; ln <= 3; ln++) {
+		val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
+		val &= ~LOADGEN_SELECT;
+
+		if ((rate <= 600000 && width == 4 && ln >= 1) ||
+		    (rate <= 600000 && width < 4 && (ln == 1 || ln == 2))) {
+			val |= LOADGEN_SELECT;
+		}
+		I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
+	}
+
+	/* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
+	val = I915_READ(ICL_PORT_CL_DW5(port));
+	val |= SUS_CLOCK_CONFIG;
+	I915_WRITE(ICL_PORT_CL_DW5(port), val);
+
+	/* 4. Clear training enable to change swing values */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	val &= ~TX_TRAINING_EN;
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+
+	/* 5. Program swing and de-emphasis */
+	icl_ddi_combo_vswing_program(dev_priv, level, port, type);
+
+	/* 6. Set training enable to trigger update */
+	val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+	val |= TX_TRAINING_EN;
+	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
+}
+
+static void icl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level,
+				    enum intel_output_type type)
+{
+	enum port port = encoder->port;
+
+	if (port == PORT_A || port == PORT_B)
+		icl_combo_phy_ddi_vswing_sequence(encoder, level, type);
+	else
+		/* Not Implemented Yet */
+		WARN_ON(1);
+}
+
 static uint32_t translate_signal_level(int signal_levels)
 {
 	int i;
@@ -2232,7 +2411,9 @@  u32 bxt_signal_levels(struct intel_dp *intel_dp)
 	struct intel_encoder *encoder = &dport->base;
 	int level = intel_ddi_dp_level(intel_dp);
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		icl_ddi_vswing_sequence(encoder, level, encoder->type);
+	else if (IS_CANNONLAKE(dev_priv))
 		cnl_ddi_vswing_sequence(encoder, level, encoder->type);
 	else
 		bxt_ddi_vswing_sequence(encoder, level, encoder->type);
@@ -2406,7 +2587,9 @@  static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 
 	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		icl_ddi_vswing_sequence(encoder, level, encoder->type);
+	else if (IS_CANNONLAKE(dev_priv))
 		cnl_ddi_vswing_sequence(encoder, level, encoder->type);
 	else if (IS_GEN9_LP(dev_priv))
 		bxt_ddi_vswing_sequence(encoder, level, encoder->type);
@@ -2436,7 +2619,9 @@  static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
 
 	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
 
-	if (IS_CANNONLAKE(dev_priv))
+	if (IS_ICELAKE(dev_priv))
+		icl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
+	else if (IS_CANNONLAKE(dev_priv))
 		cnl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);
 	else if (IS_GEN9_LP(dev_priv))
 		bxt_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI);