[Intel-gfx] [PATCH v2 2/2] drm/i915/icl: Implement voltage swing programming sequence for MG PHY DDI

Paulo Zanoni paulo.r.zanoni at intel.com
Mon Jul 16 23:48:33 UTC 2018


Em Qui, 2018-06-28 às 15:35 -0700, Manasi Navare escreveu:
> This sequence is used to setup voltage swing before enabling MG PHY
> DDI
> as well as for changing the voltage during DisplayPort Link training.
> 
> For ICL, there are two types of DDIs. This sequence needs to be used
> for MG PHY DDI which is ports C-F.

And our spec is still incomplete...

Reviewed-by: Paulo Zanoni <paulo.r.zanoni at intel.com>

> 
> v6 (From Manasi):
> * Add programming for MG_CLKHUB and MG_TX_DCC as per the
> spec updates
> 
> v5 (from Paulo):
> * Checkpatch.
> v4 (from Paulo):
> * Fix bogus error message
> * Fix copy+paste bugs (missing s/TX1/TX2/ after copy+paste)
> * Use the new mask names
> * Stay under 80 columns
> * Add some blank lines
> v3:
> * Clear the regs before writing (Paulo)
> v2:
> * Rename to MG PHY in the function def (Jani Nikula)
> * Rebase on top of new revision of other patches in series
> 
> Cc: Rodrigo Vivi <rodrigo.vivi at intel.com>
> Cc: Jani Nikula <jani.nikula at linux.intel.com>
> Signed-off-by: Manasi Navare <manasi.d.navare at intel.com>
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c | 135
> +++++++++++++++++++++++++++++++++++++--
>  1 file changed, 129 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> b/drivers/gpu/drm/i915/intel_ddi.c
> index 0319825..c91e96e 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2459,7 +2459,128 @@ static void
> icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
>  	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
>  }
>  
> -static void icl_ddi_vswing_sequence(struct intel_encoder *encoder,
> u32 level,
> +static void icl_mg_phy_ddi_vswing_sequence(struct intel_encoder
> *encoder,
> +					   int link_clock,
> +					   u32 level)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder-
> >base.dev);
> +	enum port port = encoder->port;
> +	const struct icl_mg_phy_ddi_buf_trans *ddi_translations;
> +	u32 n_entries, val;
> +	int ln;
> +
> +	n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
> +	ddi_translations = icl_mg_phy_ddi_translations;
> +	/* The table does not have values for level 3 and level 9.
> */
> +	if (level >= n_entries || level == 3 || level == 9) {
> +		DRM_DEBUG_KMS("DDI translation not found for level
> %d. Using %d instead.",
> +			      level, n_entries - 2);
> +		level = n_entries - 2;
> +	}
> +
> +	/* Set MG_TX_LINK_PARAMS cri_use_fs32 to 0. */
> +	for (ln = 0; ln < 2; ln++) {
> +		val = I915_READ(MG_TX1_LINK_PARAMS(port, ln));
> +		val &= ~CRI_USE_FS32;
> +		I915_WRITE(MG_TX1_LINK_PARAMS(port, ln), val);
> +
> +		val = I915_READ(MG_TX2_LINK_PARAMS(port, ln));
> +		val &= ~CRI_USE_FS32;
> +		I915_WRITE(MG_TX2_LINK_PARAMS(port, ln), val);
> +	}
> +
> +	/* Program MG_TX_SWINGCTRL with values from vswing table */
> +	for (ln = 0; ln < 2; ln++) {
> +		val = I915_READ(MG_TX1_SWINGCTRL(port, ln));
> +		val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK;
> +		val |= CRI_TXDEEMPH_OVERRIDE_17_12(
> +			ddi_translations[level].cri_txdeemph_overrid
> e_17_12);
> +		I915_WRITE(MG_TX1_SWINGCTRL(port, ln), val);
> +
> +		val = I915_READ(MG_TX2_SWINGCTRL(port, ln));
> +		val &= ~CRI_TXDEEMPH_OVERRIDE_17_12_MASK;
> +		val |= CRI_TXDEEMPH_OVERRIDE_17_12(
> +			ddi_translations[level].cri_txdeemph_overrid
> e_17_12);
> +		I915_WRITE(MG_TX2_SWINGCTRL(port, ln), val);
> +	}
> +
> +	/* Program MG_TX_DRVCTRL with values from vswing table */
> +	for (ln = 0; ln < 2; ln++) {
> +		val = I915_READ(MG_TX1_DRVCTRL(port, ln));
> +		val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
> +			 CRI_TXDEEMPH_OVERRIDE_5_0_MASK);
> +		val |= CRI_TXDEEMPH_OVERRIDE_5_0(
> +			ddi_translations[level].cri_txdeemph_overrid
> e_5_0) |
> +			CRI_TXDEEMPH_OVERRIDE_11_6(
> +				ddi_translations[level].cri_txdeemph
> _override_11_6) |
> +			CRI_TXDEEMPH_OVERRIDE_EN;
> +		I915_WRITE(MG_TX1_DRVCTRL(port, ln), val);
> +
> +		val = I915_READ(MG_TX2_DRVCTRL(port, ln));
> +		val &= ~(CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
> +			 CRI_TXDEEMPH_OVERRIDE_5_0_MASK);
> +		val |= CRI_TXDEEMPH_OVERRIDE_5_0(
> +			ddi_translations[level].cri_txdeemph_overrid
> e_5_0) |
> +			CRI_TXDEEMPH_OVERRIDE_11_6(
> +				ddi_translations[level].cri_txdeemph
> _override_11_6) |
> +			CRI_TXDEEMPH_OVERRIDE_EN;
> +		I915_WRITE(MG_TX2_DRVCTRL(port, ln), val);
> +
> +		/* FIXME: Program CRI_LOADGEN_SEL after the spec is
> updated */
> +	}
> +
> +	/*
> +	 * Program MG_CLKHUB<LN, port being used> with value from
> frequency table
> +	 * In case of Legacy mode on MG PHY, both TX1 and TX2
> enabled so use the
> +	 * values from table for which TX1 and TX2 enabled.
> +	 */
> +	for (ln = 0; ln < 2; ln++) {
> +		val = I915_READ(MG_CLKHUB(port, ln));
> +		if (link_clock < 300000)
> +			val |= CFG_LOW_RATE_LKREN_EN;
> +		else
> +			val &= ~CFG_LOW_RATE_LKREN_EN;
> +		I915_WRITE(MG_CLKHUB(port, ln), val);
> +	}
> +
> +	/* Program the MG_TX_DCC<LN, port being used> based on the
> link frequency */
> +	for (ln = 0; ln < 2; ln++) {
> +		val = I915_READ(MG_TX1_DCC(port, ln));
> +		val &= ~CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK;
> +		if (link_clock <= 500000) {
> +			val &= ~CFG_AMI_CK_DIV_OVERRIDE_EN;
> +		} else {
> +			val |= CFG_AMI_CK_DIV_OVERRIDE_EN |
> +				CFG_AMI_CK_DIV_OVERRIDE_VAL(1);
> +		}
> +		I915_WRITE(MG_TX1_DCC(port, ln), val);
> +
> +		val = I915_READ(MG_TX2_DCC(port, ln));
> +		val &= ~CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK;
> +		if (link_clock <= 500000) {
> +			val &= ~CFG_AMI_CK_DIV_OVERRIDE_EN;
> +		} else {
> +			val |= CFG_AMI_CK_DIV_OVERRIDE_EN |
> +				CFG_AMI_CK_DIV_OVERRIDE_VAL(1);
> +		}
> +		I915_WRITE(MG_TX2_DCC(port, ln), val);
> +	}
> +
> +	/* Program MG_TX_PISO_READLOAD with values from vswing table
> */
> +	for (ln = 0; ln < 2; ln++) {
> +		val = I915_READ(MG_TX1_PISO_READLOAD(port, ln));
> +		val |= CRI_CALCINIT;
> +		I915_WRITE(MG_TX1_PISO_READLOAD(port, ln), val);
> +
> +		val = I915_READ(MG_TX2_PISO_READLOAD(port, ln));
> +		val |= CRI_CALCINIT;
> +		I915_WRITE(MG_TX2_PISO_READLOAD(port, ln), val);
> +	}
> +}
> +
> +static void icl_ddi_vswing_sequence(struct intel_encoder *encoder,
> +				    int link_clock,
> +				    u32 level,
>  				    enum intel_output_type type)
>  {
>  	enum port port = encoder->port;
> @@ -2467,8 +2588,7 @@ static void icl_ddi_vswing_sequence(struct
> intel_encoder *encoder, u32 level,
>  	if (port == PORT_A || port == PORT_B)
>  		icl_combo_phy_ddi_vswing_sequence(encoder, level,
> type);
>  	else
> -		/* Not Implemented Yet */
> -		WARN_ON(1);
> +		icl_mg_phy_ddi_vswing_sequence(encoder, link_clock,
> level);
>  }
>  
>  static uint32_t translate_signal_level(int signal_levels)
> @@ -2503,7 +2623,8 @@ u32 bxt_signal_levels(struct intel_dp
> *intel_dp)
>  	int level = intel_ddi_dp_level(intel_dp);
>  
>  	if (IS_ICELAKE(dev_priv))
> -		icl_ddi_vswing_sequence(encoder, level, encoder-
> >type);
> +		icl_ddi_vswing_sequence(encoder, intel_dp-
> >link_rate,
> +					level, encoder->type);
>  	else if (IS_CANNONLAKE(dev_priv))
>  		cnl_ddi_vswing_sequence(encoder, level, encoder-
> >type);
>  	else
> @@ -2684,7 +2805,8 @@ 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_ICELAKE(dev_priv))
> -		icl_ddi_vswing_sequence(encoder, level, encoder-
> >type);
> +		icl_ddi_vswing_sequence(encoder, crtc_state-
> >port_clock,
> +					level, encoder->type);
>  	else if (IS_CANNONLAKE(dev_priv))
>  		cnl_ddi_vswing_sequence(encoder, level, encoder-
> >type);
>  	else if (IS_GEN9_LP(dev_priv))
> @@ -2719,7 +2841,8 @@ 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_ICELAKE(dev_priv))
> -		icl_ddi_vswing_sequence(encoder, level,
> INTEL_OUTPUT_HDMI);
> +		icl_ddi_vswing_sequence(encoder, crtc_state-
> >port_clock,
> +					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))


More information about the Intel-gfx mailing list