The EDID helpers probe DDC before consulting debugfs or firmware
overrides. This preserves connector-detection semantics for drivers that
use a successful DDC probe as presence evidence, but it prevents drivers
with independent presence detection from using an override when DDC is
unresponsive.

Add an optional connector callback that replaces drm_probe_ddc() in
drm_get_edid() and drm_edid_read_ddc(). Drivers can report presence using
their own reliable detection while retaining the unified override and
firmware EDID handling in DRM core.

Signed-off-by: Mario Limonciello <[email protected]>
---
Cc: Curtis Vogt <[email protected]>
 drivers/gpu/drm/drm_edid.c  | 15 +++++++++++++--
 include/drm/drm_connector.h | 17 +++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 3148038747b6e..c0e73ead308d3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2643,6 +2643,15 @@ drm_probe_ddc(struct i2c_adapter *adapter)
 }
 EXPORT_SYMBOL(drm_probe_ddc);
 
+static bool drm_connector_probe_ddc(struct drm_connector *connector,
+                                   struct i2c_adapter *adapter)
+{
+       if (connector->funcs->probe_ddc)
+               return connector->funcs->probe_ddc(connector);
+
+       return drm_probe_ddc(adapter);
+}
+
 /**
  * drm_get_edid - get EDID data, if available
  * @connector: connector we're probing
@@ -2661,7 +2670,8 @@ struct edid *drm_get_edid(struct drm_connector *connector,
        if (connector->force == DRM_FORCE_OFF)
                return NULL;
 
-       if (connector->force == DRM_FORCE_UNSPECIFIED && 
!drm_probe_ddc(adapter))
+       if (connector->force == DRM_FORCE_UNSPECIFIED &&
+           !drm_connector_probe_ddc(connector, adapter))
                return NULL;
 
        edid = _drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter, 
NULL);
@@ -2742,7 +2752,8 @@ const struct drm_edid *drm_edid_read_ddc(struct 
drm_connector *connector,
        if (connector->force == DRM_FORCE_OFF)
                return NULL;
 
-       if (connector->force == DRM_FORCE_UNSPECIFIED && 
!drm_probe_ddc(adapter))
+       if (connector->force == DRM_FORCE_UNSPECIFIED &&
+           !drm_connector_probe_ddc(connector, adapter))
                return NULL;
 
        drm_edid = drm_edid_read_custom(connector, drm_do_probe_ddc_edid, 
adapter);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 2ee7c59329aae..185cefe6e292f 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1640,6 +1640,23 @@ struct drm_connector_hdmi_funcs {
  * etc.
  */
 struct drm_connector_funcs {
+       /**
+        * @probe_ddc:
+        *
+        * Optional connector-specific replacement for drm_probe_ddc(). Drivers
+        * may use this to report connector presence when they have a reliable
+        * detection method other than probing the DDC bus.
+        *
+        * This callback is used by drm_get_edid() and drm_edid_read_ddc() 
before
+        * retrieving an override or reading the EDID. If it is not implemented,
+        * the helpers fall back to drm_probe_ddc().
+        *
+        * RETURNS:
+        *
+        * True if a sink is connected, false otherwise.
+        */
+       bool (*probe_ddc)(struct drm_connector *connector);
+
        /**
         * @dpms:
         *
-- 
2.43.0

Reply via email to