diff mbox

[06/36] drm/i915: train Haswell FDI at the right time

Message ID 1351714375-15284-7-git-send-email-przanoni@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Paulo Zanoni Oct. 31, 2012, 8:12 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Haswell FDI link training is very different from the previous
generations.

After this commit, hsw_fdi_link_train is responsible for implementing
all the steps described as "Enable and train FDI" from the Haswell
CRT mode set sequence documentation.

We need to train the FDI before enabling the pipes and planes, so
we're moving the call from lpt_pch_enable to haswell_crtc_enable
directly.

We are also removing ironlake_fdi_pll_enable since the PLL enablement
on Haswell is completely different and is also done during the link
training steps.

There are still quite a few things we need to fix on
hsw_fdi_link_train, so stay tuned for the next patches :)

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      | 17 +++++++++++------
 drivers/gpu/drm/i915/intel_ddi.c     | 34 ++++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_display.c |  5 +----
 3 files changed, 36 insertions(+), 20 deletions(-)

Comments

Daniel Vetter Nov. 1, 2012, 3:07 p.m. UTC | #1
On Wed, Oct 31, 2012 at 06:12:25PM -0200, Paulo Zanoni wrote:
> From: Paulo Zanoni <paulo.r.zanoni@intel.com>
> 
> Haswell FDI link training is very different from the previous
> generations.
> 
> After this commit, hsw_fdi_link_train is responsible for implementing
> all the steps described as "Enable and train FDI" from the Haswell
> CRT mode set sequence documentation.
> 
> We need to train the FDI before enabling the pipes and planes, so
> we're moving the call from lpt_pch_enable to haswell_crtc_enable
> directly.
> 
> We are also removing ironlake_fdi_pll_enable since the PLL enablement
> on Haswell is completely different and is also done during the link
> training steps.
> 
> There are still quite a few things we need to fix on
> hsw_fdi_link_train, so stay tuned for the next patches :)
> 
> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h      | 17 +++++++++++------
>  drivers/gpu/drm/i915/intel_ddi.c     | 34 ++++++++++++++++++++++++----------
>  drivers/gpu/drm/i915/intel_display.c |  5 +----
>  3 files changed, 36 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 0514823..abdc002 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -3917,16 +3917,21 @@
>  #define  FDI_PORT_WIDTH_2X_LPT			(1<<19)
>  #define  FDI_PORT_WIDTH_1X_LPT			(0<<19)
>  
> -#define _FDI_RXA_MISC            0xf0010
> -#define _FDI_RXB_MISC            0xf1010
> +#define _FDI_RXA_MISC			0xf0010
> +#define _FDI_RXB_MISC			0xf1010
> +#define  FDI_RX_PWRDN_LANE1_MASK	(3<<26)
> +#define  FDI_RX_PWRDN_LANE1_VAL(x)	((x)<<26)
> +#define  FDI_RX_PWRDN_LANE0_MASK	(3<<24)
> +#define  FDI_RX_PWRDN_LANE0_VAL(x)	((x)<<24)
> +#define  FDI_RX_TP1_TO_TP2_48		(2<<20)
> +#define  FDI_RX_TP1_TO_TP2_64		(3<<20)
> +#define  FDI_RX_FDI_DELAY_90		(0x90<<0)
> +#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
> +
>  #define _FDI_RXA_TUSIZE1         0xf0030
>  #define _FDI_RXA_TUSIZE2         0xf0038
>  #define _FDI_RXB_TUSIZE1         0xf1030
>  #define _FDI_RXB_TUSIZE2         0xf1038
> -#define  FDI_RX_TP1_TO_TP2_48	(2<<20)
> -#define  FDI_RX_TP1_TO_TP2_64	(3<<20)
> -#define  FDI_RX_FDI_DELAY_90	(0x90<<0)
> -#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
>  #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1)
>  #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2)
>  
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 67bd6ba..39a53b4 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -154,7 +154,30 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	int pipe = intel_crtc->pipe;
> -	u32 reg, temp, i;
> +	u32 reg, temp, i, rx_ctl_val;
> +
> +	/* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
> +	 * mode set "sequence for CRT port" document:
> +	 * - TP1 to TP2 time with the default value
> +	 * - FDI delay to 90h
> +	 */
> +	I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) |
> +				  FDI_RX_PWRDN_LANE0_VAL(2) |
> +				  FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
> +
> +	/* Enable the PCH Receiver FDI PLL */
> +	rx_ctl_val = FDI_RX_PLL_ENABLE | FDI_RX_ENHANCE_FRAME_ENABLE |
> +		     ((intel_crtc->fdi_lanes - 1) << 19);

You switch here to a variable selection of the port width/number of fdi
lanes you're using on the RX side. But the TX side below is still fixed to
2X. I guess this part here belongs in another patch?
-Daniel

> +	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
> +	POSTING_READ(_FDI_RXA_CTL);
> +	udelay(220);
> +
> +	/* Switch from Rawclk to PCDclk */
> +	rx_ctl_val |= FDI_PCDCLK;
> +	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
> +
> +	/* Configure Port Clock Select */
> +	I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel);
>  
>  	/* Start the training iterating through available voltages and emphasis */
>  	for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) {
> @@ -176,15 +199,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
>  
>  		udelay(600);
>  
> -		/* We need to program FDI_RX_MISC with the default TP1 to TP2
> -		 * values before enabling the receiver, and configure the delay
> -		 * for the FDI timing generator to 90h. Luckily, all the other
> -		 * bits are supposed to be zeroed, so we can write those values
> -		 * directly.
> -		 */
> -		I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 |
> -				FDI_RX_FDI_DELAY_90);
> -
>  		/* Enable CPU FDI Receiver with auto-training */
>  		reg = FDI_RX_CTL(pipe);
>  		I915_WRITE(reg,
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 2dff7b2..e0b1f8c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3147,9 +3147,6 @@ static void lpt_pch_enable(struct drm_crtc *crtc)
>  	I915_WRITE(FDI_RX_TUSIZE1(pipe),
>  		   I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
>  
> -	/* For PCH output, training FDI link */
> -	dev_priv->display.fdi_link_train(crtc);
> -
>  	/* XXX: pch pll's can be enabled any time before we enable the PCH
>  	 * transcoder, and we actually should do this to not upset any PCH
>  	 * transcoder that already use the clock when we share it.
> @@ -3389,7 +3386,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  	is_pch_port = haswell_crtc_driving_pch(crtc);
>  
>  	if (is_pch_port)
> -		ironlake_fdi_pll_enable(intel_crtc);
> +		dev_priv->display.fdi_link_train(crtc);
>  
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
>  		if (encoder->pre_enable)
> -- 
> 1.7.11.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 0514823..abdc002 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3917,16 +3917,21 @@ 
 #define  FDI_PORT_WIDTH_2X_LPT			(1<<19)
 #define  FDI_PORT_WIDTH_1X_LPT			(0<<19)
 
-#define _FDI_RXA_MISC            0xf0010
-#define _FDI_RXB_MISC            0xf1010
+#define _FDI_RXA_MISC			0xf0010
+#define _FDI_RXB_MISC			0xf1010
+#define  FDI_RX_PWRDN_LANE1_MASK	(3<<26)
+#define  FDI_RX_PWRDN_LANE1_VAL(x)	((x)<<26)
+#define  FDI_RX_PWRDN_LANE0_MASK	(3<<24)
+#define  FDI_RX_PWRDN_LANE0_VAL(x)	((x)<<24)
+#define  FDI_RX_TP1_TO_TP2_48		(2<<20)
+#define  FDI_RX_TP1_TO_TP2_64		(3<<20)
+#define  FDI_RX_FDI_DELAY_90		(0x90<<0)
+#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
+
 #define _FDI_RXA_TUSIZE1         0xf0030
 #define _FDI_RXA_TUSIZE2         0xf0038
 #define _FDI_RXB_TUSIZE1         0xf1030
 #define _FDI_RXB_TUSIZE2         0xf1038
-#define  FDI_RX_TP1_TO_TP2_48	(2<<20)
-#define  FDI_RX_TP1_TO_TP2_64	(3<<20)
-#define  FDI_RX_FDI_DELAY_90	(0x90<<0)
-#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
 #define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1)
 #define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2)
 
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 67bd6ba..39a53b4 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -154,7 +154,30 @@  void hsw_fdi_link_train(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	u32 reg, temp, i;
+	u32 reg, temp, i, rx_ctl_val;
+
+	/* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the
+	 * mode set "sequence for CRT port" document:
+	 * - TP1 to TP2 time with the default value
+	 * - FDI delay to 90h
+	 */
+	I915_WRITE(_FDI_RXA_MISC, FDI_RX_PWRDN_LANE1_VAL(2) |
+				  FDI_RX_PWRDN_LANE0_VAL(2) |
+				  FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);
+
+	/* Enable the PCH Receiver FDI PLL */
+	rx_ctl_val = FDI_RX_PLL_ENABLE | FDI_RX_ENHANCE_FRAME_ENABLE |
+		     ((intel_crtc->fdi_lanes - 1) << 19);
+	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
+	POSTING_READ(_FDI_RXA_CTL);
+	udelay(220);
+
+	/* Switch from Rawclk to PCDclk */
+	rx_ctl_val |= FDI_PCDCLK;
+	I915_WRITE(_FDI_RXA_CTL, rx_ctl_val);
+
+	/* Configure Port Clock Select */
+	I915_WRITE(PORT_CLK_SEL(PORT_E), intel_crtc->ddi_pll_sel);
 
 	/* Start the training iterating through available voltages and emphasis */
 	for (i=0; i < ARRAY_SIZE(hsw_ddi_buf_ctl_values); i++) {
@@ -176,15 +199,6 @@  void hsw_fdi_link_train(struct drm_crtc *crtc)
 
 		udelay(600);
 
-		/* We need to program FDI_RX_MISC with the default TP1 to TP2
-		 * values before enabling the receiver, and configure the delay
-		 * for the FDI timing generator to 90h. Luckily, all the other
-		 * bits are supposed to be zeroed, so we can write those values
-		 * directly.
-		 */
-		I915_WRITE(FDI_RX_MISC(pipe), FDI_RX_TP1_TO_TP2_48 |
-				FDI_RX_FDI_DELAY_90);
-
 		/* Enable CPU FDI Receiver with auto-training */
 		reg = FDI_RX_CTL(pipe);
 		I915_WRITE(reg,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2dff7b2..e0b1f8c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3147,9 +3147,6 @@  static void lpt_pch_enable(struct drm_crtc *crtc)
 	I915_WRITE(FDI_RX_TUSIZE1(pipe),
 		   I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
 
-	/* For PCH output, training FDI link */
-	dev_priv->display.fdi_link_train(crtc);
-
 	/* XXX: pch pll's can be enabled any time before we enable the PCH
 	 * transcoder, and we actually should do this to not upset any PCH
 	 * transcoder that already use the clock when we share it.
@@ -3389,7 +3386,7 @@  static void haswell_crtc_enable(struct drm_crtc *crtc)
 	is_pch_port = haswell_crtc_driving_pch(crtc);
 
 	if (is_pch_port)
-		ironlake_fdi_pll_enable(intel_crtc);
+		dev_priv->display.fdi_link_train(crtc);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)