From 87e8cd610313fa7fe902c2fd359ade18e6b22ef0 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Fri, 2 Dec 2016 11:42:11 +0800 Subject: [PATCH] usb_pd_policy: Automatically swap vconn if adapter requests it During discovery, if adapter requests vconn power in the AMA flags, make sure that we provide vconn. This, for example, is necessary for the Apple HDMI adapter to work on boot, when connected in S5. In that case, adapter does request vconn swap, but we reject that as the system is off, and, therefore 5V supply is off. On boot, we send another discovery request, which will detect this case and swap the power. BRANCH=none BUG=chromium:644663 TEST=On elm, S5. Plug adapter with power+HDMI. Switch on elm, type "pd 0 vdm ident" in console, display works. Change-Id: I55b6658c2bc0574b8427ae086f61daf03730a725 Reviewed-on: https://chromium-review.googlesource.com/415697 Commit-Ready: Nicolas Boichat Tested-by: Nicolas Boichat Reviewed-by: Vincent Palatin --- common/usb_pd_policy.c | 7 ++++++- common/usb_pd_protocol.c | 12 ++++++++++++ include/usb_pd.h | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index 9c42f5f5a3..fe204b9301 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -271,8 +271,13 @@ static void dfp_consume_identity(int port, int cnt, uint32_t *payload) */ if (!PD_VDO_AMA_VBUS_REQ(payload[VDO_I(AMA)])) pd_power_supply_reset(port); + +#if defined(CONFIG_USB_PD_DUAL_ROLE) && defined(CONFIG_USBC_VCONN_SWAP) + /* Adapter is requesting vconn, try to supply it */ + if (PD_VDO_AMA_VCONN_REQ(payload[VDO_I(AMA)])) + pd_try_vconn_src(port); +#endif break; - /* TODO(crosbug.com/p/30645) provide vconn support here */ default: break; } diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 1e9c4192ae..1055ed61c7 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -844,6 +844,18 @@ static void pd_request_vconn_swap(int port) set_state(port, PD_STATE_VCONN_SWAP_SEND); task_wake(PD_PORT_TO_TASK_ID(port)); } + +void pd_try_vconn_src(int port) +{ + /* + * If we don't currently provide vconn, and we can supply it, send + * a vconn swap request. + */ + if (!(pd[port].flags & PD_FLAGS_VCONN_ON)) { + if (pd_check_vconn_swap(port)) + pd_request_vconn_swap(port); + } +} #endif #endif /* CONFIG_USB_PD_DUAL_ROLE */ diff --git a/include/usb_pd.h b/include/usb_pd.h index e322fed381..4eef319ae2 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -1514,6 +1514,14 @@ int pd_get_partner_data_swap_capable(int port); */ void pd_request_power_swap(int port); +/** + * Try to become the VCONN source, if we are not already the source and the + * other side is willing to accept a VCONN swap. + * + * @param port USB-C port number + */ +void pd_try_vconn_src(int port); + /** * Request data swap command to be issued *