Skip to content

Commit cc7588e

Browse files
superna9999yijiyang
authored andcommitted
BACKPORT: phy: qcom: qmp-combo: register a typec mux to change the QMPPHY_MODE
Register a typec mux in order to change the PHY mode on the Type-C mux events depending on the mode and the svid when in Altmode setup. The DisplayPort phy should be left enabled if is still powered on by the DRM DisplayPort controller, so bail out until the DisplayPort PHY is not powered off. The Type-C Mode/SVID only changes on plug/unplug, and USB SAFE states will be set in between of USB-Only, Combo and DisplayPort Only so this will leave enough time to the DRM DisplayPort controller to turn of the DisplayPort PHY. Signed-off-by: Neil Armstrong <[email protected]> [konrad: renaming, rewording, bug fixes] Signed-off-by: Konrad Dybcio <[email protected]> Reviewed-by: Dmitry Baryshkov <[email protected]> Tested-by: Neil Armstrong <[email protected]> # on Lenovo Thinkpad T14S Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]> Signed-off-by: Yijie Yang <[email protected]>
1 parent 6a5a4a6 commit cc7588e

File tree

1 file changed

+113
-5
lines changed

1 file changed

+113
-5
lines changed

drivers/phy/qualcomm/phy-qcom-qmp-combo.c

Lines changed: 113 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/reset.h>
2020
#include <linux/slab.h>
2121
#include <linux/usb/typec.h>
22+
#include <linux/usb/typec_dp.h>
2223
#include <linux/usb/typec_mux.h>
2324

2425
#include <drm/bridge/aux-bridge.h>
@@ -1709,6 +1710,8 @@ struct qmp_combo {
17091710

17101711
struct typec_switch_dev *sw;
17111712
enum typec_orientation orientation;
1713+
1714+
struct typec_mux_dev *mux;
17121715
};
17131716

17141717
static void qmp_v3_dp_aux_init(struct qmp_combo *qmp);
@@ -3582,17 +3585,109 @@ static int qmp_combo_typec_switch_set(struct typec_switch_dev *sw,
35823585
return 0;
35833586
}
35843587

3585-
static void qmp_combo_typec_unregister(void *data)
3588+
static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
3589+
{
3590+
struct qmp_combo *qmp = typec_mux_get_drvdata(mux);
3591+
const struct qmp_phy_cfg *cfg = qmp->cfg;
3592+
enum qmpphy_mode new_mode;
3593+
unsigned int svid;
3594+
3595+
guard(mutex)(&qmp->phy_mutex);
3596+
3597+
if (state->alt)
3598+
svid = state->alt->svid;
3599+
else
3600+
svid = 0;
3601+
3602+
if (svid == USB_TYPEC_DP_SID) {
3603+
switch (state->mode) {
3604+
/* DP Only */
3605+
case TYPEC_DP_STATE_C:
3606+
case TYPEC_DP_STATE_E:
3607+
new_mode = QMPPHY_MODE_DP_ONLY;
3608+
break;
3609+
3610+
/* DP + USB */
3611+
case TYPEC_DP_STATE_D:
3612+
case TYPEC_DP_STATE_F:
3613+
3614+
/* Safe fallback...*/
3615+
default:
3616+
new_mode = QMPPHY_MODE_USB3DP;
3617+
break;
3618+
}
3619+
} else {
3620+
/* No DP SVID => don't care, assume it's just USB3 */
3621+
new_mode = QMPPHY_MODE_USB3_ONLY;
3622+
}
3623+
3624+
if (new_mode == qmp->qmpphy_mode) {
3625+
dev_dbg(qmp->dev, "typec_mux_set: same qmpphy mode, bail out\n");
3626+
return 0;
3627+
}
3628+
3629+
if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && qmp->dp_powered_on) {
3630+
dev_dbg(qmp->dev, "typec_mux_set: DP PHY is still in use, delaying switch\n");
3631+
return 0;
3632+
}
3633+
3634+
dev_dbg(qmp->dev, "typec_mux_set: switching from qmpphy mode %d to %d\n",
3635+
qmp->qmpphy_mode, new_mode);
3636+
3637+
qmp->qmpphy_mode = new_mode;
3638+
3639+
if (qmp->init_count) {
3640+
if (qmp->usb_init_count)
3641+
qmp_combo_usb_power_off(qmp->usb_phy);
3642+
3643+
if (qmp->dp_init_count)
3644+
writel(DP_PHY_PD_CTL_PSR_PWRDN, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
3645+
3646+
qmp_combo_com_exit(qmp, true);
3647+
3648+
/* Now everything's powered down, power up the right PHYs */
3649+
qmp_combo_com_init(qmp, true);
3650+
3651+
if (new_mode == QMPPHY_MODE_DP_ONLY) {
3652+
if (qmp->usb_init_count)
3653+
qmp->usb_init_count--;
3654+
}
3655+
3656+
if (new_mode == QMPPHY_MODE_USB3DP || new_mode == QMPPHY_MODE_USB3_ONLY) {
3657+
qmp_combo_usb_power_on(qmp->usb_phy);
3658+
if (!qmp->usb_init_count)
3659+
qmp->usb_init_count++;
3660+
}
3661+
3662+
if (new_mode == QMPPHY_MODE_DP_ONLY || new_mode == QMPPHY_MODE_USB3DP) {
3663+
if (qmp->dp_init_count)
3664+
cfg->dp_aux_init(qmp);
3665+
}
3666+
}
3667+
3668+
return 0;
3669+
}
3670+
3671+
static void qmp_combo_typec_switch_unregister(void *data)
35863672
{
35873673
struct qmp_combo *qmp = data;
35883674

35893675
typec_switch_unregister(qmp->sw);
35903676
}
35913677

3592-
static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
3678+
static void qmp_combo_typec_mux_unregister(void *data)
3679+
{
3680+
struct qmp_combo *qmp = data;
3681+
3682+
typec_mux_unregister(qmp->mux);
3683+
}
3684+
3685+
static int qmp_combo_typec_register(struct qmp_combo *qmp)
35933686
{
35943687
struct typec_switch_desc sw_desc = {};
3688+
struct typec_mux_desc mux_desc = { };
35953689
struct device *dev = qmp->dev;
3690+
int ret;
35963691

35973692
sw_desc.drvdata = qmp;
35983693
sw_desc.fwnode = dev->fwnode;
@@ -3603,10 +3698,23 @@ static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
36033698
return PTR_ERR(qmp->sw);
36043699
}
36053700

3606-
return devm_add_action_or_reset(dev, qmp_combo_typec_unregister, qmp);
3701+
ret = devm_add_action_or_reset(dev, qmp_combo_typec_switch_unregister, qmp);
3702+
if (ret)
3703+
return ret;
3704+
3705+
mux_desc.drvdata = qmp;
3706+
mux_desc.fwnode = dev->fwnode;
3707+
mux_desc.set = qmp_combo_typec_mux_set;
3708+
qmp->mux = typec_mux_register(dev, &mux_desc);
3709+
if (IS_ERR(qmp->mux)) {
3710+
dev_err(dev, "Unable to register typec mux: %pe\n", qmp->mux);
3711+
return PTR_ERR(qmp->mux);
3712+
}
3713+
3714+
return devm_add_action_or_reset(dev, qmp_combo_typec_mux_unregister, qmp);
36073715
}
36083716
#else
3609-
static int qmp_combo_typec_switch_register(struct qmp_combo *qmp)
3717+
static int qmp_combo_typec_register(struct qmp_combo *qmp)
36103718
{
36113719
return 0;
36123720
}
@@ -3839,7 +3947,7 @@ static int qmp_combo_probe(struct platform_device *pdev)
38393947
if (ret)
38403948
goto err_node_put;
38413949

3842-
ret = qmp_combo_typec_switch_register(qmp);
3950+
ret = qmp_combo_typec_register(qmp);
38433951
if (ret)
38443952
goto err_node_put;
38453953

0 commit comments

Comments
 (0)