From 35fa27dbcfa5d54b24ea92d5432c4e032e14a1f6 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Tue, 10 Dec 2024 16:33:42 +0800 Subject: [PATCH] usb: typec: tcpci_husb311: tcpm reset when resume with dp alt mode For some Type-C to DP Adapter, It need reset tcpm state when resume To avoid some thing wrong with display appear. Change-Id: Ie23d62ded05cdbc438cd354c5b886ddc45210b42 Signed-off-by: Zhang Yubing --- drivers/usb/typec/tcpm/tcpci_husb311.c | 41 +++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/tcpm/tcpci_husb311.c b/drivers/usb/typec/tcpm/tcpci_husb311.c index faed6b65fb70..31e8e28eb28d 100644 --- a/drivers/usb/typec/tcpm/tcpci_husb311.c +++ b/drivers/usb/typec/tcpm/tcpci_husb311.c @@ -344,6 +344,45 @@ static int husb311_pm_suspend(struct device *dev) return 0; } +static int match_fwnode(struct device *dev, void *data) +{ + return dev_fwnode(dev) == data; +} + +static bool is_partner_altmode_device_registered(struct device *dev) +{ + struct device *port, *partner, *altmode; + struct fwnode_handle *fwnode; + char device_name[20]; + + /* get typec port device */ + fwnode = device_get_named_child_node(dev, "connector"); + if (!fwnode) + return false; + + port = device_find_child(dev, fwnode, match_fwnode); + fwnode_handle_put(fwnode); + if (!port) + return false; + + /* get the partner device */ + snprintf(device_name, sizeof(device_name), "%s-partner", dev_name(port)); + partner = device_find_child_by_name(port, device_name); + put_device(port); + if (!partner) + return false; + + /* get the altmode device, now only dp register */ + snprintf(device_name, sizeof(device_name), "%s.0", dev_name(partner)); + altmode = device_find_child_by_name(partner, device_name); + put_device(partner); + if (!altmode) + return false; + put_device(altmode); + + return true; +} + static int husb311_pm_resume(struct device *dev) { struct husb311_chip *chip = dev->driver_data; @@ -365,7 +404,7 @@ static int husb311_pm_resume(struct device *dev) * husb311 powered off in suspend, the value would reset to default. */ ret = husb311_read8(chip, HUSB311_TCPC_FILTER, &filter); - if (filter != 0x0F || ret < 0) { + if (filter != 0x0F || ret < 0 || is_partner_altmode_device_registered(dev)) { ret = husb311_sw_reset(chip); if (ret < 0) { dev_err(chip->dev, "fail to soft reset, ret = %d\n", ret);