diff mbox

[03/11] drm/i915: update VLV PLL and DPIO code v8

Message ID 1364489747-2050-3-git-send-email-jbarnes@virtuousgeek.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jesse Barnes March 28, 2013, 4:55 p.m. UTC
In Valleyview voltage swing, pre-emphasis and lane control registers can
be programmed only through the h/w side band fabric.  Update
vlv_update_pll, i9xx_crtc_enable, and intel_enable_pll with the
appropriate programming.

We need to make sure that the tx lane reset occurs in both the full mode
set and DPMS paths, so factor things out to allow that.

v2: use different DPIO_DIVISOR values for VGA and DisplayPort
v3: Fix update pll logic to use same DPIO_DIVISOR & DPIO_REFSFR values
	for all display interfaces
v4: collapse with various updates
v5: squash with crtc enable/pll enable bits
v6: split out DP code (jbarnes)
    put phyready check under IS_VALLEYVIEW (jbarnes)
    remove unneeded check in 9xx pll div update (Jani)
    wrap VLV pll update call in IS_VALLEYVIEW (Jani)
    move port enable back to end of crtc enable (jbarnes)
    put phyready check under IS_VALLEYVIEW (jbarnes)
v7: fix up conflicts against latest drm-intel-next-queued
v8: use DPIO reg names, fix pipes (Jani)
    from mPhy_registers_VLV2_ww20p5 doc

Signed-off-by: Pallavi G <pallavi.g@intel.com>
Signed-off-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
Signed-off-by: Gajanan Bhat <gajanan.bhat@intel.com>
Signed-off-by: Ben Widawsky <benjamin.widawsky@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h      |  107 ++++++++++++-
 drivers/gpu/drm/i915/intel_display.c |  274 ++++++++++++++++++++++++++--------
 2 files changed, 320 insertions(+), 61 deletions(-)

Comments

Daniel Vetter April 2, 2013, 6:47 p.m. UTC | #1
On Thu, Mar 28, 2013 at 09:55:39AM -0700, Jesse Barnes wrote:
> In Valleyview voltage swing, pre-emphasis and lane control registers can
> be programmed only through the h/w side band fabric.  Update
> vlv_update_pll, i9xx_crtc_enable, and intel_enable_pll with the
> appropriate programming.
> 
> We need to make sure that the tx lane reset occurs in both the full mode
> set and DPMS paths, so factor things out to allow that.
> 
> v2: use different DPIO_DIVISOR values for VGA and DisplayPort
> v3: Fix update pll logic to use same DPIO_DIVISOR & DPIO_REFSFR values
> 	for all display interfaces
> v4: collapse with various updates
> v5: squash with crtc enable/pll enable bits
> v6: split out DP code (jbarnes)
>     put phyready check under IS_VALLEYVIEW (jbarnes)
>     remove unneeded check in 9xx pll div update (Jani)
>     wrap VLV pll update call in IS_VALLEYVIEW (Jani)
>     move port enable back to end of crtc enable (jbarnes)
>     put phyready check under IS_VALLEYVIEW (jbarnes)
> v7: fix up conflicts against latest drm-intel-next-queued
> v8: use DPIO reg names, fix pipes (Jani)
>     from mPhy_registers_VLV2_ww20p5 doc
> 
> Signed-off-by: Pallavi G <pallavi.g@intel.com>
> Signed-off-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
> Signed-off-by: Gajanan Bhat <gajanan.bhat@intel.com>
> Signed-off-by: Ben Widawsky <benjamin.widawsky@intel.com>

Imo this is still a bit too horrible to live. Iirc I've had a massive
bikeshed review, but then noticed that I don't understand at all what this
code does and so dropped it. A few random things I've remembered:
- There's lots of magic pipe checks, imo if (pipe == PIPE_B) reads better
  than if (pipe). Especially since we also have now platforms with more
  than just 2 pipes. Also s/1/PIPE_B/ at some places.
- This patch does too much, e.g. vlv_init_dpio seems to now be used as a
  generic reset function in crtc_disable, but is still called _init. Also
  looks like an orthogonal patch to me.
- Some of the #defines are seriously misguided as to whether they're
  dealing with a pipe or a port. Last time I've check some #defines
  weren't used, but I didn't bother this time around with checking them
  all again.
- Some of the intel_has_type checks look fishy and would look better when
  replaced with a port enum or something like that. Others look like they
  hardcode pll selections in strange ways (I have no clue with all that
  magic).
- intel_mode_get_pixel_multiplier is gone, so this doesn't apply on latest
  dinq.
- Some function extraction looks easily doable, e.g. extracting the "port
  ready" wait in mode_set and crtc_enable
- I still suspect that some of these checks/hacks predate the modeset
  rework since stuff is seemingly duplicated at a bunch of places ...

I think some gentle patch splitting, slight refactoring and liberal
sprinklig of FIXME comments should get this one here into shape.
Especially if we know that a given piece of code here is just pre-silicon
hacks or hard-wired to the sdv board layout.

Cheers, Daniel
> ---
>  drivers/gpu/drm/i915/i915_reg.h      |  107 ++++++++++++-
>  drivers/gpu/drm/i915/intel_display.c |  274 ++++++++++++++++++++++++++--------
>  2 files changed, 320 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index d0f7cb9..858a712 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -362,6 +362,11 @@
>  #define  DPIO_SFR_BYPASS		(1<<1)
>  #define  DPIO_RESET			(1<<0)
>  
> +#define _DPIO_TX3_SWING_CTL4_A		0x690
> +#define _DPIO_TX3_SWING_CTL4_B		0x2a90
> +#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \
> +					_DPIO_TX3_SWING_CTL4_B)
> +
>  #define _DPIO_DIV_A			0x800c
>  #define   DPIO_POST_DIV_SHIFT		(28) /* 3 bits */
>  #define   DPIO_K_SHIFT			(24) /* 4 bits */
> @@ -389,14 +394,109 @@
>  #define _DPIO_CORE_CLK_B		0x803c
>  #define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B)
>  
> +#define _DPIO_IREF_CTL_A		0x8040
> +#define _DPIO_IREF_CTL_B		0x8060
> +#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B)
> +
> +#define DPIO_IREF_BCAST			0xc044
> +#define _DPIO_IREF_A			0x8044
> +#define _DPIO_IREF_B			0x8064
> +#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B)
> +
> +#define _DPIO_PLL_CML_A			0x804c
> +#define _DPIO_PLL_CML_B			0x806c
> +#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B)
> +
>  #define _DPIO_LFP_COEFF_A		0x8048
>  #define _DPIO_LFP_COEFF_B		0x8068
>  #define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B)
>  
> +#define DPIO_CALIBRATION		0x80ac
> +
>  #define DPIO_FASTCLK_DISABLE		0x8100
>  
> -#define DPIO_DATA_CHANNEL1		0x8220
> -#define DPIO_DATA_CHANNEL2		0x8420
> +#define _DPIO_PCS_TX_0			0x8200
> +#define _DPIO_PCS_TX_1			0x8400
> +#define   DPIO_PCS_TX_LANE2_RESET	(1<<16)
> +#define   DPIO_PCS_TX_LANE1_RESET	(1<<7)
> +#define DPIO_PCS_TX(pipe) _PIPE(pipe, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1)
> +
> +#define _DPIO_PCS_CLK_0			0x8204
> +#define _DPIO_PCS_CLK_1			0x8404
> +#define   DPIO_PCS_CLK_CRI_RXEB_EIOS_EN	(1<<22)
> +#define   DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21)
> +#define   DPIO_PCS_CLK_DATAWIDTH_SHIFT	(6)
> +#define   DPIO_PCS_CLK_SOFT_RESET	(1<<5)
> +#define DPIO_PCS_CLK(pipe) _PIPE(pipe, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1)
> +
> +#define _DPIO_PCS_CTL_OVR1_A		0x8224
> +#define _DPIO_PCS_CTL_OVR1_B		0x8424
> +#define DPIO_PCS_CTL_OVER1(pipe) _PIPE(pipe, _DPIO_PCS_CTL_OVR1_A, \
> +				       _DPIO_PCS_CTL_OVR1_B)
> +
> +#define _DPIO_PCS_STAGGER0_A		0x822c
> +#define _DPIO_PCS_STAGGER0_B		0x842c
> +#define DPIO_PCS_STAGGER0(pipe) _PIPE(pipe, _DPIO_PCS_STAGGER0_A, \
> +				      _DPIO_PCS_STAGGER0_B)
> +
> +#define _DPIO_PCS_STAGGER1_A		0x8230
> +#define _DPIO_PCS_STAGGER1_B		0x8430
> +#define DPIO_PCS_STAGGER1(pipe) _PIPE(pipe, _DPIO_PCS_STAGGER1_A, \
> +				      _DPIO_PCS_STAGGER1_B)
> +
> +#define _DPIO_PCS_CLOCKBUF0_A		0x8238
> +#define _DPIO_PCS_CLOCKBUF0_B		0x8438
> +#define DPIO_PCS_CLOCKBUF0(pipe) _PIPE(pipe, _DPIO_PCS_CLOCKBUF0_A, \
> +				       _DPIO_PCS_CLOCKBUF0_B)
> +
> +#define _DPIO_PCS_CLOCKBUF8_A		0x825c
> +#define _DPIO_PCS_CLOCKBUF8_B		0x845c
> +#define DPIO_PCS_CLOCKBUF8(pipe) _PIPE(pipe, _DPIO_PCS_CLOCKBUF8_A, \
> +				       _DPIO_PCS_CLOCKBUF8_B)
> +
> +#define _DPIO_TX_SWING_CTL2_A		0x8288
> +#define _DPIO_TX_SWING_CTL2_B		0x8488
> +#define DPIO_TX_SWING_CTL2(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL2_A, \
> +				       _DPIO_TX_SWING_CTL2_B)
> +
> +#define _DPIO_TX_SWING_CTL3_A		0x828c
> +#define _DPIO_TX_SWING_CTL3_B		0x848c
> +#define DPIO_TX_SWING_CTL3(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL3_A, \
> +				       _DPIO_TX_SWING_CTL3_B)
> +
> +#define _DPIO_TX_SWING_CTL4_A		0x8290
> +#define _DPIO_TX_SWING_CTL4_B		0x8490
> +#define DPIO_TX_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \
> +				       _DPIO_TX_SWING_CTL4_B)
> +
> +#define _DPIO_TX_OCALINIT_0		0x8294
> +#define _DPIO_TX_OCALINIT_1		0x8494
> +#define   DPIO_TX_OCALINIT_EN		(1<<31)
> +#define DPIO_TX_OCALINIT(pipe) _PIPE(pipe, _DPIO_TX_OCALINIT_0, \
> +				     _DPIO_TX_OCALINIT_1)
> +
> +#define _DPIO_TX_CTL_0			0x82ac
> +#define _DPIO_TX_CTL_1			0x84ac
> +#define DPIO_TX_CTL(pipe) _PIPE(pipe, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1)
> +
> +#define _DPIO_TX_LANE_0			0x82b8
> +#define _DPIO_TX_LANE_1			0x84b8
> +#define DPIO_TX_LANE(pipe) _PIPE(pipe, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1)
> +
> +#define _DPIO_DATA_CHANNEL1		0x8220
> +#define _DPIO_DATA_CHANNEL2		0x8420
> +#define DPIO_DATA_CHANNEL(pipe) _PIPE(pipe, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2)
> +
> +#define _DPIO_DATA_LANE0		0x0220
> +#define _DPIO_DATA_LANE1		0x0420
> +#define _DPIO_DATA_LANE2		0x2620
> +#define _DPIO_DATA_LANE3		0x2820
> +#define DPIO_DATA_LANE_A(pipe) _PIPE(pipe, _DPIO_DATA_LANE0, _DPIO_DATA_LANE2)
> +#define DPIO_DATA_LANE_B(pipe) _PIPE(pipe, _DPIO_DATA_LANE1, _DPIO_DATA_LANE3)
> +#define DPIO_DATA_CHANNEL1              0x8220
> +#define DPIO_DATA_CHANNEL2              0x8420
> +
> +#define DPIO_TX_BROADCAST		0xc044
>  
>  /*
>   * Fence registers
> @@ -957,7 +1057,10 @@
>  #define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
>  #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW	0x00ff8000 /* Pineview */
>  #define   DPLL_LOCK_VLV			(1<<15)
> +#define   DPLL_INTEGRATED_CRI_CLK_VLV	(1<<14)
>  #define   DPLL_INTEGRATED_CLOCK_VLV	(1<<13)
> +#define   DPLL_PORTC_READY_MASK		(0xf << 4)
> +#define   DPLL_PORTB_READY_MASK		(0xf)
>  
>  #define   DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
>  /*
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 58e3a7c..9cb0b53 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3696,6 +3696,72 @@ g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
>  	}
>  }
>  
> +static void vlv_pll_enable_reset(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	int pipe = intel_crtc->pipe;
> +
> +	WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
> +
> +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
> +		u32 val;
> +		val = intel_dpio_read(dev_priv, _DPIO_DATA_LANE0);
> +		if (pipe)
> +			val |= (1<<21);
> +		val |= (1<<20);
> +		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, val);
> +
> +		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(pipe),
> +				 0x00760018);
> +		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(pipe),
> +				 0x00400888);
> +
> +		intel_dpio_write(dev_priv, DPIO_PCS_TX(pipe),
> +				 DPIO_PCS_TX_LANE2_RESET |
> +				 DPIO_PCS_TX_LANE1_RESET);
> +		intel_dpio_write(dev_priv, DPIO_PCS_CLK(pipe),
> +				 DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
> +				 DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
> +				 (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
> +				 DPIO_PCS_CLK_SOFT_RESET);
> +
> +		intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(pipe), 0);
> +		intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(pipe),
> +				 0x2b245f5f);
> +		intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(pipe),
> +				 0x5578b83a);
> +		intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(pipe),
> +				 0x0c782040);
> +		intel_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(pipe),
> +				 0x2b247878);
> +		intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(pipe), 0x00030000);
> +		intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(pipe),
> +				 0x00002000);
> +		intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(pipe),
> +				 DPIO_TX_OCALINIT_EN);
> +
> +	}
> +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
> +	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
> +		u32 val;
> +		val = intel_dpio_read(dev_priv, _DPIO_DATA_LANE2);
> +		if (pipe)
> +			val |= (1<<21);
> +		val |= (1<<20);
> +		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, val);
> +
> +		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(pipe),
> +				 0x00760018);
> +		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(pipe),
> +				 0x00400888);
> +
> +		intel_dpio_write(dev_priv, DPIO_PCS_TX(pipe), 0x10080);
> +		intel_dpio_write(dev_priv, DPIO_PCS_CLK(pipe), 0x00600060);
> +	}
> +}
> +
>  static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> @@ -3704,6 +3770,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  	struct intel_encoder *encoder;
>  	int pipe = intel_crtc->pipe;
>  	int plane = intel_crtc->plane;
> +	u32 port_mask;
>  
>  	WARN_ON(!crtc->enabled);
>  
> @@ -3715,10 +3782,27 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  
>  	intel_enable_pll(dev_priv, pipe);
>  
> +	if (IS_VALLEYVIEW(dev)) {
> +		mutex_lock(&dev_priv->dpio_lock);
> +		vlv_pll_enable_reset(crtc);
> +		mutex_unlock(&dev_priv->dpio_lock);
> +	}
> +
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
>  		if (encoder->pre_enable)
>  			encoder->pre_enable(encoder);
>  
> +	if (IS_VALLEYVIEW(dev)) {
> +		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
> +		    intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
> +			port_mask = DPLL_PORTB_READY_MASK;
> +		else
> +			port_mask = DPLL_PORTC_READY_MASK; /* eDP on port C */
> +
> +		if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 100))
> +			DRM_ERROR("timed out waiting for port ready\n");
> +	}
> +
>  	intel_enable_pipe(dev_priv, pipe, false);
>  	intel_enable_plane(dev_priv, plane, pipe);
>  	if (IS_G4X(dev))
> @@ -3770,6 +3854,21 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
>  	    ((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe)
>  		I915_WRITE(PFIT_CONTROL, 0);
>  
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		if (encoder->post_disable)
> +			encoder->post_disable(encoder);
> +
> +	/* Reset lane for VLV platform*/
> +	if (IS_VALLEYVIEW(dev)) {
> +		mutex_lock(&dev_priv->dpio_lock);
> +		intel_dpio_write(dev_priv, DPIO_PCS_TX(pipe), 0x00000000);
> +		intel_dpio_write(dev_priv, DPIO_PCS_CLK(pipe), 0x00e00060);
> +
> +		if (pipe)
> +			vlv_init_dpio(dev);
> +		mutex_unlock(&dev_priv->dpio_lock);
> +	}
> +
>  	intel_disable_pll(dev_priv, pipe);
>  
>  	intel_crtc->active = false;
> @@ -4338,6 +4437,31 @@ static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
>  	}
>  }
>  
> +static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv)
> +{
> +	u32 reg_val;
> +
> +	/*
> +	 * PLLB opamp always calibrates to max value of 0x3f, force enable it
> +	 * and set it to a reasonable value instead.
> +	 */
> +	reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1));
> +	reg_val &= 0xffffff30;
> +	intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
> +
> +	reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION);
> +	reg_val &= 0x8cffffff;
> +	intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
> +
> +	reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1));
> +	reg_val &= 0xffffff00;
> +	intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
> +
> +	reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION);
> +	reg_val &= 0xb0ffffff;
> +	intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
> +}
> +
>  static void vlv_update_pll(struct drm_crtc *crtc,
>  			   struct drm_display_mode *mode,
>  			   struct drm_display_mode *adjusted_mode,
> @@ -4348,23 +4472,14 @@ static void vlv_update_pll(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 dpll, mdiv, pdiv;
> +	u32 dpll, mdiv;
>  	u32 bestn, bestm1, bestm2, bestp1, bestp2;
> -	bool is_sdvo;
> -	u32 temp;
> +	bool is_hdmi;
> +	u32 coreclk, reg_val;
>  
>  	mutex_lock(&dev_priv->dpio_lock);
>  
> -	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
> -		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
> -
> -	dpll = DPLL_VGA_MODE_DIS;
> -	dpll |= DPLL_EXT_BUFFER_ENABLE_VLV;
> -	dpll |= DPLL_REFA_CLK_ENABLE_VLV;
> -	dpll |= DPLL_INTEGRATED_CLOCK_VLV;
> -
> -	I915_WRITE(DPLL(pipe), dpll);
> -	POSTING_READ(DPLL(pipe));
> +	is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
>  
>  	bestn = clock->n;
>  	bestm1 = clock->m1;
> @@ -4372,71 +4487,99 @@ static void vlv_update_pll(struct drm_crtc *crtc,
>  	bestp1 = clock->p1;
>  	bestp2 = clock->p2;
>  
> -	/*
> -	 * In Valleyview PLL and program lane counter registers are exposed
> -	 * through DPIO interface
> -	 */
> +	/* See eDP HDMI DPIO driver vbios notes doc */
> +
> +	/* PLL B needs special handling */
> +	if (pipe)
> +		vlv_pllb_recal_opamp(dev_priv);
> +
> +	/* Set up Tx target for periodic Rcomp update */
> +	intel_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f);
> +
> +	/* Disable target IRef on PLL */
> +	reg_val = intel_dpio_read(dev_priv, DPIO_IREF_CTL(pipe));
> +	reg_val &= 0x00ffffff;
> +	intel_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val);
> +
> +	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610);
> +
> +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
> +	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
> +		if (adjusted_mode->clock == 162000)
> +			intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
> +					 0x009f0003);
> +		else
> +			intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
> +					 0x00d0000f);
> +
> +	} else
> +		intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
> +				 0x009f0003);
> +
> +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
> +	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
> +		if (!pipe)
> +			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
> +					 0x0df40000);
> +		else
> +			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
> +					 0x0df70000);
> +	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
> +		if (!pipe)
> +			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
> +					 0x0df70000);
> +		else
> +			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
> +					 0x0df40000);
> +	}
> +
>  	mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
>  	mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
>  	mdiv |= ((bestn << DPIO_N_SHIFT));
>  	mdiv |= (1 << DPIO_POST_DIV_SHIFT);
>  	mdiv |= (1 << DPIO_K_SHIFT);
> +	intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
> +
>  	mdiv |= DPIO_ENABLE_CALIBRATION;
>  	intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
>  
> -	intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000);
> +	coreclk = intel_dpio_read(dev_priv, DPIO_CORE_CLK(pipe));
> +	coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
> +	intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk);
>  
> -	pdiv = (1 << DPIO_REFSEL_OVERRIDE) | (5 << DPIO_PLL_MODESEL_SHIFT) |
> -		(3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) |
> -		(7 << DPIO_PLL_REFCLK_SEL_SHIFT) | (8 << DPIO_DRIVER_CTL_SHIFT) |
> -		(5 << DPIO_CLK_BIAS_CTL_SHIFT);
> -	intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv);
> +	intel_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000);
>  
> -	intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x005f003b);
> +	/* Enable DPIO clock input */
> +	dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
> +		DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
> +	if (pipe)
> +		dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
>  
>  	dpll |= DPLL_VCO_ENABLE;
>  	I915_WRITE(DPLL(pipe), dpll);
>  	POSTING_READ(DPLL(pipe));
> +	udelay(150);
> +
>  	if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
>  		DRM_ERROR("DPLL %d failed to lock\n", pipe);
>  
> -	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x620);
> -
> -	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
> -		intel_dp_set_m_n(crtc, mode, adjusted_mode);
> -
> -	I915_WRITE(DPLL(pipe), dpll);
> -
> -	/* Wait for the clocks to stabilize. */
> -	POSTING_READ(DPLL(pipe));
> -	udelay(150);
> +	if (is_hdmi) {
> +		u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode);
>  
> -	temp = 0;
> -	if (is_sdvo) {
> -		temp = intel_mode_get_pixel_multiplier(adjusted_mode);
>  		if (temp > 1)
>  			temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
>  		else
>  			temp = 0;
> -	}
> -	I915_WRITE(DPLL_MD(pipe), temp);
> -	POSTING_READ(DPLL_MD(pipe));
>  
> -	/* Now program lane control registers */
> -	if(intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)
> -			|| intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
> -	{
> -		temp = 0x1000C4;
> -		if(pipe == 1)
> -			temp |= (1 << 21);
> -		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, temp);
> +		I915_WRITE(DPLL_MD(pipe), temp);
> +		POSTING_READ(DPLL_MD(pipe));
>  	}
> -	if(intel_pipe_has_type(crtc,INTEL_OUTPUT_EDP))
> -	{
> -		temp = 0x1000C4;
> -		if(pipe == 1)
> -			temp |= (1 << 21);
> -		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp);
> +
> +	vlv_pll_enable_reset(crtc);
> +
> +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
> +	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
> +		intel_dp_set_m_n(crtc, mode, adjusted_mode);
>  	}
>  
>  	mutex_unlock(&dev_priv->dpio_lock);
> @@ -4748,11 +4891,12 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
>  		i8xx_update_pll(crtc, adjusted_mode, &clock,
>  				has_reduced_clock ? &reduced_clock : NULL,
>  				num_connectors);
> -	else if (IS_VALLEYVIEW(dev))
> +	else if (IS_VALLEYVIEW(dev)) {
> +		refclk = i9xx_get_refclk(crtc, num_connectors);
>  		vlv_update_pll(crtc, mode, adjusted_mode, &clock,
>  				has_reduced_clock ? &reduced_clock : NULL,
>  				num_connectors);
> -	else
> +	} else
>  		i9xx_update_pll(crtc, mode, adjusted_mode, &clock,
>  				has_reduced_clock ? &reduced_clock : NULL,
>  				num_connectors);
> @@ -4845,6 +4989,21 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
>  
>  	intel_update_watermarks(dev);
>  
> +	if (IS_VALLEYVIEW(dev)) {
> +		u32 port_mask;
> +
> +		/* Wait for Phy status bits to go low */
> +		for_each_encoder_on_crtc(dev, crtc, encoder) {
> +			if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
> +			    encoder->type == INTEL_OUTPUT_HDMI)
> +				port_mask = DPLL_PORTB_READY_MASK;
> +			else
> +				port_mask = DPLL_PORTC_READY_MASK; /* eDP */
> +			if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 100))
> +				DRM_ERROR("timed out waiting for port ready\n");
> +		}
> +	}
> +
>  	return ret;
>  }
>  
> @@ -9284,9 +9443,6 @@ void intel_modeset_cleanup(struct drm_device *dev)
>  
>  	ironlake_teardown_rc6(dev);
>  
> -	if (IS_VALLEYVIEW(dev))
> -		vlv_init_dpio(dev);
> -
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	/* Disable the irq before mode object teardown, for the irq might
> -- 
> 1.7.10.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 d0f7cb9..858a712 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -362,6 +362,11 @@ 
 #define  DPIO_SFR_BYPASS		(1<<1)
 #define  DPIO_RESET			(1<<0)
 
+#define _DPIO_TX3_SWING_CTL4_A		0x690
+#define _DPIO_TX3_SWING_CTL4_B		0x2a90
+#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \
+					_DPIO_TX3_SWING_CTL4_B)
+
 #define _DPIO_DIV_A			0x800c
 #define   DPIO_POST_DIV_SHIFT		(28) /* 3 bits */
 #define   DPIO_K_SHIFT			(24) /* 4 bits */
@@ -389,14 +394,109 @@ 
 #define _DPIO_CORE_CLK_B		0x803c
 #define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B)
 
+#define _DPIO_IREF_CTL_A		0x8040
+#define _DPIO_IREF_CTL_B		0x8060
+#define DPIO_IREF_CTL(pipe) _PIPE(pipe, _DPIO_IREF_CTL_A, _DPIO_IREF_CTL_B)
+
+#define DPIO_IREF_BCAST			0xc044
+#define _DPIO_IREF_A			0x8044
+#define _DPIO_IREF_B			0x8064
+#define DPIO_IREF(pipe) _PIPE(pipe, _DPIO_IREF_A, _DPIO_IREF_B)
+
+#define _DPIO_PLL_CML_A			0x804c
+#define _DPIO_PLL_CML_B			0x806c
+#define DPIO_PLL_CML(pipe) _PIPE(pipe, _DPIO_PLL_CML_A, _DPIO_PLL_CML_B)
+
 #define _DPIO_LFP_COEFF_A		0x8048
 #define _DPIO_LFP_COEFF_B		0x8068
 #define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B)
 
+#define DPIO_CALIBRATION		0x80ac
+
 #define DPIO_FASTCLK_DISABLE		0x8100
 
-#define DPIO_DATA_CHANNEL1		0x8220
-#define DPIO_DATA_CHANNEL2		0x8420
+#define _DPIO_PCS_TX_0			0x8200
+#define _DPIO_PCS_TX_1			0x8400
+#define   DPIO_PCS_TX_LANE2_RESET	(1<<16)
+#define   DPIO_PCS_TX_LANE1_RESET	(1<<7)
+#define DPIO_PCS_TX(pipe) _PIPE(pipe, _DPIO_PCS_TX_0, _DPIO_PCS_TX_1)
+
+#define _DPIO_PCS_CLK_0			0x8204
+#define _DPIO_PCS_CLK_1			0x8404
+#define   DPIO_PCS_CLK_CRI_RXEB_EIOS_EN	(1<<22)
+#define   DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN (1<<21)
+#define   DPIO_PCS_CLK_DATAWIDTH_SHIFT	(6)
+#define   DPIO_PCS_CLK_SOFT_RESET	(1<<5)
+#define DPIO_PCS_CLK(pipe) _PIPE(pipe, _DPIO_PCS_CLK_0, _DPIO_PCS_CLK_1)
+
+#define _DPIO_PCS_CTL_OVR1_A		0x8224
+#define _DPIO_PCS_CTL_OVR1_B		0x8424
+#define DPIO_PCS_CTL_OVER1(pipe) _PIPE(pipe, _DPIO_PCS_CTL_OVR1_A, \
+				       _DPIO_PCS_CTL_OVR1_B)
+
+#define _DPIO_PCS_STAGGER0_A		0x822c
+#define _DPIO_PCS_STAGGER0_B		0x842c
+#define DPIO_PCS_STAGGER0(pipe) _PIPE(pipe, _DPIO_PCS_STAGGER0_A, \
+				      _DPIO_PCS_STAGGER0_B)
+
+#define _DPIO_PCS_STAGGER1_A		0x8230
+#define _DPIO_PCS_STAGGER1_B		0x8430
+#define DPIO_PCS_STAGGER1(pipe) _PIPE(pipe, _DPIO_PCS_STAGGER1_A, \
+				      _DPIO_PCS_STAGGER1_B)
+
+#define _DPIO_PCS_CLOCKBUF0_A		0x8238
+#define _DPIO_PCS_CLOCKBUF0_B		0x8438
+#define DPIO_PCS_CLOCKBUF0(pipe) _PIPE(pipe, _DPIO_PCS_CLOCKBUF0_A, \
+				       _DPIO_PCS_CLOCKBUF0_B)
+
+#define _DPIO_PCS_CLOCKBUF8_A		0x825c
+#define _DPIO_PCS_CLOCKBUF8_B		0x845c
+#define DPIO_PCS_CLOCKBUF8(pipe) _PIPE(pipe, _DPIO_PCS_CLOCKBUF8_A, \
+				       _DPIO_PCS_CLOCKBUF8_B)
+
+#define _DPIO_TX_SWING_CTL2_A		0x8288
+#define _DPIO_TX_SWING_CTL2_B		0x8488
+#define DPIO_TX_SWING_CTL2(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL2_A, \
+				       _DPIO_TX_SWING_CTL2_B)
+
+#define _DPIO_TX_SWING_CTL3_A		0x828c
+#define _DPIO_TX_SWING_CTL3_B		0x848c
+#define DPIO_TX_SWING_CTL3(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL3_A, \
+				       _DPIO_TX_SWING_CTL3_B)
+
+#define _DPIO_TX_SWING_CTL4_A		0x8290
+#define _DPIO_TX_SWING_CTL4_B		0x8490
+#define DPIO_TX_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \
+				       _DPIO_TX_SWING_CTL4_B)
+
+#define _DPIO_TX_OCALINIT_0		0x8294
+#define _DPIO_TX_OCALINIT_1		0x8494
+#define   DPIO_TX_OCALINIT_EN		(1<<31)
+#define DPIO_TX_OCALINIT(pipe) _PIPE(pipe, _DPIO_TX_OCALINIT_0, \
+				     _DPIO_TX_OCALINIT_1)
+
+#define _DPIO_TX_CTL_0			0x82ac
+#define _DPIO_TX_CTL_1			0x84ac
+#define DPIO_TX_CTL(pipe) _PIPE(pipe, _DPIO_TX_CTL_0, _DPIO_TX_CTL_1)
+
+#define _DPIO_TX_LANE_0			0x82b8
+#define _DPIO_TX_LANE_1			0x84b8
+#define DPIO_TX_LANE(pipe) _PIPE(pipe, _DPIO_TX_LANE_0, _DPIO_TX_LANE_1)
+
+#define _DPIO_DATA_CHANNEL1		0x8220
+#define _DPIO_DATA_CHANNEL2		0x8420
+#define DPIO_DATA_CHANNEL(pipe) _PIPE(pipe, _DPIO_DATA_CHANNEL1, _DPIO_DATA_CHANNEL2)
+
+#define _DPIO_DATA_LANE0		0x0220
+#define _DPIO_DATA_LANE1		0x0420
+#define _DPIO_DATA_LANE2		0x2620
+#define _DPIO_DATA_LANE3		0x2820
+#define DPIO_DATA_LANE_A(pipe) _PIPE(pipe, _DPIO_DATA_LANE0, _DPIO_DATA_LANE2)
+#define DPIO_DATA_LANE_B(pipe) _PIPE(pipe, _DPIO_DATA_LANE1, _DPIO_DATA_LANE3)
+#define DPIO_DATA_CHANNEL1              0x8220
+#define DPIO_DATA_CHANNEL2              0x8420
+
+#define DPIO_TX_BROADCAST		0xc044
 
 /*
  * Fence registers
@@ -957,7 +1057,10 @@ 
 #define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW	0x00ff8000 /* Pineview */
 #define   DPLL_LOCK_VLV			(1<<15)
+#define   DPLL_INTEGRATED_CRI_CLK_VLV	(1<<14)
 #define   DPLL_INTEGRATED_CLOCK_VLV	(1<<13)
+#define   DPLL_PORTC_READY_MASK		(0xf << 4)
+#define   DPLL_PORTB_READY_MASK		(0xf)
 
 #define   DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
 /*
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 58e3a7c..9cb0b53 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3696,6 +3696,72 @@  g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
 	}
 }
 
+static void vlv_pll_enable_reset(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock));
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+		u32 val;
+		val = intel_dpio_read(dev_priv, _DPIO_DATA_LANE0);
+		if (pipe)
+			val |= (1<<21);
+		val |= (1<<20);
+		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, val);
+
+		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(pipe),
+				 0x00760018);
+		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(pipe),
+				 0x00400888);
+
+		intel_dpio_write(dev_priv, DPIO_PCS_TX(pipe),
+				 DPIO_PCS_TX_LANE2_RESET |
+				 DPIO_PCS_TX_LANE1_RESET);
+		intel_dpio_write(dev_priv, DPIO_PCS_CLK(pipe),
+				 DPIO_PCS_CLK_CRI_RXEB_EIOS_EN |
+				 DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN |
+				 (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) |
+				 DPIO_PCS_CLK_SOFT_RESET);
+
+		intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(pipe), 0);
+		intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL4(pipe),
+				 0x2b245f5f);
+		intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL2(pipe),
+				 0x5578b83a);
+		intel_dpio_write(dev_priv, DPIO_TX_SWING_CTL3(pipe),
+				 0x0c782040);
+		intel_dpio_write(dev_priv, DPIO_TX3_SWING_CTL4(pipe),
+				 0x2b247878);
+		intel_dpio_write(dev_priv, DPIO_PCS_STAGGER0(pipe), 0x00030000);
+		intel_dpio_write(dev_priv, DPIO_PCS_CTL_OVER1(pipe),
+				 0x00002000);
+		intel_dpio_write(dev_priv, DPIO_TX_OCALINIT(pipe),
+				 DPIO_TX_OCALINIT_EN);
+
+	}
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		u32 val;
+		val = intel_dpio_read(dev_priv, _DPIO_DATA_LANE2);
+		if (pipe)
+			val |= (1<<21);
+		val |= (1<<20);
+		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, val);
+
+		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF0(pipe),
+				 0x00760018);
+		intel_dpio_write(dev_priv, DPIO_PCS_CLOCKBUF8(pipe),
+				 0x00400888);
+
+		intel_dpio_write(dev_priv, DPIO_PCS_TX(pipe), 0x10080);
+		intel_dpio_write(dev_priv, DPIO_PCS_CLK(pipe), 0x00600060);
+	}
+}
+
 static void i9xx_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
@@ -3704,6 +3770,7 @@  static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
+	u32 port_mask;
 
 	WARN_ON(!crtc->enabled);
 
@@ -3715,10 +3782,27 @@  static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	intel_enable_pll(dev_priv, pipe);
 
+	if (IS_VALLEYVIEW(dev)) {
+		mutex_lock(&dev_priv->dpio_lock);
+		vlv_pll_enable_reset(crtc);
+		mutex_unlock(&dev_priv->dpio_lock);
+	}
+
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
 
+	if (IS_VALLEYVIEW(dev)) {
+		if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
+		    intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+			port_mask = DPLL_PORTB_READY_MASK;
+		else
+			port_mask = DPLL_PORTC_READY_MASK; /* eDP on port C */
+
+		if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 100))
+			DRM_ERROR("timed out waiting for port ready\n");
+	}
+
 	intel_enable_pipe(dev_priv, pipe, false);
 	intel_enable_plane(dev_priv, plane, pipe);
 	if (IS_G4X(dev))
@@ -3770,6 +3854,21 @@  static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	    ((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe)
 		I915_WRITE(PFIT_CONTROL, 0);
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->post_disable)
+			encoder->post_disable(encoder);
+
+	/* Reset lane for VLV platform*/
+	if (IS_VALLEYVIEW(dev)) {
+		mutex_lock(&dev_priv->dpio_lock);
+		intel_dpio_write(dev_priv, DPIO_PCS_TX(pipe), 0x00000000);
+		intel_dpio_write(dev_priv, DPIO_PCS_CLK(pipe), 0x00e00060);
+
+		if (pipe)
+			vlv_init_dpio(dev);
+		mutex_unlock(&dev_priv->dpio_lock);
+	}
+
 	intel_disable_pll(dev_priv, pipe);
 
 	intel_crtc->active = false;
@@ -4338,6 +4437,31 @@  static void i9xx_update_pll_dividers(struct drm_crtc *crtc,
 	}
 }
 
+static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv)
+{
+	u32 reg_val;
+
+	/*
+	 * PLLB opamp always calibrates to max value of 0x3f, force enable it
+	 * and set it to a reasonable value instead.
+	 */
+	reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1));
+	reg_val &= 0xffffff30;
+	intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
+
+	reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION);
+	reg_val &= 0x8cffffff;
+	intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
+
+	reg_val = intel_dpio_read(dev_priv, DPIO_IREF(1));
+	reg_val &= 0xffffff00;
+	intel_dpio_write(dev_priv, DPIO_IREF(1), reg_val);
+
+	reg_val = intel_dpio_read(dev_priv, DPIO_CALIBRATION);
+	reg_val &= 0xb0ffffff;
+	intel_dpio_write(dev_priv, DPIO_CALIBRATION, reg_val);
+}
+
 static void vlv_update_pll(struct drm_crtc *crtc,
 			   struct drm_display_mode *mode,
 			   struct drm_display_mode *adjusted_mode,
@@ -4348,23 +4472,14 @@  static void vlv_update_pll(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 dpll, mdiv, pdiv;
+	u32 dpll, mdiv;
 	u32 bestn, bestm1, bestm2, bestp1, bestp2;
-	bool is_sdvo;
-	u32 temp;
+	bool is_hdmi;
+	u32 coreclk, reg_val;
 
 	mutex_lock(&dev_priv->dpio_lock);
 
-	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||
-		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
-
-	dpll = DPLL_VGA_MODE_DIS;
-	dpll |= DPLL_EXT_BUFFER_ENABLE_VLV;
-	dpll |= DPLL_REFA_CLK_ENABLE_VLV;
-	dpll |= DPLL_INTEGRATED_CLOCK_VLV;
-
-	I915_WRITE(DPLL(pipe), dpll);
-	POSTING_READ(DPLL(pipe));
+	is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI);
 
 	bestn = clock->n;
 	bestm1 = clock->m1;
@@ -4372,71 +4487,99 @@  static void vlv_update_pll(struct drm_crtc *crtc,
 	bestp1 = clock->p1;
 	bestp2 = clock->p2;
 
-	/*
-	 * In Valleyview PLL and program lane counter registers are exposed
-	 * through DPIO interface
-	 */
+	/* See eDP HDMI DPIO driver vbios notes doc */
+
+	/* PLL B needs special handling */
+	if (pipe)
+		vlv_pllb_recal_opamp(dev_priv);
+
+	/* Set up Tx target for periodic Rcomp update */
+	intel_dpio_write(dev_priv, DPIO_IREF_BCAST, 0x0100000f);
+
+	/* Disable target IRef on PLL */
+	reg_val = intel_dpio_read(dev_priv, DPIO_IREF_CTL(pipe));
+	reg_val &= 0x00ffffff;
+	intel_dpio_write(dev_priv, DPIO_IREF_CTL(pipe), reg_val);
+
+	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x610);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		if (adjusted_mode->clock == 162000)
+			intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
+					 0x009f0003);
+		else
+			intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
+					 0x00d0000f);
+
+	} else
+		intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe),
+				 0x009f0003);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		if (!pipe)
+			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+					 0x0df40000);
+		else
+			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+					 0x0df70000);
+	} else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+		if (!pipe)
+			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+					 0x0df70000);
+		else
+			intel_dpio_write(dev_priv, DPIO_REFSFR(pipe),
+					 0x0df40000);
+	}
+
 	mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK));
 	mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT));
 	mdiv |= ((bestn << DPIO_N_SHIFT));
 	mdiv |= (1 << DPIO_POST_DIV_SHIFT);
 	mdiv |= (1 << DPIO_K_SHIFT);
+	intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
+
 	mdiv |= DPIO_ENABLE_CALIBRATION;
 	intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv);
 
-	intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000);
+	coreclk = intel_dpio_read(dev_priv, DPIO_CORE_CLK(pipe));
+	coreclk = (coreclk & 0x0000ff00) | 0x01c00000;
+	intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), coreclk);
 
-	pdiv = (1 << DPIO_REFSEL_OVERRIDE) | (5 << DPIO_PLL_MODESEL_SHIFT) |
-		(3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) |
-		(7 << DPIO_PLL_REFCLK_SEL_SHIFT) | (8 << DPIO_DRIVER_CTL_SHIFT) |
-		(5 << DPIO_CLK_BIAS_CTL_SHIFT);
-	intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv);
+	intel_dpio_write(dev_priv, DPIO_PLL_CML(pipe), 0x87871000);
 
-	intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x005f003b);
+	/* Enable DPIO clock input */
+	dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV |
+		DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV;
+	if (pipe)
+		dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
 
 	dpll |= DPLL_VCO_ENABLE;
 	I915_WRITE(DPLL(pipe), dpll);
 	POSTING_READ(DPLL(pipe));
+	udelay(150);
+
 	if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
 		DRM_ERROR("DPLL %d failed to lock\n", pipe);
 
-	intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x620);
-
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
-		intel_dp_set_m_n(crtc, mode, adjusted_mode);
-
-	I915_WRITE(DPLL(pipe), dpll);
-
-	/* Wait for the clocks to stabilize. */
-	POSTING_READ(DPLL(pipe));
-	udelay(150);
+	if (is_hdmi) {
+		u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode);
 
-	temp = 0;
-	if (is_sdvo) {
-		temp = intel_mode_get_pixel_multiplier(adjusted_mode);
 		if (temp > 1)
 			temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
 		else
 			temp = 0;
-	}
-	I915_WRITE(DPLL_MD(pipe), temp);
-	POSTING_READ(DPLL_MD(pipe));
 
-	/* Now program lane control registers */
-	if(intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)
-			|| intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI))
-	{
-		temp = 0x1000C4;
-		if(pipe == 1)
-			temp |= (1 << 21);
-		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL1, temp);
+		I915_WRITE(DPLL_MD(pipe), temp);
+		POSTING_READ(DPLL_MD(pipe));
 	}
-	if(intel_pipe_has_type(crtc,INTEL_OUTPUT_EDP))
-	{
-		temp = 0x1000C4;
-		if(pipe == 1)
-			temp |= (1 << 21);
-		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp);
+
+	vlv_pll_enable_reset(crtc);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+	    intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		intel_dp_set_m_n(crtc, mode, adjusted_mode);
 	}
 
 	mutex_unlock(&dev_priv->dpio_lock);
@@ -4748,11 +4891,12 @@  static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 		i8xx_update_pll(crtc, adjusted_mode, &clock,
 				has_reduced_clock ? &reduced_clock : NULL,
 				num_connectors);
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev)) {
+		refclk = i9xx_get_refclk(crtc, num_connectors);
 		vlv_update_pll(crtc, mode, adjusted_mode, &clock,
 				has_reduced_clock ? &reduced_clock : NULL,
 				num_connectors);
-	else
+	} else
 		i9xx_update_pll(crtc, mode, adjusted_mode, &clock,
 				has_reduced_clock ? &reduced_clock : NULL,
 				num_connectors);
@@ -4845,6 +4989,21 @@  static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 
 	intel_update_watermarks(dev);
 
+	if (IS_VALLEYVIEW(dev)) {
+		u32 port_mask;
+
+		/* Wait for Phy status bits to go low */
+		for_each_encoder_on_crtc(dev, crtc, encoder) {
+			if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+			    encoder->type == INTEL_OUTPUT_HDMI)
+				port_mask = DPLL_PORTB_READY_MASK;
+			else
+				port_mask = DPLL_PORTC_READY_MASK; /* eDP */
+			if (wait_for((I915_READ(DPLL(0)) & port_mask) == 0, 100))
+				DRM_ERROR("timed out waiting for port ready\n");
+		}
+	}
+
 	return ret;
 }
 
@@ -9284,9 +9443,6 @@  void intel_modeset_cleanup(struct drm_device *dev)
 
 	ironlake_teardown_rc6(dev);
 
-	if (IS_VALLEYVIEW(dev))
-		vlv_init_dpio(dev);
-
 	mutex_unlock(&dev->struct_mutex);
 
 	/* Disable the irq before mode object teardown, for the irq might