[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