[PATCH 05/11] drm/i915: Enable SCDC RR Interrupt in the IER

Ankit Nautiyal ankit.k.nautiyal at intel.com
Wed Mar 9 06:47:36 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 7a11f2224662..4b5b8f674bef 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9757,6 +9757,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)
 {
@@ -9787,6 +9814,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 0e8bc9c3d112..2c0354f092a2 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