From: Dmitry Baryshkov Date: Sat, 21 Jun 2025 18:13:00 +0000 (+0300) Subject: usb: typec: ucsi: yoga-c630: fake AltModes for port 0 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=442392f98d20c501764dca35ddbd40e86786ea9b;p=users%2Fjedix%2Flinux-maple.git usb: typec: ucsi: yoga-c630: fake AltModes for port 0 EC firmware provides information about partner AltModes and handles the DisplayPort AltMode internally, however it doesn't report AltModes of the port to the host. Fake the DP AltMode for port0 in order to let Linux bind displayport AltMode driver. Signed-off-by: Dmitry Baryshkov Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20250621-c630-ucsi-v1-5-a86de5e11361@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index d02f6a3e2f50..b711e1ecc378 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -50,6 +50,7 @@ struct dentry; /* Command Status and Connector Change Indication (CCI) bits */ #define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1) #define UCSI_CCI_LENGTH(_c_) (((_c_) & GENMASK(15, 8)) >> 8) +#define UCSI_SET_CCI_LENGTH(_c_) ((_c_) << 8) #define UCSI_CCI_NOT_SUPPORTED BIT(25) #define UCSI_CCI_CANCEL_COMPLETE BIT(26) #define UCSI_CCI_RESET_COMPLETE BIT(27) diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c index 2005f64ebfe4..506faf31b6e3 100644 --- a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c +++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c @@ -76,6 +76,28 @@ static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi, u32 *cci, void *data, size_t size) { + int ret; + + /* + * EC doesn't return connector's DP mode even though it is supported. + * Fake it. + */ + if (UCSI_COMMAND(command) == UCSI_GET_ALTERNATE_MODES && + UCSI_GET_ALTMODE_GET_CONNECTOR_NUMBER(command) == 1 && + UCSI_ALTMODE_RECIPIENT(command) == UCSI_RECIPIENT_CON && + UCSI_ALTMODE_OFFSET(command) == 0) { + static const struct ucsi_altmode alt = { + .svid = USB_TYPEC_DP_SID, + .mid = USB_TYPEC_DP_MODE, + }; + + dev_dbg(ucsi->dev, "faking DP altmode for con1\n"); + memset(data, 0, size); + memcpy(data, &alt, min(sizeof(alt), size)); + *cci = UCSI_CCI_COMMAND_COMPLETE | UCSI_SET_CCI_LENGTH(sizeof(alt)); + return 0; + } + /* * EC can return AltModes present on CON1 (port0, right) for CON2 * (port1, left) too. Ignore all requests going to CON2 (it doesn't