Signed-off-by: Rodrigo Vivi <rodrigo.v...@gmail.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 39 ++++++++++++++++++---
 drivers/gpu/drm/i915/i915_drv.h     | 12 +++++++
 drivers/gpu/drm/i915/intel_dp.c     | 68 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 19192af..f4e9147 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1880,11 +1880,42 @@ static int i915_edp_psr_status(struct seq_file *m, void 
*data)
        struct drm_info_node *node = m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 psrctl, psrstat, psrperf;
+       u32 psrstat, psrperf;
 
-       psrctl = I915_READ(EDP_PSR_CTL);
-       seq_printf(m, "PSR Enabled: %s\n",
-                  yesno(psrctl & EDP_PSR_ENABLE));
+       if (I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE) {
+               seq_printf(m, "PSR enabled\n");
+       } else {
+               seq_printf(m, "PSR disabled: ");
+               switch (dev_priv->no_psr_reason) {
+               case PSR_NO_SOURCE:
+                       seq_printf(m, "not supported on this platform");
+                       break;
+               case PSR_NO_SINK:
+                       seq_printf(m, "not supported by panel");
+                       break;
+               case PSR_CRTC_NOT_ACTIVE:
+                       seq_printf(m, "crtc not active");
+                       break;
+               case PSR_PWR_WELL_ENABLED:
+                       seq_printf(m, "power well enabled");
+                       break;
+               case PSR_NOT_TILED:
+                       seq_printf(m, "not tiled");
+                       break;
+               case PSR_SPRITE_ENABLED:
+                       seq_printf(m, "sprite enabled");
+                       break;
+               case PSR_INTERLACED_ENABLED:
+                       seq_printf(m, "interlaced enabled");
+                       break;
+               case PSR_HSW_NOT_DDIA:
+                       seq_printf(m, "HSW ties PSR to DDI A (eDP)");
+                       break;
+               default:
+                       seq_printf(m, "unknown reason");
+               }
+               seq_printf(m, "\n");
+       }
 
        psrstat = I915_READ(EDP_PSR_STATUS_CTL);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index dd459a5..cbe842b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -509,6 +509,17 @@ enum no_fbc_reason {
        FBC_MODULE_PARAM,
 };
 
+enum no_psr_reason {
+       PSR_NO_SOURCE, /* Not supported on platform */
+       PSR_NO_SINK, /* Not supported by panel */
+       PSR_CRTC_NOT_ACTIVE,
+       PSR_PWR_WELL_ENABLED,
+       PSR_NOT_TILED,
+       PSR_SPRITE_ENABLED,
+       PSR_INTERLACED_ENABLED,
+       PSR_HSW_NOT_DDIA,
+};
+
 enum intel_pch {
        PCH_NONE = 0,   /* No PCH present */
        PCH_IBX,        /* Ibexpeak PCH */
@@ -1119,6 +1130,7 @@ typedef struct drm_i915_private {
        struct i915_power_well power_well;
 
        enum no_fbc_reason no_fbc_reason;
+       enum no_psr_reason no_psr_reason;
 
        struct drm_mm_node *compressed_fb;
        struct drm_mm_node *compressed_llb;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e9c18bd..c105236 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1455,6 +1455,71 @@ void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
        POSTING_READ(ctl_reg);
 }
 
+static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
+{
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+       struct drm_crtc *crtc = dig_port->base.base.crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+       struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+
+       if (!IS_HASWELL(dev)) {
+               DRM_DEBUG_KMS("PSR not supported on this platform\n");
+               dev_priv->no_psr_reason = PSR_NO_SOURCE;
+               return false;
+       }
+
+       if ((intel_encoder->type != INTEL_OUTPUT_EDP) ||
+           (enc_to_dig_port(&intel_encoder->base)->port != PORT_A)) {
+               DRM_DEBUG_KMS("HSW ties PSR to DDI A (eDP)\n");
+               dev_priv->no_psr_reason = PSR_HSW_NOT_DDIA;
+               return false;
+       }
+
+       if (!is_edp_psr(intel_dp)) {
+               DRM_DEBUG_KMS("PSR not supported by this panel\n");
+               dev_priv->no_psr_reason = PSR_NO_SINK;
+               return false;
+       }
+
+       if (!intel_crtc->active || !crtc->fb || !crtc->mode.clock) {
+               DRM_DEBUG_KMS("crtc not active for PSR\n");
+               dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE;
+               return false;
+       }
+
+       if ((I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_ENABLE) |
+           (I915_READ(HSW_PWR_WELL_KVMR) & HSW_PWR_WELL_ENABLE)) {
+               DRM_DEBUG_KMS("PSR condition failed: Power Well is Enabled\n");
+               dev_priv->no_psr_reason = PSR_PWR_WELL_ENABLED;
+               return false;
+       }
+
+       if (obj->tiling_mode != I915_TILING_X ||
+           obj->fence_reg == I915_FENCE_REG_NONE) {
+               DRM_DEBUG_KMS("PSR condition failed: fb not tiled or fenced\n");
+               dev_priv->no_psr_reason = PSR_NOT_TILED;
+               return false;
+       }
+
+       if (I915_READ(SPRCTL(intel_crtc->pipe)) & SPRITE_ENABLE) {
+               DRM_DEBUG_KMS("PSR condition failed: Sprite is Enabled\n");
+               dev_priv->no_psr_reason = PSR_SPRITE_ENABLED;
+               return false;
+       }
+
+       if ((I915_READ(PIPECONF(intel_crtc->config.cpu_transcoder)) &
+            PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) {
+               DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
+               dev_priv->no_psr_reason = PSR_INTERLACED_ENABLED;
+               return false;
+       }
+
+       return true;
+}
+
 void intel_edp_psr_enable(struct intel_dp* intel_dp)
 {
        struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1464,7 +1529,8 @@ void intel_edp_psr_enable(struct intel_dp* intel_dp)
        int precharge = 0x3;
        int msg_size = 5;       /* Header(4) + Message(1) */
 
-       if (!is_edp_psr(intel_dp) || intel_edp_is_psr_enabled(dev))
+       if (!intel_edp_psr_match_conditions(intel_dp) ||
+           intel_edp_is_psr_enabled(dev))
                return;
 
        /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
-- 
1.7.11.7

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to