[Intel-gfx] [PATCH 7/7] drm/i915: Disable HPD for disabled eDP ports

ville.syrjala at linux.intel.com ville.syrjala at linux.intel.com
Fri Jan 9 04:21:18 PST 2015


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

My BSW likes to generate tons of HPD interrupts while the eDP port is
disabled. I guess it leaves the HPD like floating and then stuff like
CPU activity can cause noise on the line leading to tons of spurious
interrupts.

To combat this, disable the relevant HPD interrupt whenever the port is
disabled. We don't need need HPDs on disabled eDP ports anyway since the
display can't physically disappear.

Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c  | 38 ++++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_dp.c  | 18 +++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h |  3 +++
 3 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c482903..6041d82 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -4165,7 +4165,8 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
 	I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
 }
 
-static void intel_hpd_irq_setup(struct drm_device *dev)
+static void intel_hpd_irq_setup(struct drm_device *dev,
+				bool force)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_mode_config *mode_config = &dev->mode_config;
@@ -4189,7 +4190,15 @@ static void intel_hpd_irq_setup(struct drm_device *dev)
 		if (hpd_pin == HPD_NONE)
 			continue;
 
-		polled = intel_connector->polled;
+		/*
+		 * If hpd storm detection switched to
+		 * polling don't change back unless forced.
+		 */
+		if (!force && connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
+						   DRM_CONNECTOR_POLL_DISCONNECT))
+			polled = connector->polled;
+		else
+			polled = intel_connector->polled;
 
 		if (connector->polled != polled)
 			DRM_DEBUG_KMS("%sabling HPD on connector %s (pin %d)\n",
@@ -4205,6 +4214,27 @@ static void intel_hpd_irq_setup(struct drm_device *dev)
 		dev_priv->display.hpd_irq_setup(dev);
 }
 
+void intel_connector_hpd_enable(struct intel_connector *intel_connector,
+				bool enable)
+{
+	struct drm_device *dev = intel_connector->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	spin_lock_irq(&dev_priv->irq_lock);
+
+	if (enable && intel_connector->polled == 0)
+		intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
+	else if (!enable && intel_connector->polled == DRM_CONNECTOR_POLL_HPD)
+		intel_connector->polled = 0;
+	else
+		goto out;
+
+	intel_hpd_irq_setup(dev, false);
+
+ out:
+	spin_unlock_irq(&dev_priv->irq_lock);
+}
+
 static irqreturn_t i965_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = arg;
@@ -4337,7 +4367,7 @@ static void intel_hpd_irq_reenable_work(struct work_struct *work)
 	intel_runtime_pm_get(dev_priv);
 
 	spin_lock_irq(&dev_priv->irq_lock);
-	intel_hpd_irq_setup(dev);
+	intel_hpd_irq_setup(dev, true);
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	intel_runtime_pm_put(dev_priv);
@@ -4477,7 +4507,7 @@ void intel_hpd_init(struct drm_i915_private *dev_priv)
 	for (hpd_pin = 1; hpd_pin < HPD_NUM_PINS; hpd_pin++)
 		dev_priv->hpd_stats[hpd_pin].hpd_cnt = 0;
 
-	intel_hpd_irq_setup(dev);
+	intel_hpd_irq_setup(dev, true);
 
 	spin_unlock_irq(&dev_priv->irq_lock);
 }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4d6af4c..b53a6f0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2102,6 +2102,10 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 	struct drm_device *dev = encoder->base.dev;
 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 
+	if (is_edp(intel_dp))
+		intel_connector_hpd_enable(intel_dp->attached_connector,
+					   false);
+
 	if (crtc->config.has_audio)
 		intel_audio_codec_disable(encoder);
 
@@ -2307,6 +2311,10 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	if (IS_VALLEYVIEW(dev))
 		vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp));
 
+	if (is_edp(intel_dp))
+		intel_connector_hpd_enable(intel_dp->attached_connector,
+					   true);
+
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_start_link_train(intel_dp);
 	intel_dp_complete_link_train(intel_dp);
@@ -4373,6 +4381,7 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
 
 static void intel_dp_encoder_reset(struct drm_encoder *encoder)
 {
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct intel_dp *intel_dp;
 
 	if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
@@ -4392,6 +4401,11 @@ static void intel_dp_encoder_reset(struct drm_encoder *encoder)
 	intel_edp_panel_vdd_sanitize(intel_dp);
 
 	pps_unlock(intel_dp);
+
+	/* enable HPD for eDP only if the port is currently enabled */
+	if (I915_READ(intel_dp->output_reg) & DP_PORT_EN)
+		intel_dp->attached_connector->polled = DRM_CONNECTOR_POLL_HPD;
+
 }
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
@@ -5072,7 +5086,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		BUG();
 	}
 
-	intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
+	/* enable HPD for eDP only if the port is currently enabled */
+	if (!is_edp(intel_dp) || intel_dp->DP & DP_PORT_EN)
+		intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
 
 	if (is_edp(intel_dp)) {
 		pps_lock(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bb871f3..bb72c46 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -809,6 +809,9 @@ static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv)
 
 int intel_get_crtc_scanline(struct intel_crtc *crtc);
 void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv);
+void intel_connector_hpd_enable(struct intel_connector *intel_connector,
+				bool enable);
+
 
 /* intel_crt.c */
 void intel_crt_init(struct drm_device *dev);
-- 
2.0.5



More information about the Intel-gfx mailing list