mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
usb: typec: ucsi_ccg: workaround for NVIDIA test device
NVIDIA VirtualLink (svid 0x955) has two altmode, vdo=0x1 for VirtualLink DP mode and vdo=0x3 for NVIDIA test mode. NVIDIA test device FTB (Function Test Board) reports altmode list with vdo=0x3 first and then vdo=0x1. The list is: SVID VDO 0xff01 0xc05 0x28de 0x8085 0x955 0x3 0x955 0x1 Current logic to assign mode value is based on order in altmode list. This causes a mismatch of CON and SOP altmodes since NVIDIA GPU connector has order of vdo=0x1 first and then vdo=0x3. Fixing this by changing the order of vdo values reported by NVIDIA test device. the new list will be: SVID VDO 0xff01 0xc05 0x28de 0x8085 0x955 0x1085 0x955 0x3 Also NVIDIA VirtualLink (svid 0x955) uses pin E for display mode. NVIDIA test device reports vdo of 0x1 so make sure vdo values always have pin E assignement. Signed-off-by: Ajay Gupta <ajayg@nvidia.com> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20200310121912.57879-1-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0de005d0e4
commit
706f4bbf18
@ -119,12 +119,14 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
|
||||
#define UCSI_SET_PDR_ACCEPT_ROLE_SWAPS BIT(25)
|
||||
|
||||
/* GET_ALTERNATE_MODES command bits */
|
||||
#define UCSI_ALTMODE_RECIPIENT(_r_) (((_r_) >> 16) & 0x7)
|
||||
#define UCSI_GET_ALTMODE_RECIPIENT(_r_) ((u64)(_r_) << 16)
|
||||
#define UCSI_RECIPIENT_CON 0
|
||||
#define UCSI_RECIPIENT_SOP 1
|
||||
#define UCSI_RECIPIENT_SOP_P 2
|
||||
#define UCSI_RECIPIENT_SOP_PP 3
|
||||
#define UCSI_GET_ALTMODE_CONNECTOR_NUMBER(_r_) ((u64)(_r_) << 24)
|
||||
#define UCSI_ALTMODE_OFFSET(_r_) (((_r_) >> 32) & 0xff)
|
||||
#define UCSI_GET_ALTMODE_OFFSET(_r_) ((u64)(_r_) << 32)
|
||||
#define UCSI_GET_ALTMODE_NUM_ALTMODES(_r_) ((u64)(_r_) << 40)
|
||||
|
||||
|
@ -125,6 +125,10 @@ struct version_format {
|
||||
#define CCG_FW_BUILD_NVIDIA (('n' << 8) | 'v')
|
||||
#define CCG_OLD_FW_VERSION (CCG_VERSION(0x31) | CCG_VERSION_PATCH(10))
|
||||
|
||||
/* Altmode offset for NVIDIA Function Test Board (FTB) */
|
||||
#define NVIDIA_FTB_DP_OFFSET (2)
|
||||
#define NVIDIA_FTB_DBG_OFFSET (3)
|
||||
|
||||
struct version_info {
|
||||
struct version_format base;
|
||||
struct version_format app;
|
||||
@ -477,24 +481,65 @@ static void ucsi_ccg_update_set_new_cam_cmd(struct ucsi_ccg *uc,
|
||||
*cmd |= UCSI_SET_NEW_CAM_SET_AM(cam);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the order of vdo values of NVIDIA test device FTB
|
||||
* (Function Test Board) which reports altmode list with vdo=0x3
|
||||
* first and then vdo=0x. Current logic to assign mode value is
|
||||
* based on order in altmode list and it causes a mismatch of CON
|
||||
* and SOP altmodes since NVIDIA GPU connector has order of vdo=0x1
|
||||
* first and then vdo=0x3
|
||||
*/
|
||||
static void ucsi_ccg_nvidia_altmode(struct ucsi_ccg *uc,
|
||||
struct ucsi_altmode *alt)
|
||||
{
|
||||
switch (UCSI_ALTMODE_OFFSET(uc->last_cmd_sent)) {
|
||||
case NVIDIA_FTB_DP_OFFSET:
|
||||
if (alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DBG_VDO)
|
||||
alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DP_VDO |
|
||||
DP_CAP_DP_SIGNALING | DP_CAP_USB |
|
||||
DP_CONF_SET_PIN_ASSIGN(BIT(DP_PIN_ASSIGN_E));
|
||||
break;
|
||||
case NVIDIA_FTB_DBG_OFFSET:
|
||||
if (alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO)
|
||||
alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DBG_VDO;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,
|
||||
void *val, size_t val_len)
|
||||
{
|
||||
struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi);
|
||||
int ret;
|
||||
u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
|
||||
struct ucsi_altmode *alt;
|
||||
int ret;
|
||||
|
||||
ret = ccg_read(uc, reg, val, val_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (offset == UCSI_MESSAGE_IN) {
|
||||
if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_GET_CURRENT_CAM &&
|
||||
uc->has_multiple_dp) {
|
||||
if (offset != UCSI_MESSAGE_IN)
|
||||
return ret;
|
||||
|
||||
switch (UCSI_COMMAND(uc->last_cmd_sent)) {
|
||||
case UCSI_GET_CURRENT_CAM:
|
||||
if (uc->has_multiple_dp)
|
||||
ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)val);
|
||||
break;
|
||||
case UCSI_GET_ALTERNATE_MODES:
|
||||
if (UCSI_ALTMODE_RECIPIENT(uc->last_cmd_sent) ==
|
||||
UCSI_RECIPIENT_SOP) {
|
||||
alt = val;
|
||||
if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID)
|
||||
ucsi_ccg_nvidia_altmode(uc, alt);
|
||||
}
|
||||
uc->last_cmd_sent = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uc->last_cmd_sent = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user