@@ -468,6 +468,40 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp)
return val;
}
+static u8 intel_dp_get_su_capability(struct intel_dp *intel_dp)
+{
+ u8 su_capability = 0;
+
+ if (intel_dp->psr.sink_panel_replay_su_support)
+ drm_dp_dpcd_readb(&intel_dp->aux,
+ DP_PANEL_PANEL_REPLAY_CAPABILITY,
+ &su_capability);
+ else
+ su_capability = intel_dp->psr_dpcd[1];
+
+ return su_capability;
+}
+
+static unsigned int
+intel_dp_get_su_x_granularity_offset(struct intel_dp *intel_dp)
+{
+ return intel_dp->psr.sink_panel_replay_su_support ?
+ DP_PANEL_PANEL_REPLAY_X_GRANULARITY :
+ DP_PSR2_SU_X_GRANULARITY;
+}
+
+static unsigned int
+intel_dp_get_su_y_granularity_offset(struct intel_dp *intel_dp)
+{
+ return intel_dp->psr.sink_panel_replay_su_support ?
+ DP_PANEL_PANEL_REPLAY_Y_GRANULARITY :
+ DP_PSR2_SU_Y_GRANULARITY;
+}
+
+/*
+ * Note: Bits related to granularity are same in panel replay and psr
+ * registers. Rely on PSR definitions on these "common" bits.
+ */
static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
{
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
@@ -475,18 +509,29 @@ static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
u16 w;
u8 y;
- /* If sink don't have specific granularity requirements set legacy ones */
- if (!(intel_dp->psr_dpcd[1] & DP_PSR2_SU_GRANULARITY_REQUIRED)) {
+ /*
+ * TODO: Do we need to take into account panel supporting both PSR and
+ * Panel replay?
+ */
+
+ /*
+ * If sink don't have specific granularity requirements set legacy
+ * ones.
+ */
+ if (!(intel_dp_get_su_capability(intel_dp) &
+ DP_PSR2_SU_GRANULARITY_REQUIRED)) {
/* As PSR2 HW sends full lines, we do not care about x granularity */
w = 4;
y = 4;
goto exit;
}
- r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, 2);
+ r = drm_dp_dpcd_read(&intel_dp->aux,
+ intel_dp_get_su_x_granularity_offset(intel_dp),
+ &w, 2);
if (r != 2)
drm_dbg_kms(&i915->drm,
- "Unable to read DP_PSR2_SU_X_GRANULARITY\n");
+ "Unable to read selective update x granularity\n");
/*
* Spec says that if the value read is 0 the default granularity should
* be used instead.
@@ -494,10 +539,12 @@ static void intel_dp_get_su_granularity(struct intel_dp *intel_dp)
if (r != 2 || w == 0)
w = 4;
- r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y, 1);
+ r = drm_dp_dpcd_read(&intel_dp->aux,
+ intel_dp_get_su_y_granularity_offset(intel_dp),
+ &y, 1);
if (r != 1) {
drm_dbg_kms(&i915->drm,
- "Unable to read DP_PSR2_SU_Y_GRANULARITY\n");
+ "Unable to read selective update y granularity\n");
y = 4;
}
if (y == 0)
@@ -590,7 +637,8 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
if (intel_dp->psr_dpcd[0])
_psr_init_dpcd(intel_dp);
- if (intel_dp->psr.sink_psr2_support)
+ if (intel_dp->psr.sink_psr2_support ||
+ intel_dp->psr.sink_panel_replay_su_support)
intel_dp_get_su_granularity(intel_dp);
}