[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, psr1 should be disabled.When psr2 is exited , bit 31 of reg PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL (psr1 control register)is set to 0. Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) instead of PSR2_STATUS register, which has wrong data, resulting in blankscreen. hsw_enable_source is split into hsw_enable_source_psr1 and hsw_enable_source_psr2 for easier code review and maintenance, as suggested by rodrigo and jim. v2: (Rodrigo) - Rename hsw_enable_source_psr* to intel_enable_source_psr* v3: (Rodrigo) - In hsw_psr_disable , 1) for psr active case, handle psr2 followed by psr1. 2) psr inactive case, handle psr2 followed by psr1 v4:(Rodrigo) - move psr2 restriction(32X20) to match_conditions function returning false and fully blocking PSR to a new patch before this one. v5: in source_psr2, removed val = EDP_PSR_ENABLE Cc: Rodrigo ViviCc: Jim Bride Signed-off-by: Vathsala Nagaraju Signed-off-by: Patil Deepti --- drivers/gpu/drm/i915/i915_reg.h | 3 + drivers/gpu/drm/i915/intel_psr.c | 122 +-- 2 files changed, 95 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00970aa..7830e6e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3615,6 +3615,9 @@ enum { #define EDP_PSR2_FRAME_BEFORE_SU_MASK(0xf<<4) #define EDP_PSR2_IDLE_MASK 0xf +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) + /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA_MMIO(0xe1100) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 707cae8..8827647 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -261,7 +261,7 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) VLV_EDP_PSR_ACTIVE_ENTRY); } -static void hsw_psr_enable_source(struct intel_dp *intel_dp) +static void intel_enable_source_psr1(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -312,14 +312,29 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) val |= EDP_PSR_TP1_TP2_SEL; I915_WRITE(EDP_PSR_CTL, val); +} - if (!dev_priv->psr.psr2_support) - return; +static void intel_enable_source_psr2(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + /* +* Let's respect VBT in case VBT asks a higher idle_frame value. +* Let's use 6 as the minimum to cover all known cases including +* the off-by-one issue that HW has in some cases. Also there are +* cases where sink should be able to train +* with the 5 or 6 idle patterns. +*/ + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + uint32_t val; + + val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't * good enough. */ - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; @@ -333,6 +348,19 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR2_CTL, val); } +static void hsw_psr_enable_source(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* psr1 and psr2 are mutually exclusive.*/ + if (dev_priv->psr.psr2_support) + intel_enable_source_psr2(intel_dp); + else + intel_enable_source_psr1(intel_dp); +} + static bool intel_psr_match_conditions(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -417,7 +445,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); + if (dev_priv->psr.psr2_support) + WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); + else + WARN_ON(I915_READ(EDP_PSR_CTL) &
Re: [PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
Reviewed-by: Rodrigo ViviOn Thu, 2017-01-12 at 23:30 +0530, vathsala nagaraju wrote: > Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, > psr1 should be disabled.When psr2 is exited , bit 31 of reg > PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL > (psr1 control register)is set to 0. > Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) > instead of PSR2_STATUS register, which has wrong data, resulting > in blankscreen. > hsw_enable_source is split into hsw_enable_source_psr1 and > hsw_enable_source_psr2 for easier code review and maintenance, > as suggested by rodrigo and jim. > > v2: (Rodrigo) > - Rename hsw_enable_source_psr* to intel_enable_source_psr* > > v3: (Rodrigo) > - In hsw_psr_disable , > 1) for psr active case, handle psr2 followed by psr1. > 2) psr inactive case, handle psr2 followed by psr1 > > v4:(Rodrigo) > - move psr2 restriction(32X20) to match_conditions function > returning false and fully blocking PSR to a new patch before > this one. > > v5: in source_psr2, removed val = EDP_PSR_ENABLE > > Cc: Rodrigo Vivi > Cc: Jim Bride > Signed-off-by: Vathsala Nagaraju > Signed-off-by: Patil Deepti > --- > drivers/gpu/drm/i915/i915_reg.h | 3 + > drivers/gpu/drm/i915/intel_psr.c | 122 > +-- > 2 files changed, 95 insertions(+), 30 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 00970aa..7830e6e 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3615,6 +3615,9 @@ enum { > #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) > #define EDP_PSR2_IDLE_MASK 0xf > > +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) > +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) > + > /* VGA port control */ > #define ADPA _MMIO(0x61100) > #define PCH_ADPA_MMIO(0xe1100) > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index 707cae8..8827647 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -261,7 +261,7 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) > VLV_EDP_PSR_ACTIVE_ENTRY); > } > > -static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +static void intel_enable_source_psr1(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > struct drm_device *dev = dig_port->base.base.dev; > @@ -312,14 +312,29 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > val |= EDP_PSR_TP1_TP2_SEL; > > I915_WRITE(EDP_PSR_CTL, val); > +} > > - if (!dev_priv->psr.psr2_support) > - return; > +static void intel_enable_source_psr2(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + /* > + * Let's respect VBT in case VBT asks a higher idle_frame value. > + * Let's use 6 as the minimum to cover all known cases including > + * the off-by-one issue that HW has in some cases. Also there are > + * cases where sink should be able to train > + * with the 5 or 6 idle patterns. > + */ > + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); > + uint32_t val; > + > + val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; > > /* FIXME: selective update is probably totally broken because it doesn't >* mesh at all with our frontbuffer tracking. And the hw alone isn't >* good enough. */ > - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > > if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) > val |= EDP_PSR2_TP2_TIME_2500; > @@ -333,6 +348,19 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > I915_WRITE(EDP_PSR2_CTL, val); > } > > +static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* psr1 and psr2 are mutually exclusive.*/ > + if (dev_priv->psr.psr2_support) > + intel_enable_source_psr2(intel_dp); > + else > + intel_enable_source_psr1(intel_dp); > +} > + > static bool intel_psr_match_conditions(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > @@ -417,7 +445,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) > struct drm_device *dev = intel_dig_port->base.base.dev; > struct
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, psr1 should be disabled.When psr2 is exited , bit 31 of reg PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL (psr1 control register)is set to 0. Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) instead of PSR2_STATUS register, which has wrong data, resulting in blankscreen. hsw_enable_source is split into hsw_enable_source_psr1 and hsw_enable_source_psr2 for easier code review and maintenance, as suggested by rodrigo and jim. v2: (Rodrigo) - Rename hsw_enable_source_psr* to intel_enable_source_psr* v3: (Rodrigo) - In hsw_psr_disable , 1) for psr active case, handle psr2 followed by psr1. 2) psr inactive case, handle psr2 followed by psr1 v4:(Rodrigo) - move psr2 restriction(32X20) to match_conditions function returning false and fully blocking PSR to a new patch before this one. Cc: Rodrigo ViviCc: Jim Bride Signed-off-by: Vathsala Nagaraju Signed-off-by: Patil Deepti --- drivers/gpu/drm/i915/i915_reg.h | 3 + drivers/gpu/drm/i915/intel_psr.c | 122 +-- 2 files changed, 95 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00970aa..7830e6e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3615,6 +3615,9 @@ enum { #define EDP_PSR2_FRAME_BEFORE_SU_MASK(0xf<<4) #define EDP_PSR2_IDLE_MASK 0xf +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) + /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA_MMIO(0xe1100) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 707cae8..19c7090 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -261,7 +261,7 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) VLV_EDP_PSR_ACTIVE_ENTRY); } -static void hsw_psr_enable_source(struct intel_dp *intel_dp) +static void intel_enable_source_psr1(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -312,14 +312,29 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) val |= EDP_PSR_TP1_TP2_SEL; I915_WRITE(EDP_PSR_CTL, val); +} - if (!dev_priv->psr.psr2_support) - return; +static void intel_enable_source_psr2(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + /* +* Let's respect VBT in case VBT asks a higher idle_frame value. +* Let's use 6 as the minimum to cover all known cases including +* the off-by-one issue that HW has in some cases. Also there are +* cases where sink should be able to train +* with the 5 or 6 idle patterns. +*/ + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + uint32_t val = EDP_PSR_ENABLE; + + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't * good enough. */ - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; @@ -333,6 +348,19 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR2_CTL, val); } +static void hsw_psr_enable_source(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* psr1 and psr2 are mutually exclusive.*/ + if (dev_priv->psr.psr2_support) + intel_enable_source_psr2(intel_dp); + else + intel_enable_source_psr1(intel_dp); +} + static bool intel_psr_match_conditions(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -417,7 +445,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); + if (dev_priv->psr.psr2_support) + WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); + else + WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
On Monday 09 January 2017 10:47 PM, Vivi, Rodrigo wrote: > On Mon, 2017-01-09 at 18:26 +0530, vathsala nagaraju wrote: >> Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, >> psr1 should be disabled.When psr2 is exited , bit 31 of reg >> PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL >> (psr1 control register)is set to 0. >> Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) >> instead of PSR2_STATUS register, which has wrong data, resulting >> in blankscreen. >> hsw_enable_source is split into hsw_enable_source_psr1 and >> hsw_enable_source_psr2 for easier code review and maintenance, >> as suggested by rodrigo and jim. >> >> v2: (Rodrigo) >> - Rename hsw_enable_source_psr* to intel_enable_source_psr* >> >> v3: (Rodrigo) >> - In hsw_psr_disable , >>1) for psr active case, handle psr2 followed by psr1. >>2) psr inactive case, handle psr2 followed by psr1 > much better, thanks, but still has one blocking issue imho: > >> Cc: Rodrigo Vivi >> Cc: Jim Bride >> Signed-off-by: Vathsala Nagaraju >> Signed-off-by: Patil Deepti >> --- >> drivers/gpu/drm/i915/i915_reg.h | 3 + >> drivers/gpu/drm/i915/intel_psr.c | 126 >> +-- >> 2 files changed, 97 insertions(+), 32 deletions(-) >> >> diff --git a/drivers/gpu/drm/i915/i915_reg.h >> b/drivers/gpu/drm/i915/i915_reg.h >> index 00970aa..7830e6e 100644 >> --- a/drivers/gpu/drm/i915/i915_reg.h >> +++ b/drivers/gpu/drm/i915/i915_reg.h >> @@ -3615,6 +3615,9 @@ enum { >> #define EDP_PSR2_FRAME_BEFORE_SU_MASK(0xf<<4) >> #define EDP_PSR2_IDLE_MASK 0xf >> >> +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) >> +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) >> + >> /* VGA port control */ >> #define ADPA _MMIO(0x61100) >> #define PCH_ADPA_MMIO(0xe1100) >> diff --git a/drivers/gpu/drm/i915/intel_psr.c >> b/drivers/gpu/drm/i915/intel_psr.c >> index c3aa649..6c161aa 100644 >> --- a/drivers/gpu/drm/i915/intel_psr.c >> +++ b/drivers/gpu/drm/i915/intel_psr.c >> @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) >> VLV_EDP_PSR_ACTIVE_ENTRY); >> } >> >> -static void hsw_psr_enable_source(struct intel_dp *intel_dp) >> +static void intel_enable_source_psr1(struct intel_dp *intel_dp) >> { >> struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); >> struct drm_device *dev = dig_port->base.base.dev; >> struct drm_i915_private *dev_priv = to_i915(dev); >> - >> uint32_t max_sleep_time = 0x1f; >> /* >> * Let's respect VBT in case VBT asks a higher idle_frame value. >> @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp >> *intel_dp) >> val |= EDP_PSR_TP1_TP2_SEL; >> >> I915_WRITE(EDP_PSR_CTL, val); >> +} >> >> -if (!dev_priv->psr.psr2_support) >> -return; >> +static void intel_enable_source_psr2(struct intel_dp *intel_dp) >> +{ >> +struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); >> +struct drm_device *dev = dig_port->base.base.dev; >> +struct drm_i915_private *dev_priv = to_i915(dev); >> + >> +/* >> + * Let's respect VBT in case VBT asks a higher idle_frame value. >> + * Let's use 6 as the minimum to cover all known cases including >> + * the off-by-one issue that HW has in some cases. Also there are >> + * cases where sink should be able to train >> + * with the 5 or 6 idle patterns. >> + */ >> +uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); >> +uint32_t val = EDP_PSR_ENABLE; >> + >> +val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; >> >> /* FIXME: selective update is probably totally broken because it doesn't >> * mesh at all with our frontbuffer tracking. And the hw alone isn't >> * good enough. */ >> -val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; >> +val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; >> >> if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) >> val |= EDP_PSR2_TP2_TIME_2500; >> @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp >> *intel_dp) >> I915_WRITE(EDP_PSR2_CTL, val); >> } >> >> + >> +static void hsw_psr_enable_source(struct intel_dp *intel_dp) >> +{ >> +struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); >> +struct drm_device *dev = dig_port->base.base.dev; >> +struct drm_i915_private *dev_priv = to_i915(dev); >> + >> +/* psr1 and psr2 are mutually exclusive.*/ >> +if (dev_priv->psr.psr2_support) >> +intel_enable_source_psr2(intel_dp); >> +else >> +intel_enable_source_psr1(intel_dp); >> +} >> + >> static bool intel_psr_match_conditions(struct intel_dp *intel_dp) >> { >> struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); >> @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp >> *intel_dp) >>
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, psr1 should be disabled.When psr2 is exited , bit 31 of reg PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL (psr1 control register)is set to 0. Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) instead of PSR2_STATUS register, which has wrong data, resulting in blankscreen. hsw_enable_source is split into hsw_enable_source_psr1 and hsw_enable_source_psr2 for easier code review and maintenance, as suggested by rodrigo and jim. v2: (Rodrigo) - Rename hsw_enable_source_psr* to intel_enable_source_psr* v3: (Rodrigo) - In hsw_psr_disable , 1) for psr active case, handle psr2 followed by psr1. 2) psr inactive case, handle psr2 followed by psr1 Cc: Rodrigo Vivi Cc: Jim Bride Signed-off-by: Vathsala Nagaraju Signed-off-by: Patil Deepti --- drivers/gpu/drm/i915/i915_reg.h | 3 + drivers/gpu/drm/i915/intel_psr.c | 126 +-- 2 files changed, 97 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00970aa..7830e6e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3615,6 +3615,9 @@ enum { #define EDP_PSR2_FRAME_BEFORE_SU_MASK(0xf<<4) #define EDP_PSR2_IDLE_MASK 0xf +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) + /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA_MMIO(0xe1100) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c3aa649..6c161aa 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) VLV_EDP_PSR_ACTIVE_ENTRY); } -static void hsw_psr_enable_source(struct intel_dp *intel_dp) +static void intel_enable_source_psr1(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - uint32_t max_sleep_time = 0x1f; /* * Let's respect VBT in case VBT asks a higher idle_frame value. @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) val |= EDP_PSR_TP1_TP2_SEL; I915_WRITE(EDP_PSR_CTL, val); +} - if (!dev_priv->psr.psr2_support) - return; +static void intel_enable_source_psr2(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* +* Let's respect VBT in case VBT asks a higher idle_frame value. +* Let's use 6 as the minimum to cover all known cases including +* the off-by-one issue that HW has in some cases. Also there are +* cases where sink should be able to train +* with the 5 or 6 idle patterns. +*/ + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + uint32_t val = EDP_PSR_ENABLE; + + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't * good enough. */ - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR2_CTL, val); } + +static void hsw_psr_enable_source(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* psr1 and psr2 are mutually exclusive.*/ + if (dev_priv->psr.psr2_support) + intel_enable_source_psr2(intel_dp); + else + intel_enable_source_psr1(intel_dp); +} + static bool intel_psr_match_conditions(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); + if (dev_priv->psr.psr2_support) + WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); + else + WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); WARN_ON(dev_priv->psr.active); lockdep_assert_held(_priv->psr.lock); @@ -462,8
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
On Mon, 2017-01-09 at 18:26 +0530, vathsala nagaraju wrote: > Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, > psr1 should be disabled.When psr2 is exited , bit 31 of reg > PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL > (psr1 control register)is set to 0. > Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) > instead of PSR2_STATUS register, which has wrong data, resulting > in blankscreen. > hsw_enable_source is split into hsw_enable_source_psr1 and > hsw_enable_source_psr2 for easier code review and maintenance, > as suggested by rodrigo and jim. > > v2: (Rodrigo) > - Rename hsw_enable_source_psr* to intel_enable_source_psr* > > v3: (Rodrigo) > - In hsw_psr_disable , > 1) for psr active case, handle psr2 followed by psr1. > 2) psr inactive case, handle psr2 followed by psr1 much better, thanks, but still has one blocking issue imho: > > Cc: Rodrigo Vivi > Cc: Jim Bride > Signed-off-by: Vathsala Nagaraju > Signed-off-by: Patil Deepti > --- > drivers/gpu/drm/i915/i915_reg.h | 3 + > drivers/gpu/drm/i915/intel_psr.c | 126 > +-- > 2 files changed, 97 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 00970aa..7830e6e 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3615,6 +3615,9 @@ enum { > #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) > #define EDP_PSR2_IDLE_MASK 0xf > > +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) > +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) > + > /* VGA port control */ > #define ADPA _MMIO(0x61100) > #define PCH_ADPA_MMIO(0xe1100) > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index c3aa649..6c161aa 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) > VLV_EDP_PSR_ACTIVE_ENTRY); > } > > -static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +static void intel_enable_source_psr1(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > struct drm_device *dev = dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > - > uint32_t max_sleep_time = 0x1f; > /* >* Let's respect VBT in case VBT asks a higher idle_frame value. > @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > val |= EDP_PSR_TP1_TP2_SEL; > > I915_WRITE(EDP_PSR_CTL, val); > +} > > - if (!dev_priv->psr.psr2_support) > - return; > +static void intel_enable_source_psr2(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* > + * Let's respect VBT in case VBT asks a higher idle_frame value. > + * Let's use 6 as the minimum to cover all known cases including > + * the off-by-one issue that HW has in some cases. Also there are > + * cases where sink should be able to train > + * with the 5 or 6 idle patterns. > + */ > + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); > + uint32_t val = EDP_PSR_ENABLE; > + > + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; > > /* FIXME: selective update is probably totally broken because it doesn't >* mesh at all with our frontbuffer tracking. And the hw alone isn't >* good enough. */ > - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > > if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) > val |= EDP_PSR2_TP2_TIME_2500; > @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > I915_WRITE(EDP_PSR2_CTL, val); > } > > + > +static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* psr1 and psr2 are mutually exclusive.*/ > + if (dev_priv->psr.psr2_support) > + intel_enable_source_psr2(intel_dp); > + else > + intel_enable_source_psr1(intel_dp); > +} > + > static bool intel_psr_match_conditions(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) > struct drm_device *dev = intel_dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > > - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); >
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
Rodrigo, The code is if (dev_priv->psr.psr2_support) { /* PSR2 is restricted to work with panel resolutions upto 3200x2000 */ if (crtc->config->pipe_src_w > 3200 || crtc->config->pipe_src_h > 2000) dev_priv->psr.psr2_support = false; else skl_psr_setup_su_vsc(intel_dp); } else { /* set up vsc header for psr1 */ hsw_psr_setup_vsc(intel_dp); } If psr2_support=0 , then it calls hsw_psr_setup_vsc(intel_dp); {psr1 vsc setup) If psr2_support=1 then it calls skl_psr_setup_su_vsc(intel_dp); (psr2 vsc setup) Regards, vathsala -Original Message- From: Vivi, Rodrigo Sent: Friday, January 6, 2017 2:12 AM To: Nagaraju, Vathsala Cc: dri-devel at lists.freedesktop.org; intel-gfx at lists.freedesktop.org; jim.bride at linux.intel.com; Patil, Deepti Subject: Re: [PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2 On Fri, 2017-01-06 at 00:55 +0530, vathsala nagaraju wrote: > Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, > psr1 should be disabled.When psr2 is exited , bit 31 of reg PSR2_CTL > must be set to 0 but currently bit 31 of SRD_CTL > (psr1 control register)is set to 0. > Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) > instead of PSR2_STATUS register, which has wrong data, resulting in > blankscreen. > hsw_enable_source is split into hsw_enable_source_psr1 and > hsw_enable_source_psr2 for easier code review and maintenance, as > suggested by rodrigo and jim. > > v2: (Vivi Rodrigo) > - Rename hsw_enable_source_psr* to intel_enable_source_psr* > > Cc: Rodrigo Vivi > Cc: Jim Bride > Signed-off-by: Vathsala Nagaraju > Signed-off-by: Patil Deepti > --- > drivers/gpu/drm/i915/i915_reg.h | 3 + > drivers/gpu/drm/i915/intel_psr.c | 124 > +-- > 2 files changed, 97 insertions(+), 30 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h > b/drivers/gpu/drm/i915/i915_reg.h index 00970aa..7830e6e 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3615,6 +3615,9 @@ enum { > #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) > #define EDP_PSR2_IDLE_MASK 0xf > > +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) > +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) > + > /* VGA port control */ > #define ADPA _MMIO(0x61100) > #define PCH_ADPA_MMIO(0xe1100) > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index c3aa649..d5e8bcc 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) > VLV_EDP_PSR_ACTIVE_ENTRY); > } > > -static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +static void intel_enable_source_psr1(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > struct drm_device *dev = dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > - > uint32_t max_sleep_time = 0x1f; > /* >* Let's respect VBT in case VBT asks a higher idle_frame value. > @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > val |= EDP_PSR_TP1_TP2_SEL; > > I915_WRITE(EDP_PSR_CTL, val); > +} > > - if (!dev_priv->psr.psr2_support) > - return; > +static void intel_enable_source_psr2(struct intel_dp *intel_dp) { > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* > + * Let's respect VBT in case VBT asks a higher idle_frame value. > + * Let's use 6 as the minimum to cover all known cases including > + * the off-by-one issue that HW has in some cases. Also there are > + * cases where sink should be able to train > + * with the 5 or 6 idle patterns. > + */ > + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); > + uint32_t val = EDP_PSR_ENABLE; > + > + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; > > /* FIXME: selective update is probably totally broken because it doesn't >* mesh at all with our frontbuffer tracking. And the hw alone isn't >* good enough. */ > - val = EDP_PSR
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, psr1 should be disabled.When psr2 is exited , bit 31 of reg PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL (psr1 control register)is set to 0. Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) instead of PSR2_STATUS register, which has wrong data, resulting in blankscreen. hsw_enable_source is split into hsw_enable_source_psr1 and hsw_enable_source_psr2 for easier code review and maintenance, as suggested by rodrigo and jim. v2: (Vivi Rodrigo) - Rename hsw_enable_source_psr* to intel_enable_source_psr* Cc: Rodrigo Vivi Cc: Jim Bride Signed-off-by: Vathsala Nagaraju Signed-off-by: Patil Deepti --- drivers/gpu/drm/i915/i915_reg.h | 3 + drivers/gpu/drm/i915/intel_psr.c | 124 +-- 2 files changed, 97 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00970aa..7830e6e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3615,6 +3615,9 @@ enum { #define EDP_PSR2_FRAME_BEFORE_SU_MASK(0xf<<4) #define EDP_PSR2_IDLE_MASK 0xf +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) + /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA_MMIO(0xe1100) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c3aa649..d5e8bcc 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) VLV_EDP_PSR_ACTIVE_ENTRY); } -static void hsw_psr_enable_source(struct intel_dp *intel_dp) +static void intel_enable_source_psr1(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - uint32_t max_sleep_time = 0x1f; /* * Let's respect VBT in case VBT asks a higher idle_frame value. @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) val |= EDP_PSR_TP1_TP2_SEL; I915_WRITE(EDP_PSR_CTL, val); +} - if (!dev_priv->psr.psr2_support) - return; +static void intel_enable_source_psr2(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* +* Let's respect VBT in case VBT asks a higher idle_frame value. +* Let's use 6 as the minimum to cover all known cases including +* the off-by-one issue that HW has in some cases. Also there are +* cases where sink should be able to train +* with the 5 or 6 idle patterns. +*/ + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + uint32_t val = EDP_PSR_ENABLE; + + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't * good enough. */ - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR2_CTL, val); } + +static void hsw_psr_enable_source(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* psr1 and psr2 are mutually exclusive.*/ + if (dev_priv->psr.psr2_support) + intel_enable_source_psr2(intel_dp); + else + intel_enable_source_psr1(intel_dp); +} + static bool intel_psr_match_conditions(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); + if (dev_priv->psr.psr2_support) + WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); + else + WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); WARN_ON(dev_priv->psr.active); lockdep_assert_held(_priv->psr.lock); @@ -462,8 +494,6 @@ void intel_psr_enable(struct intel_dp *intel_dp) dev_priv->psr.busy_frontbuffer_bits = 0; if (HAS_DDI(dev_priv)) { -
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
On Fri, 2017-01-06 at 00:55 +0530, vathsala nagaraju wrote: > Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, > psr1 should be disabled.When psr2 is exited , bit 31 of reg > PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL > (psr1 control register)is set to 0. > Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) > instead of PSR2_STATUS register, which has wrong data, resulting > in blankscreen. > hsw_enable_source is split into hsw_enable_source_psr1 and > hsw_enable_source_psr2 for easier code review and maintenance, > as suggested by rodrigo and jim. > > v2: (Vivi Rodrigo) > - Rename hsw_enable_source_psr* to intel_enable_source_psr* > > Cc: Rodrigo Vivi > Cc: Jim Bride > Signed-off-by: Vathsala Nagaraju > Signed-off-by: Patil Deepti > --- > drivers/gpu/drm/i915/i915_reg.h | 3 + > drivers/gpu/drm/i915/intel_psr.c | 124 > +-- > 2 files changed, 97 insertions(+), 30 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 00970aa..7830e6e 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3615,6 +3615,9 @@ enum { > #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) > #define EDP_PSR2_IDLE_MASK 0xf > > +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) > +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) > + > /* VGA port control */ > #define ADPA _MMIO(0x61100) > #define PCH_ADPA_MMIO(0xe1100) > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index c3aa649..d5e8bcc 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) > VLV_EDP_PSR_ACTIVE_ENTRY); > } > > -static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +static void intel_enable_source_psr1(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > struct drm_device *dev = dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > - > uint32_t max_sleep_time = 0x1f; > /* >* Let's respect VBT in case VBT asks a higher idle_frame value. > @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > val |= EDP_PSR_TP1_TP2_SEL; > > I915_WRITE(EDP_PSR_CTL, val); > +} > > - if (!dev_priv->psr.psr2_support) > - return; > +static void intel_enable_source_psr2(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* > + * Let's respect VBT in case VBT asks a higher idle_frame value. > + * Let's use 6 as the minimum to cover all known cases including > + * the off-by-one issue that HW has in some cases. Also there are > + * cases where sink should be able to train > + * with the 5 or 6 idle patterns. > + */ > + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); > + uint32_t val = EDP_PSR_ENABLE; > + > + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; > > /* FIXME: selective update is probably totally broken because it doesn't >* mesh at all with our frontbuffer tracking. And the hw alone isn't >* good enough. */ > - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > > if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) > val |= EDP_PSR2_TP2_TIME_2500; > @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > I915_WRITE(EDP_PSR2_CTL, val); > } > > + > +static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* psr1 and psr2 are mutually exclusive.*/ > + if (dev_priv->psr.psr2_support) > + intel_enable_source_psr2(intel_dp); > + else > + intel_enable_source_psr1(intel_dp); > +} > + > static bool intel_psr_match_conditions(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) > struct drm_device *dev = intel_dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > > - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); > + if (dev_priv->psr.psr2_support) > + WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); > + else > + WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); >
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
On Fri, Jan 06, 2017 at 12:55:59AM +0530, vathsala nagaraju wrote: > Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, > psr1 should be disabled.When psr2 is exited , bit 31 of reg > PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL > (psr1 control register)is set to 0. > Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) > instead of PSR2_STATUS register, which has wrong data, resulting > in blankscreen. > hsw_enable_source is split into hsw_enable_source_psr1 and > hsw_enable_source_psr2 for easier code review and maintenance, > as suggested by rodrigo and jim. > > v2: (Vivi Rodrigo) > - Rename hsw_enable_source_psr* to intel_enable_source_psr* > > Cc: Rodrigo Vivi > Cc: Jim Bride > Signed-off-by: Vathsala Nagaraju > Signed-off-by: Patil Deepti The new naming is much better! Reviewed-by: Jim Bride > --- > drivers/gpu/drm/i915/i915_reg.h | 3 + > drivers/gpu/drm/i915/intel_psr.c | 124 > +-- > 2 files changed, 97 insertions(+), 30 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 00970aa..7830e6e 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3615,6 +3615,9 @@ enum { > #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) > #define EDP_PSR2_IDLE_MASK 0xf > > +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) > +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) > + > /* VGA port control */ > #define ADPA _MMIO(0x61100) > #define PCH_ADPA_MMIO(0xe1100) > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index c3aa649..d5e8bcc 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) > VLV_EDP_PSR_ACTIVE_ENTRY); > } > > -static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +static void intel_enable_source_psr1(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > struct drm_device *dev = dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > - > uint32_t max_sleep_time = 0x1f; > /* >* Let's respect VBT in case VBT asks a higher idle_frame value. > @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > val |= EDP_PSR_TP1_TP2_SEL; > > I915_WRITE(EDP_PSR_CTL, val); > +} > > - if (!dev_priv->psr.psr2_support) > - return; > +static void intel_enable_source_psr2(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* > + * Let's respect VBT in case VBT asks a higher idle_frame value. > + * Let's use 6 as the minimum to cover all known cases including > + * the off-by-one issue that HW has in some cases. Also there are > + * cases where sink should be able to train > + * with the 5 or 6 idle patterns. > + */ > + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); > + uint32_t val = EDP_PSR_ENABLE; > + > + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; > > /* FIXME: selective update is probably totally broken because it doesn't >* mesh at all with our frontbuffer tracking. And the hw alone isn't >* good enough. */ > - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > > if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) > val |= EDP_PSR2_TP2_TIME_2500; > @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > I915_WRITE(EDP_PSR2_CTL, val); > } > > + > +static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* psr1 and psr2 are mutually exclusive.*/ > + if (dev_priv->psr.psr2_support) > + intel_enable_source_psr2(intel_dp); > + else > + intel_enable_source_psr1(intel_dp); > +} > + > static bool intel_psr_match_conditions(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) > struct drm_device *dev = intel_dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > > - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); > + if (dev_priv->psr.psr2_support) > + WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); > + else > +
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
On Mon, Jan 02, 2017 at 05:00:56PM +0530, vathsala nagaraju wrote: > Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, > psr1 should be disabled.When psr2 is exited , bit 31 of reg > PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL > (psr1 control register)is set to 0. > Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) > instead of PSR2_STATUS register, which has wrong data, resulting > in blankscreen. > hsw_enable_source is split into hsw_enable_source_psr1 and > hsw_enable_source_psr2 for easier code review and maintenance, > as suggested by rodrigo and jim. > > Cc: Rodrigo Vivi > Cc: Jim Bride > Signed-off-by: Vathsala Nagaraju > Signed-off-by: Patil Deepti > --- > drivers/gpu/drm/i915/i915_reg.h | 3 + > drivers/gpu/drm/i915/intel_psr.c | 124 > +-- > 2 files changed, 97 insertions(+), 30 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 00970aa..7830e6e 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3615,6 +3615,9 @@ enum { > #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) > #define EDP_PSR2_IDLE_MASK 0xf > > +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) > +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) > + > /* VGA port control */ > #define ADPA _MMIO(0x61100) > #define PCH_ADPA_MMIO(0xe1100) > diff --git a/drivers/gpu/drm/i915/intel_psr.c > b/drivers/gpu/drm/i915/intel_psr.c > index c3aa649..ff2ecfd 100644 > --- a/drivers/gpu/drm/i915/intel_psr.c > +++ b/drivers/gpu/drm/i915/intel_psr.c > @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) > VLV_EDP_PSR_ACTIVE_ENTRY); > } > > -static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +static void hsw_enable_source_psr1(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > struct drm_device *dev = dig_port->base.base.dev; > struct drm_i915_private *dev_priv = to_i915(dev); > - > uint32_t max_sleep_time = 0x1f; > /* >* Let's respect VBT in case VBT asks a higher idle_frame value. > @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > val |= EDP_PSR_TP1_TP2_SEL; > > I915_WRITE(EDP_PSR_CTL, val); > +} > > - if (!dev_priv->psr.psr2_support) > - return; > +static void hsw_enable_source_psr2(struct intel_dp *intel_dp) hm... I believe skl_enable_source_psr2 is more appropriated because psr2 was introduced on skl and not on hsw as this might lead people to think... although when we call this we check for psr2 presence and not platform itself. maybe just let hsw_ on the main one hsw_psr_enable_source and for these 2 new functions just use intel_enable_source_psr1 intel_enable_source_psr2 > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* > + * Let's respect VBT in case VBT asks a higher idle_frame value. > + * Let's use 6 as the minimum to cover all known cases including > + * the off-by-one issue that HW has in some cases. Also there are > + * cases where sink should be able to train > + * with the 5 or 6 idle patterns. > + */ > + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); > + uint32_t val = EDP_PSR_ENABLE; > + > + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; > > /* FIXME: selective update is probably totally broken because it doesn't >* mesh at all with our frontbuffer tracking. And the hw alone isn't >* good enough. */ > - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; > > if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) > val |= EDP_PSR2_TP2_TIME_2500; > @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp > *intel_dp) > I915_WRITE(EDP_PSR2_CTL, val); > } > > + > +static void hsw_psr_enable_source(struct intel_dp *intel_dp) > +{ > + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > + struct drm_device *dev = dig_port->base.base.dev; > + struct drm_i915_private *dev_priv = to_i915(dev); > + > + /* psr1 and psr2 are mutually exclusive.*/ > + if (dev_priv->psr.psr2_support) > + hsw_enable_source_psr2(intel_dp); > + else > + hsw_enable_source_psr1(intel_dp); > +} > + > static bool intel_psr_match_conditions(struct intel_dp *intel_dp) > { > struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); > @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) > struct drm_device *dev = intel_dig_port->base.base.dev; > struct drm_i915_private *dev_priv
[PATCH 03/10] drm/i915/psr: fix blank screen issue for psr2
Psr1 and psr2 are mutually exclusive,ie when psr2 is enabled, psr1 should be disabled.When psr2 is exited , bit 31 of reg PSR2_CTL must be set to 0 but currently bit 31 of SRD_CTL (psr1 control register)is set to 0. Also ,PSR2_IDLE state is looked up from SRD_STATUS(psr1 register) instead of PSR2_STATUS register, which has wrong data, resulting in blankscreen. hsw_enable_source is split into hsw_enable_source_psr1 and hsw_enable_source_psr2 for easier code review and maintenance, as suggested by rodrigo and jim. Cc: Rodrigo Vivi Cc: Jim Bride Signed-off-by: Vathsala Nagaraju Signed-off-by: Patil Deepti --- drivers/gpu/drm/i915/i915_reg.h | 3 + drivers/gpu/drm/i915/intel_psr.c | 124 +-- 2 files changed, 97 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00970aa..7830e6e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3615,6 +3615,9 @@ enum { #define EDP_PSR2_FRAME_BEFORE_SU_MASK(0xf<<4) #define EDP_PSR2_IDLE_MASK 0xf +#define EDP_PSR2_STATUS_CTL_MMIO(0x6f940) +#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) + /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA_MMIO(0xe1100) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c3aa649..ff2ecfd 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -261,12 +261,11 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) VLV_EDP_PSR_ACTIVE_ENTRY); } -static void hsw_psr_enable_source(struct intel_dp *intel_dp) +static void hsw_enable_source_psr1(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - uint32_t max_sleep_time = 0x1f; /* * Let's respect VBT in case VBT asks a higher idle_frame value. @@ -312,14 +311,30 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) val |= EDP_PSR_TP1_TP2_SEL; I915_WRITE(EDP_PSR_CTL, val); +} - if (!dev_priv->psr.psr2_support) - return; +static void hsw_enable_source_psr2(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* +* Let's respect VBT in case VBT asks a higher idle_frame value. +* Let's use 6 as the minimum to cover all known cases including +* the off-by-one issue that HW has in some cases. Also there are +* cases where sink should be able to train +* with the 5 or 6 idle patterns. +*/ + uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); + uint32_t val = EDP_PSR_ENABLE; + + val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; /* FIXME: selective update is probably totally broken because it doesn't * mesh at all with our frontbuffer tracking. And the hw alone isn't * good enough. */ - val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; + val |= EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE; if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; @@ -333,6 +348,20 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR2_CTL, val); } + +static void hsw_psr_enable_source(struct intel_dp *intel_dp) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + + /* psr1 and psr2 are mutually exclusive.*/ + if (dev_priv->psr.psr2_support) + hsw_enable_source_psr2(intel_dp); + else + hsw_enable_source_psr1(intel_dp); +} + static bool intel_psr_match_conditions(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -410,7 +439,10 @@ static void intel_psr_activate(struct intel_dp *intel_dp) struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); + if (dev_priv->psr.psr2_support) + WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE); + else + WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE); WARN_ON(dev_priv->psr.active); lockdep_assert_held(_priv->psr.lock); @@ -462,8 +494,6 @@ void intel_psr_enable(struct intel_dp *intel_dp) dev_priv->psr.busy_frontbuffer_bits = 0; if (HAS_DDI(dev_priv)) { - hsw_psr_setup_vsc(intel_dp); - if