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@xxxxxxxxx> --- 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 99b7f1d..71911b9 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4892,6 +4892,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) { /* @@ -4900,8 +4902,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 e3794d3..95242e6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1411,6 +1411,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 213581c..e5ae844 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -741,6 +741,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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx