Commit 372adf07 authored by Kyle Tso's avatar Kyle Tso Committed by Greg Kroah-Hartman

usb: typec: ucsi: Determine common SVDM Version

This patch implements the following requirement in the Spec.

PD Spec Revision 3.0 Version 2.0 + ECNs 2020-12-10
  6.4.4.2.3 Structured VDM Version
  "The Structured VDM Version field of the Discover Identity Command
  sent and received during VDM discovery Shall be used to determine the
  lowest common Structured VDM Version supported by the Port Partners or
  Cable Plug and Shall continue to operate using this Specification
  Revision until they are Detached."
Acked-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: default avatarKyle Tso <kyletso@google.com>
Link: https://lore.kernel.org/r/20210205033415.3320439-5-kyletso@google.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5e1d4c49
...@@ -49,6 +49,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo) ...@@ -49,6 +49,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
{ {
struct ucsi_dp *dp = typec_altmode_get_drvdata(alt); struct ucsi_dp *dp = typec_altmode_get_drvdata(alt);
struct ucsi *ucsi = dp->con->ucsi; struct ucsi *ucsi = dp->con->ucsi;
int svdm_version;
u64 command; u64 command;
u8 cur = 0; u8 cur = 0;
int ret; int ret;
...@@ -83,7 +84,13 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo) ...@@ -83,7 +84,13 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
* mode, and letting the alt mode driver continue. * mode, and letting the alt mode driver continue.
*/ */
dp->header = VDO(USB_TYPEC_DP_SID, 1, SVDM_VER_1_0, CMD_ENTER_MODE); svdm_version = typec_altmode_get_svdm_version(alt);
if (svdm_version < 0) {
ret = svdm_version;
goto err_unlock;
}
dp->header = VDO(USB_TYPEC_DP_SID, 1, svdm_version, CMD_ENTER_MODE);
dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE); dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
dp->header |= VDO_CMDT(CMDT_RSP_ACK); dp->header |= VDO_CMDT(CMDT_RSP_ACK);
...@@ -101,6 +108,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo) ...@@ -101,6 +108,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
static int ucsi_displayport_exit(struct typec_altmode *alt) static int ucsi_displayport_exit(struct typec_altmode *alt)
{ {
struct ucsi_dp *dp = typec_altmode_get_drvdata(alt); struct ucsi_dp *dp = typec_altmode_get_drvdata(alt);
int svdm_version;
u64 command; u64 command;
int ret = 0; int ret = 0;
...@@ -120,7 +128,13 @@ static int ucsi_displayport_exit(struct typec_altmode *alt) ...@@ -120,7 +128,13 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)
if (ret < 0) if (ret < 0)
goto out_unlock; goto out_unlock;
dp->header = VDO(USB_TYPEC_DP_SID, 1, SVDM_VER_1_0, CMD_EXIT_MODE); svdm_version = typec_altmode_get_svdm_version(alt);
if (svdm_version < 0) {
ret = svdm_version;
goto out_unlock;
}
dp->header = VDO(USB_TYPEC_DP_SID, 1, svdm_version, CMD_EXIT_MODE);
dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE); dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
dp->header |= VDO_CMDT(CMDT_RSP_ACK); dp->header |= VDO_CMDT(CMDT_RSP_ACK);
...@@ -186,6 +200,7 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt, ...@@ -186,6 +200,7 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,
struct ucsi_dp *dp = typec_altmode_get_drvdata(alt); struct ucsi_dp *dp = typec_altmode_get_drvdata(alt);
int cmd_type = PD_VDO_CMDT(header); int cmd_type = PD_VDO_CMDT(header);
int cmd = PD_VDO_CMD(header); int cmd = PD_VDO_CMD(header);
int svdm_version;
mutex_lock(&dp->con->lock); mutex_lock(&dp->con->lock);
...@@ -198,9 +213,20 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt, ...@@ -198,9 +213,20 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
svdm_version = typec_altmode_get_svdm_version(alt);
if (svdm_version < 0) {
mutex_unlock(&dp->con->lock);
return svdm_version;
}
switch (cmd_type) { switch (cmd_type) {
case CMDT_INIT: case CMDT_INIT:
dp->header = VDO(USB_TYPEC_DP_SID, 1, SVDM_VER_1_0, cmd); if (PD_VDO_SVDM_VER(header) < svdm_version) {
typec_partner_set_svdm_version(dp->con->partner, PD_VDO_SVDM_VER(header));
svdm_version = PD_VDO_SVDM_VER(header);
}
dp->header = VDO(USB_TYPEC_DP_SID, 1, svdm_version, cmd);
dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE); dp->header |= VDO_OPOS(USB_TYPEC_DP_MODE);
switch (cmd) { switch (cmd) {
......
...@@ -1052,6 +1052,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) ...@@ -1052,6 +1052,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
cap->revision = ucsi->cap.typec_version; cap->revision = ucsi->cap.typec_version;
cap->pd_revision = ucsi->cap.pd_version; cap->pd_revision = ucsi->cap.pd_version;
cap->svdm_version = SVDM_VER_2_0;
cap->prefer_role = TYPEC_NO_PREFERRED_ROLE; cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;
if (con->cap.op_mode & UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY) if (con->cap.op_mode & UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment