diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/usb_pd_alt_mode_dfp.c | 61 | ||||
-rw-r--r-- | common/usb_pd_policy.c | 51 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 52 |
4 files changed, 62 insertions, 103 deletions
diff --git a/common/build.mk b/common/build.mk index 04ec98bcd0..35aa626809 100644 --- a/common/build.mk +++ b/common/build.mk @@ -148,6 +148,7 @@ common-$(CONFIG_USB_POWER_DELIVERY)+=usb_common.o usb_pd_host_cmd.o ifeq ($(CONFIG_USB_SM_FRAMEWORK),) common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o endif +common-$(CONFIG_USB_PD_ALT_MODE_DFP)+=usb_pd_alt_mode_dfp.o common-$(CONFIG_USB_PD_LOGGING)+=event_log.o pd_log.o common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o 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); +} diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index 25dfea72f9..022cfab1ab 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -953,57 +953,6 @@ static void dfp_consume_attention(int port, uint32_t *payload) modep->fx->attention(port, payload); } -/* - * 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); -} - int pd_dfp_exit_mode(int port, uint16_t svid, int opos) { struct svdm_amode_data *modep; diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 12a991db90..b69b0acfbf 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -4839,58 +4839,6 @@ static void dfp_consume_attention(int port, uint32_t *payload) modep->fx->attention(port, payload); } -/* - * 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); -} - int pd_dfp_exit_mode(int port, uint16_t svid, int opos) { struct svdm_amode_data *modep; |