diff options
author | Vijay Hiremath <vijay.p.hiremath@intel.com> | 2020-01-30 11:15:16 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-02-04 04:07:48 +0000 |
commit | 0978c5b16a2e459f29beb1256b1ae5f2e3025768 (patch) | |
tree | d480e46d5cc7fa4d93c8e52596db76db01548631 /common/usb_pd_alt_mode_dfp.c | |
parent | f051362829eae11ef620ebc4881b16793fa61589 (diff) | |
download | chrome-ec-0978c5b16a2e459f29beb1256b1ae5f2e3025768.tar.gz |
TCPMv1/v2: Move pd_dfp_dp_get_pin_mode() to common file
BUG=b:148528713
BRANCH=none
TEST=make buildall -j
Change-Id: I9192762e7eba55d659d1ad282e62ad3849e41b65
Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2032155
Reviewed-by: Keith Short <keithshort@chromium.org>
Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Diffstat (limited to 'common/usb_pd_alt_mode_dfp.c')
-rw-r--r-- | common/usb_pd_alt_mode_dfp.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c new file mode 100644 index 0000000000..c581b0077d --- /dev/null +++ b/common/usb_pd_alt_mode_dfp.c @@ -0,0 +1,61 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Alternate Mode Downstream Facing Port (DFP) USB-PD module. + */ + +#include "usb_pd.h" +#include "util.h" + +/* + * This algorithm defaults to choosing higher pin config over lower ones in + * order to prefer multi-function if desired. + * + * NAME | SIGNALING | OUTPUT TYPE | MULTI-FUNCTION | PIN CONFIG + * ------------------------------------------------------------- + * A | USB G2 | ? | no | 00_0001 + * B | USB G2 | ? | yes | 00_0010 + * C | DP | CONVERTED | no | 00_0100 + * D | PD | CONVERTED | yes | 00_1000 + * E | DP | DP | no | 01_0000 + * F | PD | DP | yes | 10_0000 + * + * if UFP has NOT asserted multi-function preferred code masks away B/D/F + * leaving only A/C/E. For single-output dongles that should leave only one + * possible pin config depending on whether its a converter DP->(VGA|HDMI) or DP + * output. If UFP is a USB-C receptacle it may assert C/D/E/F. The DFP USB-C + * receptacle must always choose C/D in those cases. + */ +int pd_dfp_dp_get_pin_mode(int port, uint32_t status) +{ + struct svdm_amode_data *modep = + pd_get_amode_data(port, USB_SID_DISPLAYPORT); + uint32_t mode_caps; + uint32_t pin_caps; + + if (!modep) + return 0; + + mode_caps = modep->data->mode_vdo[modep->opos - 1]; + + /* TODO(crosbug.com/p/39656) revisit with DFP that can be a sink */ + pin_caps = PD_DP_PIN_CAPS(mode_caps); + + /* if don't want multi-function then ignore those pin configs */ + if (!PD_VDO_DPSTS_MF_PREF(status)) + pin_caps &= ~MODE_DP_PIN_MF_MASK; + + /* TODO(crosbug.com/p/39656) revisit if DFP drives USB Gen 2 signals */ + pin_caps &= ~MODE_DP_PIN_BR2_MASK; + + /* if C/D present they have precedence over E/F for USB-C->USB-C */ + if (pin_caps & (MODE_DP_PIN_C | MODE_DP_PIN_D)) + pin_caps &= ~(MODE_DP_PIN_E | MODE_DP_PIN_F); + + /* get_next_bit returns undefined for zero */ + if (!pin_caps) + return 0; + + return 1 << get_next_bit(&pin_caps); +} |