From c3355f3b3207b4038b05899c4670255ac1bc40d5 Mon Sep 17 00:00:00 2001 From: Linyu Yuan Date: Thu, 9 Jul 2020 11:10:54 +0800 Subject: [PATCH] usb: misc: nb7vpq904m: support 4 lanes display change to DP only mode when display is 4 lanes. Change-Id: I5bd383ccc44afc2d60fff7068f0c52f45a3a93a5 Signed-off-by: Linyu Yuan --- drivers/usb/dwc3/dwc3-msm.c | 6 +++ drivers/usb/misc/Kconfig | 4 ++ drivers/usb/misc/ssusb-redriver-nb7vpq904m.c | 43 +++++++++++++++++++- include/linux/usb/redriver.h | 22 ++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 include/linux/usb/redriver.h diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 60e12d6c18b7..ba3679758e76 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "core.h" #include "gadget.h" @@ -3985,6 +3986,7 @@ int dwc3_msm_release_ss_lane(struct device *dev) { struct dwc3_msm *mdwc = dev_get_drvdata(dev); struct dwc3 *dwc = NULL; + struct device_node *ssusb_redriver_node; if (mdwc == NULL) { dev_err(dev, "dwc3-msm is not initialized yet.\n"); @@ -4002,6 +4004,10 @@ int dwc3_msm_release_ss_lane(struct device *dev) flush_work(&mdwc->resume_work); drain_workqueue(mdwc->sm_usb_wq); + ssusb_redriver_node = + of_parse_phandle(mdwc->dev->of_node, "ssusb_redriver", 0); + redriver_release_usb_lanes(ssusb_redriver_node); + mdwc->ss_release_called = true; if (mdwc->id_state == DWC3_ID_GROUND) { /* stop USB host mode */ diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index ee57cb297173..664f61a64827 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -266,8 +266,12 @@ config USB_CHAOSKEY To compile this driver as a module, choose M here: the module will be called chaoskey. +config USB_REDRIVER + bool + config USB_REDRIVER_NB7VPQ904M tristate "USB 3.1 Gen1/Gen2 10Gbps re-driver driver for NB7VPQ904M" depends on USB_PHY + select USB_REDRIVER help Say Y here if you want to support USB super speed re-driver NB7VPQ904M. diff --git a/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c index 4e0f18549a6d..1bc4e250f0c3 100644 --- a/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c +++ b/drivers/usb/misc/ssusb-redriver-nb7vpq904m.c @@ -14,6 +14,7 @@ #include #include #include +#include /* priority: INT_MAX >= x >= 0 */ #define NOTIFIER_PRIORITY 1 @@ -503,10 +504,21 @@ static int ssusb_redriver_ucsi_notifier(struct notifier_block *nb, struct ucsi_glink_constat_info *info = data; enum operation_mode op_mode; - if (info->partner_usb && info->partner_alternate_mode) + /* + * when connect a DP only cable, + * ucsi set usb flag first, then set usb and alternate mode + * after dp start link training. + * it should only set alternate_mode flag ??? + */ + if (info->partner_usb && info->partner_alternate_mode) { + if (redriver->op_mode == OP_MODE_DP) + return NOTIFY_OK; op_mode = OP_MODE_USB_AND_DP; - else if (info->partner_usb) + } else if (info->partner_usb) { + if (redriver->op_mode == OP_MODE_DP) + return NOTIFY_OK; op_mode = OP_MODE_USB; + } else if (info->partner_alternate_mode) op_mode = OP_MODE_DP; else @@ -534,6 +546,33 @@ static int ssusb_redriver_ucsi_notifier(struct notifier_block *nb, return NOTIFY_OK; } +int redriver_release_usb_lanes(struct device_node *node) +{ + struct ssusb_redriver *redriver; + struct i2c_client *client; + + if (!node) + return -EINVAL; + + client = of_find_i2c_device_by_node(node); + if (!client) + return -EINVAL; + + redriver = i2c_get_clientdata(client); + + if (redriver->op_mode == OP_MODE_DP) + return 0; + + dev_dbg(redriver->dev, "display notify 4 lane mode\n"); + redriver->op_mode = OP_MODE_DP; + + ssusb_redriver_channel_update(redriver); + ssusb_redriver_gen_dev_set(redriver); + + return 0; +} +EXPORT_SYMBOL(redriver_release_usb_lanes); + static void ssusb_redriver_orientation_gpio_init( struct ssusb_redriver *redriver) { diff --git a/include/linux/usb/redriver.h b/include/linux/usb/redriver.h new file mode 100644 index 000000000000..7b49225820ae --- /dev/null +++ b/include/linux/usb/redriver.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef __LINUX_USB_REDRIVER_H +#define __LINUX_USB_REDRIVER_H + +#ifdef CONFIG_USB_REDRIVER + +int redriver_release_usb_lanes(struct device_node *node); + +#else + +static inline int redriver_release_usb_lanes(struct device_node *node) +{ + return 0; +} + +#endif + +#endif /*__LINUX_USB_REDRIVER_H */