Hi Jameson, On Fri, Feb 23, 2024 at 01:03:28AM +0000, Jameson Thies wrote: > Register SOP' alternate modes with a Type-C Connector Class cable plug. > Alternate modes are queried from the PPM using the GET_ALTERNATE_MODES > command with recipient set to SOP'. > Is there a plan to do the same for the SOP Double Prime for advanced active cables with two plugs? > Signed-off-by: Jameson Thies <jthies@xxxxxxxxxx> Other than that question, Reviewed-by: Benson Leung <bleung@xxxxxxxxxxxx> > --- > Tested on v6.6 kernel. SOP' GET_ALTERNATE_MODE responses from the PPM > are correctly registered as to the cable plug. > redrix-rev3 /sys/class/typec # ls port2-cable/port2-plug0/ > device port2-plug0.0 port2-plug0.1 power subsystem uevent > > drivers/usb/typec/ucsi/ucsi.c | 60 +++++++++++++++++++++++++++++++++++ > drivers/usb/typec/ucsi/ucsi.h | 2 ++ > 2 files changed, 62 insertions(+) > > diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c > index 6d6443e61faa..9b541547917b 100644 > --- a/drivers/usb/typec/ucsi/ucsi.c > +++ b/drivers/usb/typec/ucsi/ucsi.c > @@ -399,6 +399,27 @@ static int ucsi_register_altmode(struct ucsi_connector *con, > > con->partner_altmode[i] = alt; > break; > + case UCSI_RECIPIENT_SOP_P: > + i = ucsi_next_altmode(con->plug_altmode); > + if (i < 0) { > + ret = i; > + goto err; > + } > + > + ret = ucsi_altmode_next_mode(con->plug_altmode, desc->svid); > + if (ret < 0) > + return ret; > + > + desc->mode = ret; > + > + alt = typec_plug_register_altmode(con->plug, desc); > + if (IS_ERR(alt)) { > + ret = PTR_ERR(alt); > + goto err; > + } > + > + con->plug_altmode[i] = alt; > + break; > default: > return -EINVAL; > } > @@ -566,6 +587,9 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient) > case UCSI_RECIPIENT_SOP: > adev = con->partner_altmode; > break; > + case UCSI_RECIPIENT_SOP_P: > + adev = con->plug_altmode; > + break; > default: > return; > } > @@ -801,6 +825,33 @@ static void ucsi_unregister_partner_pdos(struct ucsi_connector *con) > con->partner_pd = NULL; > } > > +static int ucsi_register_plug(struct ucsi_connector *con) > +{ > + struct typec_plug *plug; > + struct typec_plug_desc desc = {.index = TYPEC_PLUG_SOP_P}; > + > + plug = typec_register_plug(con->cable, &desc); > + if (IS_ERR(plug)) { > + dev_err(con->ucsi->dev, > + "con%d: failed to register plug (%ld)\n", con->num, > + PTR_ERR(plug)); > + return PTR_ERR(plug); > + } > + > + con->plug = plug; > + return 0; > +} > + > +static void ucsi_unregister_plug(struct ucsi_connector *con) > +{ > + if (!con->plug) > + return; > + > + ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP_P); > + typec_unregister_plug(con->plug); > + con->plug = NULL; > +} > + > static int ucsi_register_cable(struct ucsi_connector *con) > { > struct typec_cable *cable; > @@ -842,6 +893,7 @@ static void ucsi_unregister_cable(struct ucsi_connector *con) > if (!con->cable) > return; > > + ucsi_unregister_plug(con); > typec_unregister_cable(con->cable); > con->cable = NULL; > memset(&con->cable_identity, 0, sizeof(con->cable_identity)); > @@ -1046,6 +1098,14 @@ static int ucsi_check_cable(struct ucsi_connector *con) > if (ret < 0) > return ret; > > + ret = ucsi_register_plug(con); > + if (ret < 0) > + return ret; > + > + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP_P); > + if (ret < 0) > + return ret; > + > return 0; > } > > diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h > index b89fae82e8ce..32daf5f58650 100644 > --- a/drivers/usb/typec/ucsi/ucsi.h > +++ b/drivers/usb/typec/ucsi/ucsi.h > @@ -429,9 +429,11 @@ struct ucsi_connector { > struct typec_port *port; > struct typec_partner *partner; > struct typec_cable *cable; > + struct typec_plug *plug; > > struct typec_altmode *port_altmode[UCSI_MAX_ALTMODES]; > struct typec_altmode *partner_altmode[UCSI_MAX_ALTMODES]; > + struct typec_altmode *plug_altmode[UCSI_MAX_ALTMODES]; > > struct typec_capability typec_cap; > > -- > 2.44.0.rc0.258.g7320e95886-goog >
Attachment:
signature.asc
Description: PGP signature