Commit 3fcb0ca1 authored by Nagaraju, Vathsala's avatar Nagaraju, Vathsala Committed by Rodrigo Vivi

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 Vivi <rodrigo.vivi@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Signed-off-by: default avatarVathsala Nagaraju <vathsala.nagaraju@intel.com>
Signed-off-by: default avatarPatil Deepti <deepti.patil@intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1484244059-9201-1-git-send-email-vathsala.nagaraju@intel.com
parent a4dbf7cf
...@@ -3615,6 +3615,9 @@ enum { ...@@ -3615,6 +3615,9 @@ enum {
#define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4)
#define EDP_PSR2_IDLE_MASK 0xf #define EDP_PSR2_IDLE_MASK 0xf
#define EDP_PSR2_STATUS_CTL _MMIO(0x6f940)
#define EDP_PSR2_STATUS_STATE_MASK (0xf<<28)
/* VGA port control */ /* VGA port control */
#define ADPA _MMIO(0x61100) #define ADPA _MMIO(0x61100)
#define PCH_ADPA _MMIO(0xe1100) #define PCH_ADPA _MMIO(0xe1100)
......
...@@ -261,7 +261,7 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) ...@@ -261,7 +261,7 @@ static void vlv_psr_activate(struct intel_dp *intel_dp)
VLV_EDP_PSR_ACTIVE_ENTRY); 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 intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = dig_port->base.base.dev; struct drm_device *dev = dig_port->base.base.dev;
...@@ -312,14 +312,29 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) ...@@ -312,14 +312,29 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
val |= EDP_PSR_TP1_TP2_SEL; val |= EDP_PSR_TP1_TP2_SEL;
I915_WRITE(EDP_PSR_CTL, val); I915_WRITE(EDP_PSR_CTL, val);
}
if (!dev_priv->psr.psr2_support) static void intel_enable_source_psr2(struct intel_dp *intel_dp)
return; {
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 /* FIXME: selective update is probably totally broken because it doesn't
* mesh at all with our frontbuffer tracking. And the hw alone isn't * mesh at all with our frontbuffer tracking. And the hw alone isn't
* good enough. */ * 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) if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
val |= EDP_PSR2_TP2_TIME_2500; val |= EDP_PSR2_TP2_TIME_2500;
...@@ -333,6 +348,19 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) ...@@ -333,6 +348,19 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp)
I915_WRITE(EDP_PSR2_CTL, val); 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) static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
{ {
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
...@@ -417,6 +445,9 @@ static void intel_psr_activate(struct intel_dp *intel_dp) ...@@ -417,6 +445,9 @@ static void intel_psr_activate(struct intel_dp *intel_dp)
struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_device *dev = intel_dig_port->base.base.dev;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
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(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
WARN_ON(dev_priv->psr.active); WARN_ON(dev_priv->psr.active);
lockdep_assert_held(&dev_priv->psr.lock); lockdep_assert_held(&dev_priv->psr.lock);
...@@ -468,10 +499,11 @@ void intel_psr_enable(struct intel_dp *intel_dp) ...@@ -468,10 +499,11 @@ void intel_psr_enable(struct intel_dp *intel_dp)
dev_priv->psr.busy_frontbuffer_bits = 0; dev_priv->psr.busy_frontbuffer_bits = 0;
if (HAS_DDI(dev_priv)) { if (HAS_DDI(dev_priv)) {
hsw_psr_setup_vsc(intel_dp);
if (dev_priv->psr.psr2_support) { if (dev_priv->psr.psr2_support) {
skl_psr_setup_su_vsc(intel_dp); skl_psr_setup_su_vsc(intel_dp);
} else {
/* set up vsc header for psr1 */
hsw_psr_setup_vsc(intel_dp);
} }
/* /*
...@@ -558,19 +590,34 @@ static void hsw_psr_disable(struct intel_dp *intel_dp) ...@@ -558,19 +590,34 @@ static void hsw_psr_disable(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
if (dev_priv->psr.active) { if (dev_priv->psr.active) {
if (dev_priv->psr.psr2_support) {
I915_WRITE(EDP_PSR2_CTL,
I915_READ(EDP_PSR2_CTL) &
~(EDP_PSR2_ENABLE |
EDP_SU_TRACK_ENABLE));
/* Wait till PSR2 is idle */
if (intel_wait_for_register(dev_priv,
EDP_PSR2_STATUS_CTL,
EDP_PSR2_STATUS_STATE_MASK,
0,
2000))
DRM_ERROR("Timed out waiting for PSR2 Idle State\n");
} else {
I915_WRITE(EDP_PSR_CTL, I915_WRITE(EDP_PSR_CTL,
I915_READ(EDP_PSR_CTL) & ~EDP_PSR_ENABLE); I915_READ(EDP_PSR_CTL) & ~EDP_PSR_ENABLE);
/* Wait till PSR1 is idle */
/* Wait till PSR is idle */
if (intel_wait_for_register(dev_priv, if (intel_wait_for_register(dev_priv,
EDP_PSR_STATUS_CTL, EDP_PSR_STATUS_CTL,
EDP_PSR_STATUS_STATE_MASK, EDP_PSR_STATUS_STATE_MASK,
0, 0,
2000)) 2000))
DRM_ERROR("Timed out waiting for PSR Idle State\n"); DRM_ERROR("Timed out waiting for PSR Idle State\n");
}
dev_priv->psr.active = false; dev_priv->psr.active = false;
} else { } else {
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(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
} }
} }
...@@ -622,6 +669,16 @@ static void intel_psr_work(struct work_struct *work) ...@@ -622,6 +669,16 @@ static void intel_psr_work(struct work_struct *work)
* and be ready for re-enable. * and be ready for re-enable.
*/ */
if (HAS_DDI(dev_priv)) { if (HAS_DDI(dev_priv)) {
if (dev_priv->psr.psr2_support) {
if (intel_wait_for_register(dev_priv,
EDP_PSR2_STATUS_CTL,
EDP_PSR2_STATUS_STATE_MASK,
0,
50)) {
DRM_ERROR("Timed out waiting for PSR2 Idle for re-enable\n");
return;
}
} else {
if (intel_wait_for_register(dev_priv, if (intel_wait_for_register(dev_priv,
EDP_PSR_STATUS_CTL, EDP_PSR_STATUS_CTL,
EDP_PSR_STATUS_STATE_MASK, EDP_PSR_STATUS_STATE_MASK,
...@@ -630,6 +687,7 @@ static void intel_psr_work(struct work_struct *work) ...@@ -630,6 +687,7 @@ static void intel_psr_work(struct work_struct *work)
DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n"); DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n");
return; return;
} }
}
} else { } else {
if (intel_wait_for_register(dev_priv, if (intel_wait_for_register(dev_priv,
VLV_PSRSTAT(pipe), VLV_PSRSTAT(pipe),
...@@ -670,11 +728,15 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) ...@@ -670,11 +728,15 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv)
return; return;
if (HAS_DDI(dev_priv)) { if (HAS_DDI(dev_priv)) {
if (dev_priv->psr.psr2_support) {
val = I915_READ(EDP_PSR2_CTL);
WARN_ON(!(val & EDP_PSR2_ENABLE));
I915_WRITE(EDP_PSR2_CTL, val & ~EDP_PSR2_ENABLE);
} else {
val = I915_READ(EDP_PSR_CTL); val = I915_READ(EDP_PSR_CTL);
WARN_ON(!(val & EDP_PSR_ENABLE)); WARN_ON(!(val & EDP_PSR_ENABLE));
I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE); I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE);
}
} else { } else {
val = I915_READ(VLV_PSRCTL(pipe)); val = I915_READ(VLV_PSRCTL(pipe));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment