[Intel-gfx] [PATCH 18/31] drm/i915: Force PSR exit when IRQ_HPD is detected on eDP.
Rodrigo Vivi
rodrigo.vivi at intel.com
Thu Nov 5 10:50:10 PST 2015
According to VESA spec: "If a Source device receives and IRQ_HPD
while in a PSR active state, and cannot identify what caused the
IRQ_HPD to be generated, based on Sink device status registers,
the Source device can take implementation-specific action.
One such action can be to exit and then re-enter a PSR active
state."
Since we aren't checking for any sink status registers and we
aren't looking for any other implementation-specific action,
in case we receive any IRQ_HPD and psr is active let's force
the exit and reschedule it back.
Signed-off-by: Rodrigo Vivi <rodrigo.vivi at intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 5 ++++-
drivers/gpu/drm/i915/intel_drv.h | 1 +
drivers/gpu/drm/i915/intel_psr.c | 33 +++++++++++++++++++++++++++++++++
3 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a421c17..4feb47e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4851,6 +4851,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
+ else
+ intel_psr_irq_hpd(dev);
if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
/*
@@ -4859,8 +4861,9 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
* would end up in an endless cycle of
* "vdd off -> long hpd -> vdd on -> detect -> vdd off -> ..."
*/
- DRM_DEBUG_KMS("ignoring long hpd on eDP port %c\n",
+ DRM_DEBUG_KMS("long hpd on eDP port %c\n",
port_name(intel_dig_port->port));
+
return IRQ_HANDLED;
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 76e0805..baa560c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1418,6 +1418,7 @@ void intel_psr_flush(struct drm_device *dev,
void intel_psr_init(struct drm_device *dev);
void intel_psr_single_frame_update(struct drm_device *dev,
unsigned frontbuffer_bits);
+void intel_psr_irq_hpd(struct drm_device *dev);
/* intel_runtime_pm.c */
int intel_power_domains_init(struct drm_i915_private *);
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 4ca682a..c49c6bd 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -764,6 +764,39 @@ void intel_psr_flush(struct drm_device *dev,
}
/**
+ * intel_psr_irq_hpd - Let PSR aware of IRQ_HPD
+ * @dev: DRM device
+ *
+ * This function is called when IRQ_HPD is received on eDP.
+ */
+void intel_psr_irq_hpd(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int delay_ms = HAS_DDI(dev) ? 100 : 500;
+
+ mutex_lock(&dev_priv->psr.lock);
+
+ /*
+ * According to VESA spec "If a Source device receives and IRQ_HPD
+ * while in a PSR active state, and cannot identify what caused the
+ * IRQ_HPD to be generated, based on Sink device status registers,
+ * the Source device can take implementation-specific action.
+ * One such action can be to exit and then re-enter a PSR active
+ * state." Since we aren't checking for any sink status registers
+ * and we aren't looking for any other implementation-specific
+ * action, in case we receive any IRQ_HPD and psr is active let's
+ * force the exit and reschedule it back.
+ */
+ if (dev_priv->psr.active) {
+ intel_psr_exit(dev);
+ schedule_delayed_work(&dev_priv->psr.work,
+ msecs_to_jiffies(delay_ms));
+ }
+
+ mutex_unlock(&dev_priv->psr.lock);
+}
+
+/**
* intel_psr_init - Init basic PSR work and mutex.
* @dev: DRM device
*
--
2.4.3
More information about the Intel-gfx
mailing list