[Intel-gfx] [PATCH 2/3] drm/i915: Disable CRT HPD around force trigger

ville.syrjala at linux.intel.com ville.syrjala at linux.intel.com
Mon Apr 18 16:03:24 UTC 2016


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

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 at redhat.com>
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 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



More information about the Intel-gfx mailing list