[PATCH 3/3] drm/i915/psr: Refactor
Dhinakaran Pandiyan
dhinakaran.pandiyan at gmail.com
Fri Aug 10 06:27:35 UTC 2018
---
drivers/gpu/drm/i915/intel_psr.c | 516 +++++++++++++++----------------
1 file changed, 249 insertions(+), 267 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 09be9bfee2be..a81fd6ca8763 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -56,6 +56,8 @@
#include "intel_drv.h"
#include "i915_drv.h"
+static void psr_disable_locked(struct intel_dp *intel_dp);
+
void intel_psr_irq_control(struct drm_i915_private *dev_priv, bool debug)
{
u32 debug_mask, mask;
@@ -160,88 +162,157 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
}
}
-static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
+void intel_psr_short_pulse(struct intel_dp *intel_dp)
{
- uint8_t dprx = 0;
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+ struct i915_psr *psr = &dev_priv->psr;
+ u8 val;
+ const u8 errors = DP_PSR_RFB_STORAGE_ERROR |
+ DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR |
+ DP_PSR_LINK_CRC_ERROR;
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
- &dprx) != 1)
- return false;
- return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
+ if (!CAN_PSR(dev_priv) || !intel_dp_is_edp(intel_dp))
+ return;
+
+ mutex_lock(&psr->lock);
+
+ if (psr->enabled != intel_dp)
+ goto exit;
+
+ if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val) != 1) {
+ DRM_ERROR("PSR_STATUS dpcd read failed\n");
+ goto exit;
+ }
+
+ if ((val & DP_PSR_SINK_STATE_MASK) == DP_PSR_SINK_INTERNAL_ERROR) {
+ DRM_DEBUG_KMS("PSR sink internal error, disabling PSR\n");
+ psr_disable_locked(intel_dp);
+ }
+
+ if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_ERROR_STATUS, &val) != 1) {
+ DRM_ERROR("PSR_ERROR_STATUS dpcd read failed\n");
+ goto exit;
+ }
+
+ if (val & DP_PSR_RFB_STORAGE_ERROR)
+ DRM_DEBUG_KMS("PSR RFB storage error, disabling PSR\n");
+ if (val & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR)
+ DRM_DEBUG_KMS("PSR VSC SDP uncorrectable error, disabling PSR\n");
+ if (val & DP_PSR_LINK_CRC_ERROR)
+ DRM_ERROR("PSR Link CRC error, disabling PSR\n");
+
+ if (val & ~errors)
+ DRM_ERROR("PSR_ERROR_STATUS unhandled errors %x\n",
+ val & ~errors);
+ if (val & errors)
+ psr_disable_locked(intel_dp);
+ /* clear status register */
+ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ERROR_STATUS, val);
+
+ /* TODO: handle PSR2 errors */
+exit:
+ mutex_unlock(&psr->lock);
}
-static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp)
+static bool psr2_config_valid(struct intel_dp *intel_dp,
+ struct intel_crtc_state *crtc_state)
{
- uint8_t alpm_caps = 0;
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+ int crtc_hdisplay = crtc_state->base.adjusted_mode.crtc_hdisplay;
+ int crtc_vdisplay = crtc_state->base.adjusted_mode.crtc_vdisplay;
+ int psr_max_h = 0, psr_max_v = 0;
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP,
- &alpm_caps) != 1)
+ /*
+ * FIXME psr2_support is messed up. It's both computed
+ * dynamically during PSR enable, and extracted from sink
+ * caps during eDP detection.
+ */
+ if (!dev_priv->psr.sink_psr2_support)
return false;
- return alpm_caps & DP_ALPM_CAP;
-}
-static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp)
-{
- u8 val = 8; /* assume the worst if we can't read the value */
+ if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
+ psr_max_h = 4096;
+ psr_max_v = 2304;
+ } else if (IS_GEN9(dev_priv)) {
+ psr_max_h = 3640;
+ psr_max_v = 2304;
+ }
- if (drm_dp_dpcd_readb(&intel_dp->aux,
- DP_SYNCHRONIZATION_LATENCY_IN_SINK, &val) == 1)
- val &= DP_MAX_RESYNC_FRAME_COUNT_MASK;
- else
- DRM_DEBUG_KMS("Unable to get sink synchronization latency, assuming 8 frames\n");
- return val;
+ if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) {
+ DRM_DEBUG_KMS("PSR2 not enabled, resolution %dx%d > max supported %dx%d\n",
+ crtc_hdisplay, crtc_vdisplay,
+ psr_max_h, psr_max_v);
+ return false;
+ }
+
+ return true;
}
-void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+void intel_psr_compute_config(struct intel_dp *intel_dp,
+ struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv =
- to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+ const struct drm_display_mode *adjusted_mode =
+ &crtc_state->base.adjusted_mode;
+ int psr_setup_time;
- drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
- sizeof(intel_dp->psr_dpcd));
+ if (!CAN_PSR(dev_priv))
+ return;
- if (!intel_dp->psr_dpcd[0])
+ if (!i915_modparams.enable_psr) {
+ DRM_DEBUG_KMS("PSR disable by flag\n");
return;
- DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
- intel_dp->psr_dpcd[0]);
+ }
- if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
- DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n");
+ /*
+ * HSW spec explicitly says PSR is tied to port A.
+ * BDW+ platforms with DDI implementation of PSR have different
+ * PSR registers per transcoder and we only implement transcoder EDP
+ * ones. Since by Display design transcoder EDP is tied to port A
+ * we can safely escape based on the port A.
+ */
+ if (dig_port->base.port != PORT_A) {
+ DRM_DEBUG_KMS("PSR condition failed: Port not supported\n");
return;
}
- dev_priv->psr.sink_support = true;
- dev_priv->psr.sink_sync_latency =
- intel_dp_get_sink_sync_latency(intel_dp);
- if (INTEL_GEN(dev_priv) >= 9 &&
- (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
- bool y_req = intel_dp->psr_dpcd[1] &
- DP_PSR2_SU_Y_COORDINATE_REQUIRED;
- bool alpm = intel_dp_get_alpm_status(intel_dp);
+ if (IS_HASWELL(dev_priv) &&
+ I915_READ(HSW_STEREO_3D_CTL(crtc_state->cpu_transcoder)) &
+ S3D_ENABLE) {
+ DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
+ return;
+ }
- /*
- * All panels that supports PSR version 03h (PSR2 +
- * Y-coordinate) can handle Y-coordinates in VSC but we are
- * only sure that it is going to be used when required by the
- * panel. This way panel is capable to do selective update
- * without a aux frame sync.
- *
- * To support PSR version 02h and PSR version 03h without
- * Y-coordinate requirement panels we would need to enable
- * GTC first.
- */
- dev_priv->psr.sink_psr2_support = y_req && alpm;
- DRM_DEBUG_KMS("PSR2 %ssupported\n",
- dev_priv->psr.sink_psr2_support ? "" : "not ");
+ if (IS_HASWELL(dev_priv) &&
+ adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+ DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
+ return;
+ }
- if (dev_priv->psr.sink_psr2_support) {
- dev_priv->psr.colorimetry_support =
- intel_dp_get_colorimetry_status(intel_dp);
- }
+ psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
+ if (psr_setup_time < 0) {
+ DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n",
+ intel_dp->psr_dpcd[1]);
+ return;
+ }
+
+ if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
+ adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) {
+ DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n",
+ psr_setup_time);
+ return;
}
+
+ crtc_state->has_psr = true;
+ crtc_state->has_psr2 = psr2_config_valid(intel_dp, crtc_state);
+ DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
}
-static void intel_psr_setup_vsc(struct intel_dp *intel_dp,
+static void psr_setup_vsc(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -307,7 +378,7 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
I915_WRITE(EDP_PSR_AUX_CTL, aux_ctl);
}
-static void intel_psr_enable_sink(struct intel_dp *intel_dp)
+static void psr_enable_sink(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;
@@ -330,7 +401,7 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
}
-static void hsw_activate_psr1(struct intel_dp *intel_dp)
+static void hsw_psr1_enable(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;
@@ -387,7 +458,7 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
I915_WRITE(EDP_PSR_CTL, val);
}
-static void hsw_activate_psr2(struct intel_dp *intel_dp)
+static void skl_psr2_enable(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;
@@ -424,124 +495,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
I915_WRITE(EDP_PSR2_CTL, val);
}
-static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state)
-{
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
- int crtc_hdisplay = crtc_state->base.adjusted_mode.crtc_hdisplay;
- int crtc_vdisplay = crtc_state->base.adjusted_mode.crtc_vdisplay;
- int psr_max_h = 0, psr_max_v = 0;
-
- /*
- * FIXME psr2_support is messed up. It's both computed
- * dynamically during PSR enable, and extracted from sink
- * caps during eDP detection.
- */
- if (!dev_priv->psr.sink_psr2_support)
- return false;
-
- if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
- psr_max_h = 4096;
- psr_max_v = 2304;
- } else if (IS_GEN9(dev_priv)) {
- psr_max_h = 3640;
- psr_max_v = 2304;
- }
-
- if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) {
- DRM_DEBUG_KMS("PSR2 not enabled, resolution %dx%d > max supported %dx%d\n",
- crtc_hdisplay, crtc_vdisplay,
- psr_max_h, psr_max_v);
- return false;
- }
-
- return true;
-}
-
-void intel_psr_compute_config(struct intel_dp *intel_dp,
- struct intel_crtc_state *crtc_state)
-{
- struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
- const struct drm_display_mode *adjusted_mode =
- &crtc_state->base.adjusted_mode;
- int psr_setup_time;
-
- if (!CAN_PSR(dev_priv))
- return;
-
- if (!i915_modparams.enable_psr) {
- DRM_DEBUG_KMS("PSR disable by flag\n");
- return;
- }
-
- /*
- * HSW spec explicitly says PSR is tied to port A.
- * BDW+ platforms with DDI implementation of PSR have different
- * PSR registers per transcoder and we only implement transcoder EDP
- * ones. Since by Display design transcoder EDP is tied to port A
- * we can safely escape based on the port A.
- */
- if (dig_port->base.port != PORT_A) {
- DRM_DEBUG_KMS("PSR condition failed: Port not supported\n");
- return;
- }
-
- if (IS_HASWELL(dev_priv) &&
- I915_READ(HSW_STEREO_3D_CTL(crtc_state->cpu_transcoder)) &
- S3D_ENABLE) {
- DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
- return;
- }
-
- if (IS_HASWELL(dev_priv) &&
- adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
- DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
- return;
- }
-
- psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd);
- if (psr_setup_time < 0) {
- DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n",
- intel_dp->psr_dpcd[1]);
- return;
- }
-
- if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) >
- adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) {
- DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n",
- psr_setup_time);
- return;
- }
-
- crtc_state->has_psr = true;
- crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state);
- DRM_DEBUG_KMS("Enabling PSR%s\n", crtc_state->has_psr2 ? "2" : "");
-}
-
-static void intel_psr_activate(struct intel_dp *intel_dp)
-{
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct drm_device *dev = intel_dig_port->base.base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
-
- if (INTEL_GEN(dev_priv) >= 9)
- WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE);
- WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
- WARN_ON(dev_priv->psr.active);
- lockdep_assert_held(&dev_priv->psr.lock);
-
- /* psr1 and psr2 are mutually exclusive.*/
- if (dev_priv->psr.psr2_enabled)
- hsw_activate_psr2(intel_dp);
- else
- hsw_activate_psr1(intel_dp);
-
- dev_priv->psr.active = true;
-}
-
-static void intel_psr_enable_source(struct intel_dp *intel_dp,
+static void psr_configure_source(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state)
{
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -589,6 +543,27 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
}
}
+static void psr_enable_source(struct intel_dp *intel_dp)
+{
+ struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+ struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct drm_i915_private *dev_priv = to_i915(dev);
+
+ if (INTEL_GEN(dev_priv) >= 9)
+ WARN_ON(I915_READ(EDP_PSR2_CTL) & EDP_PSR2_ENABLE);
+ WARN_ON(I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE);
+ WARN_ON(dev_priv->psr.active);
+ lockdep_assert_held(&dev_priv->psr.lock);
+
+ /* psr1 and psr2 are mutually exclusive.*/
+ if (dev_priv->psr.psr2_enabled)
+ skl_psr2_enable(intel_dp);
+ else
+ hsw_psr1_enable(intel_dp);
+
+ dev_priv->psr.active = true;
+}
+
/**
* intel_psr_enable - Enable PSR
* @intel_dp: Intel DP
@@ -619,19 +594,18 @@ void intel_psr_enable(struct intel_dp *intel_dp,
dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
dev_priv->psr.busy_frontbuffer_bits = 0;
- intel_psr_setup_vsc(intel_dp, crtc_state);
- intel_psr_enable_sink(intel_dp);
- intel_psr_enable_source(intel_dp, crtc_state);
+ psr_setup_vsc(intel_dp, crtc_state);
+ psr_enable_sink(intel_dp);
+ psr_configure_source(intel_dp, crtc_state);
dev_priv->psr.enabled = intel_dp;
- intel_psr_activate(intel_dp);
+ psr_enable_source(intel_dp);
unlock:
mutex_unlock(&dev_priv->psr.lock);
}
-static void
-intel_psr_disable_source(struct intel_dp *intel_dp)
+static void psr_disable_source(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
@@ -672,7 +646,7 @@ intel_psr_disable_source(struct intel_dp *intel_dp)
}
}
-static void intel_psr_disable_locked(struct intel_dp *intel_dp)
+static void psr_disable_locked(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
@@ -683,7 +657,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
if (!dev_priv->psr.enabled)
return;
- intel_psr_disable_source(intel_dp);
+ psr_disable_source(intel_dp);
/* Disable PSR on Sink */
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
@@ -712,7 +686,7 @@ void intel_psr_disable(struct intel_dp *intel_dp,
return;
mutex_lock(&dev_priv->psr.lock);
- intel_psr_disable_locked(intel_dp);
+ psr_disable_locked(intel_dp);
mutex_unlock(&dev_priv->psr.lock);
cancel_work_sync(&dev_priv->psr.work);
}
@@ -776,7 +750,7 @@ static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
return err == 0 && dev_priv->psr.enabled;
}
-static void intel_psr_work(struct work_struct *work)
+static void psr_work(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
container_of(work, typeof(*dev_priv), psr.work);
@@ -803,32 +777,13 @@ static void intel_psr_work(struct work_struct *work)
if (dev_priv->psr.busy_frontbuffer_bits || dev_priv->psr.active)
goto unlock;
- intel_psr_activate(dev_priv->psr.enabled);
+ psr_enable_source(dev_priv->psr.enabled);
unlock:
mutex_unlock(&dev_priv->psr.lock);
}
-static void intel_psr_exit(struct drm_i915_private *dev_priv)
-{
- u32 val;
-
- if (!dev_priv->psr.active)
- return;
-
- if (dev_priv->psr.psr2_enabled) {
- 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);
- WARN_ON(!(val & EDP_PSR_ENABLE));
- I915_WRITE(EDP_PSR_CTL, val & ~EDP_PSR_ENABLE);
- }
- dev_priv->psr.active = false;
-}
-
/**
- * intel_psr_invalidate - Invalidade PSR
+ * intel_psr_invalidate - Invalidate PSR
* @dev_priv: i915 device
* @frontbuffer_bits: frontbuffer plane tracking bits
* @origin: which operation caused the invalidate
@@ -865,7 +820,7 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
dev_priv->psr.busy_frontbuffer_bits |= frontbuffer_bits;
if (frontbuffer_bits)
- intel_psr_exit(dev_priv);
+ psr_disable_locked(dev_priv->psr.enabled);
mutex_unlock(&dev_priv->psr.lock);
}
@@ -910,7 +865,7 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
/* By definition flush = invalidate + flush */
if (frontbuffer_bits) {
if (dev_priv->psr.psr2_enabled) {
- intel_psr_exit(dev_priv);
+ psr_disable_locked(dev_priv->psr.enabled);
} else {
/*
* Display WA #0884: all
@@ -930,6 +885,87 @@ void intel_psr_flush(struct drm_i915_private *dev_priv,
mutex_unlock(&dev_priv->psr.lock);
}
+static bool psr_get_colorimetry_status(struct intel_dp *intel_dp)
+{
+ uint8_t dprx = 0;
+
+ if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
+ &dprx) != 1)
+ return false;
+ return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
+}
+
+static bool psr_get_alpm_status(struct intel_dp *intel_dp)
+{
+ uint8_t alpm_caps = 0;
+
+ if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP,
+ &alpm_caps) != 1)
+ return false;
+ return alpm_caps & DP_ALPM_CAP;
+}
+
+static u8 psr_get_sink_sync_latency(struct intel_dp *intel_dp)
+{
+ u8 val = 8; /* assume the worst if we can't read the value */
+
+ if (drm_dp_dpcd_readb(&intel_dp->aux,
+ DP_SYNCHRONIZATION_LATENCY_IN_SINK, &val) == 1)
+ val &= DP_MAX_RESYNC_FRAME_COUNT_MASK;
+ else
+ DRM_DEBUG_KMS("Unable to get sink synchronization latency, assuming 8 frames\n");
+ return val;
+}
+
+void intel_psr_init_dpcd(struct intel_dp *intel_dp)
+{
+ struct drm_i915_private *dev_priv =
+ to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
+
+ drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
+ sizeof(intel_dp->psr_dpcd));
+
+ if (!intel_dp->psr_dpcd[0])
+ return;
+ DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
+ intel_dp->psr_dpcd[0]);
+
+ if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
+ DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n");
+ return;
+ }
+ dev_priv->psr.sink_support = true;
+ dev_priv->psr.sink_sync_latency =
+ psr_get_sink_sync_latency(intel_dp);
+
+ if (INTEL_GEN(dev_priv) >= 9 &&
+ (intel_dp->psr_dpcd[0] == DP_PSR2_WITH_Y_COORD_IS_SUPPORTED)) {
+ bool y_req = intel_dp->psr_dpcd[1] &
+ DP_PSR2_SU_Y_COORDINATE_REQUIRED;
+ bool alpm = psr_get_alpm_status(intel_dp);
+
+ /*
+ * All panels that supports PSR version 03h (PSR2 +
+ * Y-coordinate) can handle Y-coordinates in VSC but we are
+ * only sure that it is going to be used when required by the
+ * panel. This way panel is capable to do selective update
+ * without a aux frame sync.
+ *
+ * To support PSR version 02h and PSR version 03h without
+ * Y-coordinate requirement panels we would need to enable
+ * GTC first.
+ */
+ dev_priv->psr.sink_psr2_support = y_req && alpm;
+ DRM_DEBUG_KMS("PSR2 %ssupported\n",
+ dev_priv->psr.sink_psr2_support ? "" : "not ");
+
+ if (dev_priv->psr.sink_psr2_support) {
+ dev_priv->psr.colorimetry_support =
+ psr_get_colorimetry_status(intel_dp);
+ }
+ }
+}
+
/**
* intel_psr_init - Init basic PSR work and mutex.
* @dev_priv: i915 device private
@@ -963,60 +999,6 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
/* For new platforms let's respect VBT back again */
dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
- INIT_WORK(&dev_priv->psr.work, intel_psr_work);
+ INIT_WORK(&dev_priv->psr.work, psr_work);
mutex_init(&dev_priv->psr.lock);
}
-
-void intel_psr_short_pulse(struct intel_dp *intel_dp)
-{
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct drm_device *dev = intel_dig_port->base.base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct i915_psr *psr = &dev_priv->psr;
- u8 val;
- const u8 errors = DP_PSR_RFB_STORAGE_ERROR |
- DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR |
- DP_PSR_LINK_CRC_ERROR;
-
- if (!CAN_PSR(dev_priv) || !intel_dp_is_edp(intel_dp))
- return;
-
- mutex_lock(&psr->lock);
-
- if (psr->enabled != intel_dp)
- goto exit;
-
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_STATUS, &val) != 1) {
- DRM_ERROR("PSR_STATUS dpcd read failed\n");
- goto exit;
- }
-
- if ((val & DP_PSR_SINK_STATE_MASK) == DP_PSR_SINK_INTERNAL_ERROR) {
- DRM_DEBUG_KMS("PSR sink internal error, disabling PSR\n");
- intel_psr_disable_locked(intel_dp);
- }
-
- if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_ERROR_STATUS, &val) != 1) {
- DRM_ERROR("PSR_ERROR_STATUS dpcd read failed\n");
- goto exit;
- }
-
- if (val & DP_PSR_RFB_STORAGE_ERROR)
- DRM_DEBUG_KMS("PSR RFB storage error, disabling PSR\n");
- if (val & DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR)
- DRM_DEBUG_KMS("PSR VSC SDP uncorrectable error, disabling PSR\n");
- if (val & DP_PSR_LINK_CRC_ERROR)
- DRM_ERROR("PSR Link CRC error, disabling PSR\n");
-
- if (val & ~errors)
- DRM_ERROR("PSR_ERROR_STATUS unhandled errors %x\n",
- val & ~errors);
- if (val & errors)
- intel_psr_disable_locked(intel_dp);
- /* clear status register */
- drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ERROR_STATUS, val);
-
- /* TODO: handle PSR2 errors */
-exit:
- mutex_unlock(&psr->lock);
-}
--
2.17.1
More information about the Intel-gfx-trybot
mailing list