[PATCH 5/9] drm/i915: Enable SCDC RR Interrupt in the IER

Ankit Nautiyal ankit.k.nautiyal at intel.com
Mon Mar 7 05:39:01 UTC 2022


This patch enables the SCDC RR Interrupt in Interrupt Enable Register.
After this, any SCDC interrupt from sink will be seen in IIR and can
be appropriately be handled.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 29 ++++++++++
 drivers/gpu/drm/i915/i915_irq.c              | 59 ++++++++++++++++++++
 2 files changed, 88 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 80b19c304c43..98ce2615454c 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9614,6 +9614,33 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
 	return 0;
 }
 
+static void intel_scdc_init(struct drm_i915_private *i915)
+{
+	struct intel_connector *connector;
+	struct intel_encoder *encoder;
+	enum scdc_pin pin;
+
+	if (!HAS_DISPLAY(i915))
+		return;
+
+	for_each_intel_encoder(&i915->drm, encoder) {
+		if (encoder->type != INTEL_OUTPUT_HDMI)
+			continue;
+		pin = intel_hdmi_get_scdc_pin(encoder);
+		if (pin == SCDC_PORT_NONE)
+			continue;
+		for_each_connector_on_encoder(&i915->drm, &encoder->base, connector) {
+			if (connector->base.display_info.hdmi.scdc.read_request)
+				i915->scdc_rr.stats[pin].state = SCDC_ENABLED;
+			break;
+		}
+	}
+
+	spin_lock_irq(&i915->irq_lock);
+	intel_scdc_irq_setup(i915);
+	spin_unlock_irq(&i915->irq_lock);
+}
+
 /* part #3: call after gem init */
 int intel_modeset_init(struct drm_i915_private *i915)
 {
@@ -9644,6 +9671,8 @@ int intel_modeset_init(struct drm_i915_private *i915)
 
 	intel_init_ipc(i915);
 
+	intel_scdc_init(i915);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index dad32edab874..b66c19ab9a66 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3448,10 +3448,69 @@ static void icp_hpd_irq_setup(struct drm_i915_private *dev_priv)
 	icp_tc_hpd_detection_setup(dev_priv);
 }
 
+static u32 intel_scdc_irqs(struct drm_i915_private *dev_priv)
+{
+	struct intel_encoder *encoder;
+	u32 scdc_irqs = 0;
+	enum scdc_pin pin;
+
+	for_each_intel_encoder(&dev_priv->drm, encoder) {
+		if (encoder->type != INTEL_OUTPUT_HDMI)
+			continue;
+		pin = intel_hdmi_get_scdc_pin(encoder);
+		if (pin == SCDC_PORT_NONE)
+			return 0;
+
+		scdc_irqs |= dev_priv->scdc_rr.scdc[pin];
+	}
+
+	return scdc_irqs;
+}
+
+static u32 intel_scdc_enabled_irqs(struct drm_i915_private *dev_priv)
+{
+	struct intel_encoder *encoder;
+	u32 enabled_irqs = 0;
+	enum scdc_pin pin;
+
+	for_each_intel_encoder(&dev_priv->drm, encoder) {
+		if (encoder->type != INTEL_OUTPUT_HDMI)
+			continue;
+		pin = intel_hdmi_get_scdc_pin(encoder);
+		if (pin == SCDC_PORT_NONE)
+			continue;
+
+		if (dev_priv->scdc_rr.stats[pin].state == SCDC_ENABLED)
+			enabled_irqs |= dev_priv->scdc_rr.scdc[pin];
+	}
+
+	return enabled_irqs;
+}
+
+static void icp_scdc_detection_setup(struct drm_i915_private *dev_priv)
+{
+	u32 scdc;
+
+	scdc = intel_uncore_read(&dev_priv->uncore, SDEIER);
+	scdc &= ~(SDE_DDI_SCDC_MASK_ICP | SDE_TC_SCDC_MASK_ICP);
+	scdc |= intel_scdc_irqs(dev_priv);
+	intel_uncore_write(&dev_priv->uncore, SDEIER, scdc);
+}
+
 static void icp_scdc_irq_setup(struct drm_i915_private *dev_priv)
 {
+	u32 scdc_irqs, enabled_irqs;
+
 	if (DISPLAY_VER(dev_priv) < 11)
 		return;
+
+	enabled_irqs = intel_scdc_enabled_irqs(dev_priv);
+	scdc_irqs = intel_scdc_irqs(dev_priv);
+
+	icp_scdc_detection_setup(dev_priv);
+
+	/* Clear interrupt IMR to unmasked (0) for this interrupt*/
+	ibx_display_interrupt_update(dev_priv, scdc_irqs, enabled_irqs);
 }
 
 static u32 gen11_hotplug_enables(struct drm_i915_private *i915,
-- 
2.25.1



More information about the Intel-gfx-trybot mailing list