Skip to content

Commit 7b1d318

Browse files
svenpeter42gregkh
authored andcommitted
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>
1 parent 0b31c97 commit 7b1d318

1 file changed

Lines changed: 82 additions & 3 deletions

File tree

drivers/usb/typec/tipd/core.c

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
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

190196
static 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+
9671043
static 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)
15051581
err_disconnect:
15061582
tps6598x_disconnect(tps, 0);
15071583
err_unregister_port:
1508-
typec_unregister_port(tps->port);
1584+
tps->data->unregister_port(tps);
15091585
err_role_put:
15101586
usb_role_switch_put(tps->role_sw);
15111587
err_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

Comments
 (0)