diff mbox series

drm/i915: Fix PSR2 selective update corruption after PSR1 setup

Message ID 20190312204217.31034-1-jose.souza@intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Fix PSR2 selective update corruption after PSR1 setup | expand

Commit Message

Souza, Jose March 12, 2019, 8:42 p.m. UTC
For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is kept set
while PSR2 is enabled, it causes some selective updates to fail after
got back from DC6 for the first time.
So lets clear this register before enabled PSR2, as it could be set
by a previous i915 module, firmware/BIOS or by a previous mode that
is not compatible with PSR2.

Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
---
 drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Comments

Rodrigo Vivi March 12, 2019, 8:53 p.m. UTC | #1
On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza wrote:
> For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is kept set
> while PSR2 is enabled, it causes some selective updates to fail after
> got back from DC6 for the first time.
> So lets clear this register before enabled PSR2, as it could be set
> by a previous i915 module, firmware/BIOS or by a previous mode that
> is not compatible with PSR2.

Does it happen when you don't have DMC loaded?

Because It looks like a DMC bug for me...

If by removing DMC we don't see the issue, could we please file
this bug to DMC while adding a FIXME with DMC bugged version on it?

Aa: Pavana

If it doesn't happen with DMC loaded than maybe a HSD would for hw
team would be good anyway.

Cc: Art.

Thanks,
Rodrigo.

> 
> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
> index 7bab6a009e0d..ae62f8124558 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	u32 val;
> +	int idle_frames;
> +
> +	/*
> +	 * Keeping this PSR1 register set while PSR2 is enabled causes some
> +	 * PSR2 selective updates to fail, corrupting screen.
> +	 */
> +	val = I915_READ(EDP_PSR_CTL);
> +	if (val & EDP_PSR_TP1_TP3_SEL)
> +		I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_TP1_TP3_SEL);
>  
>  	/* Let's use 6 as the minimum to cover all known cases including the
>  	 * off-by-one issue that HW has in some cases.
>  	 */
> -	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> -
> +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
>  	idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1);
>  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
>  
> -- 
> 2.21.0
>
Dhinakaran Pandiyan March 12, 2019, 9:14 p.m. UTC | #2
On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> wrote:
> > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is kept
> > set
> > while PSR2 is enabled, it causes some selective updates to fail
> > after
> > got back from DC6 for the first time.

That's suspicious, why does a PSR1 control register have any effect on
PSR2. Was PSR1 enabled before PSR2? 



> > So lets clear this register before enabled PSR2, as it could be set
> > by a previous i915 module, firmware/BIOS or by a previous mode that
> > is not compatible with PSR2.
> 
> Does it happen when you don't have DMC loaded?
> 
> Because It looks like a DMC bug for me...
> 
> If by removing DMC we don't see the issue, could we please file
> this bug to DMC while adding a FIXME with DMC bugged version on it?
> 
> Aa: Pavana
> 
> If it doesn't happen with DMC loaded than maybe a HSD would for hw
> team would be good anyway.
> 
> Cc: Art.
> 
> Thanks,
> Rodrigo.
> 
> > 
> > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> >  1 file changed, 10 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > b/drivers/gpu/drm/i915/intel_psr.c
> > index 7bab6a009e0d..ae62f8124558 100644
> > --- a/drivers/gpu/drm/i915/intel_psr.c
> > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct intel_dp
> > *intel_dp)
> >  {
> >  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> >  	u32 val;
> > +	int idle_frames;
> > +
> > +	/*
> > +	 * Keeping this PSR1 register set while PSR2 is enabled causes
> > some
> > +	 * PSR2 selective updates to fail, corrupting screen.
> > +	 */
> > +	val = I915_READ(EDP_PSR_CTL);
> > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > +		I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_TP1_TP3_SEL);

Since PSR1 should be disabled at this point, a rmw is not necessary.
Does this work? 
I915_WRITE(EDP_PSR_CTL, 0);

We could do the same thing in psr_exit() as well.

> >  
> >  	/* Let's use 6 as the minimum to cover all known cases
> > including the
> >  	 * off-by-one issue that HW has in some cases.
> >  	 */
> > -	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > -
> > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> >  	idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency
> > + 1);
> >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> >  
> > -- 
> > 2.21.0
> >
Souza, Jose March 12, 2019, 9:22 p.m. UTC | #3
On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> wrote:
> > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is kept
> > set
> > while PSR2 is enabled, it causes some selective updates to fail
> > after
> > got back from DC6 for the first time.
> > So lets clear this register before enabled PSR2, as it could be set
> > by a previous i915 module, firmware/BIOS or by a previous mode that
> > is not compatible with PSR2.
> 
> Does it happen when you don't have DMC loaded?
> 
> Because It looks like a DMC bug for me...
> 

BINGO, it do not happens without DMC.

> If by removing DMC we don't see the issue, could we please file
> this bug to DMC while adding a FIXME with DMC bugged version on it?

It happens with GEN9 and GEN10 and reproduced with: icl_dmc_ver1_07.bin
and kbl_dmc_ver1_04.bin

So updating the comment and commit description to:

I will update the comment and commit description to:

For some reason if this register is set and when DMC restore the state
after a DC6 exit, it causes some PSR2 selective updates to fail,
corrupting screen.
So for now lets have this workaround until DMC is fixed.

> 
> Aa: Pavana
> 
> If it doesn't happen with DMC loaded than maybe a HSD would for hw
> team would be good anyway.

I filled a bug in BSpec but in future I will do a HSD instead.

> 
> Cc: Art.
> 
> Thanks,
> Rodrigo.
> 
> > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> >  1 file changed, 10 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > b/drivers/gpu/drm/i915/intel_psr.c
> > index 7bab6a009e0d..ae62f8124558 100644
> > --- a/drivers/gpu/drm/i915/intel_psr.c
> > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct intel_dp
> > *intel_dp)
> >  {
> >  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> >  	u32 val;
> > +	int idle_frames;
> > +
> > +	/*
> > +	 * Keeping this PSR1 register set while PSR2 is enabled causes
> > some
> > +	 * PSR2 selective updates to fail, corrupting screen.
> > +	 */
> > +	val = I915_READ(EDP_PSR_CTL);
> > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > +		I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_TP1_TP3_SEL);
> >  
> >  	/* Let's use 6 as the minimum to cover all known cases
> > including the
> >  	 * off-by-one issue that HW has in some cases.
> >  	 */
> > -	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > -
> > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> >  	idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency
> > + 1);
> >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> >  
> > -- 
> > 2.21.0
> >
Souza, Jose March 12, 2019, 9:28 p.m. UTC | #4
On Tue, 2019-03-12 at 14:14 -0700, Dhinakaran Pandiyan wrote:
> On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> > On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> > wrote:
> > > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is kept
> > > set
> > > while PSR2 is enabled, it causes some selective updates to fail
> > > after
> > > got back from DC6 for the first time.
> 
> That's suspicious, why does a PSR1 control register have any effect
> on
> PSR2. Was PSR1 enabled before PSR2? 

Yes it only happens when switching from PSR1 -> PSR2, I caught this
issue now because I had a external connector attached so display was
never going to DC6.

> 
> 
> 
> > > So lets clear this register before enabled PSR2, as it could be
> > > set
> > > by a previous i915 module, firmware/BIOS or by a previous mode
> > > that
> > > is not compatible with PSR2.
> > 
> > Does it happen when you don't have DMC loaded?
> > 
> > Because It looks like a DMC bug for me...
> > 
> > If by removing DMC we don't see the issue, could we please file
> > this bug to DMC while adding a FIXME with DMC bugged version on it?
> > 
> > Aa: Pavana
> > 
> > If it doesn't happen with DMC loaded than maybe a HSD would for hw
> > team would be good anyway.
> > 
> > Cc: Art.
> > 
> > Thanks,
> > Rodrigo.
> > 
> > > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > > b/drivers/gpu/drm/i915/intel_psr.c
> > > index 7bab6a009e0d..ae62f8124558 100644
> > > --- a/drivers/gpu/drm/i915/intel_psr.c
> > > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct
> > > intel_dp
> > > *intel_dp)
> > >  {
> > >  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> > >  	u32 val;
> > > +	int idle_frames;
> > > +
> > > +	/*
> > > +	 * Keeping this PSR1 register set while PSR2 is enabled causes
> > > some
> > > +	 * PSR2 selective updates to fail, corrupting screen.
> > > +	 */
> > > +	val = I915_READ(EDP_PSR_CTL);
> > > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > > +		I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_TP1_TP3_SEL);
> 
> Since PSR1 should be disabled at this point, a rmw is not necessary.
> Does this work? 
> I915_WRITE(EDP_PSR_CTL, 0);
> 
> We could do the same thing in psr_exit() as well.

Write 0 also works and I'm doing RMW because I always try to save any
writes.

No need to do it in psr_exit(), the important is do it here because
other i915 module or BIOS could leave it set.

> 
> > >  
> > >  	/* Let's use 6 as the minimum to cover all known cases
> > > including the
> > >  	 * off-by-one issue that HW has in some cases.
> > >  	 */
> > > -	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > -
> > > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > >  	idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency
> > > + 1);
> > >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> > >  
> > > -- 
> > > 2.21.0
> > >
Dhinakaran Pandiyan March 12, 2019, 9:46 p.m. UTC | #5
On Tue, 2019-03-12 at 14:28 -0700, Souza, Jose wrote:
> On Tue, 2019-03-12 at 14:14 -0700, Dhinakaran Pandiyan wrote:
> > On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> > > On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> > > wrote:
> > > > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is
> > > > kept
> > > > set
> > > > while PSR2 is enabled, it causes some selective updates to fail
> > > > after
> > > > got back from DC6 for the first time.
> > 
> > That's suspicious, why does a PSR1 control register have any effect
> > on
> > PSR2. Was PSR1 enabled before PSR2? 
> 
> Yes it only happens when switching from PSR1 -> PSR2, I caught this
> issue now because I had a external connector attached so display was
> never going to DC6.

I am a bit confused now :) Do you see the issue if PSR1 was never
enabled before enabling PSR2?

> > 
> > 
> > 
> > > > So lets clear this register before enabled PSR2, as it could be
> > > > set
> > > > by a previous i915 module, firmware/BIOS or by a previous mode
> > > > that
> > > > is not compatible with PSR2.
> > > 
> > > Does it happen when you don't have DMC loaded?
> > > 
> > > Because It looks like a DMC bug for me...
> > > 
> > > If by removing DMC we don't see the issue, could we please file
> > > this bug to DMC while adding a FIXME with DMC bugged version on
> > > it?
> > > 
> > > Aa: Pavana
> > > 
> > > If it doesn't happen with DMC loaded than maybe a HSD would for
> > > hw
> > > team would be good anyway.
> > > 
> > > Cc: Art.
> > > 
> > > Thanks,
> > > Rodrigo.
> > > 
> > > > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> > > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > > > b/drivers/gpu/drm/i915/intel_psr.c
> > > > index 7bab6a009e0d..ae62f8124558 100644
> > > > --- a/drivers/gpu/drm/i915/intel_psr.c
> > > > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > > > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct
> > > > intel_dp
> > > > *intel_dp)
> > > >  {
> > > >  	struct drm_i915_private *dev_priv =
> > > > dp_to_i915(intel_dp);
> > > >  	u32 val;
> > > > +	int idle_frames;
> > > > +
> > > > +	/*
> > > > +	 * Keeping this PSR1 register set while PSR2 is enabled
> > > > causes
> > > > some
> > > > +	 * PSR2 selective updates to fail, corrupting screen.
> > > > +	 */
> > > > +	val = I915_READ(EDP_PSR_CTL);
> > > > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > > > +		I915_WRITE(EDP_PSR_CTL, val &
> > > > ~EDP_PSR_TP1_TP3_SEL);
> > 
> > Since PSR1 should be disabled at this point, a rmw is not
> > necessary.
> > Does this work? 
> > I915_WRITE(EDP_PSR_CTL, 0);
> > 
> > We could do the same thing in psr_exit() as well.
> 
> Write 0 also works and I'm doing RMW because I always try to save any
> writes.
Why so? Do we want to retain the old value in PSR_CTL when PSR2 is
enabled? 

> 
> No need to do it in psr_exit(), the important is do it here because
> other i915 module or BIOS could leave it set.
Right, that was an orthogonal suggestion to avoid the RMW that we do to
disable PSR1 and PSR2.

psr1 and psr2 activate functions recompute the values fully, so there
is no benefit in flipping just the enable bit in psr_exit().
> 
> > 
> > > >  
> > > >  	/* Let's use 6 as the minimum to cover all known cases
> > > > including the
> > > >  	 * off-by-one issue that HW has in some cases.
> > > >  	 */
> > > > -	int idle_frames = max(6, dev_priv-
> > > > >vbt.psr.idle_frames);
> > > > -
> > > > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > >  	idle_frames = max(idle_frames, dev_priv-
> > > > >psr.sink_sync_latency
> > > > + 1);
> > > >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> > > >  
> > > > -- 
> > > > 2.21.0
> > > >
Souza, Jose March 12, 2019, 10:07 p.m. UTC | #6
On Tue, 2019-03-12 at 14:46 -0700, Pandiyan, Dhinakaran wrote:
> On Tue, 2019-03-12 at 14:28 -0700, Souza, Jose wrote:
> > On Tue, 2019-03-12 at 14:14 -0700, Dhinakaran Pandiyan wrote:
> > > On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> > > > On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> > > > wrote:
> > > > > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is
> > > > > kept
> > > > > set
> > > > > while PSR2 is enabled, it causes some selective updates to
> > > > > fail
> > > > > after
> > > > > got back from DC6 for the first time.
> > > 
> > > That's suspicious, why does a PSR1 control register have any
> > > effect
> > > on
> > > PSR2. Was PSR1 enabled before PSR2? 
> > 
> > Yes it only happens when switching from PSR1 -> PSR2, I caught this
> > issue now because I had a external connector attached so display
> > was
> > never going to DC6.
> 
> I am a bit confused now :) Do you see the issue if PSR1 was never
> enabled before enabling PSR2?

I don't see, just being cautions about how this issue could be trigged.

> 
> > > 
> > > 
> > > > > So lets clear this register before enabled PSR2, as it could
> > > > > be
> > > > > set
> > > > > by a previous i915 module, firmware/BIOS or by a previous
> > > > > mode
> > > > > that
> > > > > is not compatible with PSR2.
> > > > 
> > > > Does it happen when you don't have DMC loaded?
> > > > 
> > > > Because It looks like a DMC bug for me...
> > > > 
> > > > If by removing DMC we don't see the issue, could we please file
> > > > this bug to DMC while adding a FIXME with DMC bugged version on
> > > > it?
> > > > 
> > > > Aa: Pavana
> > > > 
> > > > If it doesn't happen with DMC loaded than maybe a HSD would for
> > > > hw
> > > > team would be good anyway.
> > > > 
> > > > Cc: Art.
> > > > 
> > > > Thanks,
> > > > Rodrigo.
> > > > 
> > > > > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > > > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> > > > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > > > > b/drivers/gpu/drm/i915/intel_psr.c
> > > > > index 7bab6a009e0d..ae62f8124558 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_psr.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > > > > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct
> > > > > intel_dp
> > > > > *intel_dp)
> > > > >  {
> > > > >  	struct drm_i915_private *dev_priv =
> > > > > dp_to_i915(intel_dp);
> > > > >  	u32 val;
> > > > > +	int idle_frames;
> > > > > +
> > > > > +	/*
> > > > > +	 * Keeping this PSR1 register set while PSR2 is enabled
> > > > > causes
> > > > > some
> > > > > +	 * PSR2 selective updates to fail, corrupting screen.
> > > > > +	 */
> > > > > +	val = I915_READ(EDP_PSR_CTL);
> > > > > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > > > > +		I915_WRITE(EDP_PSR_CTL, val &
> > > > > ~EDP_PSR_TP1_TP3_SEL);
> > > 
> > > Since PSR1 should be disabled at this point, a rmw is not
> > > necessary.
> > > Does this work? 
> > > I915_WRITE(EDP_PSR_CTL, 0);
> > > 
> > > We could do the same thing in psr_exit() as well.
> > 
> > Write 0 also works and I'm doing RMW because I always try to save
> > any
> > writes.
> Why so? Do we want to retain the old value in PSR_CTL when PSR2 is
> enabled? 

We don't need the old PSR_CTL value but on psr_exit() we can't set to 0
for sure as BSpec says to not modify the other registers when the
enable bit is set, it probably uses the TP SEL and TP training values
to do the PSR exit.
Not a strong argument but in here I would say is better to unset just
the one causing the issue so we can better track the issue in DMC side.

> 
> > No need to do it in psr_exit(), the important is do it here because
> > other i915 module or BIOS could leave it set.
> Right, that was an orthogonal suggestion to avoid the RMW that we do
> to
> disable PSR1 and PSR2.
> 
> psr1 and psr2 activate functions recompute the values fully, so there
> is no benefit in flipping just the enable bit in psr_exit().
> > > > >  
> > > > >  	/* Let's use 6 as the minimum to cover all known cases
> > > > > including the
> > > > >  	 * off-by-one issue that HW has in some cases.
> > > > >  	 */
> > > > > -	int idle_frames = max(6, dev_priv-
> > > > > > vbt.psr.idle_frames);
> > > > > -
> > > > > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > > >  	idle_frames = max(idle_frames, dev_priv-
> > > > > > psr.sink_sync_latency
> > > > > + 1);
> > > > >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> > > > >  
> > > > > -- 
> > > > > 2.21.0
> > > > >
Runyan, Arthur J March 12, 2019, 11:42 p.m. UTC | #7
Strange.  DMC doesn't look at training patterns.  I've asked the PSR2 guys to look for any cross-connection.

> -----Original Message-----
> From: Souza, Jose
> Sent: Tuesday, 12 March, 2019 2:29 PM
> To: Vivi, Rodrigo <rodrigo.vivi@intel.com>; Pandiyan, Dhinakaran
> <dhinakaran.pandiyan@intel.com>
> Cc: Runyan, Arthur J <arthur.j.runyan@intel.com>; Aigal, Pavana A
> <pavana.a.aigal@intel.com>; intel-gfx@lists.freedesktop.org
> Subject: Re: [PATCH] drm/i915: Fix PSR2 selective update corruption after
> PSR1 setup
> 
> On Tue, 2019-03-12 at 14:14 -0700, Dhinakaran Pandiyan wrote:
> > On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> > > On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> > > wrote:
> > > > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is kept
> > > > set
> > > > while PSR2 is enabled, it causes some selective updates to fail
> > > > after
> > > > got back from DC6 for the first time.
> >
> > That's suspicious, why does a PSR1 control register have any effect
> > on
> > PSR2. Was PSR1 enabled before PSR2?
> 
> Yes it only happens when switching from PSR1 -> PSR2, I caught this
> issue now because I had a external connector attached so display was
> never going to DC6.
> 
> >
> >
> >
> > > > So lets clear this register before enabled PSR2, as it could be
> > > > set
> > > > by a previous i915 module, firmware/BIOS or by a previous mode
> > > > that
> > > > is not compatible with PSR2.
> > >
> > > Does it happen when you don't have DMC loaded?
> > >
> > > Because It looks like a DMC bug for me...
> > >
> > > If by removing DMC we don't see the issue, could we please file
> > > this bug to DMC while adding a FIXME with DMC bugged version on it?
> > >
> > > Aa: Pavana
> > >
> > > If it doesn't happen with DMC loaded than maybe a HSD would for hw
> > > team would be good anyway.
> > >
> > > Cc: Art.
> > >
> > > Thanks,
> > > Rodrigo.
> > >
> > > > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> > > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > > > b/drivers/gpu/drm/i915/intel_psr.c
> > > > index 7bab6a009e0d..ae62f8124558 100644
> > > > --- a/drivers/gpu/drm/i915/intel_psr.c
> > > > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > > > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct
> > > > intel_dp
> > > > *intel_dp)
> > > >  {
> > > >  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> > > >  	u32 val;
> > > > +	int idle_frames;
> > > > +
> > > > +	/*
> > > > +	 * Keeping this PSR1 register set while PSR2 is enabled causes
> > > > some
> > > > +	 * PSR2 selective updates to fail, corrupting screen.
> > > > +	 */
> > > > +	val = I915_READ(EDP_PSR_CTL);
> > > > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > > > +		I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_TP1_TP3_SEL);
> >
> > Since PSR1 should be disabled at this point, a rmw is not necessary.
> > Does this work?
> > I915_WRITE(EDP_PSR_CTL, 0);
> >
> > We could do the same thing in psr_exit() as well.
> 
> Write 0 also works and I'm doing RMW because I always try to save any
> writes.
> 
> No need to do it in psr_exit(), the important is do it here because
> other i915 module or BIOS could leave it set.
> 
> >
> > > >
> > > >  	/* Let's use 6 as the minimum to cover all known cases
> > > > including the
> > > >  	 * off-by-one issue that HW has in some cases.
> > > >  	 */
> > > > -	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > > -
> > > > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > >  	idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency
> > > > + 1);
> > > >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> > > >
> > > > --
> > > > 2.21.0
> > > >
Runyan, Arthur J March 20, 2019, 6:57 p.m. UTC | #8
PSR2 logic is incorrectly looking at this register bit during DC5 exit. 
Not a DMC problem, but DMC enables DC5.
I'll update Bspec to require the bit to be not set when PSR2 is used.

> -----Original Message-----
> From: Runyan, Arthur J
> Sent: Tuesday, 12 March, 2019 4:42 PM
> To: Souza, Jose <jose.souza@intel.com>; Vivi, Rodrigo
> <rodrigo.vivi@intel.com>; Pandiyan, Dhinakaran
> <dhinakaran.pandiyan@intel.com>
> Cc: Aigal, Pavana A <pavana.a.aigal@intel.com>; intel-
> gfx@lists.freedesktop.org
> Subject: RE: [PATCH] drm/i915: Fix PSR2 selective update corruption after
> PSR1 setup
> 
> Strange.  DMC doesn't look at training patterns.  I've asked the PSR2 guys to
> look for any cross-connection.
> 
> > -----Original Message-----
> > From: Souza, Jose
> > Sent: Tuesday, 12 March, 2019 2:29 PM
> > To: Vivi, Rodrigo <rodrigo.vivi@intel.com>; Pandiyan, Dhinakaran
> > <dhinakaran.pandiyan@intel.com>
> > Cc: Runyan, Arthur J <arthur.j.runyan@intel.com>; Aigal, Pavana A
> > <pavana.a.aigal@intel.com>; intel-gfx@lists.freedesktop.org
> > Subject: Re: [PATCH] drm/i915: Fix PSR2 selective update corruption after
> > PSR1 setup
> >
> > On Tue, 2019-03-12 at 14:14 -0700, Dhinakaran Pandiyan wrote:
> > > On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> > > > On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> > > > wrote:
> > > > > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is kept
> > > > > set
> > > > > while PSR2 is enabled, it causes some selective updates to fail
> > > > > after
> > > > > got back from DC6 for the first time.
> > >
> > > That's suspicious, why does a PSR1 control register have any effect
> > > on
> > > PSR2. Was PSR1 enabled before PSR2?
> >
> > Yes it only happens when switching from PSR1 -> PSR2, I caught this
> > issue now because I had a external connector attached so display was
> > never going to DC6.
> >
> > >
> > >
> > >
> > > > > So lets clear this register before enabled PSR2, as it could be
> > > > > set
> > > > > by a previous i915 module, firmware/BIOS or by a previous mode
> > > > > that
> > > > > is not compatible with PSR2.
> > > >
> > > > Does it happen when you don't have DMC loaded?
> > > >
> > > > Because It looks like a DMC bug for me...
> > > >
> > > > If by removing DMC we don't see the issue, could we please file
> > > > this bug to DMC while adding a FIXME with DMC bugged version on it?
> > > >
> > > > Aa: Pavana
> > > >
> > > > If it doesn't happen with DMC loaded than maybe a HSD would for hw
> > > > team would be good anyway.
> > > >
> > > > Cc: Art.
> > > >
> > > > Thanks,
> > > > Rodrigo.
> > > >
> > > > > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > > > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> > > > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > > > > b/drivers/gpu/drm/i915/intel_psr.c
> > > > > index 7bab6a009e0d..ae62f8124558 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_psr.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > > > > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct
> > > > > intel_dp
> > > > > *intel_dp)
> > > > >  {
> > > > >  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> > > > >  	u32 val;
> > > > > +	int idle_frames;
> > > > > +
> > > > > +	/*
> > > > > +	 * Keeping this PSR1 register set while PSR2 is enabled causes
> > > > > some
> > > > > +	 * PSR2 selective updates to fail, corrupting screen.
> > > > > +	 */
> > > > > +	val = I915_READ(EDP_PSR_CTL);
> > > > > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > > > > +		I915_WRITE(EDP_PSR_CTL, val &
> ~EDP_PSR_TP1_TP3_SEL);
> > >
> > > Since PSR1 should be disabled at this point, a rmw is not necessary.
> > > Does this work?
> > > I915_WRITE(EDP_PSR_CTL, 0);
> > >
> > > We could do the same thing in psr_exit() as well.
> >
> > Write 0 also works and I'm doing RMW because I always try to save any
> > writes.
> >
> > No need to do it in psr_exit(), the important is do it here because
> > other i915 module or BIOS could leave it set.
> >
> > >
> > > > >
> > > > >  	/* Let's use 6 as the minimum to cover all known cases
> > > > > including the
> > > > >  	 * off-by-one issue that HW has in some cases.
> > > > >  	 */
> > > > > -	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > > > -
> > > > > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > > >  	idle_frames = max(idle_frames, dev_priv-
> >psr.sink_sync_latency
> > > > > + 1);
> > > > >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> > > > >
> > > > > --
> > > > > 2.21.0
> > > > >
Dhinakaran Pandiyan March 20, 2019, 7:02 p.m. UTC | #9
Thanks for checking, appreciate it.

-DK

> -----Original Message-----
> From: Runyan, Arthur J
> Sent: Wednesday, March 20, 2019 11:58 AM
> To: Souza, Jose <jose.souza@intel.com>; Vivi, Rodrigo
> <rodrigo.vivi@intel.com>; Pandiyan, Dhinakaran
> <dhinakaran.pandiyan@intel.com>
> Cc: Aigal, Pavana A <pavana.a.aigal@intel.com>; 'intel-
> gfx@lists.freedesktop.org' <intel-gfx@lists.freedesktop.org>
> Subject: RE: [PATCH] drm/i915: Fix PSR2 selective update corruption after
> PSR1 setup
> 
> PSR2 logic is incorrectly looking at this register bit during DC5 exit.
> Not a DMC problem, but DMC enables DC5.
> I'll update Bspec to require the bit to be not set when PSR2 is used.
> 
> > -----Original Message-----
> > From: Runyan, Arthur J
> > Sent: Tuesday, 12 March, 2019 4:42 PM
> > To: Souza, Jose <jose.souza@intel.com>; Vivi, Rodrigo
> > <rodrigo.vivi@intel.com>; Pandiyan, Dhinakaran
> > <dhinakaran.pandiyan@intel.com>
> > Cc: Aigal, Pavana A <pavana.a.aigal@intel.com>; intel-
> > gfx@lists.freedesktop.org
> > Subject: RE: [PATCH] drm/i915: Fix PSR2 selective update corruption
> > after
> > PSR1 setup
> >
> > Strange.  DMC doesn't look at training patterns.  I've asked the PSR2
> > guys to look for any cross-connection.
> >
> > > -----Original Message-----
> > > From: Souza, Jose
> > > Sent: Tuesday, 12 March, 2019 2:29 PM
> > > To: Vivi, Rodrigo <rodrigo.vivi@intel.com>; Pandiyan, Dhinakaran
> > > <dhinakaran.pandiyan@intel.com>
> > > Cc: Runyan, Arthur J <arthur.j.runyan@intel.com>; Aigal, Pavana A
> > > <pavana.a.aigal@intel.com>; intel-gfx@lists.freedesktop.org
> > > Subject: Re: [PATCH] drm/i915: Fix PSR2 selective update corruption
> > > after
> > > PSR1 setup
> > >
> > > On Tue, 2019-03-12 at 14:14 -0700, Dhinakaran Pandiyan wrote:
> > > > On Tue, 2019-03-12 at 13:53 -0700, Rodrigo Vivi wrote:
> > > > > On Tue, Mar 12, 2019 at 01:42:17PM -0700, José Roberto de Souza
> > > > > wrote:
> > > > > > For some reason if the PSR1 EDP_PSR_TP1_TP3_SEL register is
> > > > > > kept set while PSR2 is enabled, it causes some selective
> > > > > > updates to fail after got back from DC6 for the first time.
> > > >
> > > > That's suspicious, why does a PSR1 control register have any
> > > > effect on PSR2. Was PSR1 enabled before PSR2?
> > >
> > > Yes it only happens when switching from PSR1 -> PSR2, I caught this
> > > issue now because I had a external connector attached so display was
> > > never going to DC6.
> > >
> > > >
> > > >
> > > >
> > > > > > So lets clear this register before enabled PSR2, as it could
> > > > > > be set by a previous i915 module, firmware/BIOS or by a
> > > > > > previous mode that is not compatible with PSR2.
> > > > >
> > > > > Does it happen when you don't have DMC loaded?
> > > > >
> > > > > Because It looks like a DMC bug for me...
> > > > >
> > > > > If by removing DMC we don't see the issue, could we please file
> > > > > this bug to DMC while adding a FIXME with DMC bugged version on it?
> > > > >
> > > > > Aa: Pavana
> > > > >
> > > > > If it doesn't happen with DMC loaded than maybe a HSD would for
> > > > > hw team would be good anyway.
> > > > >
> > > > > Cc: Art.
> > > > >
> > > > > Thanks,
> > > > > Rodrigo.
> > > > >
> > > > > > Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > > > > > Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
> > > > > > Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
> > > > > > ---
> > > > > >  drivers/gpu/drm/i915/intel_psr.c | 12 ++++++++++--
> > > > > >  1 file changed, 10 insertions(+), 2 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_psr.c
> > > > > > b/drivers/gpu/drm/i915/intel_psr.c
> > > > > > index 7bab6a009e0d..ae62f8124558 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_psr.c
> > > > > > +++ b/drivers/gpu/drm/i915/intel_psr.c
> > > > > > @@ -494,12 +494,20 @@ static void hsw_activate_psr2(struct
> > > > > > intel_dp
> > > > > > *intel_dp)
> > > > > >  {
> > > > > >  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> > > > > >  	u32 val;
> > > > > > +	int idle_frames;
> > > > > > +
> > > > > > +	/*
> > > > > > +	 * Keeping this PSR1 register set while PSR2 is enabled
> > > > > > +causes
> > > > > > some
> > > > > > +	 * PSR2 selective updates to fail, corrupting screen.
> > > > > > +	 */
> > > > > > +	val = I915_READ(EDP_PSR_CTL);
> > > > > > +	if (val & EDP_PSR_TP1_TP3_SEL)
> > > > > > +		I915_WRITE(EDP_PSR_CTL, val &
> > ~EDP_PSR_TP1_TP3_SEL);
> > > >
> > > > Since PSR1 should be disabled at this point, a rmw is not necessary.
> > > > Does this work?
> > > > I915_WRITE(EDP_PSR_CTL, 0);
> > > >
> > > > We could do the same thing in psr_exit() as well.
> > >
> > > Write 0 also works and I'm doing RMW because I always try to save
> > > any writes.
> > >
> > > No need to do it in psr_exit(), the important is do it here because
> > > other i915 module or BIOS could leave it set.
> > >
> > > >
> > > > > >
> > > > > >  	/* Let's use 6 as the minimum to cover all known cases
> > > > > > including the
> > > > > >  	 * off-by-one issue that HW has in some cases.
> > > > > >  	 */
> > > > > > -	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > > > > -
> > > > > > +	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
> > > > > >  	idle_frames = max(idle_frames, dev_priv-
> > >psr.sink_sync_latency
> > > > > > + 1);
> > > > > >  	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;
> > > > > >
> > > > > > --
> > > > > > 2.21.0
> > > > > >
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 7bab6a009e0d..ae62f8124558 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -494,12 +494,20 @@  static void hsw_activate_psr2(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	u32 val;
+	int idle_frames;
+
+	/*
+	 * Keeping this PSR1 register set while PSR2 is enabled causes some
+	 * PSR2 selective updates to fail, corrupting screen.
+	 */
+	val = I915_READ(EDP_PSR_CTL);
+	if (val & EDP_PSR_TP1_TP3_SEL)
+		I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_TP1_TP3_SEL);
 
 	/* Let's use 6 as the minimum to cover all known cases including the
 	 * off-by-one issue that HW has in some cases.
 	 */
-	int idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
-
+	idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
 	idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1);
 	val = idle_frames << EDP_PSR2_IDLE_FRAME_SHIFT;