Add debugfs support which will print source and sink status
per connector basis.

v1: Initial version. [rb-ed by Arun]
v2: Added check for DP 2.0 and connector type in connector_debugfs_add().

Cc: Jouni Högander <jouni.hogan...@intel.com>
Cc: Arun R Murthy <arun.r.mur...@intel.com>
Cc: Jani Nikula <jani.nik...@intel.com>
Signed-off-by: Animesh Manna <animesh.ma...@intel.com>
---
 drivers/gpu/drm/i915/display/intel_psr.c | 136 +++++++++++++++++------
 1 file changed, 102 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_psr.c 
b/drivers/gpu/drm/i915/display/intel_psr.c
index 80de831c2f60..399fc0a8e636 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -2823,6 +2823,25 @@ static int psr_get_status_and_error_status(struct 
intel_dp *intel_dp,
        return 0;
 }
 
+static int panel_replay_get_status_and_error_status(struct intel_dp *intel_dp,
+                                                   u8 *status, u8 
*error_status)
+{
+       struct drm_dp_aux *aux = &intel_dp->aux;
+       int ret;
+
+       ret = drm_dp_dpcd_readb(aux, DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS, 
status);
+       if (ret != 1)
+               return ret;
+
+       ret = drm_dp_dpcd_readb(aux, DP_PANEL_REPLAY_ERROR_STATUS, 
error_status);
+       if (ret != 1)
+               return ret;
+
+       *status = *status & DP_PSR_SINK_STATE_MASK;
+
+       return 0;
+}
+
 static void psr_alpm_check(struct intel_dp *intel_dp)
 {
        struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -3035,7 +3054,7 @@ psr_source_status(struct intel_dp *intel_dp, struct 
seq_file *m)
                        status = live_status[status_val];
        }
 
-       seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
+       seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, 
val);
 }
 
 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
@@ -3048,18 +3067,23 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
        bool enabled;
        u32 val;
 
-       seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support));
-       if (psr->sink_support)
+       seq_printf(m, "Sink support: PSR = %s, Panel Replay = %s",
+                  str_yes_no(psr->sink_support),
+                  str_yes_no(psr->sink_panel_replay_support));
+
+       if (psr->sink_support || psr->sink_panel_replay_support)
                seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
        seq_puts(m, "\n");
 
-       if (!psr->sink_support)
+       if (!(psr->sink_support || psr->sink_panel_replay_support))
                return 0;
 
        wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
        mutex_lock(&psr->lock);
 
-       if (psr->enabled)
+       if (psr->panel_replay_enabled)
+               status = "Panel Replay Enabled";
+       else if (psr->enabled)
                status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled";
        else
                status = "disabled";
@@ -3072,14 +3096,17 @@ static int intel_psr_status(struct seq_file *m, struct 
intel_dp *intel_dp)
                goto unlock;
        }
 
-       if (psr->psr2_enabled) {
+       if (psr->panel_replay_enabled) {
+               val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder));
+               enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE;
+       } else if (psr->psr2_enabled) {
                val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder));
                enabled = val & EDP_PSR2_ENABLE;
        } else {
                val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, 
cpu_transcoder));
                enabled = val & EDP_PSR_ENABLE;
        }
-       seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
+       seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n",
                   str_enabled_disabled(enabled), val);
        psr_source_status(intel_dp, m);
        seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
@@ -3221,6 +3248,7 @@ static int i915_psr_sink_status_show(struct seq_file *m, 
void *data)
 {
        struct intel_connector *connector = m->private;
        struct intel_dp *intel_dp = intel_attached_dp(connector);
+       struct intel_psr *psr = &intel_dp->psr;
        static const char * const sink_status[] = {
                "inactive",
                "transition to active, capture and display",
@@ -3231,45 +3259,82 @@ static int i915_psr_sink_status_show(struct seq_file 
*m, void *data)
                "reserved",
                "sink internal error",
        };
+       static const char * const panel_replay_status[] = {
+               "Sink device frame is locked to the Source device",
+               "Sink device is coasting, using the VTotal target",
+               "Sink device is governing the frame rate (frame rate unlock is 
granted)",
+               "Sink device in the process of re-locking with the Source 
device",
+       };
        const char *str;
        int ret;
        u8 status, error_status;
 
-       if (!CAN_PSR(intel_dp)) {
-               seq_puts(m, "PSR Unsupported\n");
+       if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp))) {
+               seq_puts(m, "PSR/Panel-Replay Unsupported\n");
                return -ENODEV;
        }
 
        if (connector->base.status != connector_status_connected)
                return -ENODEV;
 
-       ret = psr_get_status_and_error_status(intel_dp, &status, &error_status);
-       if (ret)
-               return ret;
+       if (psr->panel_replay_enabled) {
+               u32 temp;
 
-       status &= DP_PSR_SINK_STATE_MASK;
-       if (status < ARRAY_SIZE(sink_status))
-               str = sink_status[status];
-       else
-               str = "unknown";
+               ret = panel_replay_get_status_and_error_status(intel_dp, 
&status, &error_status);
+               if (ret)
+                       return ret;
 
-       seq_printf(m, "Sink PSR status: 0x%x [%s]\n", status, str);
+               temp = status & DP_SINK_FRAME_LOCKED_MASK;
+               temp >>= DP_SINK_FRAME_LOCKED_SHIFT;
+               if (temp < ARRAY_SIZE(panel_replay_status))
+                       str = panel_replay_status[temp];
+               else
+                       str = "unknown";
 
-       seq_printf(m, "Sink PSR error status: 0x%x", error_status);
+               seq_printf(m, "Sink Panel Replay status: 0x%x [%s]\n", status, 
str);
 
-       if (error_status & (DP_PSR_RFB_STORAGE_ERROR |
-                           DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR |
-                           DP_PSR_LINK_CRC_ERROR))
-               seq_puts(m, ":\n");
-       else
-               seq_puts(m, "\n");
-       if (error_status & DP_PSR_RFB_STORAGE_ERROR)
-               seq_puts(m, "\tPSR RFB storage error\n");
-       if (error_status & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR)
-               seq_puts(m, "\tPSR VSC SDP uncorrectable error\n");
-       if (error_status & DP_PSR_LINK_CRC_ERROR)
-               seq_puts(m, "\tPSR Link CRC error\n");
+               seq_printf(m, "Sink Panel Replay error status: 0x%x", 
error_status);
+
+               if (error_status & (DP_PANEL_REPLAY_RFB_STORAGE_ERROR |
+                                   DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR 
|
+                                   DP_PANEL_REPLAY_LINK_CRC_ERROR))
+                       seq_puts(m, ":\n");
+               else
+                       seq_puts(m, "\n");
+               if (error_status & DP_PANEL_REPLAY_RFB_STORAGE_ERROR)
+                       seq_puts(m, "\tPANEL-REPLAY RFB storage error\n");
+               if (error_status & DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR)
+                       seq_puts(m, "\tPANEL-REPLAY VSC SDP uncorrectable 
error\n");
+               if (error_status & DP_PANEL_REPLAY_LINK_CRC_ERROR)
+                       seq_puts(m, "\tPANEL-REPLAY Link CRC error\n");
+       } else {
+               ret = psr_get_status_and_error_status(intel_dp, &status, 
&error_status);
+               if (ret)
+                       return ret;
+
+               status &= DP_PSR_SINK_STATE_MASK;
+               if (status < ARRAY_SIZE(sink_status))
+                       str = sink_status[status];
+               else
+                       str = "unknown";
+
+               seq_printf(m, "Sink PSR status: 0x%x [%s]\n", status, str);
+
+               seq_printf(m, "Sink PSR error status: 0x%x", error_status);
 
+               if (error_status & (DP_PSR_RFB_STORAGE_ERROR |
+                                   DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR |
+                                   DP_PSR_LINK_CRC_ERROR))
+                       seq_puts(m, ":\n");
+               else
+                       seq_puts(m, "\n");
+               if (error_status & DP_PSR_RFB_STORAGE_ERROR)
+                       seq_puts(m, "\tPSR RFB storage error\n");
+               if (error_status & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR)
+                       seq_puts(m, "\tPSR VSC SDP uncorrectable error\n");
+               if (error_status & DP_PSR_LINK_CRC_ERROR)
+                       seq_puts(m, "\tPSR Link CRC error\n");
+       }
        return ret;
 }
 DEFINE_SHOW_ATTRIBUTE(i915_psr_sink_status);
@@ -3288,13 +3353,16 @@ void intel_psr_connector_debugfs_add(struct 
intel_connector *connector)
        struct drm_i915_private *i915 = to_i915(connector->base.dev);
        struct dentry *root = connector->base.debugfs_entry;
 
-       if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP)
-               return;
+       if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) {
+               if (!(HAS_DP20(i915) &&
+                     connector->base.connector_type == 
DRM_MODE_CONNECTOR_DisplayPort))
+                       return;
+       }
 
        debugfs_create_file("i915_psr_sink_status", 0444, root,
                            connector, &i915_psr_sink_status_fops);
 
-       if (HAS_PSR(i915))
+       if (HAS_PSR(i915) || HAS_DP20(i915))
                debugfs_create_file("i915_psr_status", 0444, root,
                                    connector, &i915_psr_status_fops);
 }
-- 
2.29.0

Reply via email to