summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c95
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h51
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c600
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h38
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c42
10 files changed, 487 insertions, 376 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index c290339dc022..5a36575ba370 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -14155,8 +14155,6 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
intel_dvo_init(dev_priv);
}
- intel_psr_init(dev_priv);
-
for_each_intel_encoder(&dev_priv->drm, encoder) {
encoder->base.possible_crtcs =
intel_encoder_possible_crtcs(encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 64ffa34544a7..c72e41b61349 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -417,10 +417,19 @@ enum phy_fia {
for_each_if((encoder_mask) & \
drm_encoder_mask(&intel_encoder->base))
+#define for_each_intel_encoder_mask_can_psr(dev, intel_encoder, encoder_mask) \
+ list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
+ for_each_if(((encoder_mask) & drm_encoder_mask(&(intel_encoder)->base)) && \
+ intel_encoder_can_psr(intel_encoder))
+
#define for_each_intel_dp(dev, intel_encoder) \
for_each_intel_encoder(dev, intel_encoder) \
for_each_if(intel_encoder_is_dp(intel_encoder))
+#define for_each_intel_encoder_can_psr(dev, intel_encoder) \
+ for_each_intel_encoder((dev), (intel_encoder)) \
+ for_each_if(intel_encoder_can_psr(intel_encoder))
+
#define for_each_intel_connector_iter(intel_connector, iter) \
while ((intel_connector = to_intel_connector(drm_connector_list_iter_next(iter))))
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index d62b18d5ecd8..b1bda1f5ef16 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -249,12 +249,11 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
"sink internal error",
};
struct drm_connector *connector = m->private;
- struct drm_i915_private *dev_priv = to_i915(connector->dev);
struct intel_dp *intel_dp =
intel_attached_dp(to_intel_connector(connector));
int ret;
- if (!CAN_PSR(dev_priv)) {
+ if (!CAN_PSR(intel_dp)) {
seq_puts(m, "PSR Unsupported\n");
return -ENODEV;
}
@@ -280,12 +279,13 @@ static int i915_psr_sink_status_show(struct seq_file *m, void *data)
DEFINE_SHOW_ATTRIBUTE(i915_psr_sink_status);
static void
-psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
+psr_source_status(struct intel_dp *intel_dp, struct seq_file *m)
{
- u32 val, status_val;
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
const char *status = "unknown";
+ u32 val, status_val;
- if (dev_priv->psr.psr2_enabled) {
+ if (intel_dp->psr.psr2_enabled) {
static const char * const live_status[] = {
"IDLE",
"CAPTURE",
@@ -300,7 +300,7 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
"TG_ON"
};
val = intel_de_read(dev_priv,
- EDP_PSR2_STATUS(dev_priv->psr.transcoder));
+ EDP_PSR2_STATUS(intel_dp->psr.transcoder));
status_val = (val & EDP_PSR2_STATUS_STATE_MASK) >>
EDP_PSR2_STATUS_STATE_SHIFT;
if (status_val < ARRAY_SIZE(live_status))
@@ -317,7 +317,7 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
"SRDENT_ON",
};
val = intel_de_read(dev_priv,
- EDP_PSR_STATUS(dev_priv->psr.transcoder));
+ EDP_PSR_STATUS(intel_dp->psr.transcoder));
status_val = (val & EDP_PSR_STATUS_STATE_MASK) >>
EDP_PSR_STATUS_STATE_SHIFT;
if (status_val < ARRAY_SIZE(live_status))
@@ -327,21 +327,18 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
seq_printf(m, "Source PSR status: %s [0x%08x]\n", status, val);
}
-static int i915_edp_psr_status(struct seq_file *m, void *data)
+static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp)
{
- struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct i915_psr *psr = &dev_priv->psr;
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ struct intel_psr *psr = &intel_dp->psr;
intel_wakeref_t wakeref;
const char *status;
bool enabled;
u32 val;
- if (!HAS_PSR(dev_priv))
- return -ENODEV;
-
seq_printf(m, "Sink support: %s", yesno(psr->sink_support));
- if (psr->dp)
- seq_printf(m, " [0x%02x]", psr->dp->psr_dpcd[0]);
+ if (psr->sink_support)
+ seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]);
seq_puts(m, "\n");
if (!psr->sink_support)
@@ -365,16 +362,16 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
if (psr->psr2_enabled) {
val = intel_de_read(dev_priv,
- EDP_PSR2_CTL(dev_priv->psr.transcoder));
+ EDP_PSR2_CTL(intel_dp->psr.transcoder));
enabled = val & EDP_PSR2_ENABLE;
} else {
val = intel_de_read(dev_priv,
- EDP_PSR_CTL(dev_priv->psr.transcoder));
+ EDP_PSR_CTL(intel_dp->psr.transcoder));
enabled = val & EDP_PSR_ENABLE;
}
seq_printf(m, "Source PSR ctl: %s [0x%08x]\n",
enableddisabled(enabled), val);
- psr_source_status(dev_priv, m);
+ psr_source_status(intel_dp, m);
seq_printf(m, "Busy frontbuffer bits: 0x%08x\n",
psr->busy_frontbuffer_bits);
@@ -383,7 +380,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
*/
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
val = intel_de_read(dev_priv,
- EDP_PSR_PERF_CNT(dev_priv->psr.transcoder));
+ EDP_PSR_PERF_CNT(intel_dp->psr.transcoder));
val &= EDP_PSR_PERF_CNT_MASK;
seq_printf(m, "Performance counter: %u\n", val);
}
@@ -404,7 +401,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
*/
for (frame = 0; frame < PSR2_SU_STATUS_FRAMES; frame += 3) {
val = intel_de_read(dev_priv,
- PSR2_SU_STATUS(dev_priv->psr.transcoder, frame));
+ PSR2_SU_STATUS(intel_dp->psr.transcoder, frame));
su_frames_val[frame / 3] = val;
}
@@ -430,23 +427,50 @@ unlock:
return 0;
}
+static int i915_edp_psr_status(struct seq_file *m, void *data)
+{
+ struct drm_i915_private *dev_priv = node_to_i915(m->private);
+ struct intel_dp *intel_dp = NULL;
+ struct intel_encoder *encoder;
+
+ if (!HAS_PSR(dev_priv))
+ return -ENODEV;
+
+ /* Find the first EDP which supports PSR */
+ for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) {
+ intel_dp = enc_to_intel_dp(encoder);
+ break;
+ }
+
+ if (!intel_dp)
+ return -ENODEV;
+
+ return intel_psr_status(m, intel_dp);
+}
+
static int
i915_edp_psr_debug_set(void *data, u64 val)
{
struct drm_i915_private *dev_priv = data;
+ struct intel_encoder *encoder;
intel_wakeref_t wakeref;
- int ret;
+ int ret = -ENODEV;
- if (!CAN_PSR(dev_priv))
- return -ENODEV;
+ if (!HAS_PSR(dev_priv))
+ return ret;
- drm_dbg_kms(&dev_priv->drm, "Setting PSR debug to %llx\n", val);
+ for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
+ drm_dbg_kms(&dev_priv->drm, "Setting PSR debug to %llx\n", val);
- ret = intel_psr_debug_set(dev_priv, val);
+ wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
- intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
+ // TODO: split to each transcoder's PSR debug state
+ ret = intel_psr_debug_set(intel_dp, val);
+
+ intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
+ }
return ret;
}
@@ -455,12 +479,20 @@ static int
i915_edp_psr_debug_get(void *data, u64 *val)
{
struct drm_i915_private *dev_priv = data;
+ struct intel_encoder *encoder;
- if (!CAN_PSR(dev_priv))
+ if (!HAS_PSR(dev_priv))
return -ENODEV;
- *val = READ_ONCE(dev_priv->psr.debug);
- return 0;
+ for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ // TODO: split to each transcoder's PSR debug state
+ *val = READ_ONCE(intel_dp->psr.debug);
+ return 0;
+ }
+
+ return -ENODEV;
}
DEFINE_SIMPLE_ATTRIBUTE(i915_edp_psr_debug_fops,
@@ -1233,9 +1265,6 @@ static void drrs_status_per_crtc(struct seq_file *m,
/* disable_drrs() will make drrs->dp NULL */
if (!drrs->dp) {
seq_puts(m, "Idleness DRRS: Disabled\n");
- if (dev_priv->psr.enabled)
- seq_puts(m,
- "\tAs PSR is enabled, DRRS is not enabled\n");
mutex_unlock(&drrs->mutex);
return;
}
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 39397748b4b0..307ff4b771f4 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1415,6 +1415,43 @@ struct intel_pps {
struct edp_power_seq pps_delays;
};
+struct intel_psr {
+ /* Mutex for PSR state of the transcoder */
+ struct mutex lock;
+
+#define I915_PSR_DEBUG_MODE_MASK 0x0f
+#define I915_PSR_DEBUG_DEFAULT 0x00
+#define I915_PSR_DEBUG_DISABLE 0x01
+#define I915_PSR_DEBUG_ENABLE 0x02
+#define I915_PSR_DEBUG_FORCE_PSR1 0x03
+#define I915_PSR_DEBUG_IRQ 0x10
+
+ u32 debug;
+ bool sink_support;
+ bool source_support;
+ bool enabled;
+ enum pipe pipe;
+ enum transcoder transcoder;
+ bool active;
+ struct work_struct work;
+ unsigned int busy_frontbuffer_bits;
+ bool sink_psr2_support;
+ bool link_standby;
+ bool colorimetry_support;
+ bool psr2_enabled;
+ bool psr2_sel_fetch_enabled;
+ u8 sink_sync_latency;
+ ktime_t last_entry_attempt;
+ ktime_t last_exit;
+ bool sink_not_reliable;
+ bool irq_aux_error;
+ u16 su_x_granularity;
+ bool dc3co_enabled;
+ u32 dc3co_exit_delay;
+ struct delayed_work dc3co_work;
+ struct drm_dp_vsc_sdp vsc;
+};
+
struct intel_dp {
i915_reg_t output_reg;
u32 DP;
@@ -1517,6 +1554,8 @@ struct intel_dp {
bool hobl_active;
struct intel_dp_pcon_frl frl;
+
+ struct intel_psr psr;
};
enum lspcon_vendor {
@@ -1753,6 +1792,18 @@ dp_to_i915(struct intel_dp *intel_dp)
return to_i915(dp_to_dig_port(intel_dp)->base.base.dev);
}
+#define CAN_PSR(intel_dp) (HAS_PSR(dp_to_i915(intel_dp)) && \
+ (intel_dp)->psr.sink_support && \
+ (intel_dp)->psr.source_support)
+
+static inline bool intel_encoder_can_psr(struct intel_encoder *encoder)
+{
+ if (!intel_encoder_is_dp(encoder))
+ return false;
+
+ return CAN_PSR(enc_to_intel_dp(encoder));
+}
+
static inline struct intel_digital_port *
hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
{
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index a338720cee2e..96789fbd4c06 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1663,12 +1663,10 @@ void intel_dp_compute_psr_vsc_sdp(struct intel_dp *intel_dp,
const struct drm_connector_state *conn_state,
struct drm_dp_vsc_sdp *vsc)
{
- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
vsc->sdp_type = DP_SDP_VSC;
- if (dev_priv->psr.psr2_enabled) {
- if (dev_priv->psr.colorimetry_support &&
+ if (intel_dp->psr.psr2_enabled) {
+ if (intel_dp->psr.colorimetry_support &&
intel_dp_needs_vsc_sdp(crtc_state, conn_state)) {
/* [PSR2, +Colorimetry] */
intel_dp_compute_vsc_colorimetry(crtc_state, conn_state,
@@ -2359,7 +2357,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
return false;
}
- if (CAN_PSR(i915) && intel_dp_is_edp(intel_dp)) {
+ if (CAN_PSR(intel_dp) && intel_dp_is_edp(intel_dp)) {
drm_dbg_kms(&i915->drm, "Forcing full modeset to compute PSR state\n");
crtc_state->uapi.mode_changed = true;
return false;
@@ -6641,6 +6639,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
intel_dp->frl.is_trained = false;
intel_dp->frl.trained_rate_gbps = 0;
+ intel_psr_init(intel_dp);
+
return true;
fail:
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 2c365b778f74..bf48eb4e1a84 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -80,9 +80,11 @@
* use page flips.
*/
-static bool psr_global_enabled(struct drm_i915_private *i915)
+static bool psr_global_enabled(struct intel_dp *intel_dp)
{
- switch (i915->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+ switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
case I915_PSR_DEBUG_DEFAULT:
return i915->params.enable_psr;
case I915_PSR_DEBUG_DISABLE:
@@ -92,9 +94,9 @@ static bool psr_global_enabled(struct drm_i915_private *i915)
}
}
-static bool psr2_global_enabled(struct drm_i915_private *dev_priv)
+static bool psr2_global_enabled(struct intel_dp *intel_dp)
{
- switch (dev_priv->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
+ switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) {
case I915_PSR_DEBUG_DISABLE:
case I915_PSR_DEBUG_FORCE_PSR1:
return false;
@@ -103,11 +105,12 @@ static bool psr2_global_enabled(struct drm_i915_private *dev_priv)
}
}
-static void psr_irq_control(struct drm_i915_private *dev_priv)
+static void psr_irq_control(struct intel_dp *intel_dp)
{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum transcoder trans_shift;
- u32 mask, val;
i915_reg_t imr_reg;
+ u32 mask, val;
/*
* gen12+ has registers relative to transcoder and one per transcoder
@@ -116,14 +119,14 @@ static void psr_irq_control(struct drm_i915_private *dev_priv)
*/
if (INTEL_GEN(dev_priv) >= 12) {
trans_shift = 0;
- imr_reg = TRANS_PSR_IMR(dev_priv->psr.transcoder);
+ imr_reg = TRANS_PSR_IMR(intel_dp->psr.transcoder);
} else {
- trans_shift = dev_priv->psr.transcoder;
+ trans_shift = intel_dp->psr.transcoder;
imr_reg = EDP_PSR_IMR;
}
mask = EDP_PSR_ERROR(trans_shift);
- if (dev_priv->psr.debug & I915_PSR_DEBUG_IRQ)
+ if (intel_dp->psr.debug & I915_PSR_DEBUG_IRQ)
mask |= EDP_PSR_POST_EXIT(trans_shift) |
EDP_PSR_PRE_ENTRY(trans_shift);
@@ -172,30 +175,31 @@ static void psr_event_print(struct drm_i915_private *i915,
drm_dbg_kms(&i915->drm, "\tPSR disabled\n");
}
-void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
+void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir)
{
- enum transcoder cpu_transcoder = dev_priv->psr.transcoder;
+ enum transcoder cpu_transcoder = intel_dp->psr.transcoder;
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ ktime_t time_ns = ktime_get();
enum transcoder trans_shift;
i915_reg_t imr_reg;
- ktime_t time_ns = ktime_get();
if (INTEL_GEN(dev_priv) >= 12) {
trans_shift = 0;
- imr_reg = TRANS_PSR_IMR(dev_priv->psr.transcoder);
+ imr_reg = TRANS_PSR_IMR(intel_dp->psr.transcoder);
} else {
- trans_shift = dev_priv->psr.transcoder;
+ trans_shift = intel_dp->psr.transcoder;
imr_reg = EDP_PSR_IMR;
}
if (psr_iir & EDP_PSR_PRE_ENTRY(trans_shift)) {
- dev_priv->psr.last_entry_attempt = time_ns;
+ intel_dp->psr.last_entry_attempt = time_ns;
drm_dbg_kms(&dev_priv->drm,
"[transcoder %s] PSR entry attempt in 2 vblanks\n",
transcoder_name(cpu_transcoder));
}
if (psr_iir & EDP_PSR_POST_EXIT(trans_shift)) {
- dev_priv->psr.last_exit = time_ns;
+ intel_dp->psr.last_exit = time_ns;
drm_dbg_kms(&dev_priv->drm,
"[transcoder %s] PSR exit completed\n",
transcoder_name(cpu_transcoder));
@@ -203,7 +207,7 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
if (INTEL_GEN(dev_priv) >= 9) {
u32 val = intel_de_read(dev_priv,
PSR_EVENT(cpu_transcoder));
- bool psr2_enabled = dev_priv->psr.psr2_enabled;
+ bool psr2_enabled = intel_dp->psr.psr2_enabled;
intel_de_write(dev_priv, PSR_EVENT(cpu_transcoder),
val);
@@ -217,7 +221,7 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
drm_warn(&dev_priv->drm, "[transcoder %s] PSR aux error\n",
transcoder_name(cpu_transcoder));
- dev_priv->psr.irq_aux_error = true;
+ intel_dp->psr.irq_aux_error = true;
/*
* If this interruption is not masked it will keep
@@ -231,7 +235,7 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
val |= EDP_PSR_ERROR(trans_shift);
intel_de_write(dev_priv, imr_reg, val);
- schedule_work(&dev_priv->psr.work);
+ schedule_work(&intel_dp->psr.work);
}
}
@@ -292,12 +296,6 @@ 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);
- if (dev_priv->psr.dp) {
- drm_warn(&dev_priv->drm,
- "More than one eDP panel found, PSR support should be extended\n");
- return;
- }
-
drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT, intel_dp->psr_dpcd,
sizeof(intel_dp->psr_dpcd));
@@ -318,12 +316,10 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
return;
}
- dev_priv->psr.sink_support = true;
- dev_priv->psr.sink_sync_latency =
+ intel_dp->psr.sink_support = true;
+ intel_dp->psr.sink_sync_latency =
intel_dp_get_sink_sync_latency(intel_dp);
- dev_priv->psr.dp = 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] &
@@ -341,14 +337,14 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
* Y-coordinate requirement panels we would need to enable
* GTC first.
*/
- dev_priv->psr.sink_psr2_support = y_req && alpm;
+ intel_dp->psr.sink_psr2_support = y_req && alpm;
drm_dbg_kms(&dev_priv->drm, "PSR2 %ssupported\n",
- dev_priv->psr.sink_psr2_support ? "" : "not ");
+ intel_dp->psr.sink_psr2_support ? "" : "not ");
- if (dev_priv->psr.sink_psr2_support) {
- dev_priv->psr.colorimetry_support =
+ if (intel_dp->psr.sink_psr2_support) {
+ intel_dp->psr.colorimetry_support =
intel_dp_get_colorimetry_status(intel_dp);
- dev_priv->psr.su_x_granularity =
+ intel_dp->psr.su_x_granularity =
intel_dp_get_su_x_granulartiy(intel_dp);
}
}
@@ -374,7 +370,7 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
BUILD_BUG_ON(sizeof(aux_msg) > 20);
for (i = 0; i < sizeof(aux_msg); i += 4)
intel_de_write(dev_priv,
- EDP_PSR_AUX_DATA(dev_priv->psr.transcoder, i >> 2),
+ EDP_PSR_AUX_DATA(intel_dp->psr.transcoder, i >> 2),
intel_dp_pack_aux(&aux_msg[i], sizeof(aux_msg) - i));
aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, 0);
@@ -385,7 +381,7 @@ static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
/* Select only valid bits for SRD_AUX_CTL */
aux_ctl &= psr_aux_mask;
- intel_de_write(dev_priv, EDP_PSR_AUX_CTL(dev_priv->psr.transcoder),
+ intel_de_write(dev_priv, EDP_PSR_AUX_CTL(intel_dp->psr.transcoder),
aux_ctl);
}
@@ -395,14 +391,14 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp)
u8 dpcd_val = DP_PSR_ENABLE;
/* Enable ALPM at sink for psr2 */
- if (dev_priv->psr.psr2_enabled) {
+ if (intel_dp->psr.psr2_enabled) {
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG,
DP_ALPM_ENABLE |
DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE);
dpcd_val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS;
} else {
- if (dev_priv->psr.link_standby)
+ if (intel_dp->psr.link_standby)
dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE;
if (INTEL_GEN(dev_priv) >= 8)
@@ -465,7 +461,7 @@ static u8 psr_compute_idle_frames(struct intel_dp *intel_dp)
* off-by-one issue that HW has in some cases.
*/
idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
- idle_frames = max(idle_frames, dev_priv->psr.sink_sync_latency + 1);
+ idle_frames = max(idle_frames, intel_dp->psr.sink_sync_latency + 1);
if (drm_WARN_ON(&dev_priv->drm, idle_frames > 0xf))
idle_frames = 0xf;
@@ -485,7 +481,7 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
if (IS_HASWELL(dev_priv))
val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
- if (dev_priv->psr.link_standby)
+ if (intel_dp->psr.link_standby)
val |= EDP_PSR_LINK_STANDBY;
val |= intel_psr1_get_tp_time(intel_dp);
@@ -493,9 +489,9 @@ static void hsw_activate_psr1(struct intel_dp *intel_dp)
if (INTEL_GEN(dev_priv) >= 8)
val |= EDP_PSR_CRC_ENABLE;
- val |= (intel_de_read(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder)) &
+ val |= (intel_de_read(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder)) &
EDP_PSR_RESTORE_PSR_ACTIVE_CTX_MASK);
- intel_de_write(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder), val);
+ intel_de_write(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder), val);
}
static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp)
@@ -530,7 +526,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
val |= EDP_Y_COORDINATE_ENABLE;
- val |= EDP_PSR2_FRAME_BEFORE_SU(dev_priv->psr.sink_sync_latency + 1);
+ val |= EDP_PSR2_FRAME_BEFORE_SU(intel_dp->psr.sink_sync_latency + 1);
val |= intel_psr2_get_tp_time(intel_dp);
if (INTEL_GEN(dev_priv) >= 12) {
@@ -549,7 +545,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
val |= EDP_PSR2_FAST_WAKE(7);
}
- if (dev_priv->psr.psr2_sel_fetch_enabled) {
+ if (intel_dp->psr.psr2_sel_fetch_enabled) {
/* WA 1408330847 */
if (IS_TGL_DISP_STEPPING(dev_priv, STEP_A0, STEP_A0) ||
IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0))
@@ -558,20 +554,20 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
DIS_RAM_BYPASS_PSR2_MAN_TRACK);
intel_de_write(dev_priv,
- PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder),
+ PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder),
PSR2_MAN_TRK_CTL_ENABLE);
} else if (HAS_PSR2_SEL_FETCH(dev_priv)) {
intel_de_write(dev_priv,
- PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), 0);
+ PSR2_MAN_TRK_CTL(intel_dp->psr.transcoder), 0);
}
/*
* PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is
* recommending keep this bit unset while PSR2 is enabled.
*/
- intel_de_write(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder), 0);
+ intel_de_write(dev_priv, EDP_PSR_CTL(intel_dp->psr.transcoder), 0);
- intel_de_write(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder), val);
+ intel_de_write(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
}
static bool
@@ -594,55 +590,58 @@ static u32 intel_get_frame_time_us(const struct intel_crtc_state *cstate)
drm_mode_vrefresh(&cstate->hw.adjusted_mode));
}
-static void psr2_program_idle_frames(struct drm_i915_private *dev_priv,
+static void psr2_program_idle_frames(struct intel_dp *intel_dp,
u32 idle_frames)
{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u32 val;
idle_frames <<= EDP_PSR2_IDLE_FRAME_SHIFT;
- val = intel_de_read(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder));
+ val = intel_de_read(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder));
val &= ~EDP_PSR2_IDLE_FRAME_MASK;
val |= idle_frames;
- intel_de_write(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder), val);
+ intel_de_write(dev_priv, EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
}
-static void tgl_psr2_enable_dc3co(struct drm_i915_private *dev_priv)
+static void tgl_psr2_enable_dc3co(struct intel_dp *intel_dp)
{
- psr2_program_idle_frames(dev_priv, 0);
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+ psr2_program_idle_frames(intel_dp, 0);
intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_DC3CO);
}
-static void tgl_psr2_disable_dc3co(struct drm_i915_private *dev_priv)
+static void tgl_psr2_disable_dc3co(struct intel_dp *intel_dp)
{
- struct intel_dp *intel_dp = dev_priv->psr.dp;
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
intel_display_power_set_target_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
- psr2_program_idle_frames(dev_priv, psr_compute_idle_frames(intel_dp));
+ psr2_program_idle_frames(intel_dp, psr_compute_idle_frames(intel_dp));
}
static void tgl_dc3co_disable_work(struct work_struct *work)
{
- struct drm_i915_private *dev_priv =
- container_of(work, typeof(*dev_priv), psr.dc3co_work.work);
+ struct intel_dp *intel_dp =
+ container_of(work, typeof(*intel_dp), psr.dc3co_work.work);
- mutex_lock(&dev_priv->psr.lock);
+ mutex_lock(&intel_dp->psr.lock);
/* If delayed work is pending, it is not idle */
- if (delayed_work_pending(&dev_priv->psr.dc3co_work))
+ if (delayed_work_pending(&intel_dp->psr.dc3co_work))
goto unlock;
- tgl_psr2_disable_dc3co(dev_priv);
+ tgl_psr2_disable_dc3co(intel_dp);
unlock:
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_unlock(&intel_dp->psr.lock);
}
-static void tgl_disallow_dc3co_on_psr2_exit(struct drm_i915_private *dev_priv)
+static void tgl_disallow_dc3co_on_psr2_exit(struct intel_dp *intel_dp)
{
- if (!dev_priv->psr.dc3co_enabled)
+ if (!intel_dp->psr.dc3co_enabled)
return;
- cancel_delayed_work(&dev_priv->psr.dc3co_work);
+ cancel_delayed_work(&intel_dp->psr.dc3co_work);
/* Before PSR2 exit disallow dc3co*/
- tgl_psr2_disable_dc3co(dev_priv);
+ tgl_psr2_disable_dc3co(intel_dp);
}
static void
@@ -715,7 +714,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay;
int psr_max_h = 0, psr_max_v = 0, max_bpp = 0;
- if (!dev_priv->psr.sink_psr2_support)
+ if (!intel_dp->psr.sink_psr2_support)
return false;
if (!transcoder_has_psr2(dev_priv, crtc_state->cpu_transcoder)) {
@@ -725,7 +724,7 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
return false;
}
- if (!psr2_global_enabled(dev_priv)) {
+ if (!psr2_global_enabled(intel_dp)) {
drm_dbg_kms(&dev_priv->drm, "PSR2 disabled by flag\n");
return false;
}
@@ -774,10 +773,10 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
* only need to validate the SU block width is a multiple of
* x granularity.
*/
- if (crtc_hdisplay % dev_priv->psr.su_x_granularity) {
+ if (crtc_hdisplay % intel_dp->psr.su_x_granularity) {
drm_dbg_kms(&dev_priv->drm,
"PSR2 not enabled, hdisplay(%d) not multiple of %d\n",
- crtc_hdisplay, dev_priv->psr.su_x_granularity);
+ crtc_hdisplay, intel_dp->psr.su_x_granularity);
return false;
}
@@ -806,7 +805,6 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
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 = dp_to_i915(intel_dp);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
@@ -819,30 +817,15 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
if (crtc_state->vrr.enable)
return;
- if (!CAN_PSR(dev_priv))
+ if (!CAN_PSR(intel_dp))
return;
- if (intel_dp != dev_priv->psr.dp)
- return;
-
- if (!psr_global_enabled(dev_priv)) {
+ if (!psr_global_enabled(intel_dp)) {
drm_dbg_kms(&dev_priv->drm, "PSR disabled by flag\n");
return;
}
- /*
- * HSW spec explicitly says PSR is tied to port A.
- * BDW+ platforms have a instance of PSR registers per transcoder but
- * for now it only supports one instance of PSR, so lets keep it
- * hardcoded to PORT_A
- */
- if (dig_port->base.port != PORT_A) {
- drm_dbg_kms(&dev_priv->drm,
- "PSR condition failed: Port not supported\n");
- return;
- }
-
- if (dev_priv->psr.sink_not_reliable) {
+ if (intel_dp->psr.sink_not_reliable) {
drm_dbg_kms(&dev_priv->drm,
"PSR sink implementation is not reliable\n");
return;
@@ -878,23 +861,24 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
static void intel_psr_activate(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ enum transcoder transcoder = intel_dp->psr.transcoder;
- if (transcoder_has_psr2(dev_priv, dev_priv->psr.transcoder))
+ if (transcoder_has_psr2(dev_priv, transcoder))
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, EDP_PSR2_CTL(dev_priv->psr.transcoder)) & EDP_PSR2_ENABLE);
+ intel_de_read(dev_priv, EDP_PSR2_CTL(transcoder)) & EDP_PSR2_ENABLE);
drm_WARN_ON(&dev_priv->drm,
- intel_de_read(dev_priv, EDP_PSR_CTL(dev_priv->psr.transcoder)) & EDP_PSR_ENABLE);
- drm_WARN_ON(&dev_priv->drm, dev_priv->psr.active);
- lockdep_assert_held(&dev_priv->psr.lock);
+ intel_de_read(dev_priv, EDP_PSR_CTL(transcoder)) & EDP_PSR_ENABLE);
+ drm_WARN_ON(&dev_priv->drm, intel_dp->psr.active);
+ lockdep_assert_held(&intel_dp->psr.lock);
/* psr1 and psr2 are mutually exclusive.*/
- if (dev_priv->psr.psr2_enabled)
+ if (intel_dp->psr.psr2_enabled)
hsw_activate_psr2(intel_dp);
else
hsw_activate_psr1(intel_dp);
- dev_priv->psr.active = true;
+ intel_dp->psr.active = true;
}
static void intel_psr_enable_source(struct intel_dp *intel_dp,
@@ -910,7 +894,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
hsw_psr_setup_aux(intel_dp);
- if (dev_priv->psr.psr2_enabled && (IS_GEN(dev_priv, 9) &&
+ if (intel_dp->psr.psr2_enabled && (IS_GEN(dev_priv, 9) &&
!IS_GEMINILAKE(dev_priv))) {
i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder);
u32 chicken = intel_de_read(dev_priv, reg);
@@ -934,10 +918,10 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
if (INTEL_GEN(dev_priv) < 11)
mask |= EDP_PSR_DEBUG_MASK_DISP_REG_WRITE;
- intel_de_write(dev_priv, EDP_PSR_DEBUG(dev_priv->psr.transcoder),
+ intel_de_write(dev_priv, EDP_PSR_DEBUG(intel_dp->psr.transcoder),
mask);
- psr_irq_control(dev_priv);
+ psr_irq_control(intel_dp);
if (crtc_state->dc3co_exitline) {
u32 val;
@@ -955,30 +939,30 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp,
if (HAS_PSR_HW_TRACKING(dev_priv) && HAS_PSR2_SEL_FETCH(dev_priv))
intel_de_rmw(dev_priv, CHICKEN_PAR1_1, IGNORE_PSR2_HW_TRACKING,
- dev_priv->psr.psr2_sel_fetch_enabled ?
+ intel_dp->psr.psr2_sel_fetch_enabled ?
IGNORE_PSR2_HW_TRACKING : 0);
}
-static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
+static void intel_psr_enable_locked(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct intel_dp *intel_dp = dev_priv->psr.dp;
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct intel_encoder *encoder = &dig_port->base;
u32 val;
- drm_WARN_ON(&dev_priv->drm, dev_priv->psr.enabled);
+ drm_WARN_ON(&dev_priv->drm, intel_dp->psr.enabled);
- dev_priv->psr.psr2_enabled = crtc_state->has_psr2;
- dev_priv->psr.busy_frontbuffer_bits = 0;
- dev_priv->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
- dev_priv->psr.dc3co_enabled = !!crtc_state->dc3co_exitline;
- dev_priv->psr.transcoder = crtc_state->cpu_transcoder;
+ intel_dp->psr.psr2_enabled = crtc_state->has_psr2;
+ intel_dp->psr.busy_frontbuffer_bits = 0;
+ intel_dp->psr.pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
+ intel_dp->psr.dc3co_enabled = !!crtc_state->dc3co_exitline;
+ intel_dp->psr.transcoder = crtc_state->cpu_transcoder;
/* DC5/DC6 requires at least 6 idle frames */
val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6);
- dev_priv->psr.dc3co_exit_delay = val;
- dev_priv->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch;
+ intel_dp->psr.dc3co_exit_delay = val;
+ intel_dp->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch;
/*
* If a PSR error happened and the driver is reloaded, the EDP_PSR_IIR
@@ -990,27 +974,27 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv,
*/
if (INTEL_GEN(dev_priv) >= 12) {
val = intel_de_read(dev_priv,
- TRANS_PSR_IIR(dev_priv->psr.transcoder));
+ TRANS_PSR_IIR(intel_dp->psr.transcoder));
val &= EDP_PSR_ERROR(0);
} else {
val = intel_de_read(dev_priv, EDP_PSR_IIR);
- val &= EDP_PSR_ERROR(dev_priv->psr.transcoder);
+ val &= EDP_PSR_ERROR(intel_dp->psr.transcoder);
}
if (val) {
- dev_priv->psr.sink_not_reliable = true;
+ intel_dp->psr.sink_not_reliable = true;
drm_dbg_kms(&dev_priv->drm,
"PSR interruption error set, not enabling PSR\n");
return;
}
drm_dbg_kms(&dev_priv->drm, "Enabling PSR%s\n",
- dev_priv->psr.psr2_enabled ? "2" : "1");
+ intel_dp->psr.psr2_enabled ? "2" : "1");
intel_dp_compute_psr_vsc_sdp(intel_dp, crtc_state, conn_state,
- &dev_priv->psr.vsc);
- intel_write_dp_vsc_sdp(encoder, crtc_state, &dev_priv->psr.vsc);
+ &intel_dp->psr.vsc);
+ intel_write_dp_vsc_sdp(encoder, crtc_state, &intel_dp->psr.vsc);
intel_psr_enable_sink(intel_dp);
intel_psr_enable_source(intel_dp, crtc_state);
- dev_priv->psr.enabled = true;
+ intel_dp->psr.enabled = true;
intel_psr_activate(intel_dp);
}
@@ -1029,7 +1013,7 @@ void intel_psr_enable(struct intel_dp *intel_dp,
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- if (!CAN_PSR(dev_priv) || dev_priv->psr.dp != intel_dp)
+ if (!CAN_PSR(intel_dp))
return;
if (!crtc_state->has_psr)
@@ -1037,46 +1021,47 @@ void intel_psr_enable(struct intel_dp *intel_dp,
drm_WARN_ON(&dev_priv->drm, dev_priv->drrs.dp);
- mutex_lock(&dev_priv->psr.lock);
- intel_psr_enable_locked(dev_priv, crtc_state, conn_state);
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_lock(&intel_dp->psr.lock);
+ intel_psr_enable_locked(intel_dp, crtc_state, conn_state);
+ mutex_unlock(&intel_dp->psr.lock);
}
-static void intel_psr_exit(struct drm_i915_private *dev_priv)
+static void intel_psr_exit(struct intel_dp *intel_dp)
{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
u32 val;
- if (!dev_priv->psr.active) {
- if (transcoder_has_psr2(dev_priv, dev_priv->psr.transcoder)) {
+ if (!intel_dp->psr.active) {
+ if (transcoder_has_psr2(dev_priv, intel_dp->psr.transcoder)) {
val = intel_de_read(dev_priv,
- EDP_PSR2_CTL(dev_priv->psr.transcoder));
+ EDP_PSR2_CTL(intel_dp->psr.transcoder));
drm_WARN_ON(&dev_priv->drm, val & EDP_PSR2_ENABLE);
}
val = intel_de_read(dev_priv,
- EDP_PSR_CTL(dev_priv->psr.transcoder));
+ EDP_PSR_CTL(intel_dp->psr.transcoder));
drm_WARN_ON(&dev_priv->drm, val & EDP_PSR_ENABLE);
return;
}
- if (dev_priv->psr.psr2_enabled) {
- tgl_disallow_dc3co_on_psr2_exit(dev_priv);
+ if (intel_dp->psr.psr2_enabled) {
+ tgl_disallow_dc3co_on_psr2_exit(intel_dp);
val = intel_de_read(dev_priv,
- EDP_PSR2_CTL(dev_priv->psr.transcoder));
+ EDP_PSR2_CTL(intel_dp->psr.transcoder));
drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR2_ENABLE));
val &= ~EDP_PSR2_ENABLE;
intel_de_write(dev_priv,
- EDP_PSR2_CTL(dev_priv->psr.transcoder), val);
+ EDP_PSR2_CTL(intel_dp->psr.transcoder), val);
} else {
val = intel_de_read(dev_priv,
- EDP_PSR_CTL(dev_priv->psr.transcoder));
+ EDP_PSR_CTL(intel_dp->psr.transcoder));
drm_WARN_ON(&dev_priv->drm, !(val & EDP_PSR_ENABLE));
val &= ~EDP_PSR_ENABLE;
intel_de_write(dev_priv,
- EDP_PSR_CTL(dev_priv->psr.transcoder), val);
+ EDP_PSR_CTL(intel_dp->psr.transcoder), val);
}
- dev_priv->psr.active = false;
+ intel_dp->psr.active = false;
}
static void intel_psr_disable_locked(struct intel_dp *intel_dp)
@@ -1085,21 +1070,21 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
i915_reg_t psr_status;
u32 psr_status_mask;
- lockdep_assert_held(&dev_priv->psr.lock);
+ lockdep_assert_held(&intel_dp->psr.lock);
- if (!dev_priv->psr.enabled)
+ if (!intel_dp->psr.enabled)
return;
drm_dbg_kms(&dev_priv->drm, "Disabling PSR%s\n",
- dev_priv->psr.psr2_enabled ? "2" : "1");
+ intel_dp->psr.psr2_enabled ? "2" : "1");
- intel_psr_exit(dev_priv);
+ intel_psr_exit(intel_dp);
- if (dev_priv->psr.psr2_enabled) {
- psr_status = EDP_PSR2_STATUS(dev_priv->psr.transcoder);
+ if (intel_dp->psr.psr2_enabled) {
+ psr_status = EDP_PSR2_STATUS(intel_dp->psr.transcoder);
psr_status_mask = EDP_PSR2_STATUS_STATE_MASK;
} else {
- psr_status = EDP_PSR_STATUS(dev_priv->psr.transcoder);
+ psr_status = EDP_PSR_STATUS(intel_dp->psr.transcoder);
psr_status_mask = EDP_PSR_STATUS_STATE_MASK;
}
@@ -1109,7 +1094,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
drm_err(&dev_priv->drm, "Timed out waiting PSR idle state\n");
/* WA 1408330847 */
- if (dev_priv->psr.psr2_sel_fetch_enabled &&
+ if (intel_dp->psr.psr2_sel_fetch_enabled &&
(IS_TGL_DISP_STEPPING(dev_priv, STEP_A0, STEP_A0) ||
IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0)))
intel_de_rmw(dev_priv, CHICKEN_PAR1_1,
@@ -1118,10 +1103,10 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp)
/* Disable PSR on Sink */
drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
- if (dev_priv->psr.psr2_enabled)
+ if (intel_dp->psr.psr2_enabled)
drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, 0);
- dev_priv->psr.enabled = false;
+ intel_dp->psr.enabled = false;
}
/**
@@ -1139,20 +1124,22 @@ void intel_psr_disable(struct intel_dp *intel_dp,
if (!old_crtc_state->has_psr)
return;
- if (drm_WARN_ON(&dev_priv->drm, !CAN_PSR(dev_priv)))
+ if (drm_WARN_ON(&dev_priv->drm, !CAN_PSR(intel_dp)))
return;
- mutex_lock(&dev_priv->psr.lock);
+ mutex_lock(&intel_dp->psr.lock);
intel_psr_disable_locked(intel_dp);
- mutex_unlock(&dev_priv->psr.lock);
- cancel_work_sync(&dev_priv->psr.work);
- cancel_delayed_work_sync(&dev_priv->psr.dc3co_work);
+ mutex_unlock(&intel_dp->psr.lock);
+ cancel_work_sync(&intel_dp->psr.work);
+ cancel_delayed_work_sync(&intel_dp->psr.dc3co_work);
}
-static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
+static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
if (IS_TIGERLAKE(dev_priv))
/*
* Writes to CURSURFLIVE in TGL are causing IOMMU errors and
@@ -1166,7 +1153,7 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
* So using this workaround until this issue is root caused
* and a better fix is found.
*/
- intel_psr_exit(dev_priv);
+ intel_psr_exit(intel_dp);
else if (INTEL_GEN(dev_priv) >= 9)
/*
* Display WA #0884: skl+
@@ -1177,13 +1164,13 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
* but it makes more sense write to the current active
* pipe.
*/
- intel_de_write(dev_priv, CURSURFLIVE(dev_priv->psr.pipe), 0);
+ intel_de_write(dev_priv, CURSURFLIVE(intel_dp->psr.pipe), 0);
else
/*
* A write to CURSURFLIVE do not cause HW tracking to exit PSR
* on older gens so doing the manual exit instead.
*/
- intel_psr_exit(dev_priv);
+ intel_psr_exit(intel_dp);
}
void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
@@ -1231,16 +1218,24 @@ void intel_psr2_program_plane_sel_fetch(struct intel_plane *plane,
void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state)
{
- struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct i915_psr *psr = &dev_priv->psr;
+ struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct intel_encoder *encoder;
if (!HAS_PSR2_SEL_FETCH(dev_priv) ||
!crtc_state->enable_psr2_sel_fetch)
return;
- intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(psr->transcoder),
- crtc_state->psr2_man_track_ctl);
+ for_each_intel_encoder_mask_can_psr(&dev_priv->drm, encoder,
+ crtc_state->uapi.encoder_mask) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ if (!intel_dp->psr.enabled)
+ continue;
+
+ intel_de_write(dev_priv,
+ PSR2_MAN_TRK_CTL(crtc_state->cpu_transcoder),
+ crtc_state->psr2_man_track_ctl);
+ }
}
static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
@@ -1435,13 +1430,13 @@ void intel_psr_update(struct intel_dp *intel_dp,
const struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- struct i915_psr *psr = &dev_priv->psr;
+ struct intel_psr *psr = &intel_dp->psr;
bool enable, psr2_enable;
- if (!CAN_PSR(dev_priv) || READ_ONCE(psr->dp) != intel_dp)
+ if (!CAN_PSR(intel_dp))
return;
- mutex_lock(&dev_priv->psr.lock);
+ mutex_lock(&intel_dp->psr.lock);
enable = crtc_state->has_psr;
psr2_enable = crtc_state->has_psr2;
@@ -1449,15 +1444,15 @@ void intel_psr_update(struct intel_dp *intel_dp,
if (enable == psr->enabled && psr2_enable == psr->psr2_enabled) {
/* Force a PSR exit when enabling CRC to avoid CRC timeouts */
if (crtc_state->crc_enabled && psr->enabled)
- psr_force_hw_tracking_exit(dev_priv);
+ psr_force_hw_tracking_exit(intel_dp);
else if (INTEL_GEN(dev_priv) < 9 && psr->enabled) {
/*
* Activate PSR again after a force exit when enabling
* CRC in older gens
*/
- if (!dev_priv->psr.active &&
- !dev_priv->psr.busy_frontbuffer_bits)
- schedule_work(&dev_priv->psr.work);
+ if (!intel_dp->psr.active &&
+ !intel_dp->psr.busy_frontbuffer_bits)
+ schedule_work(&intel_dp->psr.work);
}
goto unlock;
@@ -1467,34 +1462,23 @@ void intel_psr_update(struct intel_dp *intel_dp,
intel_psr_disable_locked(intel_dp);
if (enable)
- intel_psr_enable_locked(dev_priv, crtc_state, conn_state);
+ intel_psr_enable_locked(intel_dp, crtc_state, conn_state);
unlock:
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_unlock(&intel_dp->psr.lock);
}
/**
- * intel_psr_wait_for_idle - wait for PSR1 to idle
- * @new_crtc_state: new CRTC state
+ * psr_wait_for_idle - wait for PSR1 to idle
+ * @intel_dp: Intel DP
* @out_value: PSR status in case of failure
*
- * This function is expected to be called from pipe_update_start() where it is
- * not expected to race with PSR enable or disable.
- *
* Returns: 0 on success or -ETIMEOUT if PSR status does not idle.
+ *
*/
-int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state,
- u32 *out_value)
+static int psr_wait_for_idle(struct intel_dp *intel_dp, u32 *out_value)
{
- struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-
- if (!dev_priv->psr.enabled || !new_crtc_state->has_psr)
- return 0;
-
- /* FIXME: Update this for PSR2 if we need to wait for idle */
- if (READ_ONCE(dev_priv->psr.psr2_enabled))
- return 0;
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
/*
* From bspec: Panel Self Refresh (BDW+)
@@ -1502,32 +1486,68 @@ int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state,
* exit training time + 1.5 ms of aux channel handshake. 50 ms is
* defensive enough to cover everything.
*/
-
return __intel_wait_for_register(&dev_priv->uncore,
- EDP_PSR_STATUS(dev_priv->psr.transcoder),
+ EDP_PSR_STATUS(intel_dp->psr.transcoder),
EDP_PSR_STATUS_STATE_MASK,
EDP_PSR_STATUS_STATE_IDLE, 2, 50,
out_value);
}
-static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
+/**
+ * intel_psr_wait_for_idle - wait for PSR1 to idle
+ * @new_crtc_state: new CRTC state
+ *
+ * This function is expected to be called from pipe_update_start() where it is
+ * not expected to race with PSR enable or disable.
+ */
+void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(new_crtc_state->uapi.crtc->dev);
+ struct intel_encoder *encoder;
+
+ if (!new_crtc_state->has_psr)
+ return;
+
+ for_each_intel_encoder_mask_can_psr(&dev_priv->drm, encoder,
+ new_crtc_state->uapi.encoder_mask) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ u32 psr_status;
+
+ mutex_lock(&intel_dp->psr.lock);
+ if (!intel_dp->psr.enabled ||
+ (intel_dp->psr.enabled && intel_dp->psr.psr2_enabled)) {
+ mutex_unlock(&intel_dp->psr.lock);
+ continue;
+ }
+
+ /* when the PSR1 is enabled */
+ if (psr_wait_for_idle(intel_dp, &psr_status))
+ drm_err(&dev_priv->drm,
+ "PSR idle timed out 0x%x, atomic update may fail\n",
+ psr_status);
+ mutex_unlock(&intel_dp->psr.lock);
+ }
+}
+
+static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp)
{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
i915_reg_t reg;
u32 mask;
int err;
- if (!dev_priv->psr.enabled)
+ if (!intel_dp->psr.enabled)
return false;
- if (dev_priv->psr.psr2_enabled) {
- reg = EDP_PSR2_STATUS(dev_priv->psr.transcoder);
+ if (intel_dp->psr.psr2_enabled) {
+ reg = EDP_PSR2_STATUS(intel_dp->psr.transcoder);
mask = EDP_PSR2_STATUS_STATE_MASK;
} else {
- reg = EDP_PSR_STATUS(dev_priv->psr.transcoder);
+ reg = EDP_PSR_STATUS(intel_dp->psr.transcoder);
mask = EDP_PSR_STATUS_STATE_MASK;
}
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_unlock(&intel_dp->psr.lock);
err = intel_de_wait_for_clear(dev_priv, reg, mask, 50);
if (err)
@@ -1535,8 +1555,8 @@ static bool __psr_wait_for_idle_locked(struct drm_i915_private *dev_priv)
"Timed out waiting for PSR Idle for re-enable\n");
/* After the unlocked wait, verify that PSR is still wanted! */
- mutex_lock(&dev_priv->psr.lock);
- return err == 0 && dev_priv->psr.enabled;
+ mutex_lock(&intel_dp->psr.lock);
+ return err == 0 && intel_dp->psr.enabled;
}
static int intel_psr_fastset_force(struct drm_i915_private *dev_priv)
@@ -1602,8 +1622,9 @@ retry:
return err;
}
-int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 val)
+int intel_psr_debug_set(struct intel_dp *intel_dp, u64 val)
{
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
const u32 mode = val & I915_PSR_DEBUG_MODE_MASK;
u32 old_mode;
int ret;
@@ -1614,21 +1635,21 @@ int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 val)
return -EINVAL;
}
- ret = mutex_lock_interruptible(&dev_priv->psr.lock);
+ ret = mutex_lock_interruptible(&intel_dp->psr.lock);
if (ret)
return ret;
- old_mode = dev_priv->psr.debug & I915_PSR_DEBUG_MODE_MASK;
- dev_priv->psr.debug = val;
+ old_mode = intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK;
+ intel_dp->psr.debug = val;
/*
* Do it right away if it's already enabled, otherwise it will be done
* when enabling the source.
*/
- if (dev_priv->psr.enabled)
- psr_irq_control(dev_priv);
+ if (intel_dp->psr.enabled)
+ psr_irq_control(intel_dp);
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_unlock(&intel_dp->psr.lock);
if (old_mode != mode)
ret = intel_psr_fastset_force(dev_priv);
@@ -1636,28 +1657,28 @@ int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 val)
return ret;
}
-static void intel_psr_handle_irq(struct drm_i915_private *dev_priv)
+static void intel_psr_handle_irq(struct intel_dp *intel_dp)
{
- struct i915_psr *psr = &dev_priv->psr;
+ struct intel_psr *psr = &intel_dp->psr;
- intel_psr_disable_locked(psr->dp);
+ intel_psr_disable_locked(intel_dp);
psr->sink_not_reliable = true;
/* let's make sure that sink is awaken */
- drm_dp_dpcd_writeb(&psr->dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
+ drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0);
}
static void intel_psr_work(struct work_struct *work)
{
- struct drm_i915_private *dev_priv =
- container_of(work, typeof(*dev_priv), psr.work);
+ struct intel_dp *intel_dp =
+ container_of(work, typeof(*intel_dp), psr.work);
- mutex_lock(&dev_priv->psr.lock);
+ mutex_lock(&intel_dp->psr.lock);
- if (!dev_priv->psr.enabled)
+ if (!intel_dp->psr.enabled)
goto unlock;
- if (READ_ONCE(dev_priv->psr.irq_aux_error))
- intel_psr_handle_irq(dev_priv);
+ if (READ_ONCE(intel_dp->psr.irq_aux_error))
+ intel_psr_handle_irq(intel_dp);
/*
* We have to make sure PSR is ready for re-enable
@@ -1665,7 +1686,7 @@ static void intel_psr_work(struct work_struct *work)
* PSR might take some time to get fully disabled
* and be ready for re-enable.
*/
- if (!__psr_wait_for_idle_locked(dev_priv))
+ if (!__psr_wait_for_idle_locked(intel_dp))
goto unlock;
/*
@@ -1673,12 +1694,12 @@ static void intel_psr_work(struct work_struct *work)
* recheck. Since psr_flush first clears this and then reschedules we
* won't ever miss a flush when bailing out here.
*/
- if (dev_priv->psr.busy_frontbuffer_bits || dev_priv->psr.active)
+ if (intel_dp->psr.busy_frontbuffer_bits || intel_dp->psr.active)
goto unlock;
- intel_psr_activate(dev_priv->psr.dp);
+ intel_psr_activate(intel_dp);
unlock:
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_unlock(&intel_dp->psr.lock);
}
/**
@@ -1697,27 +1718,31 @@ unlock:
void intel_psr_invalidate(struct drm_i915_private *dev_priv,
unsigned frontbuffer_bits, enum fb_op_origin origin)
{
- if (!CAN_PSR(dev_priv))
- return;
+ struct intel_encoder *encoder;
if (origin == ORIGIN_FLIP)
return;
- mutex_lock(&dev_priv->psr.lock);
- if (!dev_priv->psr.enabled) {
- mutex_unlock(&dev_priv->psr.lock);
- return;
- }
+ for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) {
+ unsigned int pipe_frontbuffer_bits = frontbuffer_bits;
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(dev_priv->psr.pipe);
- dev_priv->psr.busy_frontbuffer_bits |= frontbuffer_bits;
+ mutex_lock(&intel_dp->psr.lock);
+ if (!intel_dp->psr.enabled) {
+ mutex_unlock(&intel_dp->psr.lock);
+ continue;
+ }
- if (frontbuffer_bits)
- intel_psr_exit(dev_priv);
+ pipe_frontbuffer_bits &=
+ INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe);
+ intel_dp->psr.busy_frontbuffer_bits |= pipe_frontbuffer_bits;
- mutex_unlock(&dev_priv->psr.lock);
-}
+ if (pipe_frontbuffer_bits)
+ intel_psr_exit(intel_dp);
+ mutex_unlock(&intel_dp->psr.lock);
+ }
+}
/*
* When we will be completely rely on PSR2 S/W tracking in future,
* intel_psr_flush() will invalidate and flush the PSR for ORIGIN_FLIP
@@ -1725,15 +1750,15 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv,
* accordingly in future.
*/
static void
-tgl_dc3co_flush(struct drm_i915_private *dev_priv,
- unsigned int frontbuffer_bits, enum fb_op_origin origin)
+tgl_dc3co_flush(struct intel_dp *intel_dp, unsigned int frontbuffer_bits,
+ enum fb_op_origin origin)
{
- mutex_lock(&dev_priv->psr.lock);
+ mutex_lock(&intel_dp->psr.lock);
- if (!dev_priv->psr.dc3co_enabled)
+ if (!intel_dp->psr.dc3co_enabled)
goto unlock;
- if (!dev_priv->psr.psr2_enabled || !dev_priv->psr.active)
+ if (!intel_dp->psr.psr2_enabled || !intel_dp->psr.active)
goto unlock;
/*
@@ -1741,15 +1766,15 @@ tgl_dc3co_flush(struct drm_i915_private *dev_priv,
* when delayed work schedules that means display has been idle.
*/
if (!(frontbuffer_bits &
- INTEL_FRONTBUFFER_ALL_MASK(dev_priv->psr.pipe)))
+ INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe)))
goto unlock;
- tgl_psr2_enable_dc3co(dev_priv);
- mod_delayed_work(system_wq, &dev_priv->psr.dc3co_work,
- dev_priv->psr.dc3co_exit_delay);
+ tgl_psr2_enable_dc3co(intel_dp);
+ mod_delayed_work(system_wq, &intel_dp->psr.dc3co_work,
+ intel_dp->psr.dc3co_exit_delay);
unlock:
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_unlock(&intel_dp->psr.lock);
}
/**
@@ -1768,47 +1793,73 @@ unlock:
void intel_psr_flush(struct drm_i915_private *dev_priv,
unsigned frontbuffer_bits, enum fb_op_origin origin)
{
- if (!CAN_PSR(dev_priv))
- return;
+ struct intel_encoder *encoder;
- if (origin == ORIGIN_FLIP) {
- tgl_dc3co_flush(dev_priv, frontbuffer_bits, origin);
- return;
- }
+ for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) {
+ unsigned int pipe_frontbuffer_bits = frontbuffer_bits;
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- mutex_lock(&dev_priv->psr.lock);
- if (!dev_priv->psr.enabled) {
- mutex_unlock(&dev_priv->psr.lock);
- return;
- }
+ if (origin == ORIGIN_FLIP) {
+ tgl_dc3co_flush(intel_dp, frontbuffer_bits, origin);
+ continue;
+ }
+
+ mutex_lock(&intel_dp->psr.lock);
+ if (!intel_dp->psr.enabled) {
+ mutex_unlock(&intel_dp->psr.lock);
+ continue;
+ }
- frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(dev_priv->psr.pipe);
- dev_priv->psr.busy_frontbuffer_bits &= ~frontbuffer_bits;
+ pipe_frontbuffer_bits &=
+ INTEL_FRONTBUFFER_ALL_MASK(intel_dp->psr.pipe);
+ intel_dp->psr.busy_frontbuffer_bits &= ~pipe_frontbuffer_bits;
- /* By definition flush = invalidate + flush */
- if (frontbuffer_bits)
- psr_force_hw_tracking_exit(dev_priv);
+ /* By definition flush = invalidate + flush */
+ if (pipe_frontbuffer_bits)
+ psr_force_hw_tracking_exit(intel_dp);
- if (!dev_priv->psr.active && !dev_priv->psr.busy_frontbuffer_bits)
- schedule_work(&dev_priv->psr.work);
- mutex_unlock(&dev_priv->psr.lock);
+ if (!intel_dp->psr.active && !intel_dp->psr.busy_frontbuffer_bits)
+ schedule_work(&intel_dp->psr.work);
+ mutex_unlock(&intel_dp->psr.lock);
+ }
}
/**
* intel_psr_init - Init basic PSR work and mutex.
- * @dev_priv: i915 device private
+ * @intel_dp: Intel DP
*
- * This function is called only once at driver load to initialize basic
- * PSR stuff.
+ * This function is called after the initializing connector.
+ * (the initializing of connector treats the handling of connector capabilities)
+ * And it initializes basic PSR stuff for each DP Encoder.
*/
-void intel_psr_init(struct drm_i915_private *dev_priv)
+void intel_psr_init(struct intel_dp *intel_dp)
{
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+ struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
if (!HAS_PSR(dev_priv))
return;
- if (!dev_priv->psr.sink_support)
+ if (!intel_dp->psr.sink_support)
return;
+ /*
+ * HSW spec explicitly says PSR is tied to port A.
+ * BDW+ platforms have a instance of PSR registers per transcoder but
+ * BDW, GEN9 and GEN11 are not validated by HW team in other transcoder
+ * than eDP one.
+ * For now it only supports one instance of PSR for BDW, GEN9 and GEN11.
+ * So lets keep it hardcoded to PORT_A for BDW, GEN9 and GEN11.
+ * But GEN12 supports a instance of PSR registers per transcoder.
+ */
+ if (INTEL_GEN(dev_priv) < 12 && dig_port->base.port != PORT_A) {
+ drm_dbg_kms(&dev_priv->drm,
+ "PSR condition failed: Port not supported\n");
+ return;
+ }
+
+ intel_dp->psr.source_support = true;
+
if (IS_HASWELL(dev_priv))
/*
* HSW don't have PSR registers on the same space as transcoder
@@ -1824,14 +1875,14 @@ void intel_psr_init(struct drm_i915_private *dev_priv)
/* Set link_standby x link_off defaults */
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
/* HSW and BDW require workarounds that we don't implement. */
- dev_priv->psr.link_standby = false;
+ intel_dp->psr.link_standby = false;
else if (INTEL_GEN(dev_priv) < 12)
/* For new platforms up to TGL let's respect VBT back again */
- dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link;
+ intel_dp->psr.link_standby = dev_priv->vbt.psr.full_link;
- INIT_WORK(&dev_priv->psr.work, intel_psr_work);
- INIT_DELAYED_WORK(&dev_priv->psr.dc3co_work, tgl_dc3co_disable_work);
- mutex_init(&dev_priv->psr.lock);
+ INIT_WORK(&intel_dp->psr.work, intel_psr_work);
+ INIT_DELAYED_WORK(&intel_dp->psr.dc3co_work, tgl_dc3co_disable_work);
+ mutex_init(&intel_dp->psr.lock);
}
static int psr_get_status_and_error_status(struct intel_dp *intel_dp,
@@ -1857,7 +1908,7 @@ static void psr_alpm_check(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct drm_dp_aux *aux = &intel_dp->aux;
- struct i915_psr *psr = &dev_priv->psr;
+ struct intel_psr *psr = &intel_dp->psr;
u8 val;
int r;
@@ -1884,7 +1935,7 @@ static void psr_alpm_check(struct intel_dp *intel_dp)
static void psr_capability_changed_check(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- struct i915_psr *psr = &dev_priv->psr;
+ struct intel_psr *psr = &intel_dp->psr;
u8 val;
int r;
@@ -1908,18 +1959,18 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp)
void intel_psr_short_pulse(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- struct i915_psr *psr = &dev_priv->psr;
+ struct intel_psr *psr = &intel_dp->psr;
u8 status, error_status;
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))
+ if (!CAN_PSR(intel_dp) || !intel_dp_is_edp(intel_dp))
return;
mutex_lock(&psr->lock);
- if (!psr->enabled || psr->dp != intel_dp)
+ if (!psr->enabled)
goto exit;
if (psr_get_status_and_error_status(intel_dp, &status, &error_status)) {
@@ -1962,15 +2013,14 @@ exit:
bool intel_psr_enabled(struct intel_dp *intel_dp)
{
- struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
bool ret;
- if (!CAN_PSR(dev_priv) || !intel_dp_is_edp(intel_dp))
+ if (!CAN_PSR(intel_dp) || !intel_dp_is_edp(intel_dp))
return false;
- mutex_lock(&dev_priv->psr.lock);
- ret = (dev_priv->psr.dp == intel_dp && dev_priv->psr.enabled);
- mutex_unlock(&dev_priv->psr.lock);
+ mutex_lock(&intel_dp->psr.lock);
+ ret = intel_dp->psr.enabled;
+ mutex_unlock(&intel_dp->psr.lock);
return ret;
}
diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h
index 0a517978e8af..0491a49ffd50 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.h
+++ b/drivers/gpu/drm/i915/display/intel_psr.h
@@ -18,7 +18,6 @@ struct intel_atomic_state;
struct intel_plane_state;
struct intel_plane;
-#define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support)
void intel_psr_init_dpcd(struct intel_dp *intel_dp);
void intel_psr_enable(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
@@ -28,20 +27,19 @@ void intel_psr_disable(struct intel_dp *intel_dp,
void intel_psr_update(struct intel_dp *intel_dp,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state);
-int intel_psr_debug_set(struct drm_i915_private *dev_priv, u64 value);
+int intel_psr_debug_set(struct intel_dp *intel_dp, u64 value);
void intel_psr_invalidate(struct drm_i915_private *dev_priv,
unsigned frontbuffer_bits,
enum fb_op_origin origin);
void intel_psr_flush(struct drm_i915_private *dev_priv,
unsigned frontbuffer_bits,
enum fb_op_origin origin);
-void intel_psr_init(struct drm_i915_private *dev_priv);
+void intel_psr_init(struct intel_dp *intel_dp);
void intel_psr_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state);
-void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir);
+void intel_psr_irq_handler(struct intel_dp *intel_dp, u32 psr_iir);
void intel_psr_short_pulse(struct intel_dp *intel_dp);
-int intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state,
- u32 *out_value);
+void intel_psr_wait_for_idle(const struct intel_crtc_state *new_crtc_state);
bool intel_psr_enabled(struct intel_dp *intel_dp);
int intel_psr2_sel_fetch_update(struct intel_atomic_state *state,
struct intel_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 402030251c64..26025251b038 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -96,7 +96,6 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
DEFINE_WAIT(wait);
- u32 psr_status;
if (new_crtc_state->uapi.async_flip)
return;
@@ -122,10 +121,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
* VBL interrupts will start the PSR exit and prevent a PSR
* re-entry as well.
*/
- if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
- drm_err(&dev_priv->drm,
- "PSR idle timed out 0x%x, atomic update may fail\n",
- psr_status);
+ intel_psr_wait_for_idle(new_crtc_state);
local_irq_disable();
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 60c52588d552..017208ff8df4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -475,42 +475,6 @@ struct i915_drrs {
enum drrs_support_type type;
};
-struct i915_psr {
- struct mutex lock;
-
-#define I915_PSR_DEBUG_MODE_MASK 0x0f
-#define I915_PSR_DEBUG_DEFAULT 0x00
-#define I915_PSR_DEBUG_DISABLE 0x01
-#define I915_PSR_DEBUG_ENABLE 0x02
-#define I915_PSR_DEBUG_FORCE_PSR1 0x03
-#define I915_PSR_DEBUG_IRQ 0x10
-
- u32 debug;
- bool sink_support;
- bool enabled;
- struct intel_dp *dp;
- enum pipe pipe;
- enum transcoder transcoder;
- bool active;
- struct work_struct work;
- unsigned busy_frontbuffer_bits;
- bool sink_psr2_support;
- bool link_standby;
- bool colorimetry_support;
- bool psr2_enabled;
- bool psr2_sel_fetch_enabled;
- u8 sink_sync_latency;
- ktime_t last_entry_attempt;
- ktime_t last_exit;
- bool sink_not_reliable;
- bool irq_aux_error;
- u16 su_x_granularity;
- bool dc3co_enabled;
- u32 dc3co_exit_delay;
- struct delayed_work dc3co_work;
- struct drm_dp_vsc_sdp vsc;
-};
-
#define QUIRK_LVDS_SSC_DISABLE (1<<1)
#define QUIRK_INVERT_BRIGHTNESS (1<<2)
#define QUIRK_BACKLIGHT_PRESENT (1<<3)
@@ -1038,8 +1002,6 @@ struct drm_i915_private {
struct i915_power_domains power_domains;
- struct i915_psr psr;
-
struct i915_gpu_error gpu_error;
struct drm_i915_gem_object *vlv_pctx;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9d47da8ec86d..374a65d05391 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2094,10 +2094,19 @@ static void ivb_display_irq_handler(struct drm_i915_private *dev_priv,
ivb_err_int_handler(dev_priv);
if (de_iir & DE_EDP_PSR_INT_HSW) {
- u32 psr_iir = intel_uncore_read(&dev_priv->uncore, EDP_PSR_IIR);
+ struct intel_encoder *encoder;
- intel_psr_irq_handler(dev_priv, psr_iir);
- intel_uncore_write(&dev_priv->uncore, EDP_PSR_IIR, psr_iir);
+ for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ u32 psr_iir = intel_uncore_read(&dev_priv->uncore,
+ EDP_PSR_IIR);
+
+ intel_psr_irq_handler(intel_dp, psr_iir);
+ intel_uncore_write(&dev_priv->uncore,
+ EDP_PSR_IIR, psr_iir);
+ break;
+ }
}
if (de_iir & DE_AUX_CHANNEL_A_IVB)
@@ -2310,21 +2319,30 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
}
if (iir & GEN8_DE_EDP_PSR) {
+ struct intel_encoder *encoder;
u32 psr_iir;
i915_reg_t iir_reg;
- if (INTEL_GEN(dev_priv) >= 12)
- iir_reg = TRANS_PSR_IIR(dev_priv->psr.transcoder);
- else
- iir_reg = EDP_PSR_IIR;
+ for_each_intel_encoder_can_psr(&dev_priv->drm, encoder) {
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
- psr_iir = intel_uncore_read(&dev_priv->uncore, iir_reg);
- intel_uncore_write(&dev_priv->uncore, iir_reg, psr_iir);
+ if (INTEL_GEN(dev_priv) >= 12)
+ iir_reg = TRANS_PSR_IIR(intel_dp->psr.transcoder);
+ else
+ iir_reg = EDP_PSR_IIR;
- if (psr_iir)
- found = true;
+ psr_iir = intel_uncore_read(&dev_priv->uncore, iir_reg);
+ intel_uncore_write(&dev_priv->uncore, iir_reg, psr_iir);
- intel_psr_irq_handler(dev_priv, psr_iir);
+ if (psr_iir)
+ found = true;
+
+ intel_psr_irq_handler(intel_dp, psr_iir);
+
+ /* prior GEN12 only have one EDP PSR */
+ if (INTEL_GEN(dev_priv) < 12)
+ break;
+ }
}
if (!found)