[PATCH v4 03/10] drm/bridge: synopsys: dw-dp: Add follow-up bridge support

From: Sebastian Reichel

Date: Tue Jul 21 2026 - 15:08:01 EST


Add support to use USB-C connectors with the DP altmode helper code on
devicetree based platforms. To get this working there must be a DRM
bridge chain from the DisplayPort controller to the USB-C connector.
E.g. on Rockchip RK3576:

root@rk3576 # cat /sys/kernel/debug/dri/0/encoder-0/bridges
bridge[0]: dw_dp_bridge_funcs
refcount: 7
type: [10] DP
OF: /soc/dp@27e40000:rockchip,rk3576-dp
ops: [0x47] detect edid hpd
bridge[1]: drm_aux_bridge_funcs
refcount: 4
type: [0] Unknown
OF: /soc/phy@2b010000:rockchip,rk3576-usbdp-phy
ops: [0x0]
bridge[2]: drm_aux_hpd_bridge_funcs
refcount: 5
type: [10] DP
OF: /soc/i2c@2ac50000/typec-portc@22/connector:usb-c-connector
ops: [0x4] hpd

It's fine to fatally error out when there is no follow-up bridge
as the Rockchip Designware Displayport controller is the only
user of the bridge helper and has the port marked as required
in its binding.

Signed-off-by: Sebastian Reichel <sebastian.reichel@xxxxxxxxxxxxx>
---
drivers/gpu/drm/bridge/synopsys/dw-dp.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
index aca6816febe6..0e8ecd73a000 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
@@ -329,6 +329,8 @@ struct dw_dp {
struct dw_dp_plat_data plat_data;
u8 pixel_mode;

+ struct drm_bridge *next_bridge;
+
DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
};

@@ -1988,18 +1990,35 @@ int dw_dp_bind(struct dw_dp *dp, struct drm_encoder *encoder)
goto unregister_aux;
}

+ dp->next_bridge = of_drm_get_bridge_by_endpoint(dev->of_node, 1, 0);
+ if (IS_ERR(dp->next_bridge)) {
+ ret = PTR_ERR(dp->next_bridge);
+ dev_err_probe(dev, ret, "failed to get follow-up bridge.\n");
+ goto unregister_aux;
+ }
+
+ ret = drm_bridge_attach(encoder, dp->next_bridge, bridge,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to attach next bridge\n");
+ goto put_next_bridge;
+ }
+
dw_dp_init_hw(dp);

ret = phy_init(dp->phy);
if (ret) {
dev_err_probe(dev, ret, "phy init failed\n");
- goto unregister_aux;
+ goto put_next_bridge;
}

enable_irq(dp->irq);

return 0;

+put_next_bridge:
+ drm_bridge_put(dp->next_bridge);
+
unregister_aux:
drm_dp_aux_unregister(&dp->aux);

@@ -2014,6 +2033,7 @@ void dw_dp_unbind(struct dw_dp *dp)
{
disable_irq(dp->irq);
phy_exit(dp->phy);
+ drm_bridge_put(dp->next_bridge);
drm_dp_aux_unregister(&dp->aux);
drm_bridge_remove(&dp->bridge);
}

--
2.53.0