This series adds mux control support for USB and DP alternate modes on
devices using the cros-ec-typec driver with Type C switch handles
provided by firmware bindings.
The first patch imports some recent updates to the
EC_CMD_USB_PD_MUX_INFO bit fields from the Chrome EC
code base[1], while the rest add the aforementioned functionality.
This series depends on the following patch :
https://lkml.org/lkml/2020/5/19/1219
[1] : https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h
Prashant Malani (4):
platform/chrome: cros_ec: Update mux state bits
platform/chrome: typec: Register PD CTRL cmd v2
platform/chrome: typec: Add USB mux control
platform/chrome: typec: Support DP alt mode
drivers/platform/chrome/cros_ec_typec.c | 190 ++++++++++++++++--
.../linux/platform_data/cros_ec_commands.h | 14 +-
2 files changed, 187 insertions(+), 17 deletions(-)
--
2.27.0.rc0.183.gde8f92d652-goog
Sync the EC_CMD_USB_PD_MUX_INFO mux state bit fields with the Chrome EC
code base. The newly added bit fields will be used for cros-ec-typec mux
control.
Signed-off-by: Prashant Malani <[email protected]>
---
include/linux/platform_data/cros_ec_commands.h | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/include/linux/platform_data/cros_ec_commands.h b/include/linux/platform_data/cros_ec_commands.h
index 69210881ebac..a7b0fc440c35 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -5207,11 +5207,15 @@ struct ec_params_usb_pd_mux_info {
} __ec_align1;
/* Flags representing mux state */
-#define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */
-#define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */
-#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */
-#define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */
-#define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */
+#define USB_PD_MUX_NONE 0 /* Open switch */
+#define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */
+#define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */
+#define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */
+#define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */
+#define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */
+#define USB_PD_MUX_SAFE_MODE BIT(5) /* DP is in safe mode */
+#define USB_PD_MUX_TBT_COMPAT_ENABLED BIT(6) /* TBT compat enabled */
+#define USB_PD_MUX_USB4_ENABLED BIT(7) /* USB4 enabled */
struct ec_response_usb_pd_mux_info {
uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */
--
2.27.0.rc0.183.gde8f92d652-goog
Recognize EC_CMD_USB_PD_CONTROL command version 2. This is necessary in
order to process Type C mux information (like DP alt mode pin
configuration), which is needed by the Type C Connector class API to
configure the Type C muxes correctly
While we are here, rename the struct member storing this version number
from cmd_ver to pd_ctrl_ver, which more accurately reflects what is
being stored.
Also, slightly change the logic for calling
cros_typec_set_port_params_*(). Now, v0 is called when pd_ctrl_ver is 0,
and v1 is called otherwise.
Signed-off-by: Prashant Malani <[email protected]>
---
drivers/platform/chrome/cros_ec_typec.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 6e79f917314b..d69a88464cef 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -37,7 +37,7 @@ struct cros_typec_data {
struct device *dev;
struct cros_ec_device *ec;
int num_ports;
- unsigned int cmd_ver;
+ unsigned int pd_ctrl_ver;
/* Array of ports, indexed by port number. */
struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
struct notifier_block nb;
@@ -340,7 +340,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
req.mux = USB_PD_CTRL_MUX_NO_CHANGE;
req.swap = USB_PD_CTRL_SWAP_NONE;
- ret = cros_typec_ec_command(typec, typec->cmd_ver,
+ ret = cros_typec_ec_command(typec, typec->pd_ctrl_ver,
EC_CMD_USB_PD_CONTROL, &req, sizeof(req),
&resp, sizeof(resp));
if (ret < 0)
@@ -351,7 +351,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity);
dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
- if (typec->cmd_ver == 1)
+ if (typec->pd_ctrl_ver != 0)
cros_typec_set_port_params_v1(typec, port_num, &resp);
else
cros_typec_set_port_params_v0(typec, port_num,
@@ -374,13 +374,15 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
if (ret < 0)
return ret;
- if (resp.version_mask & EC_VER_MASK(1))
- typec->cmd_ver = 1;
+ if (resp.version_mask & EC_VER_MASK(2))
+ typec->pd_ctrl_ver = 2;
+ else if (resp.version_mask & EC_VER_MASK(1))
+ typec->pd_ctrl_ver = 1;
else
- typec->cmd_ver = 0;
+ typec->pd_ctrl_ver = 0;
dev_dbg(typec->dev, "PD Control has version mask 0x%hhx\n",
- typec->cmd_ver);
+ typec->pd_ctrl_ver);
return 0;
}
--
2.27.0.rc0.183.gde8f92d652-goog
Add support to configure various Type C switches appropriately using the
Type C connector class API, when the Chrome OS EC informs the AP that
the USB operating mode has been entered.
Signed-off-by: Prashant Malani <[email protected]>
---
drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++-
1 file changed, 97 insertions(+), 3 deletions(-)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index d69a88464cef..9ebf9abed16f 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -14,6 +14,7 @@
#include <linux/platform_data/cros_usbpd_notify.h>
#include <linux/platform_device.h>
#include <linux/usb/typec.h>
+#include <linux/usb/typec_altmode.h>
#include <linux/usb/typec_mux.h>
#include <linux/usb/role.h>
@@ -30,6 +31,10 @@ struct cros_typec_port {
struct typec_switch *ori_sw;
struct typec_mux *mux;
struct usb_role_switch *role_sw;
+
+ /* Variables keeping track of switch state. */
+ struct typec_mux_state state;
+ uint8_t mux_flags;
};
/* Platform-specific data for the Chrome OS EC Type C controller. */
@@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
return ret;
}
+static void cros_typec_remove_partner(struct cros_typec_data *typec,
+ int port_num)
+{
+ struct cros_typec_port *port = typec->ports[port_num];
+
+ port->state.alt = NULL;
+ port->state.mode = TYPEC_STATE_USB;
+ port->state.data = NULL;
+
+ usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
+ typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
+ typec_mux_set(port->mux, &port->state);
+
+ typec_unregister_partner(port->partner);
+ port->partner = NULL;
+}
+
static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
int port_num, struct ec_response_usb_pd_control *resp)
{
@@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
} else {
if (!typec->ports[port_num]->partner)
return;
+ cros_typec_remove_partner(typec, port_num);
+ }
+}
+
+static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
+ struct ec_response_usb_pd_mux_info *resp)
+{
+ struct ec_params_usb_pd_mux_info req = {
+ .port = port_num,
+ };
+
+ return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req,
+ sizeof(req), resp, sizeof(*resp));
+}
+
+static int cros_typec_usb_safe_state(struct cros_typec_port *port)
+{
+ port->state.mode = TYPEC_STATE_SAFE;
+
+ return typec_mux_set(port->mux, &port->state);
+}
- typec_unregister_partner(typec->ports[port_num]->partner);
- typec->ports[port_num]->partner = NULL;
+int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
+ uint8_t mux_flags)
+{
+ struct cros_typec_port *port = typec->ports[port_num];
+ enum typec_orientation orientation;
+ int ret;
+
+ if (!port->partner)
+ return 0;
+
+ if (mux_flags & USB_PD_MUX_POLARITY_INVERTED)
+ orientation = TYPEC_ORIENTATION_REVERSE;
+ else
+ orientation = TYPEC_ORIENTATION_NORMAL;
+
+ ret = typec_switch_set(port->ori_sw, orientation);
+ if (ret)
+ return ret;
+
+ port->state.alt = NULL;
+ port->state.mode = TYPEC_STATE_USB;
+
+ if (mux_flags & USB_PD_MUX_SAFE_MODE)
+ ret = cros_typec_usb_safe_state(port);
+ else if (mux_flags & USB_PD_MUX_USB_ENABLED)
+ ret = typec_mux_set(port->mux, &port->state);
+ else {
+ dev_info(typec->dev,
+ "Unsupported mode requested, mux flags: %x\n",
+ mux_flags);
+ ret = -ENOTSUPP;
}
+
+ return ret;
}
static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
{
struct ec_params_usb_pd_control req;
struct ec_response_usb_pd_control_v1 resp;
+ struct ec_response_usb_pd_mux_info mux_resp;
int ret;
if (port_num < 0 || port_num >= typec->num_ports) {
@@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
cros_typec_set_port_params_v0(typec, port_num,
(struct ec_response_usb_pd_control *) &resp);
- return 0;
+ /* Update the switches if they exist, according to requested state */
+ ret = cros_typec_get_mux_info(typec, port_num, &mux_resp);
+ if (ret < 0) {
+ dev_warn(typec->dev,
+ "Failed to get mux info for port: %d, err = %d\n",
+ port_num, ret);
+ return 0;
+ }
+
+ /* No change needs to be made, let's exit early. */
+ if (typec->ports[port_num]->mux_flags == mux_resp.flags)
+ return 0;
+
+ typec->ports[port_num]->mux_flags = mux_resp.flags;
+ ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
+ if (ret)
+ dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
+
+ return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
+ !!(resp.role & PD_CTRL_RESP_ROLE_DATA));
}
static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
--
2.27.0.rc0.183.gde8f92d652-goog
Handle Chrome EC mux events to configure on-board muxes correctly while
entering DP alternate mode. Since we don't surface SVID and VDO
information regarding the DP alternate mode, configure the Type C
muxes directly from the port driver. Later, when mode discovery
information is correctly surfaced to the driver, we can register the DP
alternate mode driver and let it handle the mux configuration.
Also, modify the struct_typec_state state management to account for the
addition of DP alternate mode.
Signed-off-by: Prashant Malani <[email protected]>
---
drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++---
1 file changed, 80 insertions(+), 10 deletions(-)
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 9ebf9abed16f..509fc761906b 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -15,11 +15,18 @@
#include <linux/platform_device.h>
#include <linux/usb/typec.h>
#include <linux/usb/typec_altmode.h>
+#include <linux/usb/typec_dp.h>
#include <linux/usb/typec_mux.h>
#include <linux/usb/role.h>
#define DRV_NAME "cros-ec-typec"
+/* Supported alt modes. */
+enum {
+ CROS_EC_ALTMODE_DP = 0,
+ CROS_EC_ALTMODE_MAX,
+};
+
/* Per port data. */
struct cros_typec_port {
struct typec_port *port;
@@ -35,6 +42,9 @@ struct cros_typec_port {
/* Variables keeping track of switch state. */
struct typec_mux_state state;
uint8_t mux_flags;
+
+ /* Port alt modes. */
+ struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
};
/* Platform-specific data for the Chrome OS EC Type C controller. */
@@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
}
}
+/*
+ * Fake the alt mode structs until we actually start registering Type C port
+ * and partner alt modes.
+ */
+static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
+ int port_num)
+{
+ struct cros_typec_port *port = typec->ports[port_num];
+
+ /* All PD capable CrOS devices are assumed to support DP altmode. */
+ port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
+ port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
+
+ port->state.alt = NULL;
+ port->state.mode = TYPEC_STATE_USB;
+ port->state.data = NULL;
+}
+
static int cros_typec_init_ports(struct cros_typec_data *typec)
{
struct device *dev = typec->dev;
@@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
if (ret)
dev_dbg(dev, "No switch control for port %d\n",
port_num);
+
+ cros_typec_register_port_altmodes(typec, port_num);
}
return 0;
@@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port)
return typec_mux_set(port->mux, &port->state);
}
+/* Spoof the VDOs that were likely communicated by the partner. */
+static int cros_typec_enable_dp(struct cros_typec_data *typec,
+ int port_num,
+ struct ec_response_usb_pd_control_v2 *pd_ctrl)
+{
+ struct cros_typec_port *port = typec->ports[port_num];
+ struct typec_displayport_data dp_data;
+ int ret;
+
+ if (typec->pd_ctrl_ver < 2) {
+ dev_err(typec->dev,
+ "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
+ return -ENOTSUPP;
+ }
+
+ /* Status VDO. */
+ dp_data.status = DP_STATUS_ENABLED;
+ if (port->mux_flags & USB_PD_MUX_HPD_IRQ)
+ dp_data.status |= DP_STATUS_IRQ_HPD;
+ if (port->mux_flags & USB_PD_MUX_HPD_LVL)
+ dp_data.status |= DP_STATUS_HPD_STATE;
+
+ /* Configuration VDO. */
+ dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
+ if (!port->state.alt) {
+ port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP];
+ ret = cros_typec_usb_safe_state(port);
+ if (ret)
+ return ret;
+ }
+
+ port->state.data = &dp_data;
+ port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
+
+ return typec_mux_set(port->mux, &port->state);
+}
+
int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
- uint8_t mux_flags)
+ uint8_t mux_flags,
+ struct ec_response_usb_pd_control_v2 *pd_ctrl)
{
struct cros_typec_port *port = typec->ports[port_num];
enum typec_orientation orientation;
@@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
if (ret)
return ret;
- port->state.alt = NULL;
- port->state.mode = TYPEC_STATE_USB;
-
- if (mux_flags & USB_PD_MUX_SAFE_MODE)
+ if (mux_flags & USB_PD_MUX_DP_ENABLED) {
+ ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
+ } else if (mux_flags & USB_PD_MUX_SAFE_MODE) {
ret = cros_typec_usb_safe_state(port);
- else if (mux_flags & USB_PD_MUX_USB_ENABLED)
+ } else if (mux_flags & USB_PD_MUX_USB_ENABLED) {
+ port->state.alt = NULL;
+ port->state.mode = TYPEC_STATE_USB;
ret = typec_mux_set(port->mux, &port->state);
- else {
+ } else {
dev_info(typec->dev,
"Unsupported mode requested, mux flags: %x\n",
mux_flags);
@@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
{
struct ec_params_usb_pd_control req;
- struct ec_response_usb_pd_control_v1 resp;
+ struct ec_response_usb_pd_control_v2 resp;
struct ec_response_usb_pd_mux_info mux_resp;
int ret;
@@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
if (typec->pd_ctrl_ver != 0)
- cros_typec_set_port_params_v1(typec, port_num, &resp);
+ cros_typec_set_port_params_v1(typec, port_num,
+ (struct ec_response_usb_pd_control_v1 *)&resp);
else
cros_typec_set_port_params_v0(typec, port_num,
(struct ec_response_usb_pd_control *) &resp);
@@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
return 0;
typec->ports[port_num]->mux_flags = mux_resp.flags;
- ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
+ ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp);
if (ret)
dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
--
2.27.0.rc0.183.gde8f92d652-goog
Hi,
On Thu, May 28, 2020 at 04:36:10AM -0700, Prashant Malani wrote:
> Handle Chrome EC mux events to configure on-board muxes correctly while
> entering DP alternate mode. Since we don't surface SVID and VDO
> information regarding the DP alternate mode, configure the Type C
> muxes directly from the port driver. Later, when mode discovery
> information is correctly surfaced to the driver, we can register the DP
> alternate mode driver and let it handle the mux configuration.
>
> Also, modify the struct_typec_state state management to account for the
> addition of DP alternate mode.
>
> Signed-off-by: Prashant Malani <[email protected]>
Sorry, forgot to mention (and will add to subsequent versions):
Suggested-by: Heikki Krogerus <[email protected]>
> ---
> drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++---
> 1 file changed, 80 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 9ebf9abed16f..509fc761906b 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -15,11 +15,18 @@
> #include <linux/platform_device.h>
> #include <linux/usb/typec.h>
> #include <linux/usb/typec_altmode.h>
> +#include <linux/usb/typec_dp.h>
> #include <linux/usb/typec_mux.h>
> #include <linux/usb/role.h>
>
> #define DRV_NAME "cros-ec-typec"
>
> +/* Supported alt modes. */
> +enum {
> + CROS_EC_ALTMODE_DP = 0,
> + CROS_EC_ALTMODE_MAX,
> +};
> +
> /* Per port data. */
> struct cros_typec_port {
> struct typec_port *port;
> @@ -35,6 +42,9 @@ struct cros_typec_port {
> /* Variables keeping track of switch state. */
> struct typec_mux_state state;
> uint8_t mux_flags;
> +
> + /* Port alt modes. */
> + struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
> };
>
> /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
> }
> }
>
> +/*
> + * Fake the alt mode structs until we actually start registering Type C port
> + * and partner alt modes.
> + */
> +static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
> + int port_num)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> +
> + /* All PD capable CrOS devices are assumed to support DP altmode. */
> + port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
> + port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
> +
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> + port->state.data = NULL;
> +}
> +
> static int cros_typec_init_ports(struct cros_typec_data *typec)
> {
> struct device *dev = typec->dev;
> @@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
> if (ret)
> dev_dbg(dev, "No switch control for port %d\n",
> port_num);
> +
> + cros_typec_register_port_altmodes(typec, port_num);
> }
>
> return 0;
> @@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port)
> return typec_mux_set(port->mux, &port->state);
> }
>
> +/* Spoof the VDOs that were likely communicated by the partner. */
> +static int cros_typec_enable_dp(struct cros_typec_data *typec,
> + int port_num,
> + struct ec_response_usb_pd_control_v2 *pd_ctrl)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> + struct typec_displayport_data dp_data;
> + int ret;
> +
> + if (typec->pd_ctrl_ver < 2) {
> + dev_err(typec->dev,
> + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
> + return -ENOTSUPP;
> + }
> +
> + /* Status VDO. */
> + dp_data.status = DP_STATUS_ENABLED;
> + if (port->mux_flags & USB_PD_MUX_HPD_IRQ)
> + dp_data.status |= DP_STATUS_IRQ_HPD;
> + if (port->mux_flags & USB_PD_MUX_HPD_LVL)
> + dp_data.status |= DP_STATUS_HPD_STATE;
> +
> + /* Configuration VDO. */
> + dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
> + if (!port->state.alt) {
> + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP];
> + ret = cros_typec_usb_safe_state(port);
> + if (ret)
> + return ret;
> + }
> +
> + port->state.data = &dp_data;
> + port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
> +
> + return typec_mux_set(port->mux, &port->state);
> +}
> +
> int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> - uint8_t mux_flags)
> + uint8_t mux_flags,
> + struct ec_response_usb_pd_control_v2 *pd_ctrl)
> {
> struct cros_typec_port *port = typec->ports[port_num];
> enum typec_orientation orientation;
> @@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> if (ret)
> return ret;
>
> - port->state.alt = NULL;
> - port->state.mode = TYPEC_STATE_USB;
> -
> - if (mux_flags & USB_PD_MUX_SAFE_MODE)
> + if (mux_flags & USB_PD_MUX_DP_ENABLED) {
> + ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
> + } else if (mux_flags & USB_PD_MUX_SAFE_MODE) {
> ret = cros_typec_usb_safe_state(port);
> - else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> + } else if (mux_flags & USB_PD_MUX_USB_ENABLED) {
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> ret = typec_mux_set(port->mux, &port->state);
> - else {
> + } else {
> dev_info(typec->dev,
> "Unsupported mode requested, mux flags: %x\n",
> mux_flags);
> @@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> {
> struct ec_params_usb_pd_control req;
> - struct ec_response_usb_pd_control_v1 resp;
> + struct ec_response_usb_pd_control_v2 resp;
> struct ec_response_usb_pd_mux_info mux_resp;
> int ret;
>
> @@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
>
> if (typec->pd_ctrl_ver != 0)
> - cros_typec_set_port_params_v1(typec, port_num, &resp);
> + cros_typec_set_port_params_v1(typec, port_num,
> + (struct ec_response_usb_pd_control_v1 *)&resp);
> else
> cros_typec_set_port_params_v0(typec, port_num,
> (struct ec_response_usb_pd_control *) &resp);
> @@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> return 0;
>
> typec->ports[port_num]->mux_flags = mux_resp.flags;
> - ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp);
> if (ret)
> dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
>
> --
> 2.27.0.rc0.183.gde8f92d652-goog
>
Hi,
On Thu, May 28, 2020 at 04:36:07AM -0700, Prashant Malani wrote:
> Add support to configure various Type C switches appropriately using the
> Type C connector class API, when the Chrome OS EC informs the AP that
> the USB operating mode has been entered.
>
> Signed-off-by: Prashant Malani <[email protected]>
Forgot to mention (and will add in subsequent versions):
Suggested-by: Heikki Krogerus <[email protected]>
> ---
> drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++-
> 1 file changed, 97 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index d69a88464cef..9ebf9abed16f 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -14,6 +14,7 @@
> #include <linux/platform_data/cros_usbpd_notify.h>
> #include <linux/platform_device.h>
> #include <linux/usb/typec.h>
> +#include <linux/usb/typec_altmode.h>
> #include <linux/usb/typec_mux.h>
> #include <linux/usb/role.h>
>
> @@ -30,6 +31,10 @@ struct cros_typec_port {
> struct typec_switch *ori_sw;
> struct typec_mux *mux;
> struct usb_role_switch *role_sw;
> +
> + /* Variables keeping track of switch state. */
> + struct typec_mux_state state;
> + uint8_t mux_flags;
> };
>
> /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
> return ret;
> }
>
> +static void cros_typec_remove_partner(struct cros_typec_data *typec,
> + int port_num)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> +
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> + port->state.data = NULL;
> +
> + usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
> + typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
> + typec_mux_set(port->mux, &port->state);
> +
> + typec_unregister_partner(port->partner);
> + port->partner = NULL;
> +}
> +
> static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
> int port_num, struct ec_response_usb_pd_control *resp)
> {
> @@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
> } else {
> if (!typec->ports[port_num]->partner)
> return;
> + cros_typec_remove_partner(typec, port_num);
> + }
> +}
> +
> +static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
> + struct ec_response_usb_pd_mux_info *resp)
> +{
> + struct ec_params_usb_pd_mux_info req = {
> + .port = port_num,
> + };
> +
> + return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req,
> + sizeof(req), resp, sizeof(*resp));
> +}
> +
> +static int cros_typec_usb_safe_state(struct cros_typec_port *port)
> +{
> + port->state.mode = TYPEC_STATE_SAFE;
> +
> + return typec_mux_set(port->mux, &port->state);
> +}
>
> - typec_unregister_partner(typec->ports[port_num]->partner);
> - typec->ports[port_num]->partner = NULL;
> +int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> + uint8_t mux_flags)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> + enum typec_orientation orientation;
> + int ret;
> +
> + if (!port->partner)
> + return 0;
> +
> + if (mux_flags & USB_PD_MUX_POLARITY_INVERTED)
> + orientation = TYPEC_ORIENTATION_REVERSE;
> + else
> + orientation = TYPEC_ORIENTATION_NORMAL;
> +
> + ret = typec_switch_set(port->ori_sw, orientation);
> + if (ret)
> + return ret;
> +
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> +
> + if (mux_flags & USB_PD_MUX_SAFE_MODE)
> + ret = cros_typec_usb_safe_state(port);
> + else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> + ret = typec_mux_set(port->mux, &port->state);
> + else {
> + dev_info(typec->dev,
> + "Unsupported mode requested, mux flags: %x\n",
> + mux_flags);
> + ret = -ENOTSUPP;
> }
> +
> + return ret;
> }
>
> static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> {
> struct ec_params_usb_pd_control req;
> struct ec_response_usb_pd_control_v1 resp;
> + struct ec_response_usb_pd_mux_info mux_resp;
> int ret;
>
> if (port_num < 0 || port_num >= typec->num_ports) {
> @@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> cros_typec_set_port_params_v0(typec, port_num,
> (struct ec_response_usb_pd_control *) &resp);
>
> - return 0;
> + /* Update the switches if they exist, according to requested state */
> + ret = cros_typec_get_mux_info(typec, port_num, &mux_resp);
> + if (ret < 0) {
> + dev_warn(typec->dev,
> + "Failed to get mux info for port: %d, err = %d\n",
> + port_num, ret);
> + return 0;
> + }
> +
> + /* No change needs to be made, let's exit early. */
> + if (typec->ports[port_num]->mux_flags == mux_resp.flags)
> + return 0;
> +
> + typec->ports[port_num]->mux_flags = mux_resp.flags;
> + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> + if (ret)
> + dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
> +
> + return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
> + !!(resp.role & PD_CTRL_RESP_ROLE_DATA));
> }
>
> static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
> --
> 2.27.0.rc0.183.gde8f92d652-goog
>
On Thu, May 28, 2020 at 04:36:05AM -0700, Prashant Malani wrote:
> Recognize EC_CMD_USB_PD_CONTROL command version 2. This is necessary in
> order to process Type C mux information (like DP alt mode pin
> configuration), which is needed by the Type C Connector class API to
> configure the Type C muxes correctly
>
> While we are here, rename the struct member storing this version number
> from cmd_ver to pd_ctrl_ver, which more accurately reflects what is
> being stored.
>
> Also, slightly change the logic for calling
> cros_typec_set_port_params_*(). Now, v0 is called when pd_ctrl_ver is 0,
> and v1 is called otherwise.
>
> Signed-off-by: Prashant Malani <[email protected]>
LGTM. One nitpick bellow, but don't prepare v2 just because of that.
FWIW:
Reviewed-by: Heikki Krogerus <[email protected]>
> ---
> drivers/platform/chrome/cros_ec_typec.c | 16 +++++++++-------
> 1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 6e79f917314b..d69a88464cef 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -37,7 +37,7 @@ struct cros_typec_data {
> struct device *dev;
> struct cros_ec_device *ec;
> int num_ports;
> - unsigned int cmd_ver;
> + unsigned int pd_ctrl_ver;
> /* Array of ports, indexed by port number. */
> struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
> struct notifier_block nb;
> @@ -340,7 +340,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> req.mux = USB_PD_CTRL_MUX_NO_CHANGE;
> req.swap = USB_PD_CTRL_SWAP_NONE;
>
> - ret = cros_typec_ec_command(typec, typec->cmd_ver,
> + ret = cros_typec_ec_command(typec, typec->pd_ctrl_ver,
> EC_CMD_USB_PD_CONTROL, &req, sizeof(req),
> &resp, sizeof(resp));
> if (ret < 0)
> @@ -351,7 +351,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity);
> dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
>
> - if (typec->cmd_ver == 1)
> + if (typec->pd_ctrl_ver != 0)
How about:
if (typec->pd_ctrl_ver)
> cros_typec_set_port_params_v1(typec, port_num, &resp);
> else
> cros_typec_set_port_params_v0(typec, port_num,
> @@ -374,13 +374,15 @@ static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
> if (ret < 0)
> return ret;
>
> - if (resp.version_mask & EC_VER_MASK(1))
> - typec->cmd_ver = 1;
> + if (resp.version_mask & EC_VER_MASK(2))
> + typec->pd_ctrl_ver = 2;
> + else if (resp.version_mask & EC_VER_MASK(1))
> + typec->pd_ctrl_ver = 1;
> else
> - typec->cmd_ver = 0;
> + typec->pd_ctrl_ver = 0;
>
> dev_dbg(typec->dev, "PD Control has version mask 0x%hhx\n",
> - typec->cmd_ver);
> + typec->pd_ctrl_ver);
>
> return 0;
> }
thanks,
--
heikki
On Thu, May 28, 2020 at 04:36:07AM -0700, Prashant Malani wrote:
> Add support to configure various Type C switches appropriately using the
> Type C connector class API, when the Chrome OS EC informs the AP that
> the USB operating mode has been entered.
>
> Signed-off-by: Prashant Malani <[email protected]>
Reviewed-by: Heikki Krogerus <[email protected]>
> ---
> drivers/platform/chrome/cros_ec_typec.c | 100 +++++++++++++++++++++++-
> 1 file changed, 97 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index d69a88464cef..9ebf9abed16f 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -14,6 +14,7 @@
> #include <linux/platform_data/cros_usbpd_notify.h>
> #include <linux/platform_device.h>
> #include <linux/usb/typec.h>
> +#include <linux/usb/typec_altmode.h>
> #include <linux/usb/typec_mux.h>
> #include <linux/usb/role.h>
>
> @@ -30,6 +31,10 @@ struct cros_typec_port {
> struct typec_switch *ori_sw;
> struct typec_mux *mux;
> struct usb_role_switch *role_sw;
> +
> + /* Variables keeping track of switch state. */
> + struct typec_mux_state state;
> + uint8_t mux_flags;
> };
>
> /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -264,6 +269,23 @@ static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
> return ret;
> }
>
> +static void cros_typec_remove_partner(struct cros_typec_data *typec,
> + int port_num)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> +
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> + port->state.data = NULL;
> +
> + usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
> + typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
> + typec_mux_set(port->mux, &port->state);
> +
> + typec_unregister_partner(port->partner);
> + port->partner = NULL;
> +}
> +
> static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
> int port_num, struct ec_response_usb_pd_control *resp)
> {
> @@ -317,16 +339,69 @@ static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
> } else {
> if (!typec->ports[port_num]->partner)
> return;
> + cros_typec_remove_partner(typec, port_num);
> + }
> +}
> +
> +static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num,
> + struct ec_response_usb_pd_mux_info *resp)
> +{
> + struct ec_params_usb_pd_mux_info req = {
> + .port = port_num,
> + };
> +
> + return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req,
> + sizeof(req), resp, sizeof(*resp));
> +}
> +
> +static int cros_typec_usb_safe_state(struct cros_typec_port *port)
> +{
> + port->state.mode = TYPEC_STATE_SAFE;
> +
> + return typec_mux_set(port->mux, &port->state);
> +}
>
> - typec_unregister_partner(typec->ports[port_num]->partner);
> - typec->ports[port_num]->partner = NULL;
> +int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> + uint8_t mux_flags)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> + enum typec_orientation orientation;
> + int ret;
> +
> + if (!port->partner)
> + return 0;
> +
> + if (mux_flags & USB_PD_MUX_POLARITY_INVERTED)
> + orientation = TYPEC_ORIENTATION_REVERSE;
> + else
> + orientation = TYPEC_ORIENTATION_NORMAL;
> +
> + ret = typec_switch_set(port->ori_sw, orientation);
> + if (ret)
> + return ret;
> +
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> +
> + if (mux_flags & USB_PD_MUX_SAFE_MODE)
> + ret = cros_typec_usb_safe_state(port);
> + else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> + ret = typec_mux_set(port->mux, &port->state);
> + else {
> + dev_info(typec->dev,
> + "Unsupported mode requested, mux flags: %x\n",
> + mux_flags);
> + ret = -ENOTSUPP;
> }
> +
> + return ret;
> }
>
> static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> {
> struct ec_params_usb_pd_control req;
> struct ec_response_usb_pd_control_v1 resp;
> + struct ec_response_usb_pd_mux_info mux_resp;
> int ret;
>
> if (port_num < 0 || port_num >= typec->num_ports) {
> @@ -357,7 +432,26 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> cros_typec_set_port_params_v0(typec, port_num,
> (struct ec_response_usb_pd_control *) &resp);
>
> - return 0;
> + /* Update the switches if they exist, according to requested state */
> + ret = cros_typec_get_mux_info(typec, port_num, &mux_resp);
> + if (ret < 0) {
> + dev_warn(typec->dev,
> + "Failed to get mux info for port: %d, err = %d\n",
> + port_num, ret);
> + return 0;
> + }
> +
> + /* No change needs to be made, let's exit early. */
> + if (typec->ports[port_num]->mux_flags == mux_resp.flags)
> + return 0;
> +
> + typec->ports[port_num]->mux_flags = mux_resp.flags;
> + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> + if (ret)
> + dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
> +
> + return usb_role_switch_set_role(typec->ports[port_num]->role_sw,
> + !!(resp.role & PD_CTRL_RESP_ROLE_DATA));
> }
>
> static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
> --
> 2.27.0.rc0.183.gde8f92d652-goog
--
heikki
On Thu, May 28, 2020 at 04:36:10AM -0700, Prashant Malani wrote:
> Handle Chrome EC mux events to configure on-board muxes correctly while
> entering DP alternate mode. Since we don't surface SVID and VDO
> information regarding the DP alternate mode, configure the Type C
> muxes directly from the port driver. Later, when mode discovery
> information is correctly surfaced to the driver, we can register the DP
> alternate mode driver and let it handle the mux configuration.
>
> Also, modify the struct_typec_state state management to account for the
> addition of DP alternate mode.
>
> Signed-off-by: Prashant Malani <[email protected]>
FWIW:
Reviewed-by: Heikki Krogerus <[email protected]>
> ---
> drivers/platform/chrome/cros_ec_typec.c | 90 ++++++++++++++++++++++---
> 1 file changed, 80 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 9ebf9abed16f..509fc761906b 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -15,11 +15,18 @@
> #include <linux/platform_device.h>
> #include <linux/usb/typec.h>
> #include <linux/usb/typec_altmode.h>
> +#include <linux/usb/typec_dp.h>
> #include <linux/usb/typec_mux.h>
> #include <linux/usb/role.h>
>
> #define DRV_NAME "cros-ec-typec"
>
> +/* Supported alt modes. */
> +enum {
> + CROS_EC_ALTMODE_DP = 0,
> + CROS_EC_ALTMODE_MAX,
> +};
> +
> /* Per port data. */
> struct cros_typec_port {
> struct typec_port *port;
> @@ -35,6 +42,9 @@ struct cros_typec_port {
> /* Variables keeping track of switch state. */
> struct typec_mux_state state;
> uint8_t mux_flags;
> +
> + /* Port alt modes. */
> + struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
> };
>
> /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -142,6 +152,24 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
> }
> }
>
> +/*
> + * Fake the alt mode structs until we actually start registering Type C port
> + * and partner alt modes.
> + */
> +static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
> + int port_num)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> +
> + /* All PD capable CrOS devices are assumed to support DP altmode. */
> + port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
> + port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
> +
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> + port->state.data = NULL;
> +}
> +
> static int cros_typec_init_ports(struct cros_typec_data *typec)
> {
> struct device *dev = typec->dev;
> @@ -205,6 +233,8 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
> if (ret)
> dev_dbg(dev, "No switch control for port %d\n",
> port_num);
> +
> + cros_typec_register_port_altmodes(typec, port_num);
> }
>
> return 0;
> @@ -361,8 +391,46 @@ static int cros_typec_usb_safe_state(struct cros_typec_port *port)
> return typec_mux_set(port->mux, &port->state);
> }
>
> +/* Spoof the VDOs that were likely communicated by the partner. */
> +static int cros_typec_enable_dp(struct cros_typec_data *typec,
> + int port_num,
> + struct ec_response_usb_pd_control_v2 *pd_ctrl)
> +{
> + struct cros_typec_port *port = typec->ports[port_num];
> + struct typec_displayport_data dp_data;
> + int ret;
> +
> + if (typec->pd_ctrl_ver < 2) {
> + dev_err(typec->dev,
> + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
> + return -ENOTSUPP;
> + }
> +
> + /* Status VDO. */
> + dp_data.status = DP_STATUS_ENABLED;
> + if (port->mux_flags & USB_PD_MUX_HPD_IRQ)
> + dp_data.status |= DP_STATUS_IRQ_HPD;
> + if (port->mux_flags & USB_PD_MUX_HPD_LVL)
> + dp_data.status |= DP_STATUS_HPD_STATE;
> +
> + /* Configuration VDO. */
> + dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
> + if (!port->state.alt) {
> + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP];
> + ret = cros_typec_usb_safe_state(port);
> + if (ret)
> + return ret;
> + }
> +
> + port->state.data = &dp_data;
> + port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
> +
> + return typec_mux_set(port->mux, &port->state);
> +}
> +
> int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> - uint8_t mux_flags)
> + uint8_t mux_flags,
> + struct ec_response_usb_pd_control_v2 *pd_ctrl)
> {
> struct cros_typec_port *port = typec->ports[port_num];
> enum typec_orientation orientation;
> @@ -380,14 +448,15 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> if (ret)
> return ret;
>
> - port->state.alt = NULL;
> - port->state.mode = TYPEC_STATE_USB;
> -
> - if (mux_flags & USB_PD_MUX_SAFE_MODE)
> + if (mux_flags & USB_PD_MUX_DP_ENABLED) {
> + ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
> + } else if (mux_flags & USB_PD_MUX_SAFE_MODE) {
> ret = cros_typec_usb_safe_state(port);
> - else if (mux_flags & USB_PD_MUX_USB_ENABLED)
> + } else if (mux_flags & USB_PD_MUX_USB_ENABLED) {
> + port->state.alt = NULL;
> + port->state.mode = TYPEC_STATE_USB;
> ret = typec_mux_set(port->mux, &port->state);
> - else {
> + } else {
> dev_info(typec->dev,
> "Unsupported mode requested, mux flags: %x\n",
> mux_flags);
> @@ -400,7 +469,7 @@ int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
> static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> {
> struct ec_params_usb_pd_control req;
> - struct ec_response_usb_pd_control_v1 resp;
> + struct ec_response_usb_pd_control_v2 resp;
> struct ec_response_usb_pd_mux_info mux_resp;
> int ret;
>
> @@ -427,7 +496,8 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
>
> if (typec->pd_ctrl_ver != 0)
> - cros_typec_set_port_params_v1(typec, port_num, &resp);
> + cros_typec_set_port_params_v1(typec, port_num,
> + (struct ec_response_usb_pd_control_v1 *)&resp);
> else
> cros_typec_set_port_params_v0(typec, port_num,
> (struct ec_response_usb_pd_control *) &resp);
> @@ -446,7 +516,7 @@ static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
> return 0;
>
> typec->ports[port_num]->mux_flags = mux_resp.flags;
> - ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags);
> + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp);
> if (ret)
> dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
>
> --
> 2.27.0.rc0.183.gde8f92d652-goog
thanks,
--
heikki
Hi Prashant,
On 28/5/20 13:36, Prashant Malani wrote:
> This series adds mux control support for USB and DP alternate modes on
> devices using the cros-ec-typec driver with Type C switch handles
> provided by firmware bindings.
>
> The first patch imports some recent updates to the
> EC_CMD_USB_PD_MUX_INFO bit fields from the Chrome EC
> code base[1], while the rest add the aforementioned functionality.
>
> This series depends on the following patch :
> https://lkml.org/lkml/2020/5/19/1219
>
> [1] : https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h
>
> Prashant Malani (4):
> platform/chrome: cros_ec: Update mux state bits
> platform/chrome: typec: Register PD CTRL cmd v2
> platform/chrome: typec: Add USB mux control
> platform/chrome: typec: Support DP alt mode
>
> drivers/platform/chrome/cros_ec_typec.c | 190 ++++++++++++++++--
> .../linux/platform_data/cros_ec_commands.h | 14 +-
> 2 files changed, 187 insertions(+), 17 deletions(-)
>
Tweaked a bit the subject, s/typec/cros_ec_typec/ and queued the four patches
for 5.9.
Thanks,
Enric
Thanks Enric!
On Thu, Jun 25, 2020 at 4:56 AM Enric Balletbo i Serra
<[email protected]> wrote:
>
> Hi Prashant,
>
> On 28/5/20 13:36, Prashant Malani wrote:
> > This series adds mux control support for USB and DP alternate modes on
> > devices using the cros-ec-typec driver with Type C switch handles
> > provided by firmware bindings.
> >
> > The first patch imports some recent updates to the
> > EC_CMD_USB_PD_MUX_INFO bit fields from the Chrome EC
> > code base[1], while the rest add the aforementioned functionality.
> >
> > This series depends on the following patch :
> > https://lkml.org/lkml/2020/5/19/1219
> >
> > [1] : https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/ec_commands.h
> >
> > Prashant Malani (4):
> > platform/chrome: cros_ec: Update mux state bits
> > platform/chrome: typec: Register PD CTRL cmd v2
> > platform/chrome: typec: Add USB mux control
> > platform/chrome: typec: Support DP alt mode
> >
> > drivers/platform/chrome/cros_ec_typec.c | 190 ++++++++++++++++--
> > .../linux/platform_data/cros_ec_commands.h | 14 +-
> > 2 files changed, 187 insertions(+), 17 deletions(-)
> >
>
> Tweaked a bit the subject, s/typec/cros_ec_typec/ and queued the four patches
> for 5.9.
>
> Thanks,
> Enric