* [PATCH] usb: typec: ucsi_ccg: workaround for NVIDIA test device
@ 2020-03-10 12:19 Heikki Krogerus
0 siblings, 0 replies; 5+ messages in thread
From: Heikki Krogerus @ 2020-03-10 12:19 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-usb, Ajay Gupta
From: Ajay Gupta <ajayg@nvidia.com>
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>
---
drivers/usb/typec/ucsi/ucsi.h | 2 ++
drivers/usb/typec/ucsi/ucsi_ccg.c | 55 ++++++++++++++++++++++++++++---
2 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 65cd2f01eaed..cc87a72ff481 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -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)
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index a5b8530490db..61543573290e 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -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;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* RE: [PATCH] usb: typec: ucsi_ccg: workaround for NVIDIA test device
2020-02-27 14:15 ` Heikki Krogerus
@ 2020-02-27 20:07 ` Ajay Gupta
0 siblings, 0 replies; 5+ messages in thread
From: Ajay Gupta @ 2020-02-27 20:07 UTC (permalink / raw)
To: Heikki Krogerus, Ajay Gupta; +Cc: linux-usb
Hi Heikki
> -----Original Message-----
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Sent: Thursday, February 27, 2020 6:16 AM
> To: Ajay Gupta <ajaykuee@gmail.com>
> Cc: linux-usb@vger.kernel.org; Ajay Gupta <ajayg@nvidia.com>
> Subject: Re: [PATCH] usb: typec: ucsi_ccg: workaround for NVIDIA test device
>
>
> On Thu, Feb 27, 2020 at 04:02:07PM +0200, Heikki Krogerus wrote:
> > This did not compile:
> >
> > drivers/usb/typec/ucsi/ucsi_ccg.c: In function ‘ucsi_ccg_read’:
> > drivers/usb/typec/ucsi/ucsi_ccg.c:505:22: error:
> ‘USB_TYPEC_NVIDIA_VLINK_DBG_VDO’ undeclared (first use in this function);
> did you mean ‘USB_TYPEC_NVIDIA_VLINK_SID’?
> > 505 | alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DBG_VDO) {
> > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > | USB_TYPEC_NVIDIA_VLINK_SID
> > drivers/usb/typec/ucsi/ucsi_ccg.c:505:22: note: each undeclared
> > identifier is reported only once for each function it appears in
> > drivers/usb/typec/ucsi/ucsi_ccg.c:506:18: error:
> ‘USB_TYPEC_NVIDIA_VLINK_DP_VDO’ undeclared (first use in this function);
> did you mean ‘USB_TYPEC_NVIDIA_VLINK_SID’?
> > 506 | alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DP_VDO |
> > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > | USB_TYPEC_NVIDIA_VLINK_SID
>
> Sorry, I was working on top of the wrong branch. The patch does compile
> fine...
>
> > All those nested conditions make the code a bit difficult to read for
> > me. You could handle the NVIDIA alt mode in its own function. I'm
> > attaching a diff that you should be able to apply on top of your patch
> > that should make the code a bit easier to read.
>
> I attached a fixed version of the diff.
Thanks for review. I have updated the change and posted v2.
thanks
> nvpublic
>
> thanks,
>
> --
> heikki
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] usb: typec: ucsi_ccg: workaround for NVIDIA test device
2020-02-27 14:02 ` Heikki Krogerus
@ 2020-02-27 14:15 ` Heikki Krogerus
2020-02-27 20:07 ` Ajay Gupta
0 siblings, 1 reply; 5+ messages in thread
From: Heikki Krogerus @ 2020-02-27 14:15 UTC (permalink / raw)
To: Ajay Gupta; +Cc: linux-usb, Ajay Gupta
[-- Attachment #1: Type: text/plain, Size: 1407 bytes --]
On Thu, Feb 27, 2020 at 04:02:07PM +0200, Heikki Krogerus wrote:
> This did not compile:
>
> drivers/usb/typec/ucsi/ucsi_ccg.c: In function ‘ucsi_ccg_read’:
> drivers/usb/typec/ucsi/ucsi_ccg.c:505:22: error: ‘USB_TYPEC_NVIDIA_VLINK_DBG_VDO’ undeclared (first use in this function); did you mean ‘USB_TYPEC_NVIDIA_VLINK_SID’?
> 505 | alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DBG_VDO) {
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> | USB_TYPEC_NVIDIA_VLINK_SID
> drivers/usb/typec/ucsi/ucsi_ccg.c:505:22: note: each undeclared identifier is reported only once for each function it appears in
> drivers/usb/typec/ucsi/ucsi_ccg.c:506:18: error: ‘USB_TYPEC_NVIDIA_VLINK_DP_VDO’ undeclared (first use in this function); did you mean ‘USB_TYPEC_NVIDIA_VLINK_SID’?
> 506 | alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DP_VDO |
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> | USB_TYPEC_NVIDIA_VLINK_SID
Sorry, I was working on top of the wrong branch. The patch does
compile fine...
> All those nested conditions make the code a bit difficult to read for
> me. You could handle the NVIDIA alt mode in its own function. I'm
> attaching a diff that you should be able to apply on top of your patch
> that should make the code a bit easier to read.
I attached a fixed version of the diff.
thanks,
--
heikki
[-- Attachment #2: ucsi_ccg_nvidia_altmode.diff --]
[-- Type: text/plain, Size: 3181 bytes --]
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index b421b0045448..65fa648eea19 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -126,8 +126,8 @@ struct version_format {
#define CCG_OLD_FW_VERSION (CCG_VERSION(0x31) | CCG_VERSION_PATCH(10))
/* Altmode offset for NVIDIA Function Test Board (FTB) */
-#define USB_TYPEC_NVIDIA_FTB_DP_OFFSET (2)
-#define USB_TYPEC_NVIDIA_FTB_DBG_OFFSET (3)
+#define NVIDIA_FTB_DP_OFFSET (2)
+#define NVIDIA_FTB_DBG_OFFSET (3)
struct version_info {
struct version_format base;
@@ -481,49 +481,55 @@ static void ucsi_ccg_update_set_new_cam_cmd(struct ucsi_ccg *uc,
*cmd |= UCSI_SET_NEW_CAM_SET_AM(cam);
}
+/*
+ * FIXME: A short explanation what this function does.
+ */
+static int ucsi_ccg_nvidia_altmode(struct ucsi_ccg *uc,
+ struct ucsi_altmode *alt)
+{
+ if (UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) == NVIDIA_FTB_DP_OFFSET &&
+ 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));
+
+ if (UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) == NVIDIA_FTB_DBG_OFFSET &&
+ alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO)
+ alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DBG_VDO;
+
+ return 0;
+}
+
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_ALTERNATE_MODES &&
- UCSI_ALTMODE_RECIPIENT(uc->last_cmd_sent) ==
- UCSI_RECIPIENT_SOP) {
- struct ucsi_altmode *alt = (struct ucsi_altmode *)val;
-
- if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
- UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
- USB_TYPEC_NVIDIA_FTB_DP_OFFSET &&
- 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));
- }
- if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
- UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
- USB_TYPEC_NVIDIA_FTB_DBG_OFFSET &&
- alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO) {
- alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DBG_VDO;
- }
- }
- if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_GET_CURRENT_CAM &&
- uc->has_multiple_dp) {
+ if (offset != UCSI_MESSAGE_IN)
+ return 0;
+
+ 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);
- }
- uc->last_cmd_sent = 0;
+ break;
+ case UCSI_GET_ALTERNATE_MODES:
+ alt = val;
+ if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID)
+ return ucsi_ccg_nvidia_altmode(uc, alt);
+ break;
+ default:
+ break;
}
- return ret;
+ return 0;
}
static int ucsi_ccg_async_write(struct ucsi *ucsi, unsigned int offset,
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] usb: typec: ucsi_ccg: workaround for NVIDIA test device
2020-02-18 23:15 Ajay Gupta
@ 2020-02-27 14:02 ` Heikki Krogerus
2020-02-27 14:15 ` Heikki Krogerus
0 siblings, 1 reply; 5+ messages in thread
From: Heikki Krogerus @ 2020-02-27 14:02 UTC (permalink / raw)
To: Ajay Gupta; +Cc: linux-usb, Ajay Gupta
[-- Attachment #1: Type: text/plain, Size: 5112 bytes --]
Hi Ajay,
On Tue, Feb 18, 2020 at 03:15:20PM -0800, Ajay Gupta wrote:
> From: Ajay Gupta <ajayg@nvidia.com>
>
> 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>
> ---
> drivers/usb/typec/ucsi/ucsi.h | 2 ++
> drivers/usb/typec/ucsi/ucsi_ccg.c | 27 +++++++++++++++++++++++++++
> 2 files changed, 29 insertions(+)
>
> diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
> index a89112b69cd5..8e831108f481 100644
> --- a/drivers/usb/typec/ucsi/ucsi.h
> +++ b/drivers/usb/typec/ucsi/ucsi.h
> @@ -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)
>
> diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
> index 2658cda5da11..b421b0045448 100644
> --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> @@ -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 USB_TYPEC_NVIDIA_FTB_DP_OFFSET (2)
> +#define USB_TYPEC_NVIDIA_FTB_DBG_OFFSET (3)
> +
> struct version_info {
> struct version_format base;
> struct version_format app;
> @@ -489,6 +493,29 @@ static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,
> return ret;
>
> if (offset == UCSI_MESSAGE_IN) {
> + if (UCSI_COMMAND(uc->last_cmd_sent) ==
> + UCSI_GET_ALTERNATE_MODES &&
> + UCSI_ALTMODE_RECIPIENT(uc->last_cmd_sent) ==
> + UCSI_RECIPIENT_SOP) {
> + struct ucsi_altmode *alt = (struct ucsi_altmode *)val;
> +
> + if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
> + UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
> + USB_TYPEC_NVIDIA_FTB_DP_OFFSET &&
> + 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));
> + }
> + if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
> + UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
> + USB_TYPEC_NVIDIA_FTB_DBG_OFFSET &&
> + alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO) {
> + alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DBG_VDO;
> + }
> + }
> if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_GET_CURRENT_CAM &&
> uc->has_multiple_dp) {
> ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)val);
This did not compile:
drivers/usb/typec/ucsi/ucsi_ccg.c: In function ‘ucsi_ccg_read’:
drivers/usb/typec/ucsi/ucsi_ccg.c:505:22: error: ‘USB_TYPEC_NVIDIA_VLINK_DBG_VDO’ undeclared (first use in this function); did you mean ‘USB_TYPEC_NVIDIA_VLINK_SID’?
505 | alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DBG_VDO) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| USB_TYPEC_NVIDIA_VLINK_SID
drivers/usb/typec/ucsi/ucsi_ccg.c:505:22: note: each undeclared identifier is reported only once for each function it appears in
drivers/usb/typec/ucsi/ucsi_ccg.c:506:18: error: ‘USB_TYPEC_NVIDIA_VLINK_DP_VDO’ undeclared (first use in this function); did you mean ‘USB_TYPEC_NVIDIA_VLINK_SID’?
506 | alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DP_VDO |
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| USB_TYPEC_NVIDIA_VLINK_SID
All those nested conditions make the code a bit difficult to read for
me. You could handle the NVIDIA alt mode in its own function. I'm
attaching a diff that you should be able to apply on top of your patch
that should make the code a bit easier to read.
thanks,
--
heikki
[-- Attachment #2: ucsi_ccg_nvidia_altmode.diff --]
[-- Type: text/plain, Size: 3161 bytes --]
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index d2bc5681fe8e..4c8c799181b9 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -126,8 +126,8 @@ struct version_format {
#define CCG_OLD_FW_VERSION (CCG_VERSION(0x31) | CCG_VERSION_PATCH(10))
/* Altmode offset for NVIDIA Function Test Board (FTB) */
-#define USB_TYPEC_NVIDIA_FTB_DP_OFFSET (2)
-#define USB_TYPEC_NVIDIA_FTB_DBG_OFFSET (3)
+#define NVIDIA_FTB_DP_OFFSET (2)
+#define NVIDIA_FTB_DBG_OFFSET (3)
struct version_info {
struct version_format base;
@@ -481,49 +481,55 @@ static void ucsi_ccg_update_set_new_cam_cmd(struct ucsi_ccg *uc,
*cmd |= UCSI_SET_NEW_CAM_SET_AM(cam);
}
+/*
+ * FIXME: A short explanation what this function does.
+ */
+static int ucsi_ccg_nvidia_altmode(struct ucsi_ccg *uc,
+ struct ucsi_altmode *alt)
+{
+ if (UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) == NVIDIA_FTB_DP_OFFSET &&
+ alt[0].mid == 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));
+
+ if (UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) == NVIDIA_FTB_DBG_OFFSET &&
+ alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO)
+ alt[0].mid = NVIDIA_VLINK_DBG_VDO;
+
+ return 0;
+}
+
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_ALTERNATE_MODES &&
- UCSI_ALTMODE_RECIPIENT(uc->last_cmd_sent) ==
- UCSI_RECIPIENT_SOP) {
- struct ucsi_altmode *alt = (struct ucsi_altmode *)val;
-
- if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
- UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
- USB_TYPEC_NVIDIA_FTB_DP_OFFSET &&
- 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));
- }
- if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
- UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
- USB_TYPEC_NVIDIA_FTB_DBG_OFFSET &&
- alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO) {
- alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DBG_VDO;
- }
- }
- if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_GET_CURRENT_CAM &&
- uc->has_multiple_dp) {
+ if (offset != UCSI_MESSAGE_IN)
+ return 0;
+
+ 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);
- }
- uc->last_cmd_sent = 0;
+ break;
+ case UCSI_GET_ALTERNATE_MODES:
+ alt = val;
+ if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID)
+ return ucsi_ccg_nvidia_altmode(uc, alt);
+ break;
+ default:
+ break;
}
- return ret;
+ return 0;
}
static int ucsi_ccg_async_write(struct ucsi *ucsi, unsigned int offset,
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] usb: typec: ucsi_ccg: workaround for NVIDIA test device
@ 2020-02-18 23:15 Ajay Gupta
2020-02-27 14:02 ` Heikki Krogerus
0 siblings, 1 reply; 5+ messages in thread
From: Ajay Gupta @ 2020-02-18 23:15 UTC (permalink / raw)
To: heikki.krogerus; +Cc: linux-usb, Ajay Gupta
From: Ajay Gupta <ajayg@nvidia.com>
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>
---
drivers/usb/typec/ucsi/ucsi.h | 2 ++
drivers/usb/typec/ucsi/ucsi_ccg.c | 27 +++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index a89112b69cd5..8e831108f481 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -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)
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index 2658cda5da11..b421b0045448 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -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 USB_TYPEC_NVIDIA_FTB_DP_OFFSET (2)
+#define USB_TYPEC_NVIDIA_FTB_DBG_OFFSET (3)
+
struct version_info {
struct version_format base;
struct version_format app;
@@ -489,6 +493,29 @@ static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,
return ret;
if (offset == UCSI_MESSAGE_IN) {
+ if (UCSI_COMMAND(uc->last_cmd_sent) ==
+ UCSI_GET_ALTERNATE_MODES &&
+ UCSI_ALTMODE_RECIPIENT(uc->last_cmd_sent) ==
+ UCSI_RECIPIENT_SOP) {
+ struct ucsi_altmode *alt = (struct ucsi_altmode *)val;
+
+ if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
+ UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
+ USB_TYPEC_NVIDIA_FTB_DP_OFFSET &&
+ 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));
+ }
+ if (alt[0].svid == USB_TYPEC_NVIDIA_VLINK_SID &&
+ UCSI_ALTMODE_OFFSET(uc->last_cmd_sent) ==
+ USB_TYPEC_NVIDIA_FTB_DBG_OFFSET &&
+ alt[0].mid == USB_TYPEC_NVIDIA_VLINK_DP_VDO) {
+ alt[0].mid = USB_TYPEC_NVIDIA_VLINK_DBG_VDO;
+ }
+ }
if (UCSI_COMMAND(uc->last_cmd_sent) == UCSI_GET_CURRENT_CAM &&
uc->has_multiple_dp) {
ucsi_ccg_update_get_current_cam_cmd(uc, (u8 *)val);
--
2.17.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-03-10 12:19 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-10 12:19 [PATCH] usb: typec: ucsi_ccg: workaround for NVIDIA test device Heikki Krogerus
-- strict thread matches above, loose matches on Subject: below --
2020-02-18 23:15 Ajay Gupta
2020-02-27 14:02 ` Heikki Krogerus
2020-02-27 14:15 ` Heikki Krogerus
2020-02-27 20:07 ` Ajay Gupta
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.