Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915/panelreplay: Debugfs support for panel replay

Add debugfs support which will print source and sink status
per connector basis. Existing i915_psr_status and
i915_psr_sink_status will be used to get the source and
sink status of panel replay.

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

Cc: Jouni Högander <jouni.hogander@intel.com>
Cc: Arun R Murthy <arun.r.murthy@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Reviewed-by: Jouni Högander <jouni.hogander@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231108072303.3414118-7-animesh.manna@intel.com

+63 -24
+63 -24
drivers/gpu/drm/i915/display/intel_psr.c
··· 2865 2865 { 2866 2866 struct drm_dp_aux *aux = &intel_dp->aux; 2867 2867 int ret; 2868 + unsigned int offset; 2868 2869 2869 - ret = drm_dp_dpcd_readb(aux, DP_PSR_STATUS, status); 2870 + offset = intel_dp->psr.panel_replay_enabled ? 2871 + DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS : DP_PSR_STATUS; 2872 + 2873 + ret = drm_dp_dpcd_readb(aux, offset, status); 2870 2874 if (ret != 1) 2871 2875 return ret; 2872 2876 2873 - ret = drm_dp_dpcd_readb(aux, DP_PSR_ERROR_STATUS, error_status); 2877 + offset = intel_dp->psr.panel_replay_enabled ? 2878 + DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS; 2879 + 2880 + ret = drm_dp_dpcd_readb(aux, offset, error_status); 2874 2881 if (ret != 1) 2875 2882 return ret; 2876 2883 ··· 3098 3091 status = live_status[status_val]; 3099 3092 } 3100 3093 3101 - seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val); 3094 + seq_printf(m, "Source PSR/PanelReplay status: %s [0x%08x]\n", status, val); 3102 3095 } 3103 3096 3104 3097 static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) ··· 3111 3104 bool enabled; 3112 3105 u32 val; 3113 3106 3114 - seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support)); 3107 + seq_printf(m, "Sink support: PSR = %s", 3108 + str_yes_no(psr->sink_support)); 3109 + 3115 3110 if (psr->sink_support) 3116 3111 seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]); 3117 - seq_puts(m, "\n"); 3112 + seq_printf(m, ", Panel Replay = %s\n", str_yes_no(psr->sink_panel_replay_support)); 3118 3113 3119 - if (!psr->sink_support) 3114 + if (!(psr->sink_support || psr->sink_panel_replay_support)) 3120 3115 return 0; 3121 3116 3122 3117 wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); 3123 3118 mutex_lock(&psr->lock); 3124 3119 3125 - if (psr->enabled) 3120 + if (psr->panel_replay_enabled) 3121 + status = "Panel Replay Enabled"; 3122 + else if (psr->enabled) 3126 3123 status = psr->psr2_enabled ? "PSR2 enabled" : "PSR1 enabled"; 3127 3124 else 3128 3125 status = "disabled"; ··· 3139 3128 goto unlock; 3140 3129 } 3141 3130 3142 - if (psr->psr2_enabled) { 3131 + if (psr->panel_replay_enabled) { 3132 + val = intel_de_read(dev_priv, TRANS_DP2_CTL(cpu_transcoder)); 3133 + enabled = val & TRANS_DP2_PANEL_REPLAY_ENABLE; 3134 + } else if (psr->psr2_enabled) { 3143 3135 val = intel_de_read(dev_priv, EDP_PSR2_CTL(cpu_transcoder)); 3144 3136 enabled = val & EDP_PSR2_ENABLE; 3145 3137 } else { 3146 3138 val = intel_de_read(dev_priv, psr_ctl_reg(dev_priv, cpu_transcoder)); 3147 3139 enabled = val & EDP_PSR_ENABLE; 3148 3140 } 3149 - seq_printf(m, "Source PSR ctl: %s [0x%08x]\n", 3141 + seq_printf(m, "Source PSR/PanelReplay ctl: %s [0x%08x]\n", 3150 3142 str_enabled_disabled(enabled), val); 3151 3143 psr_source_status(intel_dp, m); 3152 3144 seq_printf(m, "Busy frontbuffer bits: 0x%08x\n", ··· 3287 3273 i915, &i915_edp_psr_status_fops); 3288 3274 } 3289 3275 3276 + static const char *psr_mode_str(struct intel_dp *intel_dp) 3277 + { 3278 + if (intel_dp->psr.panel_replay_enabled) 3279 + return "PANEL-REPLAY"; 3280 + else if (intel_dp->psr.enabled) 3281 + return "PSR"; 3282 + 3283 + return "unknown"; 3284 + } 3285 + 3290 3286 static int i915_psr_sink_status_show(struct seq_file *m, void *data) 3291 3287 { 3292 3288 struct intel_connector *connector = m->private; ··· 3311 3287 "reserved", 3312 3288 "sink internal error", 3313 3289 }; 3290 + static const char * const panel_replay_status[] = { 3291 + "Sink device frame is locked to the Source device", 3292 + "Sink device is coasting, using the VTotal target", 3293 + "Sink device is governing the frame rate (frame rate unlock is granted)", 3294 + "Sink device in the process of re-locking with the Source device", 3295 + }; 3314 3296 const char *str; 3315 3297 int ret; 3316 3298 u8 status, error_status; 3299 + u32 idx; 3317 3300 3318 - if (!CAN_PSR(intel_dp)) { 3319 - seq_puts(m, "PSR Unsupported\n"); 3301 + if (!(CAN_PSR(intel_dp) || CAN_PANEL_REPLAY(intel_dp))) { 3302 + seq_puts(m, "PSR/Panel-Replay Unsupported\n"); 3320 3303 return -ENODEV; 3321 3304 } 3322 3305 ··· 3334 3303 if (ret) 3335 3304 return ret; 3336 3305 3337 - status &= DP_PSR_SINK_STATE_MASK; 3338 - if (status < ARRAY_SIZE(sink_status)) 3339 - str = sink_status[status]; 3340 - else 3341 - str = "unknown"; 3306 + str = "unknown"; 3307 + if (intel_dp->psr.panel_replay_enabled) { 3308 + idx = (status & DP_SINK_FRAME_LOCKED_MASK) >> DP_SINK_FRAME_LOCKED_SHIFT; 3309 + if (idx < ARRAY_SIZE(panel_replay_status)) 3310 + str = panel_replay_status[idx]; 3311 + } else if (intel_dp->psr.enabled) { 3312 + idx = status & DP_PSR_SINK_STATE_MASK; 3313 + if (idx < ARRAY_SIZE(sink_status)) 3314 + str = sink_status[idx]; 3315 + } 3342 3316 3343 - seq_printf(m, "Sink PSR status: 0x%x [%s]\n", status, str); 3317 + seq_printf(m, "Sink %s status: 0x%x [%s]\n", psr_mode_str(intel_dp), status, str); 3344 3318 3345 - seq_printf(m, "Sink PSR error status: 0x%x", error_status); 3319 + seq_printf(m, "Sink %s error status: 0x%x", psr_mode_str(intel_dp), error_status); 3346 3320 3347 3321 if (error_status & (DP_PSR_RFB_STORAGE_ERROR | 3348 3322 DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR | ··· 3356 3320 else 3357 3321 seq_puts(m, "\n"); 3358 3322 if (error_status & DP_PSR_RFB_STORAGE_ERROR) 3359 - seq_puts(m, "\tPSR RFB storage error\n"); 3323 + seq_printf(m, "\t%s RFB storage error\n", psr_mode_str(intel_dp)); 3360 3324 if (error_status & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR) 3361 - seq_puts(m, "\tPSR VSC SDP uncorrectable error\n"); 3325 + seq_printf(m, "\t%s VSC SDP uncorrectable error\n", psr_mode_str(intel_dp)); 3362 3326 if (error_status & DP_PSR_LINK_CRC_ERROR) 3363 - seq_puts(m, "\tPSR Link CRC error\n"); 3327 + seq_printf(m, "\t%s Link CRC error\n", psr_mode_str(intel_dp)); 3364 3328 3365 3329 return ret; 3366 3330 } ··· 3380 3344 struct drm_i915_private *i915 = to_i915(connector->base.dev); 3381 3345 struct dentry *root = connector->base.debugfs_entry; 3382 3346 3383 - if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) 3384 - return; 3347 + if (connector->base.connector_type != DRM_MODE_CONNECTOR_eDP) { 3348 + if (!(HAS_DP20(i915) && 3349 + connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort)) 3350 + return; 3351 + } 3385 3352 3386 3353 debugfs_create_file("i915_psr_sink_status", 0444, root, 3387 3354 connector, &i915_psr_sink_status_fops); 3388 3355 3389 - if (HAS_PSR(i915)) 3356 + if (HAS_PSR(i915) || HAS_DP20(i915)) 3390 3357 debugfs_create_file("i915_psr_status", 0444, root, 3391 3358 connector, &i915_psr_status_fops); 3392 3359 }