On DisplayPort and eDP connectors DDC is tunneled over the AUX channel,
but amdgpu_dm registers the physical i2c bus ("AMDGPU DM i2c hw bus N")
as the connector's ddc adapter.  The "ddc" sysfs symlink therefore points
at a bus that does not reach the sink, while the AUX backed adapter
("AMDGPU DM aux hw bus N"), which is registered as a child of the
connector, does.  Userspace such as fwupd, which uses the "ddc" link for
DDC/CI, has to work around this.

Pass the AUX ddc adapter to drm_connector_init_with_ddc() for DP and eDP
connectors.  The adapter is registered in late_register, before the core
creates the "ddc" link, so the link resolves correctly.  Other connector
types keep using the physical i2c bus.

Reported-by: [email protected]
Closes: https://github.com/fwupd/fwupd/pull/11308
Signed-off-by: Mario Limonciello <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c   | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index b498fc5fbb140..656249dc3f69b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -3483,6 +3483,7 @@ int amdgpu_dm_connector_init(struct 
amdgpu_display_manager *dm,
        struct dc *dc = dm->dc;
        struct dc_link *link = dc_get_link_at_index(dc, link_index);
        struct amdgpu_i2c_adapter *i2c;
+       struct i2c_adapter *ddc;
 
        /* Not needed for writeback connector */
        link->priv = aconnector;
@@ -3504,12 +3505,24 @@ int amdgpu_dm_connector_init(struct 
amdgpu_display_manager *dm,
 
        connector_type = to_drm_connector_type(link->connector_signal, 
link->link_id.id);
 
+       /*
+        * On DisplayPort DDC is tunneled over the AUX channel, so expose the
+        * AUX backed i2c adapter (registered in late_register) as the
+        * connector's "ddc" sysfs link.  The physical i2c bus doesn't reach
+        * the sink.
+        */
+       if (connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+           connector_type == DRM_MODE_CONNECTOR_eDP)
+               ddc = &aconnector->dm_dp_aux.aux.ddc;
+       else
+               ddc = &i2c->base;
+
        res = drm_connector_init_with_ddc(
                        dm->ddev,
                        &aconnector->base,
                        &amdgpu_dm_connector_funcs,
                        connector_type,
-                       &i2c->base);
+                       ddc);
 
        if (res) {
                drm_err(adev_to_drm(dm->adev), "connector_init failed\n");

---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261102-superm1-amdgpu-ddc-63f0eb10c022

Best regards,
--  
Mario Limonciello <[email protected]>

Reply via email to