diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 45330e0f66fe4..67a45d95250d6 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -60,8 +60,10 @@ config PHY_QCOM_QMP_COMBO tristate "Qualcomm QMP Combo PHY Driver" default PHY_QCOM_QMP depends on TYPEC || TYPEC=n + depends on DRM || DRM=n select GENERIC_PHY select MFD_SYSCON + select DRM_PANEL_BRIDGE if DRM help Enable this to support the QMP Combo PHY transceiver that is used with USB3 and DisplayPort controllers on Qualcomm chips. diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index d1300696d3e18..33cc99d9c77dd 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -22,6 +22,8 @@ #include #include +#include + #include #include "phy-qcom-qmp.h" @@ -1332,6 +1334,8 @@ struct qmp_combo { struct clk_hw dp_link_hw; struct clk_hw dp_pixel_hw; + struct drm_bridge bridge; + struct typec_switch_dev *sw; enum typec_orientation orientation; }; @@ -3274,6 +3278,44 @@ static int qmp_combo_typec_switch_register(struct qmp_combo *qmp) } #endif +#if IS_ENABLED(CONFIG_DRM) +static int qmp_combo_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); + struct drm_bridge *next_bridge; + + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) + return -EINVAL; + + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); + if (IS_ERR(next_bridge)) { + dev_err(qmp->dev, "failed to acquire drm_bridge: %pe\n", next_bridge); + return PTR_ERR(next_bridge); + } + + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); +} + +static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { + .attach = qmp_combo_bridge_attach, +}; + +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) +{ + qmp->bridge.funcs = &qmp_combo_bridge_funcs; + qmp->bridge.of_node = qmp->dev->of_node; + + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); +} +#else +static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) +{ + return 0; +} +#endif + static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) { struct device *dev = qmp->dev; @@ -3478,6 +3520,10 @@ static int qmp_combo_probe(struct platform_device *pdev) if (ret) return ret; + ret = qmp_combo_dp_register_bridge(qmp); + if (ret) + return ret; + /* Check for legacy binding with child nodes. */ usb_np = of_get_child_by_name(dev->of_node, "usb3-phy"); if (usb_np) {