From 48a7374baa9887bab4ea87c878a40e2a692ff4fd Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Mon, 10 Jul 2023 15:52:00 +0800 Subject: [PATCH] usb: typec: tcpm: fix dp altmode negotiation failure Do DR_SWAP (UFP/Sink swap to DFP/Sink) when received VDM DiscIdentity NAK or terminated in VDM DiscModes to fix altmode negotiation failure. This can fix a few odd DP monitor (DFP/Source) can not start DR_SWAP to UFP/Source role at DP altmode negotiation stage. Signed-off-by: Frank Wang Signed-off-by: Zhang Yubing Change-Id: Ieae9489c068064a20e04151f322ac82a71a72aa4 --- drivers/usb/typec/tcpm/tcpm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index a088c6e91e37..141a14305335 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -1724,6 +1724,14 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, rlen = 1; } else if (port->data_role == TYPEC_HOST) { tcpm_register_partner_altmodes(port); + } else { + /* Do dr_swap for ufp if the port supports drd */ + if (port->typec_caps.data == TYPEC_PORT_DRD && + !IS_ERR_OR_NULL(port->port_altmode[0])) { + port->vdm_sm_running = false; + port->upcoming_state = DR_SWAP_SEND; + tcpm_ams_start(port, DATA_ROLE_SWAP); + } } break; case CMD_ENTER_MODE: @@ -1755,6 +1763,16 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, tcpm_ams_finish(port); switch (cmd) { case CMD_DISCOVER_IDENT: + /* Do dr_swap for ufp if the port supports drd */ + if (port->typec_caps.data == TYPEC_PORT_DRD && + port->data_role == TYPEC_DEVICE && + !IS_ERR_OR_NULL(port->port_altmode[0])) { + port->vdm_sm_running = false; + port->upcoming_state = DR_SWAP_SEND; + tcpm_ams_start(port, DATA_ROLE_SWAP); + break; + } + fallthrough; case CMD_DISCOVER_SVID: case CMD_DISCOVER_MODES: case VDO_CMD_VENDOR(0) ... VDO_CMD_VENDOR(15):