[PATCH v2 6/9] drm/i915/gmbus: Set SCDC_RR interrupt during GPIO xfers

Ankit Nautiyal ankit.k.nautiyal at intel.com
Mon Mar 7 09:03:16 UTC 2022


Disable/Enable SCDC_RR pre and post GPIO xfer.

This patch:
-Adds new field in intel_gmbus structure to store SCDC port
-Initializes the new field, based on if SCDC_RR is supported.
-Sets the SCDC_RR pre/post GPIO xfers for the SCDC port.

Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
 drivers/gpu/drm/i915/display/intel_gmbus.c | 38 ++++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_gmbus.h |  2 ++
 drivers/gpu/drm/i915/display/intel_hdmi.c  | 11 +++++++
 3 files changed, 51 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index 2bb3494b93e2..3f375d9906d0 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -43,6 +43,7 @@ struct intel_gmbus {
 #define GMBUS_FORCE_BIT_RETRY (1U << 31)
 	u32 force_bit;
 	u32 reg0;
+	enum scdc_pin scdc_port;
 	i915_reg_t gpio_reg;
 	struct i2c_algo_bit_data bit_algo;
 	struct drm_i915_private *dev_priv;
@@ -297,6 +298,27 @@ static void set_data(void *data, int state_high)
 	intel_uncore_posting_read(uncore, bus->gpio_reg);
 }
 
+static void
+set_scdc(struct drm_i915_private *dev_priv, enum scdc_pin pin, bool enable)
+{
+	u32 scdc_bit;
+
+	if (pin == SCDC_PORT_NONE)
+		return;
+
+	if (DISPLAY_VER(dev_priv) < 11)
+		return;
+
+	scdc_bit = dev_priv->scdc_rr.scdc[pin];
+
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (enable)
+		ibx_disable_display_interrupt(dev_priv, scdc_bit);
+	else
+		ibx_disable_display_interrupt(dev_priv, scdc_bit);
+	spin_unlock_irq(&dev_priv->irq_lock);
+}
+
 static int
 intel_gpio_pre_xfer(struct i2c_adapter *adapter)
 {
@@ -307,6 +329,8 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
 
 	intel_gmbus_reset(dev_priv);
 
+	set_scdc(dev_priv, bus->scdc_port, false);
+
 	if (IS_PINEVIEW(dev_priv))
 		pnv_gmbus_clock_gating(dev_priv, false);
 
@@ -327,6 +351,8 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter)
 	set_data(bus, 1);
 	set_clock(bus, 1);
 
+	set_scdc(dev_priv, bus->scdc_port, true);
+
 	if (IS_PINEVIEW(dev_priv))
 		pnv_gmbus_clock_gating(dev_priv, true);
 }
@@ -992,3 +1018,15 @@ void intel_gmbus_teardown(struct drm_i915_private *dev_priv)
 		dev_priv->gmbus[pin] = NULL;
 	}
 }
+
+void intel_gmbus_set_scdc_port(struct i2c_adapter *adapter, enum scdc_pin port)
+{
+	struct intel_gmbus *bus = to_intel_gmbus(adapter);
+	struct drm_i915_private *dev_priv = bus->dev_priv;
+
+	mutex_lock(&dev_priv->gmbus_mutex);
+
+	bus->scdc_port = port;
+
+	mutex_unlock(&dev_priv->gmbus_mutex);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.h b/drivers/gpu/drm/i915/display/intel_gmbus.h
index 8edc2e99cf53..40744c84ac7c 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.h
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.h
@@ -10,6 +10,7 @@
 
 struct drm_i915_private;
 struct i2c_adapter;
+enum scdc_pin;
 
 #define GMBUS_PIN_DISABLED	0
 #define GMBUS_PIN_SSC		1
@@ -44,5 +45,6 @@ intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
 void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
 bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter);
 void intel_gmbus_reset(struct drm_i915_private *dev_priv);
+void intel_gmbus_set_scdc_port(struct i2c_adapter *adapter, enum scdc_pin port);
 
 #endif /* __INTEL_GMBUS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 36d4d086d8e7..5f73c8bff5c0 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2323,6 +2323,9 @@ static void
 intel_hdmi_unset_edid(struct drm_connector *connector)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(to_intel_connector(connector));
+	struct drm_i915_private *dev_priv = to_i915(connector->dev);
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
 
 	intel_hdmi->has_hdmi_sink = false;
 	intel_hdmi->has_audio = false;
@@ -2332,6 +2335,7 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
 
 	kfree(to_intel_connector(connector)->detect_edid);
 	to_intel_connector(connector)->detect_edid = NULL;
+	intel_gmbus_set_scdc_port(adapter, SCDC_NUM_PINS);
 }
 
 static void
@@ -2417,6 +2421,13 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 
 	intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
 
+	if (connector->display_info.hdmi.scdc.read_request) {
+		struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
+		enum scdc_pin scdc = intel_hdmi_get_scdc_pin(encoder);
+
+		intel_gmbus_set_scdc_port(i2c, scdc);
+	}
+
 	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
 	to_intel_connector(connector)->detect_edid = edid;
-- 
2.25.1



More information about the Intel-gfx-trybot mailing list