[PATCH v14 11/38] phy: rockchip: usbdp: Support single-lane DP
Sebastian Reichel <[email protected]>
| Newsgroups | org.kernel.vger.linux-usb,org.infradead.lists.linux-arm-kernel,org.infradead.lists.linux-phy,org.infradead.lists.linux-rockchip,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260813-rockchip-usbdp-cleanup-v14-11-b5ad9c68fa11@collabora.com> |
From: Zhang Yubing <[email protected]> Implement support for using just a single DisplayPort line. Signed-off-by: Zhang Yubing <[email protected]> Tested-by: Igor Paunovic <[email protected]> # Orange Pi 5 Plus Signed-off-by: Sebastian Reichel <[email protected]> --- drivers/phy/rockchip/phy-rockchip-usbdp.c | 64 +++++++++++++------------------ 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c index 7540c897dde1..c4d62b234ea8 100644 --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c @@ -193,6 +193,7 @@ struct rk_udphy { int id; bool dp_in_use; + int dp_lanes; /* PHY const config */ const struct rk_udphy_cfg *cfgs; @@ -535,6 +536,13 @@ static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable) * <0 1> dpln0 dpln1 usbrx usbtx * <2 3> usbrx usbtx dpln0 dpln1 * --------------------------------------------------------------------------- + * if 1 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = <x>; + * sample as follow: + * --------------------------------------------------------------------------- + * B11-B10 A2-A3 A11-A10 B2-B3 + * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) + * <0> dpln0 \ usbrx usbtx + * --------------------------------------------------------------------------- */ static void rk_udphy_dplane_select(struct rk_udphy *udphy) @@ -542,18 +550,18 @@ static void rk_udphy_dplane_select(struct rk_udphy *udphy) const struct rk_udphy_cfg *cfg = udphy->cfgs; u32 value = 0; - switch (udphy->mode) { - case UDPHY_MODE_DP: - value |= 2 << udphy->dp_lane_sel[2] * 2; + switch (udphy->dp_lanes) { + case 4: value |= 3 << udphy->dp_lane_sel[3] * 2; + value |= 2 << udphy->dp_lane_sel[2] * 2; fallthrough; - case UDPHY_MODE_DP_USB: - value |= 0 << udphy->dp_lane_sel[0] * 2; + case 2: value |= 1 << udphy->dp_lane_sel[1] * 2; - break; + fallthrough; - case UDPHY_MODE_USB: + case 1: + value |= 0 << udphy->dp_lane_sel[0] * 2; break; default: @@ -566,28 +574,6 @@ static void rk_udphy_dplane_select(struct rk_udphy *udphy) FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); } -static int rk_udphy_dplane_get(struct rk_udphy *udphy) -{ - int dp_lanes; - - switch (udphy->mode) { - case UDPHY_MODE_DP: - dp_lanes = 4; - break; - - case UDPHY_MODE_DP_USB: - dp_lanes = 2; - break; - - case UDPHY_MODE_USB: - default: - dp_lanes = 0; - break; - } - - return dp_lanes; -} - static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes) { u32 val = 0; @@ -657,6 +643,7 @@ static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy) } rk_udphy_mode_set(udphy, UDPHY_MODE_DP_USB); + udphy->dp_lanes = 2; } static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw, @@ -895,7 +882,7 @@ static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy) return 0; } - if (num_lanes != 2 && num_lanes != 4) + if (num_lanes != 1 && num_lanes != 2 && num_lanes != 4) return dev_err_probe(udphy->dev, -EINVAL, "invalid number of lane mux\n"); @@ -921,9 +908,11 @@ static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy) } udphy->mode = UDPHY_MODE_DP; - if (num_lanes == 2) { + udphy->dp_lanes = num_lanes; + if (num_lanes == 1 || num_lanes == 2) { udphy->mode |= UDPHY_MODE_USB; - udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP); + udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP) || + (udphy->lane_mux_sel[1] == PHY_LANE_MUX_DP); } return 0; @@ -1050,18 +1039,17 @@ static int rk_udphy_dp_phy_exit(struct phy *phy) static int rk_udphy_dp_phy_power_on(struct phy *phy) { struct rk_udphy *udphy = phy_get_drvdata(phy); - int ret, dp_lanes; + int ret; mutex_lock(&udphy->mutex); - dp_lanes = rk_udphy_dplane_get(udphy); - phy_set_bus_width(phy, dp_lanes); + phy_set_bus_width(phy, udphy->dp_lanes); ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP); if (ret) goto unlock; - rk_udphy_dplane_enable(udphy, dp_lanes); + rk_udphy_dplane_enable(udphy, udphy->dp_lanes); rk_udphy_dplane_select(udphy); @@ -1341,6 +1329,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux, udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; mode = UDPHY_MODE_DP; + udphy->dp_lanes = 4; break; case TYPEC_DP_STATE_D: @@ -1357,6 +1346,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux, udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; } mode = UDPHY_MODE_DP_USB; + udphy->dp_lanes = 2; break; } @@ -1501,7 +1491,7 @@ static int rk_udphy_probe(struct platform_device *pdev) ret = PTR_ERR(udphy->phy_dp); return dev_err_probe(dev, ret, "failed to create DP phy\n"); } - phy_set_bus_width(udphy->phy_dp, rk_udphy_dplane_get(udphy)); + phy_set_bus_width(udphy->phy_dp, udphy->dp_lanes); udphy->phy_dp->attrs.max_link_rate = 8100; phy_set_drvdata(udphy->phy_dp, udphy); -- 2.53.0