Re: [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 19, 2015 at 02:29:37PM +0300, Ville Syrjälä wrote:
> On Wed, Aug 19, 2015 at 07:47:41AM +0530, Deepak wrote:
> > 
> > 
> > On 07/09/2015 02:15 AM, ville.syrjala@xxxxxxxxxxxxxxx wrote:
> > > From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
> > >
> > > Normmally the common lane in a PHY channel gets powered up when some
> > > of the data lanes get powered up. But when we're driving port B with
> > > pipe B we don't want to enabled any of the data lanes, and just want
> > > the DPLL in the common lane to be active.
> > >
> > > To make that happens we have to temporarily enable some data lanes
> > > after which we can access the DPLL registers in the common lane. Once
> > > the pipe is up and running we can drop the power override on the data
> > > lanes allowing them to shut down. From this point forward the common
> > > lane will in fact stay powered on until the data lanes in the other
> > > channel get powered down.
> > Patch looks fine. It does what it says. One Q, why only for port B? Port 
> > C is also in same common lane right?
> 
> Port B is in the first PHY channel which also houses CL1. CL1 always
> powers up whenever any lanes in either PHY channel are powered up.
> CL2 only powers up if lanes in the second channel (ie. the one with
> port C) powers up.
> 
> So in this scenario (pipe B->port B) we want the DPLL from CL2, but
> ideally we only want to power up the lanes for port B. Powering up
> port B lanes will only power up CL1, but as we need CL2 instead we
> need to, temporarily, power up some lanes in port C as well.
> 
> Crossing the streams the other way (pipe A->port C) is not a problem
> since CL1 powers up whenever anything else powers up. So powering up
> some port C lanes is enough on its own to make the CL1 DPLL
> operational, even though CL1 and the lanes live in separate channels.

I added this to the commit message when merging, seemed useful for the
future.
-Daniel

> 
> > Reviewed-by: Deepak S <deepak.s@xxxxxxxxxxxxxxx>
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx>
> > > ---
> > >   drivers/gpu/drm/i915/intel_dp.c         | 23 +++++++++++++++++++++++
> > >   drivers/gpu/drm/i915/intel_drv.h        |  3 +++
> > >   drivers/gpu/drm/i915/intel_hdmi.c       | 23 +++++++++++++++++++++++
> > >   drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++
> > >   4 files changed, 78 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 6058129..8d088f3 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -2865,6 +2865,12 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
> > >   	mutex_unlock(&dev_priv->sb_lock);
> > >   
> > >   	intel_enable_dp(encoder);
> > > +
> > > +	/* Second common lane will stay alive on its own now */
> > > +	if (dport->release_cl2_override) {
> > > +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> > > +		dport->release_cl2_override = false;
> > > +	}
> > >   }
> > >   
> > >   static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> > > @@ -2882,6 +2888,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> > >   
> > >   	intel_dp_prepare(encoder);
> > >   
> > > +	/*
> > > +	 * Must trick the second common lane into life.
> > > +	 * Otherwise we can't even access the PLL.
> > > +	 */
> > > +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> > > +		dport->release_cl2_override =
> > > +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> > > +
> > >   	chv_phy_powergate_lanes(encoder, true, lane_mask);
> > >   
> > >   	mutex_lock(&dev_priv->sb_lock);
> > > @@ -2960,6 +2974,15 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
> > >   
> > >   	mutex_unlock(&dev_priv->sb_lock);
> > >   
> > > +	/*
> > > +	 * Leave the power down bit cleared for at least one
> > > +	 * lane so that chv_powergate_phy_ch() will power
> > > +	 * on something when the channel is otherwise unused.
> > > +	 * When the port is off and the override is removed
> > > +	 * the lanes power down anyway, so otherwise it doesn't
> > > +	 * really matter what the state of power down bits is
> > > +	 * after this.
> > > +	 */
> > >   	chv_phy_powergate_lanes(encoder, false, 0x0);
> > >   }
> > >   
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index f8a16dc..6133a98 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -782,6 +782,7 @@ struct intel_digital_port {
> > >   	struct intel_dp dp;
> > >   	struct intel_hdmi hdmi;
> > >   	enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
> > > +	bool release_cl2_override;
> > >   };
> > >   
> > >   struct intel_dp_mst_encoder {
> > > @@ -1372,6 +1373,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
> > >   
> > >   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> > >   			     bool override, unsigned int mask);
> > > +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> > > +			  enum dpio_channel ch, bool override);
> > >   
> > >   
> > >   /* intel_pm.c */
> > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > > index b3f6c9f..4b604ee 100644
> > > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > > @@ -1625,6 +1625,14 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
> > >   
> > >   	intel_hdmi_prepare(encoder);
> > >   
> > > +	/*
> > > +	 * Must trick the second common lane into life.
> > > +	 * Otherwise we can't even access the PLL.
> > > +	 */
> > > +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> > > +		dport->release_cl2_override =
> > > +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> > > +
> > >   	chv_phy_powergate_lanes(encoder, true, 0x0);
> > >   
> > >   	mutex_lock(&dev_priv->sb_lock);
> > > @@ -1701,6 +1709,15 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
> > >   
> > >   	mutex_unlock(&dev_priv->sb_lock);
> > >   
> > > +	/*
> > > +	 * Leave the power down bit cleared for at least one
> > > +	 * lane so that chv_powergate_phy_ch() will power
> > > +	 * on something when the channel is otherwise unused.
> > > +	 * When the port is off and the override is removed
> > > +	 * the lanes power down anyway, so otherwise it doesn't
> > > +	 * really matter what the state of power down bits is
> > > +	 * after this.
> > > +	 */
> > >   	chv_phy_powergate_lanes(encoder, false, 0x0);
> > >   }
> > >   
> > > @@ -1922,6 +1939,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
> > >   	g4x_enable_hdmi(encoder);
> > >   
> > >   	vlv_wait_port_ready(dev_priv, dport, 0x0);
> > > +
> > > +	/* Second common lane will stay alive on its own now */
> > > +	if (dport->release_cl2_override) {
> > > +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> > > +		dport->release_cl2_override = false;
> > > +	}
> > >   }
> > >   
> > >   static void intel_hdmi_destroy(struct drm_connector *connector)
> > > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > index 506a8cc..551cf08 100644
> > > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > @@ -1016,6 +1016,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> > >   		      phy, dev_priv->chv_phy_control);
> > >   }
> > >   
> > > +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> > > +			  enum dpio_channel ch, bool override)
> > > +{
> > > +	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> > > +	bool was_override;
> > > +
> > > +	mutex_lock(&power_domains->lock);
> > > +
> > > +	was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > > +
> > > +	if (override == was_override)
> > > +		goto out;
> > > +
> > > +	if (override)
> > > +		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > > +	else
> > > +		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > > +
> > > +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> > > +
> > > +	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
> > > +		      phy, ch, dev_priv->chv_phy_control);
> > > +
> > > +out:
> > > +	mutex_unlock(&power_domains->lock);
> > > +
> > > +	return was_override;
> > > +}
> > > +
> > >   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> > >   			     bool override, unsigned int mask)
> > >   {
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux