Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: typec: tipd: Register DisplayPort and Thunderbolt altmodes for cd321x

Ports equipped with a CD321x are only found on Apple Silicon machines
and always support DisplayPort, Thunderbolt and USB4. Register these
port modes unconditionally.

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Sven Peter <sven@kernel.org>
Link: https://lore.kernel.org/r/20250914-apple-usb3-tipd-v1-7-4e99c8649024@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sven Peter and committed by
Greg Kroah-Hartman
7b1d3185 0b31c978

+82 -3
+82 -3
drivers/usb/typec/tipd/core.c
··· 16 16 #include <linux/interrupt.h> 17 17 #include <linux/usb/typec.h> 18 18 #include <linux/usb/typec_altmode.h> 19 + #include <linux/usb/typec_dp.h> 20 + #include <linux/usb/typec_tbt.h> 19 21 #include <linux/usb/role.h> 20 22 #include <linux/workqueue.h> 21 23 #include <linux/firmware.h> ··· 146 144 u64 irq_mask1; 147 145 size_t tps_struct_size; 148 146 int (*register_port)(struct tps6598x *tps, struct fwnode_handle *node); 147 + void (*unregister_port)(struct tps6598x *tps); 149 148 void (*trace_data_status)(u32 status); 150 149 void (*trace_power_status)(u16 status); 151 150 void (*trace_status)(u32 status); ··· 188 185 struct tps6598x_dp_sid_status_reg dp_sid_status; 189 186 struct tps6598x_intel_vid_status_reg intel_vid_status; 190 187 struct tps6598x_usb4_status_reg usb4_status; 188 + 189 + struct typec_altmode *port_altmode_dp; 190 + struct typec_altmode *port_altmode_tbt; 191 191 }; 192 192 193 193 static enum power_supply_property tps6598x_psy_props[] = { ··· 970 964 return 0; 971 965 } 972 966 967 + static int cd321x_register_port_altmodes(struct cd321x *cd321x) 968 + { 969 + struct typec_altmode_desc desc; 970 + struct typec_altmode *amode; 971 + 972 + memset(&desc, 0, sizeof(desc)); 973 + desc.svid = USB_TYPEC_DP_SID; 974 + desc.mode = USB_TYPEC_DP_MODE; 975 + desc.vdo = DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_C) | BIT(DP_PIN_ASSIGN_D)); 976 + desc.vdo |= DP_CAP_DFP_D; 977 + amode = typec_port_register_altmode(cd321x->tps.port, &desc); 978 + if (IS_ERR(amode)) 979 + return PTR_ERR(amode); 980 + cd321x->port_altmode_dp = amode; 981 + 982 + memset(&desc, 0, sizeof(desc)); 983 + desc.svid = USB_TYPEC_TBT_SID; 984 + desc.mode = TYPEC_ANY_MODE; 985 + amode = typec_port_register_altmode(cd321x->tps.port, &desc); 986 + if (IS_ERR(amode)) { 987 + typec_unregister_altmode(cd321x->port_altmode_dp); 988 + cd321x->port_altmode_dp = NULL; 989 + return PTR_ERR(amode); 990 + } 991 + cd321x->port_altmode_tbt = amode; 992 + 993 + return 0; 994 + } 995 + 996 + static int 997 + cd321x_register_port(struct tps6598x *tps, struct fwnode_handle *fwnode) 998 + { 999 + struct cd321x *cd321x = container_of(tps, struct cd321x, tps); 1000 + int ret; 1001 + 1002 + ret = tps6598x_register_port(tps, fwnode); 1003 + if (ret) 1004 + return ret; 1005 + 1006 + ret = cd321x_register_port_altmodes(cd321x); 1007 + if (ret) 1008 + goto err_unregister_port; 1009 + 1010 + typec_set_mode(tps->port, TYPEC_STATE_SAFE); 1011 + 1012 + return 0; 1013 + 1014 + err_unregister_port: 1015 + typec_unregister_port(tps->port); 1016 + return ret; 1017 + } 1018 + 1019 + static void 1020 + tps6598x_unregister_port(struct tps6598x *tps) 1021 + { 1022 + typec_unregister_port(tps->port); 1023 + } 1024 + 1025 + static void 1026 + cd321x_unregister_port(struct tps6598x *tps) 1027 + { 1028 + struct cd321x *cd321x = container_of(tps, struct cd321x, tps); 1029 + 1030 + typec_unregister_altmode(cd321x->port_altmode_dp); 1031 + cd321x->port_altmode_dp = NULL; 1032 + typec_unregister_altmode(cd321x->port_altmode_tbt); 1033 + cd321x->port_altmode_tbt = NULL; 1034 + typec_unregister_port(tps->port); 1035 + } 1036 + 973 1037 static int tps_request_firmware(struct tps6598x *tps, const struct firmware **fw, 974 1038 const char **firmware_name) 975 1039 { ··· 1581 1505 err_disconnect: 1582 1506 tps6598x_disconnect(tps, 0); 1583 1507 err_unregister_port: 1584 - typec_unregister_port(tps->port); 1508 + tps->data->unregister_port(tps); 1585 1509 err_role_put: 1586 1510 usb_role_switch_put(tps->role_sw); 1587 1511 err_fwnode_put: ··· 1605 1529 devm_free_irq(tps->dev, client->irq, tps); 1606 1530 1607 1531 tps6598x_disconnect(tps, 0); 1608 - typec_unregister_port(tps->port); 1532 + tps->data->unregister_port(tps); 1609 1533 usb_role_switch_put(tps->role_sw); 1610 1534 1611 1535 /* Reset PD controller to remove any applied patch */ ··· 1674 1598 APPLE_CD_REG_INT_DATA_STATUS_UPDATE | 1675 1599 APPLE_CD_REG_INT_PLUG_EVENT, 1676 1600 .tps_struct_size = sizeof(struct cd321x), 1677 - .register_port = tps6598x_register_port, 1601 + .register_port = cd321x_register_port, 1602 + .unregister_port = cd321x_unregister_port, 1678 1603 .trace_data_status = trace_cd321x_data_status, 1679 1604 .trace_power_status = trace_tps6598x_power_status, 1680 1605 .trace_status = trace_tps6598x_status, ··· 1692 1615 TPS_REG_INT_PLUG_EVENT, 1693 1616 .tps_struct_size = sizeof(struct tps6598x), 1694 1617 .register_port = tps6598x_register_port, 1618 + .unregister_port = tps6598x_unregister_port, 1695 1619 .trace_data_status = trace_tps6598x_data_status, 1696 1620 .trace_power_status = trace_tps6598x_power_status, 1697 1621 .trace_status = trace_tps6598x_status, ··· 1709 1631 TPS_REG_INT_PLUG_EVENT, 1710 1632 .tps_struct_size = sizeof(struct tps6598x), 1711 1633 .register_port = tps25750_register_port, 1634 + .unregister_port = tps6598x_unregister_port, 1712 1635 .trace_data_status = trace_tps6598x_data_status, 1713 1636 .trace_power_status = trace_tps25750_power_status, 1714 1637 .trace_status = trace_tps25750_status,