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

Deepak deepak.s at linux.intel.com
Tue Aug 18 19:17:41 PDT 2015



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?
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)
>   {



More information about the Intel-gfx mailing list