@@ -1720,6 +1720,173 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
17201720 DP_TRAIN_VOLTAGE_SWING_MASK ;
17211721}
17221722
1723+ static const struct cnl_ddi_buf_trans *
1724+ cnl_get_buf_trans_hdmi (struct drm_i915_private * dev_priv ,
1725+ u32 voltage , int * n_entries )
1726+ {
1727+ if (voltage == VOLTAGE_INFO_0_85V ) {
1728+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_hdmi_0_85V );
1729+ return cnl_ddi_translations_hdmi_0_85V ;
1730+ } else if (voltage == VOLTAGE_INFO_0_95V ) {
1731+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_hdmi_0_95V );
1732+ return cnl_ddi_translations_hdmi_0_95V ;
1733+ } else if (voltage == VOLTAGE_INFO_1_05V ) {
1734+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_hdmi_1_05V );
1735+ return cnl_ddi_translations_hdmi_1_05V ;
1736+ }
1737+ return NULL ;
1738+ }
1739+
1740+ static const struct cnl_ddi_buf_trans *
1741+ cnl_get_buf_trans_dp (struct drm_i915_private * dev_priv ,
1742+ u32 voltage , int * n_entries )
1743+ {
1744+ if (voltage == VOLTAGE_INFO_0_85V ) {
1745+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_dp_0_85V );
1746+ return cnl_ddi_translations_dp_0_85V ;
1747+ } else if (voltage == VOLTAGE_INFO_0_95V ) {
1748+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_dp_0_95V );
1749+ return cnl_ddi_translations_dp_0_95V ;
1750+ } else if (voltage == VOLTAGE_INFO_1_05V ) {
1751+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_dp_1_05V );
1752+ return cnl_ddi_translations_dp_1_05V ;
1753+ }
1754+ return NULL ;
1755+ }
1756+
1757+ static const struct cnl_ddi_buf_trans *
1758+ cnl_get_buf_trans_edp (struct drm_i915_private * dev_priv ,
1759+ u32 voltage , int * n_entries )
1760+ {
1761+ if (dev_priv -> vbt .edp .low_vswing ) {
1762+ if (voltage == VOLTAGE_INFO_0_85V ) {
1763+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_edp_0_85V );
1764+ return cnl_ddi_translations_dp_0_85V ;
1765+ } else if (voltage == VOLTAGE_INFO_0_95V ) {
1766+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_edp_0_95V );
1767+ return cnl_ddi_translations_edp_0_95V ;
1768+ } else if (voltage == VOLTAGE_INFO_1_05V ) {
1769+ * n_entries = ARRAY_SIZE (cnl_ddi_translations_edp_1_05V );
1770+ return cnl_ddi_translations_edp_1_05V ;
1771+ }
1772+ return NULL ;
1773+ } else {
1774+ return cnl_get_buf_trans_dp (dev_priv , voltage , n_entries );
1775+ }
1776+ }
1777+
1778+ static void cnl_ddi_vswing_program (struct drm_i915_private * dev_priv ,
1779+ u32 level , enum port port , int type )
1780+ {
1781+ const struct cnl_ddi_buf_trans * ddi_translations = NULL ;
1782+ u32 n_entries , val , voltage ;
1783+ int ln ;
1784+
1785+ /*
1786+ * Values for each port type are listed in
1787+ * voltage swing programming tables.
1788+ * Vccio voltage found in PORT_COMP_DW3.
1789+ */
1790+ voltage = I915_READ (CNL_PORT_COMP_DW3 ) & VOLTAGE_INFO_MASK ;
1791+
1792+ if (type == INTEL_OUTPUT_HDMI ) {
1793+ ddi_translations = cnl_get_buf_trans_hdmi (dev_priv ,
1794+ voltage , & n_entries );
1795+ } else if (type == INTEL_OUTPUT_DP ) {
1796+ ddi_translations = cnl_get_buf_trans_dp (dev_priv ,
1797+ voltage , & n_entries );
1798+ } else if (type == INTEL_OUTPUT_EDP ) {
1799+ ddi_translations = cnl_get_buf_trans_edp (dev_priv ,
1800+ voltage , & n_entries );
1801+ }
1802+
1803+ if (ddi_translations == NULL ) {
1804+ MISSING_CASE (voltage );
1805+ return ;
1806+ }
1807+
1808+ if (level >= n_entries ) {
1809+ DRM_DEBUG_KMS ("DDI translation not found for level %d. Using %d instead." , level , n_entries - 1 );
1810+ level = n_entries - 1 ;
1811+ }
1812+
1813+ /* Set PORT_TX_DW5 Scaling Mode Sel to 010b. */
1814+ val = I915_READ (CNL_PORT_TX_DW5_LN0 (port ));
1815+ val |= SCALING_MODE_SEL (2 );
1816+ I915_WRITE (CNL_PORT_TX_DW5_GRP (port ), val );
1817+
1818+ /* Program PORT_TX_DW2 */
1819+ val = I915_READ (CNL_PORT_TX_DW2_LN0 (port ));
1820+ val |= SWING_SEL_UPPER (ddi_translations [level ].dw2_swing_sel );
1821+ val |= SWING_SEL_LOWER (ddi_translations [level ].dw2_swing_sel );
1822+ /* Rcomp scalar is fixed as 0x98 for every table entry */
1823+ val |= RCOMP_SCALAR (0x98 );
1824+ I915_WRITE (CNL_PORT_TX_DW2_GRP (port ), val );
1825+
1826+ /* Program PORT_TX_DW4 */
1827+ /* We cannot write to GRP. It would overrite individual loadgen */
1828+ for (ln = 0 ; ln < 4 ; ln ++ ) {
1829+ val = I915_READ (CNL_PORT_TX_DW4_LN (port , ln ));
1830+ val |= POST_CURSOR_1 (ddi_translations [level ].dw4_post_cursor_1 );
1831+ val |= POST_CURSOR_2 (ddi_translations [level ].dw4_post_cursor_2 );
1832+ val |= CURSOR_COEFF (ddi_translations [level ].dw4_cursor_coeff );
1833+ I915_WRITE (CNL_PORT_TX_DW4_LN (port , ln ), val );
1834+ }
1835+
1836+ /* Program PORT_TX_DW5 */
1837+ /* All DW5 values are fixed for every table entry */
1838+ val = I915_READ (CNL_PORT_TX_DW5_LN0 (port ));
1839+ val |= RTERM_SELECT (6 );
1840+ val |= TAP3_DISABLE ;
1841+ I915_WRITE (CNL_PORT_TX_DW5_GRP (port ), val );
1842+
1843+ /* Program PORT_TX_DW7 */
1844+ val = I915_READ (CNL_PORT_TX_DW7_LN0 (port ));
1845+ val |= N_SCALAR (ddi_translations [level ].dw7_n_scalar );
1846+ I915_WRITE (CNL_PORT_TX_DW7_GRP (port ), val );
1847+ }
1848+
1849+ static void cnl_ddi_vswing_sequence (struct drm_i915_private * dev_priv ,
1850+ u32 level , enum port port , int type )
1851+ {
1852+ u32 val ;
1853+
1854+ /*
1855+ * 1. If port type is eDP or DP,
1856+ * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
1857+ * else clear to 0b.
1858+ */
1859+ val = I915_READ (CNL_PORT_PCS_DW1_LN0 (port ));
1860+ if (type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP )
1861+ val |= COMMON_KEEPER_EN ;
1862+ else
1863+ val &= ~COMMON_KEEPER_EN ;
1864+ I915_WRITE (CNL_PORT_PCS_DW1_GRP (port ), val );
1865+
1866+ /* 2. Program loadgen select */
1867+ /*
1868+ * FIXME: Program PORT_TX_DW4_LN depending on Bit rate and used lanes
1869+ */
1870+
1871+ /* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
1872+ val = I915_READ (CNL_PORT_CL1CM_DW5 );
1873+ val |= SUS_CLOCK_CONFIG ;
1874+ I915_WRITE (CNL_PORT_CL1CM_DW5 , val );
1875+
1876+ /* 4. Clear training enable to change swing values */
1877+ val = I915_READ (CNL_PORT_TX_DW5_LN0 (port ));
1878+ val &= ~TX_TRAINING_EN ;
1879+ I915_WRITE (CNL_PORT_TX_DW5_GRP (port ), val );
1880+
1881+ /* 5. Program swing and de-emphasis */
1882+ cnl_ddi_vswing_program (dev_priv , level , port , type );
1883+
1884+ /* 6. Set training enable to trigger update */
1885+ val = I915_READ (CNL_PORT_TX_DW5_LN0 (port ));
1886+ val |= TX_TRAINING_EN ;
1887+ I915_WRITE (CNL_PORT_TX_DW5_GRP (port ), val );
1888+ }
1889+
17231890static uint32_t translate_signal_level (int signal_levels )
17241891{
17251892 int i ;
@@ -1752,7 +1919,11 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
17521919 skl_ddi_set_iboost (encoder , level );
17531920 else if (IS_GEN9_LP (dev_priv ))
17541921 bxt_ddi_vswing_sequence (dev_priv , level , port , encoder -> type );
1755-
1922+ else if (IS_CANNONLAKE (dev_priv )) {
1923+ cnl_ddi_vswing_sequence (dev_priv , level , port , encoder -> type );
1924+ /* DDI_BUF_CTL bits 27:24 are reserved on CNL */
1925+ return 0 ;
1926+ }
17561927 return DDI_BUF_TRANS_SELECT (level );
17571928}
17581929
@@ -1850,6 +2021,9 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
18502021 else if (IS_GEN9_LP (dev_priv ))
18512022 bxt_ddi_vswing_sequence (dev_priv , level , port ,
18522023 INTEL_OUTPUT_HDMI );
2024+ else if (IS_CANNONLAKE (dev_priv ))
2025+ cnl_ddi_vswing_sequence (dev_priv , level , port ,
2026+ INTEL_OUTPUT_HDMI );
18532027
18542028 intel_hdmi -> set_infoframes (drm_encoder ,
18552029 has_hdmi_sink ,
0 commit comments