]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
soc: qcom: pmic_glink_altmode: Fix TBT->SAFE->!TBT transition
authorKonrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Tue, 17 Mar 2026 14:14:40 +0000 (15:14 +0100)
committerBjorn Andersson <andersson@kernel.org>
Thu, 19 Mar 2026 02:51:11 +0000 (21:51 -0500)
Similar to the case of commit d48708500610 ("soc: qcom:
pmic_glink_altmode: Fix SVID=DP && unconnected edge case"), leaving the
TBT altmode makes pmic_glink_altmode report a SVID=TBT && mux_ctrl=0
message.

Said commit reordered the check such that the SVID is processed before
checking for NO_CONN. Rework this to take into account valid values of
mux_ctrl first and hopefully solve this for good..

Fixes: d48708500610 ("soc: qcom: pmic_glink_altmode: Fix SVID=DP && unconnected edge case")
Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260317-topic-tbt_pg_fixup-v1-1-325b8647bc82@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
drivers/soc/qcom/pmic_glink_altmode.c

index b496b88842a27ec79eafd52382a140a46634d252..619bad2c27eeb36bb0237a67dfc6522ce9497bf6 100644 (file)
@@ -62,6 +62,9 @@ struct usbc_notify {
        u8 orientation;
        u8 mux_ctrl;
 #define MUX_CTRL_STATE_NO_CONN                 0
+#define MUX_CTRL_STATE_USB3_ONLY               1
+#define MUX_CTRL_STATE_DP4LN                   2
+#define MUX_CTRL_STATE_USB3_DP                 3
 #define MUX_CTRL_STATE_TUNNELING               4
 
        u8 res;
@@ -350,9 +353,12 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
 
        typec_switch_set(alt_port->typec_switch, alt_port->orientation);
 
-       if (alt_port->svid == USB_TYPEC_TBT_SID) {
-               pmic_glink_altmode_enable_tbt(altmode, alt_port);
-       } else if (alt_port->svid == USB_TYPEC_DP_SID) {
+       /*
+        * MUX_CTRL_STATE_DP4LN/USB3_DP may only be set if SVID=DP, but we need
+        * to special-case the SVID=DP && mux_ctrl=NO_CONN case to deliver a
+        * HPD notification
+        */
+       if (alt_port->svid == USB_TYPEC_DP_SID) {
                if (alt_port->mux_ctrl == MUX_CTRL_STATE_NO_CONN) {
                        pmic_glink_altmode_safe(altmode, alt_port);
                } else {
@@ -369,11 +375,18 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
 
                drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status);
        } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_TUNNELING) {
-               pmic_glink_altmode_enable_usb4(altmode, alt_port);
+               if (alt_port->svid == USB_TYPEC_TBT_SID)
+                       pmic_glink_altmode_enable_tbt(altmode, alt_port);
+               else
+                       pmic_glink_altmode_enable_usb4(altmode, alt_port);
+       } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_USB3_ONLY) {
+               pmic_glink_altmode_enable_usb(altmode, alt_port);
        } else if (alt_port->mux_ctrl == MUX_CTRL_STATE_NO_CONN) {
                pmic_glink_altmode_safe(altmode, alt_port);
        } else {
-               pmic_glink_altmode_enable_usb(altmode, alt_port);
+               dev_err(altmode->dev, "Got unknown mux_ctrl: %u on port %u, forcing safe mode\n",
+                       alt_port->mux_ctrl, alt_port->index);
+               pmic_glink_altmode_safe(altmode, alt_port);
        }
 
        pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, alt_port->index);