From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> The CRT HPD force trigger will generate a HPD irq. Let's ignore it since we're already doing the detect and there's no point in scheduling another one immediately. This is rather important on VLV since turning on the disp2d power well will trigger a CRT HPD and when processing it we'll do the force trigger. If we were to schedule another cycle of HPD processing due to the force trigger, we might end up in an infinite loop: turn on disp2d -> crt hpd -> run hpd work -> force trigger -> crt hpd -> turn off disp2d -> run hpd work -> turn on disp2d -> crt hpd -> ... Cc: Lyude <cpaul@xxxxxxxxxx> Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_crt.c | 6 ++++++ drivers/gpu/drm/i915/intel_hotplug.c | 27 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 85102ad75962..cd9e64c16d73 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2777,6 +2777,8 @@ void intel_hpd_init(struct drm_i915_private *dev_priv); void intel_hpd_init_work(struct drm_i915_private *dev_priv); void intel_hpd_cancel_work(struct drm_i915_private *dev_priv); bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port); +bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin); +void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin); /* i915_irq.c */ void i915_queue_hangcheck(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index d10dea5bd08a..e8597d77cf6d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -282,6 +282,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) /* The first time through, trigger an explicit detection cycle */ if (crt->force_hotplug_required) { bool turn_off_dac = HAS_PCH_SPLIT(dev); + bool enable_hpd; u32 save_adpa; crt->force_hotplug_required = 0; @@ -289,6 +290,8 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) save_adpa = adpa = I915_READ(crt->adpa_reg); DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); + enable_hpd = intel_hpd_disable(dev_priv, crt->base.hpd_pin); + adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; if (turn_off_dac) adpa &= ~ADPA_DAC_ENABLE; @@ -303,6 +306,9 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) I915_WRITE(crt->adpa_reg, save_adpa); POSTING_READ(crt->adpa_reg); } + + if (enable_hpd) + intel_hpd_enable(dev_priv, crt->base.hpd_pin); } /* Check the status to see if both blue and green are on now */ diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index bee673005d48..0c9ee3fe4c1f 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -511,3 +511,30 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) cancel_work_sync(&dev_priv->hotplug.hotplug_work); cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work); } + +bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin) +{ + bool ret = false; + + if (pin == HPD_NONE) + return false; + + spin_lock_irq(&dev_priv->irq_lock); + if (dev_priv->hotplug.stats[pin].state == HPD_ENABLED) { + dev_priv->hotplug.stats[pin].state = HPD_DISABLED; + ret = true; + } + spin_unlock_irq(&dev_priv->irq_lock); + + return ret; +} + +void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin) +{ + if (pin == HPD_NONE) + return; + + spin_lock_irq(&dev_priv->irq_lock); + dev_priv->hotplug.stats[pin].state = HPD_ENABLED; + spin_unlock_irq(&dev_priv->irq_lock); +} -- 2.7.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx