1616#include <linux/interrupt.h>
1717#include <linux/usb/typec.h>
1818#include <linux/usb/typec_altmode.h>
19+ #include <linux/usb/typec_dp.h>
20+ #include <linux/usb/typec_tbt.h>
1921#include <linux/usb/role.h>
2022#include <linux/workqueue.h>
2123#include <linux/firmware.h>
@@ -144,6 +146,7 @@ struct tipd_data {
144146 u64 irq_mask1 ;
145147 size_t tps_struct_size ;
146148 int (* register_port )(struct tps6598x * tps , struct fwnode_handle * node );
149+ void (* unregister_port )(struct tps6598x * tps );
147150 void (* trace_data_status )(u32 status );
148151 void (* trace_power_status )(u16 status );
149152 void (* trace_status )(u32 status );
@@ -185,6 +188,9 @@ struct cd321x {
185188 struct tps6598x_dp_sid_status_reg dp_sid_status ;
186189 struct tps6598x_intel_vid_status_reg intel_vid_status ;
187190 struct tps6598x_usb4_status_reg usb4_status ;
191+
192+ struct typec_altmode * port_altmode_dp ;
193+ struct typec_altmode * port_altmode_tbt ;
188194};
189195
190196static enum power_supply_property tps6598x_psy_props [] = {
@@ -964,6 +970,76 @@ tps6598x_register_port(struct tps6598x *tps, struct fwnode_handle *fwnode)
964970 return 0 ;
965971}
966972
973+ static int cd321x_register_port_altmodes (struct cd321x * cd321x )
974+ {
975+ struct typec_altmode_desc desc ;
976+ struct typec_altmode * amode ;
977+
978+ memset (& desc , 0 , sizeof (desc ));
979+ desc .svid = USB_TYPEC_DP_SID ;
980+ desc .mode = USB_TYPEC_DP_MODE ;
981+ desc .vdo = DP_CONF_SET_PIN_ASSIGN (BIT (DP_PIN_ASSIGN_C ) | BIT (DP_PIN_ASSIGN_D ));
982+ desc .vdo |= DP_CAP_DFP_D ;
983+ amode = typec_port_register_altmode (cd321x -> tps .port , & desc );
984+ if (IS_ERR (amode ))
985+ return PTR_ERR (amode );
986+ cd321x -> port_altmode_dp = amode ;
987+
988+ memset (& desc , 0 , sizeof (desc ));
989+ desc .svid = USB_TYPEC_TBT_SID ;
990+ desc .mode = TYPEC_ANY_MODE ;
991+ amode = typec_port_register_altmode (cd321x -> tps .port , & desc );
992+ if (IS_ERR (amode )) {
993+ typec_unregister_altmode (cd321x -> port_altmode_dp );
994+ cd321x -> port_altmode_dp = NULL ;
995+ return PTR_ERR (amode );
996+ }
997+ cd321x -> port_altmode_tbt = amode ;
998+
999+ return 0 ;
1000+ }
1001+
1002+ static int
1003+ cd321x_register_port (struct tps6598x * tps , struct fwnode_handle * fwnode )
1004+ {
1005+ struct cd321x * cd321x = container_of (tps , struct cd321x , tps );
1006+ int ret ;
1007+
1008+ ret = tps6598x_register_port (tps , fwnode );
1009+ if (ret )
1010+ return ret ;
1011+
1012+ ret = cd321x_register_port_altmodes (cd321x );
1013+ if (ret )
1014+ goto err_unregister_port ;
1015+
1016+ typec_set_mode (tps -> port , TYPEC_STATE_SAFE );
1017+
1018+ return 0 ;
1019+
1020+ err_unregister_port :
1021+ typec_unregister_port (tps -> port );
1022+ return ret ;
1023+ }
1024+
1025+ static void
1026+ tps6598x_unregister_port (struct tps6598x * tps )
1027+ {
1028+ typec_unregister_port (tps -> port );
1029+ }
1030+
1031+ static void
1032+ cd321x_unregister_port (struct tps6598x * tps )
1033+ {
1034+ struct cd321x * cd321x = container_of (tps , struct cd321x , tps );
1035+
1036+ typec_unregister_altmode (cd321x -> port_altmode_dp );
1037+ cd321x -> port_altmode_dp = NULL ;
1038+ typec_unregister_altmode (cd321x -> port_altmode_tbt );
1039+ cd321x -> port_altmode_tbt = NULL ;
1040+ typec_unregister_port (tps -> port );
1041+ }
1042+
9671043static int tps_request_firmware (struct tps6598x * tps , const struct firmware * * fw ,
9681044 const char * * firmware_name )
9691045{
@@ -1505,7 +1581,7 @@ static int tps6598x_probe(struct i2c_client *client)
15051581err_disconnect :
15061582 tps6598x_disconnect (tps , 0 );
15071583err_unregister_port :
1508- typec_unregister_port ( tps -> port );
1584+ tps -> data -> unregister_port ( tps );
15091585err_role_put :
15101586 usb_role_switch_put (tps -> role_sw );
15111587err_fwnode_put :
@@ -1529,7 +1605,7 @@ static void tps6598x_remove(struct i2c_client *client)
15291605 devm_free_irq (tps -> dev , client -> irq , tps );
15301606
15311607 tps6598x_disconnect (tps , 0 );
1532- typec_unregister_port ( tps -> port );
1608+ tps -> data -> unregister_port ( tps );
15331609 usb_role_switch_put (tps -> role_sw );
15341610
15351611 /* Reset PD controller to remove any applied patch */
@@ -1598,7 +1674,8 @@ static const struct tipd_data cd321x_data = {
15981674 APPLE_CD_REG_INT_DATA_STATUS_UPDATE |
15991675 APPLE_CD_REG_INT_PLUG_EVENT ,
16001676 .tps_struct_size = sizeof (struct cd321x ),
1601- .register_port = tps6598x_register_port ,
1677+ .register_port = cd321x_register_port ,
1678+ .unregister_port = cd321x_unregister_port ,
16021679 .trace_data_status = trace_cd321x_data_status ,
16031680 .trace_power_status = trace_tps6598x_power_status ,
16041681 .trace_status = trace_tps6598x_status ,
@@ -1615,6 +1692,7 @@ static const struct tipd_data tps6598x_data = {
16151692 TPS_REG_INT_PLUG_EVENT ,
16161693 .tps_struct_size = sizeof (struct tps6598x ),
16171694 .register_port = tps6598x_register_port ,
1695+ .unregister_port = tps6598x_unregister_port ,
16181696 .trace_data_status = trace_tps6598x_data_status ,
16191697 .trace_power_status = trace_tps6598x_power_status ,
16201698 .trace_status = trace_tps6598x_status ,
@@ -1631,6 +1709,7 @@ static const struct tipd_data tps25750_data = {
16311709 TPS_REG_INT_PLUG_EVENT ,
16321710 .tps_struct_size = sizeof (struct tps6598x ),
16331711 .register_port = tps25750_register_port ,
1712+ .unregister_port = tps6598x_unregister_port ,
16341713 .trace_data_status = trace_tps6598x_data_status ,
16351714 .trace_power_status = trace_tps25750_power_status ,
16361715 .trace_status = trace_tps25750_status ,
0 commit comments