@@ -1556,7 +1556,7 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
1556
1556
}
1557
1557
1558
1558
static void tcpm_queue_vdm_unlocked (struct tcpm_port * port , const u32 header ,
1559
- const u32 * data , int cnt )
1559
+ const u32 * data , int cnt , enum tcpm_transmit_type tx_sop_type )
1560
1560
{
1561
1561
mutex_lock (& port -> lock );
1562
1562
tcpm_queue_vdm (port , header , data , cnt , TCPC_TX_SOP );
@@ -2144,14 +2144,28 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
2144
2144
}
2145
2145
break ;
2146
2146
case CMD_ENTER_MODE :
2147
- if (adev && pdev )
2148
- * adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL ;
2147
+ * response_tx_sop_type = rx_sop_type ;
2148
+ if (rx_sop_type == TCPC_TX_SOP ) {
2149
+ if (adev && pdev ) {
2150
+ typec_altmode_update_active (pdev , true);
2151
+ * adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL ;
2152
+ }
2153
+ } else if (rx_sop_type == TCPC_TX_SOP_PRIME ) {
2154
+ if (adev && pdev_prime ) {
2155
+ typec_altmode_update_active (pdev_prime , true);
2156
+ * adev_action = ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL ;
2157
+ }
2158
+ }
2149
2159
return 0 ;
2150
2160
case CMD_EXIT_MODE :
2151
- if (adev && pdev ) {
2152
- /* Back to USB Operation */
2153
- * adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM ;
2154
- return 0 ;
2161
+ * response_tx_sop_type = rx_sop_type ;
2162
+ if (rx_sop_type == TCPC_TX_SOP ) {
2163
+ if (adev && pdev ) {
2164
+ typec_altmode_update_active (pdev , false);
2165
+ /* Back to USB Operation */
2166
+ * adev_action = ADEV_NOTIFY_USB_AND_QUEUE_VDM ;
2167
+ return 0 ;
2168
+ }
2155
2169
}
2156
2170
break ;
2157
2171
case VDO_CMD_VENDOR (0 ) ... VDO_CMD_VENDOR (15 ):
@@ -2284,19 +2298,37 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
2284
2298
typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt );
2285
2299
break ;
2286
2300
case ADEV_QUEUE_VDM :
2287
- typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt );
2301
+ if (response_tx_sop_type == TCPC_TX_SOP_PRIME )
2302
+ typec_cable_altmode_vdm (adev , TYPEC_PLUG_SOP_P , p [0 ], & p [1 ], cnt );
2303
+ else
2304
+ typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt );
2288
2305
break ;
2289
2306
case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL :
2290
- if (typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt )) {
2291
- int svdm_version = typec_get_negotiated_svdm_version (
2292
- port -> typec_port );
2293
- if (svdm_version < 0 )
2294
- break ;
2307
+ if (response_tx_sop_type == TCPC_TX_SOP_PRIME ) {
2308
+ if (typec_cable_altmode_vdm (adev , TYPEC_PLUG_SOP_P ,
2309
+ p [0 ], & p [1 ], cnt )) {
2310
+ int svdm_version = typec_get_cable_svdm_version (
2311
+ port -> typec_port );
2312
+ if (svdm_version < 0 )
2313
+ break ;
2295
2314
2296
- response [0 ] = VDO (adev -> svid , 1 , svdm_version ,
2297
- CMD_EXIT_MODE );
2298
- response [0 ] |= VDO_OPOS (adev -> mode );
2299
- rlen = 1 ;
2315
+ response [0 ] = VDO (adev -> svid , 1 , svdm_version ,
2316
+ CMD_EXIT_MODE );
2317
+ response [0 ] |= VDO_OPOS (adev -> mode );
2318
+ rlen = 1 ;
2319
+ }
2320
+ } else {
2321
+ if (typec_altmode_vdm (adev , p [0 ], & p [1 ], cnt )) {
2322
+ int svdm_version = typec_get_negotiated_svdm_version (
2323
+ port -> typec_port );
2324
+ if (svdm_version < 0 )
2325
+ break ;
2326
+
2327
+ response [0 ] = VDO (adev -> svid , 1 , svdm_version ,
2328
+ CMD_EXIT_MODE );
2329
+ response [0 ] |= VDO_OPOS (adev -> mode );
2330
+ rlen = 1 ;
2331
+ }
2300
2332
}
2301
2333
break ;
2302
2334
case ADEV_ATTENTION :
@@ -2731,7 +2763,7 @@ static int tcpm_altmode_enter(struct typec_altmode *altmode, u32 *vdo)
2731
2763
header = VDO (altmode -> svid , vdo ? 2 : 1 , svdm_version , CMD_ENTER_MODE );
2732
2764
header |= VDO_OPOS (altmode -> mode );
2733
2765
2734
- tcpm_queue_vdm_unlocked (port , header , vdo , vdo ? 1 : 0 );
2766
+ tcpm_queue_vdm_unlocked (port , header , vdo , vdo ? 1 : 0 , TCPC_TX_SOP );
2735
2767
return 0 ;
2736
2768
}
2737
2769
@@ -2748,7 +2780,7 @@ static int tcpm_altmode_exit(struct typec_altmode *altmode)
2748
2780
header = VDO (altmode -> svid , 1 , svdm_version , CMD_EXIT_MODE );
2749
2781
header |= VDO_OPOS (altmode -> mode );
2750
2782
2751
- tcpm_queue_vdm_unlocked (port , header , NULL , 0 );
2783
+ tcpm_queue_vdm_unlocked (port , header , NULL , 0 , TCPC_TX_SOP );
2752
2784
return 0 ;
2753
2785
}
2754
2786
@@ -2757,7 +2789,7 @@ static int tcpm_altmode_vdm(struct typec_altmode *altmode,
2757
2789
{
2758
2790
struct tcpm_port * port = typec_altmode_get_drvdata (altmode );
2759
2791
2760
- tcpm_queue_vdm_unlocked (port , header , data , count - 1 );
2792
+ tcpm_queue_vdm_unlocked (port , header , data , count - 1 , TCPC_TX_SOP );
2761
2793
2762
2794
return 0 ;
2763
2795
}
@@ -2768,6 +2800,58 @@ static const struct typec_altmode_ops tcpm_altmode_ops = {
2768
2800
.vdm = tcpm_altmode_vdm ,
2769
2801
};
2770
2802
2803
+
2804
+ static int tcpm_cable_altmode_enter (struct typec_altmode * altmode , enum typec_plug_index sop ,
2805
+ u32 * vdo )
2806
+ {
2807
+ struct tcpm_port * port = typec_altmode_get_drvdata (altmode );
2808
+ int svdm_version ;
2809
+ u32 header ;
2810
+
2811
+ svdm_version = typec_get_cable_svdm_version (port -> typec_port );
2812
+ if (svdm_version < 0 )
2813
+ return svdm_version ;
2814
+
2815
+ header = VDO (altmode -> svid , vdo ? 2 : 1 , svdm_version , CMD_ENTER_MODE );
2816
+ header |= VDO_OPOS (altmode -> mode );
2817
+
2818
+ tcpm_queue_vdm_unlocked (port , header , vdo , vdo ? 1 : 0 , TCPC_TX_SOP_PRIME );
2819
+ return 0 ;
2820
+ }
2821
+
2822
+ static int tcpm_cable_altmode_exit (struct typec_altmode * altmode , enum typec_plug_index sop )
2823
+ {
2824
+ struct tcpm_port * port = typec_altmode_get_drvdata (altmode );
2825
+ int svdm_version ;
2826
+ u32 header ;
2827
+
2828
+ svdm_version = typec_get_cable_svdm_version (port -> typec_port );
2829
+ if (svdm_version < 0 )
2830
+ return svdm_version ;
2831
+
2832
+ header = VDO (altmode -> svid , 1 , svdm_version , CMD_EXIT_MODE );
2833
+ header |= VDO_OPOS (altmode -> mode );
2834
+
2835
+ tcpm_queue_vdm_unlocked (port , header , NULL , 0 , TCPC_TX_SOP_PRIME );
2836
+ return 0 ;
2837
+ }
2838
+
2839
+ static int tcpm_cable_altmode_vdm (struct typec_altmode * altmode , enum typec_plug_index sop ,
2840
+ u32 header , const u32 * data , int count )
2841
+ {
2842
+ struct tcpm_port * port = typec_altmode_get_drvdata (altmode );
2843
+
2844
+ tcpm_queue_vdm_unlocked (port , header , data , count - 1 , TCPC_TX_SOP_PRIME );
2845
+
2846
+ return 0 ;
2847
+ }
2848
+
2849
+ static const struct typec_cable_ops tcpm_cable_ops = {
2850
+ .enter = tcpm_cable_altmode_enter ,
2851
+ .exit = tcpm_cable_altmode_exit ,
2852
+ .vdm = tcpm_cable_altmode_vdm ,
2853
+ };
2854
+
2771
2855
/*
2772
2856
* PD (data, control) command handling functions
2773
2857
*/
@@ -7507,6 +7591,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
7507
7591
typec_port_register_altmodes (port -> typec_port ,
7508
7592
& tcpm_altmode_ops , port ,
7509
7593
port -> port_altmode , ALTMODE_DISCOVERY_MAX );
7594
+ typec_port_register_cable_ops (port -> port_altmode , ARRAY_SIZE (port -> port_altmode ),
7595
+ & tcpm_cable_ops );
7510
7596
port -> registered = true;
7511
7597
7512
7598
mutex_lock (& port -> lock );
0 commit comments