[Intel-gfx] [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B
Daniel Vetter
daniel at ffwll.ch
Wed Aug 26 05:36:39 PDT 2015
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 at linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > >
> > > 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 at linux.intel.com>
> > > Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > > ---
> > > 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 at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the Intel-gfx
mailing list