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 <[email protected]> Suggested-by: Dmitry Baryshkov <[email protected]> --- .../gpu/drm/display/drm_bridge_connector.c | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index baacd21e7341..0ca6f140e85b 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -640,6 +640,7 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, struct drm_connector *connector; struct i2c_adapter *ddc = NULL; struct drm_bridge *bridge, *panel_bridge = NULL; + struct drm_bridge *pre_bridge_edid, *pre_bridge_modes; unsigned int supported_formats = BIT(HDMI_COLORSPACE_RGB); unsigned int max_bpc = 8; bool support_hdcp = false; @@ -668,6 +669,9 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, */ connector_type = DRM_MODE_CONNECTOR_Unknown; drm_for_each_bridge_in_chain(encoder, bridge) { + pre_bridge_edid = bridge_connector->bridge_edid; + pre_bridge_modes = bridge_connector->bridge_modes; + if (!bridge->interlace_allowed) connector->interlace_allowed = false; if (!bridge->ycbcr_420_allowed) @@ -681,6 +685,44 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, bridge_connector->bridge_detect = bridge; if (bridge->ops & DRM_BRIDGE_OP_MODES) bridge_connector->bridge_modes = bridge; + + /* + * 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 &drm_bridge_connector.bridge_modes to this bridge. + * - Just leave transfer of these two capabilities as before. + */ + if (bridge->ops & DRM_BRIDGE_OP_EDID && + !(bridge->ops & DRM_BRIDGE_OP_MODES)) { + if (pre_bridge_modes) + bridge_connector->bridge_modes = NULL; + } + if (bridge->ops & DRM_BRIDGE_OP_MODES && + !(bridge->ops & DRM_BRIDGE_OP_EDID)) { + if (pre_bridge_edid) + bridge_connector->bridge_edid = NULL; + } + if (bridge->ops & DRM_BRIDGE_OP_HDMI) { if (bridge_connector->bridge_hdmi) return ERR_PTR(-EBUSY); -- 2.34.1
