[PATCH 4/9] drm/i915: Add support to identify the SCDC Interrupt from IIR

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


This patch identifies the SCDC Interrupt and schedules the bottomhalf
by adding scdc work function in the system work queue.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 28 ++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_hdmi.h |  1 +
 drivers/gpu/drm/i915/i915_irq.c           | 32 +++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 1aa5bdc7b0dc..bbbc2b63aa62 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -3213,3 +3213,31 @@ intel_hdmi_dsc_get_bpp(int src_fractional_bpp, int slice_width, int num_slices,
 
 	return 0;
 }
+
+enum scdc_pin intel_hdmi_get_scdc_pin(struct intel_encoder *encoder)
+{
+	switch (encoder->hpd_pin) {
+	case HPD_PORT_A:
+		return SCDC_PORT_A;
+	case HPD_PORT_B:
+		return SCDC_PORT_B;
+	case HPD_PORT_C:
+		return SCDC_PORT_C;
+	case HPD_PORT_TC1:
+		return SCDC_PORT_TC1;
+	case HPD_PORT_TC2:
+		return SCDC_PORT_TC2;
+	case HPD_PORT_TC3:
+		return SCDC_PORT_TC3;
+	case HPD_PORT_TC4:
+		return SCDC_PORT_TC4;
+	case HPD_PORT_TC5:
+		return SCDC_PORT_TC5;
+	case HPD_PORT_TC6:
+		return SCDC_PORT_TC6;
+	default:
+		break;
+	}
+
+	return SCDC_PORT_NONE;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 93f65a917c36..49da11b30632 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -54,5 +54,6 @@ int intel_hdmi_dsc_get_num_slices(const struct intel_crtc_state *crtc_state,
 				  int src_max_slices, int src_max_slice_width,
 				  int hdmi_max_slices, int hdmi_throughput);
 int intel_hdmi_dsc_get_slice_height(int vactive);
+enum scdc_pin intel_hdmi_get_scdc_pin(struct intel_encoder *encoder);
 
 #endif /* __INTEL_HDMI_H__ */
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 4dc2542146cd..dad32edab874 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -40,6 +40,7 @@
 #include "display/intel_display_types.h"
 #include "display/intel_fifo_underrun.h"
 #include "display/intel_hotplug.h"
+#include "display/intel_hdmi.h"
 #include "display/intel_lpe_audio.h"
 #include "display/intel_psr.h"
 
@@ -1993,6 +1994,34 @@ static void cpt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
 		cpt_serr_int_handler(dev_priv);
 }
 
+static void scdc_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
+{
+	struct intel_encoder *encoder;
+	enum scdc_pin pin;
+	bool scdc_interrupt = false;
+
+	/*
+	 * Identify the port on which scdc interrupt received
+	 * #TODO Check if spin lock be used here before this loop to avoid
+	 * race condition for event_bits?
+	 */
+	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 (pch_iir & dev_priv->scdc_rr.scdc[pin] ||
+		    pch_iir & dev_priv->scdc_rr.scdc[pin]) {
+			dev_priv->scdc_rr.event_bits |= pin;
+			scdc_interrupt = true;
+			break;
+		}
+	}
+	if (scdc_interrupt)
+		queue_work(system_wq, &dev_priv->scdc_rr.scdc_rr_work);
+}
+
 static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
 {
 	u32 ddi_hotplug_trigger = pch_iir & SDE_DDI_HOTPLUG_MASK_ICP;
@@ -2028,6 +2057,9 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
 
 	if (pch_iir & SDE_GMBUS_ICP)
 		gmbus_irq_handler(dev_priv);
+
+	if (pch_iir & SDE_DDI_SCDC_MASK_ICP || pch_iir & SDE_TC_SCDC_MASK_ICP)
+		scdc_irq_handler(dev_priv, pch_iir);
 }
 
 static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
-- 
2.25.1



More information about the Intel-gfx-trybot mailing list