Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: qcom-qmp-combo: Introduce drm_bridge

The QMP combo PHY sits in an of_graph connected between the DisplayPort
controller and a USB Type-C connector (or possibly a redriver).

The TCPM needs to be able to convey the HPD signal to the DisplayPort
controller, but no directly link is provided by DeviceTree so the signal
needs to "pass through" the QMP combo phy.

Handle this by introducing a drm_bridge which upon initialization finds
the next bridge (i.e. the usb-c-connector) and chain this together. This
way HPD changes in the connector will propagate to the DisplayPort
driver.

The connector bridge is resolved lazily, as the TCPM is expected to be
able to resolve the typec mux and switch at probe time, so the QMP combo
phy will probe before the TCPM.

Acked-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: Abel Vesa <abel.vesa@linaro.org>
Tested-by: Steev Klimaszewski <steev@kali.org>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on HDK8450
Tested-by: Johan Hovold <johan+linaro@kernel.org> # X13s
Reviewed-by: Johan Hovold <johan+linaro@kernel.org>
Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com>
Link: https://lore.kernel.org/r/20230515032743.400170-7-quic_bjorande@quicinc.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Bjorn Andersson and committed by
Vinod Koul
1904c3f5 2851117f

+48
+2
drivers/phy/qualcomm/Kconfig
··· 60 60 tristate "Qualcomm QMP Combo PHY Driver" 61 61 default PHY_QCOM_QMP 62 62 depends on TYPEC || TYPEC=n 63 + depends on DRM || DRM=n 63 64 select GENERIC_PHY 64 65 select MFD_SYSCON 66 + select DRM_PANEL_BRIDGE if DRM 65 67 help 66 68 Enable this to support the QMP Combo PHY transceiver that is used 67 69 with USB3 and DisplayPort controllers on Qualcomm chips.
+46
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
··· 22 22 #include <linux/usb/typec.h> 23 23 #include <linux/usb/typec_mux.h> 24 24 25 + #include <drm/drm_bridge.h> 26 + 25 27 #include <dt-bindings/phy/phy-qcom-qmp.h> 26 28 27 29 #include "phy-qcom-qmp.h" ··· 1333 1331 struct clk_fixed_rate pipe_clk_fixed; 1334 1332 struct clk_hw dp_link_hw; 1335 1333 struct clk_hw dp_pixel_hw; 1334 + 1335 + struct drm_bridge bridge; 1336 1336 1337 1337 struct typec_switch_dev *sw; 1338 1338 enum typec_orientation orientation; ··· 3278 3274 } 3279 3275 #endif 3280 3276 3277 + #if IS_ENABLED(CONFIG_DRM) 3278 + static int qmp_combo_bridge_attach(struct drm_bridge *bridge, 3279 + enum drm_bridge_attach_flags flags) 3280 + { 3281 + struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); 3282 + struct drm_bridge *next_bridge; 3283 + 3284 + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 3285 + return -EINVAL; 3286 + 3287 + next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); 3288 + if (IS_ERR(next_bridge)) { 3289 + dev_err(qmp->dev, "failed to acquire drm_bridge: %pe\n", next_bridge); 3290 + return PTR_ERR(next_bridge); 3291 + } 3292 + 3293 + return drm_bridge_attach(bridge->encoder, next_bridge, bridge, 3294 + DRM_BRIDGE_ATTACH_NO_CONNECTOR); 3295 + } 3296 + 3297 + static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { 3298 + .attach = qmp_combo_bridge_attach, 3299 + }; 3300 + 3301 + static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) 3302 + { 3303 + qmp->bridge.funcs = &qmp_combo_bridge_funcs; 3304 + qmp->bridge.of_node = qmp->dev->of_node; 3305 + 3306 + return devm_drm_bridge_add(qmp->dev, &qmp->bridge); 3307 + } 3308 + #else 3309 + static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) 3310 + { 3311 + return 0; 3312 + } 3313 + #endif 3314 + 3281 3315 static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) 3282 3316 { 3283 3317 struct device *dev = qmp->dev; ··· 3517 3475 return ret; 3518 3476 3519 3477 ret = qmp_combo_typec_switch_register(qmp); 3478 + if (ret) 3479 + return ret; 3480 + 3481 + ret = qmp_combo_dp_register_bridge(qmp); 3520 3482 if (ret) 3521 3483 return ret; 3522 3484