]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/display: bridge_connector: Ensure last bridge determines EDID/modes detection...
authorDamon Ding <damon.ding@rock-chips.com>
Wed, 17 Dec 2025 09:33:04 +0000 (17:33 +0800)
committerLuca Ceresoli <luca.ceresoli@bootlin.com>
Tue, 3 Feb 2026 11:43:04 +0000 (12:43 +0100)
When multiple bridges are present, EDID detection capability
(DRM_BRIDGE_OP_EDID) takes precedence over modes detection
(DRM_BRIDGE_OP_MODES). To ensure the above two capabilities are
determined by the last bridge in the chain, we handle three cases:

Case 1: The later bridge declares only DRM_BRIDGE_OP_MODES
 - If the previous bridge declares DRM_BRIDGE_OP_EDID, set
   &drm_bridge_connector.bridge_edid to NULL and set
   &drm_bridge_connector.bridge_modes to the later bridge.
 - Ensure modes detection capability of the later bridge will not
   be ignored.

Case 2: The later bridge declares only DRM_BRIDGE_OP_EDID
 - If the previous bridge declares DRM_BRIDGE_OP_MODES, set
   &drm_bridge_connector.bridge_modes to NULL and set
   &drm_bridge_connector.bridge_edid to the later bridge.
 - Although EDID detection capability has higher priority, this
   operation is for balance and makes sense.

Case 3: the later bridge declares both of them
 - Assign later bridge as &drm_bridge_connector.bridge_edid and
   and &drm_bridge_connector.bridge_modes to this bridge.
 - Just leave transfer of these two capabilities as before.

Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Tested-by: Heiko Stuebner <heiko@sntech.de> (on rk3588)
Link: https://patch.msgid.link/20251217093321.3108939-2-damon.ding@rock-chips.com
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
drivers/gpu/drm/display/drm_bridge_connector.c

index ba8ff113cff12e3e1cc7f4102e5b9dba090d6616..d49ccf28d2b2ba1d1f0e326f0fe095d4c033dbc5 100644 (file)
@@ -826,9 +826,19 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
                if (!bridge->ycbcr_420_allowed)
                        connector->ycbcr_420_allowed = false;
 
-               if (bridge->ops & DRM_BRIDGE_OP_EDID) {
+               /*
+                * Ensure the last bridge declares OP_EDID or OP_MODES or both.
+                */
+               if (bridge->ops & DRM_BRIDGE_OP_EDID || bridge->ops & DRM_BRIDGE_OP_MODES) {
                        drm_bridge_put(bridge_connector->bridge_edid);
-                       bridge_connector->bridge_edid = drm_bridge_get(bridge);
+                       bridge_connector->bridge_edid = NULL;
+                       drm_bridge_put(bridge_connector->bridge_modes);
+                       bridge_connector->bridge_modes = NULL;
+
+                       if (bridge->ops & DRM_BRIDGE_OP_EDID)
+                               bridge_connector->bridge_edid = drm_bridge_get(bridge);
+                       if (bridge->ops & DRM_BRIDGE_OP_MODES)
+                               bridge_connector->bridge_modes = drm_bridge_get(bridge);
                }
                if (bridge->ops & DRM_BRIDGE_OP_HPD) {
                        drm_bridge_put(bridge_connector->bridge_hpd);
@@ -838,10 +848,6 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
                        drm_bridge_put(bridge_connector->bridge_detect);
                        bridge_connector->bridge_detect = drm_bridge_get(bridge);
                }
-               if (bridge->ops & DRM_BRIDGE_OP_MODES) {
-                       drm_bridge_put(bridge_connector->bridge_modes);
-                       bridge_connector->bridge_modes = drm_bridge_get(bridge);
-               }
                if (bridge->ops & DRM_BRIDGE_OP_HDMI) {
                        if (bridge_connector->bridge_hdmi)
                                return ERR_PTR(-EBUSY);