[Intel-gfx] [PATCH] drm/i915: wait PSR state back to idle when turn PSR off

Souza, Jose jose.souza at intel.com
Wed Oct 21 17:13:44 UTC 2020


On Wed, 2020-10-21 at 22:24 +0800, Lee Shawn C wrote:
> Driver should refer to commit 'b2fc2252ce41 ("drm/i915/psr:
> Always wait for idle state when disabling PSR")' to wait for
> idle state when turn PSR off. But it did not follow
> previous method. Driver just call intel_psr_exit() in
> intel_psr_invalidate() and psr_force_hw_tracking_exit().
> Then leave the function right away.
> 
> After PSR disabled, we found some user space applications
> would enabled PSR again immediately. That caused particular
> TCON to get into incorrect state machine and can't recognize
> video data from source properly.

How? I don't see how this is possible this change is only adding delay between userspace calls.

Take a look at intel_psr_work(), PSR will only be enabled again when idle.

> 
> Add this change to wait PSR idle state in intel_psr_invalidate()
> and psr_force_hw_tracking_exit(). This symptom is not able
> to replicate anymore.
> 
> Fixes: b2fc2252ce41 (drm/i915/psr: Always wait for idle state
> when disabling PSR).
> 
> Cc: Manasi Navare <manasi.d.navare at intel.com>
> Cc: Jani Nikula <jani.nikula at linux.intel.com>
> Cc: Ville Syrjala <ville.syrjala at linux.intel.com>
> Cc: José Roberto de Souza <jose.souza at intel.com>
> Cc: Cooper Chiou <cooper.chiou at intel.com>
> Cc: Khaled Almahallawy <khaled.almahallawy at intel.com>
> Signed-off-by: Lee Shawn C <shawn.c.lee at intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_psr.c | 43 ++++++++++++++----------
>  1 file changed, 26 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
> index a591a475f148..83b642a5567e 100644
> --- a/drivers/gpu/drm/i915/display/intel_psr.c
> +++ b/drivers/gpu/drm/i915/display/intel_psr.c
> @@ -1036,6 +1036,25 @@ void intel_psr_enable(struct intel_dp *intel_dp,
>  	mutex_unlock(&dev_priv->psr.lock);
>  }
>  
> 
> 
> 
> +static void intel_psr_wait_idle(struct drm_i915_private *dev_priv)
> +{
> +	i915_reg_t psr_status;
> +	u32 psr_status_mask;
> +
> +	if (dev_priv->psr.psr2_enabled) {
> +		psr_status = EDP_PSR2_STATUS(dev_priv->psr.transcoder);
> +		psr_status_mask = EDP_PSR2_STATUS_STATE_MASK;
> +	} else {
> +		psr_status = EDP_PSR_STATUS(dev_priv->psr.transcoder);
> +		psr_status_mask = EDP_PSR_STATUS_STATE_MASK;
> +	}
> +
> +	/* Wait till PSR is idle */
> +	if (intel_de_wait_for_clear(dev_priv, psr_status,
> +				    psr_status_mask, 2000))
> +		drm_err(&dev_priv->drm, "Timed out waiting PSR idle state\n");
> +}
> +
>  static void intel_psr_exit(struct drm_i915_private *dev_priv)
>  {
>  	u32 val;
> @@ -1076,8 +1095,6 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv)
>  static void intel_psr_disable_locked(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	i915_reg_t psr_status;
> -	u32 psr_status_mask;
>  
> 
> 
> 
>  	lockdep_assert_held(&dev_priv->psr.lock);
>  
> 
> 
> 
> @@ -1088,19 +1105,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
>  		    dev_priv->psr.psr2_enabled ? "2" : "1");
>  
> 
> 
> 
>  	intel_psr_exit(dev_priv);
> -
> -	if (dev_priv->psr.psr2_enabled) {
> -		psr_status = EDP_PSR2_STATUS(dev_priv->psr.transcoder);
> -		psr_status_mask = EDP_PSR2_STATUS_STATE_MASK;
> -	} else {
> -		psr_status = EDP_PSR_STATUS(dev_priv->psr.transcoder);
> -		psr_status_mask = EDP_PSR_STATUS_STATE_MASK;
> -	}
> -
> -	/* Wait till PSR is idle */
> -	if (intel_de_wait_for_clear(dev_priv, psr_status,
> -				    psr_status_mask, 2000))
> -		drm_err(&dev_priv->drm, "Timed out waiting PSR idle state\n");
> +	intel_psr_wait_idle(dev_priv);
>  
> 
> 
> 
>  	/* WA 1408330847 */
>  	if (dev_priv->psr.psr2_sel_fetch_enabled &&
> @@ -1158,12 +1163,14 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
>  		 * pipe.
>  		 */
>  		intel_de_write(dev_priv, CURSURFLIVE(dev_priv->psr.pipe), 0);
> -	else
> +	else {
>  		/*
>  		 * A write to CURSURFLIVE do not cause HW tracking to exit PSR
>  		 * on older gens so doing the manual exit instead.
>  		 */
>  		intel_psr_exit(dev_priv);
> +		intel_psr_wait_idle(dev_priv);
> +	}
>  }
>  
> 
> 
> 
>  void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
> @@ -1593,8 +1600,10 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
>  	frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(dev_priv->psr.pipe);
>  	dev_priv->psr.busy_frontbuffer_bits |= frontbuffer_bits;
>  
> 
> 
> 
> -	if (frontbuffer_bits)
> +	if (frontbuffer_bits) {
>  		intel_psr_exit(dev_priv);
> +		intel_psr_wait_idle(dev_priv);
> +	}
>  
> 
> 
> 
>  	mutex_unlock(&dev_priv->psr.lock);
>  }



More information about the Intel-gfx mailing list