* [PATCH 0/2] usb: typec: support Qualcomm WCD939X USB SubSystem Altmode Mux
@ 2023-12-08 15:27 Neil Armstrong
2023-12-08 15:27 ` [PATCH 1/2] dt-bindings: usb: Document WCD939x USB SubSystem Altmode/Analog Audio Switch Neil Armstrong
2023-12-08 15:27 ` [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver Neil Armstrong
0 siblings, 2 replies; 7+ messages in thread
From: Neil Armstrong @ 2023-12-08 15:27 UTC (permalink / raw)
To: Andy Gross, Bjorn Andersson, Konrad Dybcio, Greg Kroah-Hartman,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus,
Liam Girdwood, Mark Brown
Cc: linux-arm-msm, linux-usb, devicetree, linux-kernel,
Neil Armstrong
Qualcomm WCD9390/WCD9395 is a standalone Hi-Fi audio codec IC with a
functionally separate USB SubSystem for Altmode/Analog Audio Switch
accessible over an I2C interface.
It provides switching USB-C USB2.0 lines between USB and Audio Headphones
speaker lines, and the USB-C SBU lines between DisplayPort AUX and Audio
Headphones Microphone/Ground.
The Audio Headphone and Microphone data path between the Codec and the
USB-C Mux subsystems are external to the IC, thus requiring DT
port-endpoint graph description to handle USB-C altmode & orientation
switching for Audio Accessory Mode.
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
---
Neil Armstrong (2):
dt-bindings: usb: Document WCD939x USB SubSystem Altmode/Analog Audio Switch
usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver
.../bindings/usb/qcom,wcd939x-usbss.yaml | 99 +++
drivers/usb/typec/mux/Kconfig | 10 +
drivers/usb/typec/mux/Makefile | 1 +
drivers/usb/typec/mux/wcd939x-usbss.c | 779 +++++++++++++++++++++
4 files changed, 889 insertions(+)
---
base-commit: bc63de6e6ba0b16652c5fb4b9c9916b9e7ca1f23
change-id: 20231208-topic-sm8650-upstream-wcd939x-usbss-030c011a1709
Best regards,
--
Neil Armstrong <neil.armstrong@linaro.org>
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/2] dt-bindings: usb: Document WCD939x USB SubSystem Altmode/Analog Audio Switch 2023-12-08 15:27 [PATCH 0/2] usb: typec: support Qualcomm WCD939X USB SubSystem Altmode Mux Neil Armstrong @ 2023-12-08 15:27 ` Neil Armstrong 2023-12-09 8:11 ` Krzysztof Kozlowski 2023-12-08 15:27 ` [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver Neil Armstrong 1 sibling, 1 reply; 7+ messages in thread From: Neil Armstrong @ 2023-12-08 15:27 UTC (permalink / raw) To: Andy Gross, Bjorn Andersson, Konrad Dybcio, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus, Liam Girdwood, Mark Brown Cc: linux-arm-msm, linux-usb, devicetree, linux-kernel, Neil Armstrong Document the Qualcomm WCD9390/WCD9395 USB SubSystem Altmode/Analog Audio Switch which is a separate USB SubSystem for Altmode/Analog Audio Switch accessible over an I2C interface. Since Audio Headphone and Microphone data path between the Codec and the USB-C Mux subsystems are external to the IC, it requires a second port to handle USB-C altmode & orientation switching for Audio Accessory Mode to the Codec SubSystem. Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> --- .../bindings/usb/qcom,wcd939x-usbss.yaml | 99 ++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/qcom,wcd939x-usbss.yaml b/Documentation/devicetree/bindings/usb/qcom,wcd939x-usbss.yaml new file mode 100644 index 000000000000..da86b1d119d4 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/qcom,wcd939x-usbss.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/qcom,wcd939x-usbss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm WCD9380/WCD9385 USB SubSystem Altmode/Analog Audio Switch + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + +description: | + Qualcomm WCD9390/WCD9395 is a standalone Hi-Fi audio codec IC with a functionally + separate USB SubSystem for Altmode/Analog Audio Switch accessible over an I2C interface. + The Audio Headphone and Microphone data path between the Codec and the USB-C Mux + subsystems are external to the IC, thus requiring DT port-endpoint graph description + to handle USB-C altmode & orientation switching for Audio Accessory Mode. + +properties: + compatible: + oneOf: + - const: qcom,wcd9390-usbss + - items: + - const: qcom,wcd9395-usbss + - const: qcom,wcd9390-usbss + + reg: + maxItems: 1 + + reset-gpios: true + + vdd-supply: + description: USBSS VDD power supply + + mode-switch: + description: Flag the port as possible handle of altmode switching + type: boolean + + orientation-switch: + description: Flag the port as possible handler of orientation switching + type: boolean + + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: + A port node to link the WCD939x USB SubSystem to a TypeC controller for the + purpose of handling altmode muxing and orientation switching. + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: + A port node to link the WCD939x USB SubSystem to the Codec SubSystem for the + purpose of handling USB-C Audio Accessory Mode muxing and orientation switching. + +required: + - compatible + - reg + - ports + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + typec-mux@42 { + compatible = "qcom,wcd9390-usbss"; + reg = <0x42>; + + vdd-supply = <&vreg_bob>; + + mode-switch; + orientation-switch; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + wcd9390_usbss_sbu: endpoint { + remote-endpoint = <&typec_sbu>; + }; + }; + port@1 { + reg = <1>; + wcd9390_usbss_codec: endpoint { + remote-endpoint = <&wcd9390_codec_usbss>; + }; + }; + }; + }; + }; +... -- 2.34.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] dt-bindings: usb: Document WCD939x USB SubSystem Altmode/Analog Audio Switch 2023-12-08 15:27 ` [PATCH 1/2] dt-bindings: usb: Document WCD939x USB SubSystem Altmode/Analog Audio Switch Neil Armstrong @ 2023-12-09 8:11 ` Krzysztof Kozlowski 0 siblings, 0 replies; 7+ messages in thread From: Krzysztof Kozlowski @ 2023-12-09 8:11 UTC (permalink / raw) To: Neil Armstrong, Andy Gross, Bjorn Andersson, Konrad Dybcio, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus, Liam Girdwood, Mark Brown Cc: linux-arm-msm, linux-usb, devicetree, linux-kernel On 08/12/2023 16:27, Neil Armstrong wrote: > Document the Qualcomm WCD9390/WCD9395 USB SubSystem Altmode/Analog Audio Switch > which is a separate USB SubSystem for Altmode/Analog Audio Switch accessible > over an I2C interface. > > Since Audio Headphone and Microphone data path between the Codec and the USB-C Mux > subsystems are external to the IC, it requires a second port to handle USB-C altmode > & orientation switching for Audio Accessory Mode to the Codec SubSystem. > > Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> > --- > .../bindings/usb/qcom,wcd939x-usbss.yaml | 99 ++++++++++++++++++++++ > 1 file changed, 99 insertions(+) > > diff --git a/Documentation/devicetree/bindings/usb/qcom,wcd939x-usbss.yaml b/Documentation/devicetree/bindings/usb/qcom,wcd939x-usbss.yaml > new file mode 100644 > index 000000000000..da86b1d119d4 > --- /dev/null > +++ b/Documentation/devicetree/bindings/usb/qcom,wcd939x-usbss.yaml > @@ -0,0 +1,99 @@ > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/usb/qcom,wcd939x-usbss.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Qualcomm WCD9380/WCD9385 USB SubSystem Altmode/Analog Audio Switch > + > +maintainers: > + - Neil Armstrong <neil.armstrong@linaro.org> > + > +description: | Do not need '|' unless you need to preserve formatting. > + Qualcomm WCD9390/WCD9395 is a standalone Hi-Fi audio codec IC with a functionally > + separate USB SubSystem for Altmode/Analog Audio Switch accessible over an I2C interface. Please wrap at 80. In other descriptions as well. > + The Audio Headphone and Microphone data path between the Codec and the USB-C Mux > + subsystems are external to the IC, thus requiring DT port-endpoint graph description > + to handle USB-C altmode & orientation switching for Audio Accessory Mode. > + > +properties: > + compatible: > + oneOf: > + - const: qcom,wcd9390-usbss > + - items: > + - const: qcom,wcd9395-usbss > + - const: qcom,wcd9390-usbss > + > + reg: > + maxItems: 1 > + > + reset-gpios: true This is the only GPIO from common GPIOs which actually needs maxItems. Please add maxItems: 1 Best regards, Krzysztof ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver 2023-12-08 15:27 [PATCH 0/2] usb: typec: support Qualcomm WCD939X USB SubSystem Altmode Mux Neil Armstrong 2023-12-08 15:27 ` [PATCH 1/2] dt-bindings: usb: Document WCD939x USB SubSystem Altmode/Analog Audio Switch Neil Armstrong @ 2023-12-08 15:27 ` Neil Armstrong 2023-12-09 8:06 ` Krzysztof Kozlowski ` (2 more replies) 1 sibling, 3 replies; 7+ messages in thread From: Neil Armstrong @ 2023-12-08 15:27 UTC (permalink / raw) To: Andy Gross, Bjorn Andersson, Konrad Dybcio, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus, Liam Girdwood, Mark Brown Cc: linux-arm-msm, linux-usb, devicetree, linux-kernel, Neil Armstrong Qualcomm WCD9390/WCD9395 is a standalone Hi-Fi audio codec IC with a functionally separate USB SubSystem for Altmode/Analog Audio Switch accessible over an I2C interface. It provides switching USB-C USB2.0 lines between USB and Audio Headphones speaker lines, and the USB-C SBU lines between DisplayPort AUX and Audio Headphones Microphone/Ground. The Audio Headphone and Microphone data path between the Codec and the USB-C Mux subsystems are external to the IC, thus requiring DT port-endpoint graph description to handle USB-C altmode & orientation switching for Audio Accessory Mode. Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> --- drivers/usb/typec/mux/Kconfig | 10 + drivers/usb/typec/mux/Makefile | 1 + drivers/usb/typec/mux/wcd939x-usbss.c | 779 ++++++++++++++++++++++++++++++++++ 3 files changed, 790 insertions(+) diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig index 38416fb0cc3c..d2cb5e733e57 100644 --- a/drivers/usb/typec/mux/Kconfig +++ b/drivers/usb/typec/mux/Kconfig @@ -56,4 +56,14 @@ config TYPEC_MUX_PTN36502 Say Y or M if your system has a NXP PTN36502 Type-C redriver chip found on some devices with a Type-C port. +config TYPEC_MUX_WCD939X_USBSS + tristate "Qualcomm WCD939x USBSS Analog Audio Switch driver" + depends on I2C + select REGMAP_I2C + help + Driver for the Qualcomm WCD939x Audio Codec USBSS domain which + provides support for muxing analog audio and sideband signals on a + common USB Type-C connector. + If compiled as a module, the module will be named wcd939x-usbss. + endmenu diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile index 9d6a5557b0bd..57dc9ac6f8dc 100644 --- a/drivers/usb/typec/mux/Makefile +++ b/drivers/usb/typec/mux/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_TYPEC_MUX_PI3USB30532) += pi3usb30532.o obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o +obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o diff --git a/drivers/usb/typec/mux/wcd939x-usbss.c b/drivers/usb/typec/mux/wcd939x-usbss.c new file mode 100644 index 000000000000..6fd7afc848eb --- /dev/null +++ b/drivers/usb/typec/mux/wcd939x-usbss.c @@ -0,0 +1,779 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (C) 2023 Linaro Ltd. + */ + +#include <linux/bits.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/regmap.h> +#include <linux/usb/typec_dp.h> +#include <linux/usb/typec_mux.h> + +#define WCD_USBSS_PMP_OUT1 0x2 + +#define WCD_USBSS_DP_DN_MISC1 0x20 + +#define WCD_USBSS_DP_DN_MISC1_DP_PCOMP_2X_DYN_BST_ON_EN BIT(3) +#define WCD_USBSS_DP_DN_MISC1_DN_PCOMP_2X_DYN_BST_ON_EN BIT(0) + +#define WCD_USBSS_MG1_EN 0x24 + +#define WCD_USBSS_MG1_EN_CT_SNS_EN BIT(1) + +#define WCD_USBSS_MG1_BIAS 0x25 + +#define WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN BIT(3) + +#define WCD_USBSS_MG1_MISC 0x27 + +#define WCD_USBSS_MG1_MISC_PCOMP_2X_DYN_BST_ON_EN BIT(5) + +#define WCD_USBSS_MG2_EN 0x28 + +#define WCD_USBSS_MG2_EN_CT_SNS_EN BIT(1) + +#define WCD_USBSS_MG2_BIAS 0x29 + +#define WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN BIT(3) + +#define WCD_USBSS_MG2_MISC 0x30 + +#define WCD_USBSS_MG2_MISC_PCOMP_2X_DYN_BST_ON_EN BIT(5) + +#define WCD_USBSS_DISP_AUXP_THRESH 0x80 + +#define WCD_USBSS_DISP_AUXP_THRESH_DISP_AUXP_OVPON_CM GENMASK(7, 5) + +#define WCD_USBSS_DISP_AUXP_CTL 0x81 + +#define WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF GENMASK(2, 0) + +#define WCD_USBSS_CPLDO_CTL2 0xa1 + +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE 0x403 + +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DEVICE_ENABLE BIT(7) +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES BIT(6) +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES BIT(5) +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES BIT(4) +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES BIT(3) +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES BIT(2) +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES BIT(1) +#define WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES BIT(0) + +#define WCD_USBSS_SWITCH_SELECT0 0x404 + +#define WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES BIT(7) /* 1-> MG2 */ +#define WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES BIT(6) /* 1-> MG2 */ +#define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES GENMASK(5, 4) +#define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES GENMASK(3, 2) +#define WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES BIT(1) /* 1-> SBU2 */ +#define WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES BIT(0) /* 1-> MG2 */ + +#define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_L 0 +#define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN 1 +#define WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN2 2 + +#define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_R 0 +#define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DP 1 +#define WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DR2 2 + +#define WCD_USBSS_SWITCH_SELECT1 0x405 + +#define WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES BIT(0) /* 1-> MG2 */ + +#define WCD_USBSS_DELAY_R_SW 0x40d +#define WCD_USBSS_DELAY_MIC_SW 0x40e +#define WCD_USBSS_DELAY_SENSE_SW 0x40f +#define WCD_USBSS_DELAY_GND_SW 0x410 +#define WCD_USBSS_DELAY_L_SW 0x411 + +#define WCD_USBSS_FUNCTION_ENABLE 0x413 + +#define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT GENMASK(1, 0) + +#define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_MANUAL 1 +#define WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_AUDIO_FSM 2 + +#define WCD_USBSS_EQUALIZER1 0x415 + +#define WCD_USBSS_EQUALIZER1_EQ_EN BIT(7) +#define WCD_USBSS_EQUALIZER1_BW_SETTINGS GENMASK(6, 3) + +#define WCD_USBSS_USB_SS_CNTL 0x419 + +#define WCD_USBSS_USB_SS_CNTL_STANDBY_STATE BIT(4) +#define WCD_USBSS_USB_SS_CNTL_RCO_EN BIT(3) +#define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE GENMASK(2, 0) + +#define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_AATC 2 +#define WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_USB 5 + +#define WCD_USBSS_AUDIO_FSM_START 0x433 + +#define WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG BIT(0) + +#define WCD_USBSS_RATIO_SPKR_REXT_L_LSB 0x461 +#define WCD_USBSS_RATIO_SPKR_REXT_L_MSB 0x462 +#define WCD_USBSS_RATIO_SPKR_REXT_R_LSB 0x463 +#define WCD_USBSS_RATIO_SPKR_REXT_R_MSB 0x464 +#define WCD_USBSS_AUD_COEF_L_K0_0 0x475 +#define WCD_USBSS_AUD_COEF_L_K0_1 0x476 +#define WCD_USBSS_AUD_COEF_L_K0_2 0x477 +#define WCD_USBSS_AUD_COEF_L_K1_0 0x478 +#define WCD_USBSS_AUD_COEF_L_K1_1 0x479 +#define WCD_USBSS_AUD_COEF_L_K2_0 0x47a +#define WCD_USBSS_AUD_COEF_L_K2_1 0x47b +#define WCD_USBSS_AUD_COEF_L_K3_0 0x47c +#define WCD_USBSS_AUD_COEF_L_K3_1 0x47d +#define WCD_USBSS_AUD_COEF_L_K4_0 0x47e +#define WCD_USBSS_AUD_COEF_L_K4_1 0x47f +#define WCD_USBSS_AUD_COEF_L_K5_0 0x480 +#define WCD_USBSS_AUD_COEF_L_K5_1 0x481 +#define WCD_USBSS_AUD_COEF_R_K0_0 0x482 +#define WCD_USBSS_AUD_COEF_R_K0_1 0x483 +#define WCD_USBSS_AUD_COEF_R_K0_2 0x484 +#define WCD_USBSS_AUD_COEF_R_K1_0 0x485 +#define WCD_USBSS_AUD_COEF_R_K1_1 0x486 +#define WCD_USBSS_AUD_COEF_R_K2_0 0x487 +#define WCD_USBSS_AUD_COEF_R_K2_1 0x488 +#define WCD_USBSS_AUD_COEF_R_K3_0 0x489 +#define WCD_USBSS_AUD_COEF_R_K3_1 0x48a +#define WCD_USBSS_AUD_COEF_R_K4_0 0x48b +#define WCD_USBSS_AUD_COEF_R_K4_1 0x48c +#define WCD_USBSS_AUD_COEF_R_K5_0 0x48d +#define WCD_USBSS_AUD_COEF_R_K5_1 0x48e +#define WCD_USBSS_GND_COEF_L_K0_0 0x48f +#define WCD_USBSS_GND_COEF_L_K0_1 0x490 +#define WCD_USBSS_GND_COEF_L_K0_2 0x491 +#define WCD_USBSS_GND_COEF_L_K1_0 0x492 +#define WCD_USBSS_GND_COEF_L_K1_1 0x493 +#define WCD_USBSS_GND_COEF_L_K2_0 0x494 +#define WCD_USBSS_GND_COEF_L_K2_1 0x495 +#define WCD_USBSS_GND_COEF_L_K3_0 0x496 +#define WCD_USBSS_GND_COEF_L_K3_1 0x497 +#define WCD_USBSS_GND_COEF_L_K4_0 0x498 +#define WCD_USBSS_GND_COEF_L_K4_1 0x499 +#define WCD_USBSS_GND_COEF_L_K5_0 0x49a +#define WCD_USBSS_GND_COEF_L_K5_1 0x49b +#define WCD_USBSS_GND_COEF_R_K0_0 0x49c +#define WCD_USBSS_GND_COEF_R_K0_1 0x49d +#define WCD_USBSS_GND_COEF_R_K0_2 0x49e +#define WCD_USBSS_GND_COEF_R_K1_0 0x49f +#define WCD_USBSS_GND_COEF_R_K1_1 0x4a0 +#define WCD_USBSS_GND_COEF_R_K2_0 0x4a1 +#define WCD_USBSS_GND_COEF_R_K2_1 0x4a2 +#define WCD_USBSS_GND_COEF_R_K3_0 0x4a3 +#define WCD_USBSS_GND_COEF_R_K3_1 0x4a4 +#define WCD_USBSS_GND_COEF_R_K4_0 0x4a5 +#define WCD_USBSS_GND_COEF_R_K4_1 0x4a6 +#define WCD_USBSS_GND_COEF_R_K5_0 0x4a7 +#define WCD_USBSS_GND_COEF_R_K5_1 0x4a8 + +#define WCD_USBSS_MAX_REGISTER 0x4c1 + +struct wcd939x_usbss { + struct i2c_client *client; + struct gpio_desc *reset_gpio; + struct regulator *vdd_supply; + + /* used to serialize concurrent change requests */ + struct mutex lock; + + struct typec_switch_dev *sw; + struct typec_mux_dev *mux; + + struct regmap *regmap; + + struct typec_mux *codec; + struct typec_switch *codec_switch; + + enum typec_orientation orientation; + unsigned long mode; + unsigned int svid; +}; + +static const struct regmap_range_cfg wcd939x_usbss_ranges[] = { + { + .range_min = 0, + .range_max = WCD_USBSS_MAX_REGISTER, + .selector_reg = 0x0, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x100, + }, +}; + +static const struct regmap_config wcd939x_usbss_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = WCD_USBSS_MAX_REGISTER, + .ranges = wcd939x_usbss_ranges, + .num_ranges = ARRAY_SIZE(wcd939x_usbss_ranges), +}; + +/* Linearlizer coefficients for 32ohm load */ +static const struct { + unsigned int offset; + unsigned int mask; + unsigned int value; +} wcd939x_usbss_coeff_init[] = { + { WCD_USBSS_AUD_COEF_L_K5_0, GENMASK(7, 0), 0x39 }, + { WCD_USBSS_AUD_COEF_R_K5_0, GENMASK(7, 0), 0x39 }, + { WCD_USBSS_GND_COEF_L_K2_0, GENMASK(7, 0), 0xe8 }, + { WCD_USBSS_GND_COEF_L_K4_0, GENMASK(7, 0), 0x73 }, + { WCD_USBSS_GND_COEF_R_K2_0, GENMASK(7, 0), 0xe8 }, + { WCD_USBSS_GND_COEF_R_K4_0, GENMASK(7, 0), 0x73 }, + { WCD_USBSS_RATIO_SPKR_REXT_L_LSB, GENMASK(7, 0), 0x00 }, + { WCD_USBSS_RATIO_SPKR_REXT_L_MSB, GENMASK(6, 0), 0x04 }, + { WCD_USBSS_RATIO_SPKR_REXT_R_LSB, GENMASK(7, 0), 0x00 }, + { WCD_USBSS_RATIO_SPKR_REXT_R_MSB, GENMASK(6, 0), 0x04 }, +}; + +static int wcd939x_usbss_set(struct wcd939x_usbss *usbss) +{ + bool reverse = (usbss->orientation == TYPEC_ORIENTATION_REVERSE); + bool enable_audio = false; + bool enable_usb = false; + bool enable_dp = false; + int ret; + + /* USB Mode */ + if (usbss->mode < TYPEC_STATE_MODAL || + (!usbss->svid && (usbss->mode == TYPEC_MODE_USB2 || + usbss->mode == TYPEC_MODE_USB3))) { + enable_usb = true; + } else if (usbss->svid) { + switch (usbss->mode) { + /* DP Only */ + case TYPEC_DP_STATE_C: + case TYPEC_DP_STATE_E: + enable_dp = true; + break; + + /* DP + USB */ + case TYPEC_DP_STATE_D: + case TYPEC_DP_STATE_F: + enable_usb = true; + enable_dp = true; + break; + + default: + return -EOPNOTSUPP; + } + } else if (usbss->mode == TYPEC_MODE_AUDIO) { + enable_audio = true; + } else { + return -EOPNOTSUPP; + } + + /* Disable all switches */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES); + if (ret) + return ret; + + /* Clear switches */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, + WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES); + if (ret) + return ret; + + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, + WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); + if (ret) + return ret; + + /* Enable OVP_MG1_BIAS PCOMP_DYN_BST_EN */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG1_BIAS, + WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN); + if (ret) + return ret; + + /* Enable OVP_MG2_BIAS PCOMP_DYN_BST_EN */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG2_BIAS, + WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN); + if (ret) + return ret; + + /* Disable Equalizer in safe mode */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_EQUALIZER1, + WCD_USBSS_EQUALIZER1_EQ_EN); + if (ret) + return ret; + + /* Start FSM with all disabled, force write */ + ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START, + WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG, + WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG); + + /* 35us to allow the SBU switch to turn off */ + usleep_range(35, 1000); + + /* Setup Audio Accessory mux/switch */ + if (enable_audio) { + int i; + + /* + * AATC switch configuration: + * "Normal": + * - R: DNR + * - L: DNL + * - Sense: GSBU2 + * - Mic: MG1 + * - AGND: MG2 + * "Swapped": + * - R: DNR + * - L: DNL + * - Sense: GSBU1 + * - Mic: MG2 + * - AGND: MG1 + * Swapped information is given by the codec MBHC logic + */ + + /* Set AATC mode */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, + WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, + FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, + WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_AATC)); + if (ret) + return ret; + + /* Select L for DNL_SWITCHES and R for DPR_SWITCHES */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, + WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, + FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_L) | + FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_R)); + if (ret) + return ret; + + if (reverse) + /* Select MG2 for MIC, SBU1 for Sense */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, + WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES); + else + /* Select MG1 for MIC, SBU2 for Sense */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, + WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES); + if (ret) + return ret; + + if (reverse) + /* Disable OVP_MG1_BIAS PCOMP_DYN_BST_EN */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG1_BIAS, + WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN); + else + /* Disable OVP_MG2_BIAS PCOMP_DYN_BST_EN */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG2_BIAS, + WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN); + if (ret) + return ret; + + /* Enable SENSE, MIC switches */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, + WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES); + if (ret) + return ret; + + if (reverse) + /* Select MG1 for AGND_SWITCHES */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, + WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); + else + /* Select MG2 for AGND_SWITCHES */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, + WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); + if (ret) + return ret; + + /* Enable AGND switches */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, + WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES); + if (ret) + return ret; + + /* Enable DPR, DNL switches */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES); + if (ret) + return ret; + + /* Setup FSM delays */ + ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_L_SW, 0x02); + if (ret) + return ret; + + ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_R_SW, 0x02); + if (ret) + return ret; + + ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_MIC_SW, 0x01); + if (ret) + return ret; + + /* Start FSM, force write */ + ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START, + WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG, + WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG); + if (ret) + return ret; + + /* Default Linearlizer coefficients */ + for (i = 0; i < ARRAY_SIZE(wcd939x_usbss_coeff_init); ++i) + regmap_update_bits(usbss->regmap, + wcd939x_usbss_coeff_init[i].offset, + wcd939x_usbss_coeff_init[i].mask, + wcd939x_usbss_coeff_init[i].value); + + return 0; + } + + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, + WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, + FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, + WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_USB)); + if (ret) + return ret; + + /* Enable USB muxes */ + if (enable_usb) { + /* Do not enable Equalizer in safe mode */ + if (usbss->mode != TYPEC_STATE_SAFE) { + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_EQUALIZER1, + WCD_USBSS_EQUALIZER1_EQ_EN); + if (ret) + return ret; + } + + /* Select DN for DNL_SWITCHES and DP for DPR_SWITCHES */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, + WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, + FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN) | + FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DP)); + if (ret) + return ret; + + /* Enable DNL_SWITCHES and DPR_SWITCHES */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES); + if (ret) + return ret; + } + + /* Enable DP AUX muxes */ + if (enable_dp) { + /* Update Leakage Canceller Coefficient for AUXP pins */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_CTL, + WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF, + FIELD_PREP(WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF, + 5)); + if (ret) + return ret; + + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_THRESH, + WCD_USBSS_DISP_AUXP_THRESH_DISP_AUXP_OVPON_CM); + if (ret) + return ret; + + if (reverse) + /* Select MG2 for AUXP and MG1 for AUXM */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, + WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES); + else + /* Select MG1 for AUXP and MG2 for AUXM */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, + WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | + WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES, + WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES); + if (ret) + return ret; + + /* Enable DP_AUXP_TO_MGX and DP_AUXM_TO_MGX switches */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES | + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES); + + /* 15us to allow the SBU switch to turn on again */ + usleep_range(15, 1000); + } + + return 0; +} + +static int wcd939x_usbss_switch_set(struct typec_switch_dev *sw, + enum typec_orientation orientation) +{ + struct wcd939x_usbss *usbss = typec_switch_get_drvdata(sw); + int ret = 0; + + mutex_lock(&usbss->lock); + + if (usbss->orientation != orientation) { + usbss->orientation = orientation; + + ret = wcd939x_usbss_set(usbss); + } + + mutex_unlock(&usbss->lock); + + if (ret) + return ret; + + /* Report orientation to codec after switch has been done */ + return typec_switch_set(usbss->codec_switch, orientation); +} + +static int wcd939x_usbss_mux_set(struct typec_mux_dev *mux, + struct typec_mux_state *state) +{ + struct wcd939x_usbss *usbss = typec_mux_get_drvdata(mux); + int ret = 0; + + mutex_lock(&usbss->lock); + + if (usbss->mode != state->mode) { + usbss->mode = state->mode; + + if (state->alt) + usbss->svid = state->alt->svid; + else + usbss->svid = 0; // No SVID + + ret = wcd939x_usbss_set(usbss); + } + + mutex_unlock(&usbss->lock); + + if (ret) + return ret; + + /* Report event to codec after switch has been done */ + return typec_mux_set(usbss->codec, state); +} + +static int wcd939x_usbss_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct typec_switch_desc sw_desc = { }; + struct typec_mux_desc mux_desc = { }; + struct wcd939x_usbss *usbss; + int ret; + + usbss = devm_kzalloc(dev, sizeof(*usbss), GFP_KERNEL); + if (!usbss) + return -ENOMEM; + + usbss->client = client; + mutex_init(&usbss->lock); + + usbss->regmap = devm_regmap_init_i2c(client, &wcd939x_usbss_regmap_config); + if (IS_ERR(usbss->regmap)) + return dev_err_probe(dev, PTR_ERR(usbss->regmap), "failed to initialize regmap\n"); + + usbss->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(usbss->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(usbss->reset_gpio), + "unable to acquire reset gpio\n"); + + usbss->vdd_supply = devm_regulator_get_optional(dev, "vdd"); + if (IS_ERR(usbss->vdd_supply)) + return PTR_ERR(usbss->vdd_supply); + + /* Get Codec's MUX & Switch devices */ + usbss->codec = fwnode_typec_mux_get(dev->fwnode); + if (IS_ERR(usbss->codec)) + return dev_err_probe(dev, PTR_ERR(usbss->codec), + "failed to acquire codec mode-switch\n"); + + usbss->codec_switch = fwnode_typec_switch_get(dev->fwnode); + if (IS_ERR(usbss->codec_switch)) { + ret = dev_err_probe(dev, PTR_ERR(usbss->codec_switch), + "failed to acquire codec orientation-switch\n"); + goto err_mux_put; + } + + usbss->mode = TYPEC_STATE_SAFE; + usbss->orientation = TYPEC_ORIENTATION_NONE; + + gpiod_set_value(usbss->reset_gpio, 1); + + ret = regulator_enable(usbss->vdd_supply); + if (ret) { + dev_err(dev, "Failed to enable vdd: %d\n", ret); + goto err_mux_switch; + } + + msleep(20); + + gpiod_set_value(usbss->reset_gpio, 0); + + msleep(20); + + /* Disable standby */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, + WCD_USBSS_USB_SS_CNTL_STANDBY_STATE); + if (ret) + goto err_regulator_disable; + + /* Set manual mode by default */ + ret = regmap_update_bits(usbss->regmap, WCD_USBSS_FUNCTION_ENABLE, + WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT, + FIELD_PREP(WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT, + WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT_MANUAL)); + if (ret) + goto err_regulator_disable; + + /* Enable dynamic boosting for DP and DN */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_DP_DN_MISC1, + WCD_USBSS_DP_DN_MISC1_DP_PCOMP_2X_DYN_BST_ON_EN | + WCD_USBSS_DP_DN_MISC1_DN_PCOMP_2X_DYN_BST_ON_EN); + if (ret) + goto err_regulator_disable; + + /* Enable dynamic boosting for MG1 OVP */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG1_MISC, + WCD_USBSS_MG1_MISC_PCOMP_2X_DYN_BST_ON_EN); + if (ret) + goto err_regulator_disable; + + /* Enable dynamic boosting for MG2 OVP */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG2_MISC, + WCD_USBSS_MG2_MISC_PCOMP_2X_DYN_BST_ON_EN); + if (ret) + goto err_regulator_disable; + + /* Write 0xFF to WCD_USBSS_CPLDO_CTL2 */ + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_CPLDO_CTL2, 0xff); + if (ret) + goto err_regulator_disable; + + /* Set RCO_EN: WCD_USBSS_USB_SS_CNTL Bit<3> --> 0x0 --> 0x1 */ + ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, + WCD_USBSS_USB_SS_CNTL_RCO_EN); + if (ret) + goto err_regulator_disable; + + ret = regmap_set_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, + WCD_USBSS_USB_SS_CNTL_RCO_EN); + if (ret) + goto err_regulator_disable; + + /* Disable all switches but enable the mux */ + ret = regmap_write(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, + WCD_USBSS_SWITCH_SETTINGS_ENABLE_DEVICE_ENABLE); + if (ret) + goto err_regulator_disable; + + /* Setup in SAFE mode */ + ret = wcd939x_usbss_set(usbss); + if (ret) + goto err_regulator_disable; + + sw_desc.drvdata = usbss; + sw_desc.fwnode = dev_fwnode(dev); + sw_desc.set = wcd939x_usbss_switch_set; + + usbss->sw = typec_switch_register(dev, &sw_desc); + if (IS_ERR(usbss->sw)) { + ret = dev_err_probe(dev, PTR_ERR(usbss->sw), "failed to register typec switch\n"); + goto err_regulator_disable; + } + + mux_desc.drvdata = usbss; + mux_desc.fwnode = dev_fwnode(dev); + mux_desc.set = wcd939x_usbss_mux_set; + + usbss->mux = typec_mux_register(dev, &mux_desc); + if (IS_ERR(usbss->mux)) { + typec_switch_unregister(usbss->sw); + ret = dev_err_probe(dev, PTR_ERR(usbss->mux), "failed to register typec mux\n"); + goto err_switch_unregister; + } + + i2c_set_clientdata(client, usbss); + + return 0; + +err_switch_unregister: + typec_switch_unregister(usbss->sw); + +err_regulator_disable: + regulator_disable(usbss->vdd_supply); + +err_mux_switch: + typec_switch_put(usbss->codec_switch); + +err_mux_put: + typec_mux_put(usbss->codec); + + return ret; +} + +static void wcd939x_usbss_remove(struct i2c_client *client) +{ + struct wcd939x_usbss *usbss = i2c_get_clientdata(client); + + typec_mux_unregister(usbss->mux); + typec_switch_unregister(usbss->sw); + + regulator_disable(usbss->vdd_supply); + + typec_mux_put(usbss->codec); +} + +static const struct i2c_device_id wcd939x_usbss_table[] = { + { "wcd9390-usbss" }, + { "wcd9395-usbss" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wcd939x_usbss_table); + +static const struct of_device_id wcd939x_usbss_of_table[] = { + { .compatible = "qcom,wcd9390-usbss" }, + { .compatible = "qcom,wcd9395-usbss" }, + { } +}; +MODULE_DEVICE_TABLE(of, wcd939x_usbss_of_table); + +static struct i2c_driver wcd939x_usbss_driver = { + .driver = { + .name = "wcd939x-usbss", + .of_match_table = wcd939x_usbss_of_table, + }, + .probe = wcd939x_usbss_probe, + .remove = wcd939x_usbss_remove, + .id_table = wcd939x_usbss_table, +}; +module_i2c_driver(wcd939x_usbss_driver); + +MODULE_DESCRIPTION("Qualcomm WCD939x USBSS driver"); +MODULE_LICENSE("GPL"); -- 2.34.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver 2023-12-08 15:27 ` [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver Neil Armstrong @ 2023-12-09 8:06 ` Krzysztof Kozlowski 2023-12-09 8:42 ` Christophe JAILLET 2023-12-10 20:05 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: Krzysztof Kozlowski @ 2023-12-09 8:06 UTC (permalink / raw) To: Neil Armstrong, Andy Gross, Bjorn Andersson, Konrad Dybcio, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus, Liam Girdwood, Mark Brown Cc: linux-arm-msm, linux-usb, devicetree, linux-kernel On 08/12/2023 16:27, Neil Armstrong wrote: > Qualcomm WCD9390/WCD9395 is a standalone Hi-Fi audio codec IC with a > functionally separate USB SubSystem for Altmode/Analog Audio Switch > accessible over an I2C interface. > > It provides switching USB-C USB2.0 lines between USB and Audio Headphones ... > + > +static const struct i2c_device_id wcd939x_usbss_table[] = { > + { "wcd9390-usbss" }, > + { "wcd9395-usbss" }, You can drop this entry (also in of_device_id). Best regards, Krzysztof ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver 2023-12-08 15:27 ` [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver Neil Armstrong 2023-12-09 8:06 ` Krzysztof Kozlowski @ 2023-12-09 8:42 ` Christophe JAILLET 2023-12-10 20:05 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: Christophe JAILLET @ 2023-12-09 8:42 UTC (permalink / raw) To: Neil Armstrong, Andy Gross, Bjorn Andersson, Konrad Dybcio, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus, Liam Girdwood, Mark Brown Cc: linux-arm-msm, linux-usb, devicetree, linux-kernel Le 08/12/2023 à 16:27, Neil Armstrong a écrit : > Qualcomm WCD9390/WCD9395 is a standalone Hi-Fi audio codec IC with a > functionally separate USB SubSystem for Altmode/Analog Audio Switch > accessible over an I2C interface. > > It provides switching USB-C USB2.0 lines between USB and Audio Headphones > speaker lines, and the USB-C SBU lines between DisplayPort AUX and Audio > Headphones Microphone/Ground. > > The Audio Headphone and Microphone data path between the Codec and the > USB-C Mux subsystems are external to the IC, thus requiring DT > port-endpoint graph description to handle USB-C altmode & orientation > switching for Audio Accessory Mode. > > Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org> > --- ... > + usbss->sw = typec_switch_register(dev, &sw_desc); > + if (IS_ERR(usbss->sw)) { > + ret = dev_err_probe(dev, PTR_ERR(usbss->sw), "failed to register typec switch\n"); > + goto err_regulator_disable; > + } > + > + mux_desc.drvdata = usbss; > + mux_desc.fwnode = dev_fwnode(dev); > + mux_desc.set = wcd939x_usbss_mux_set; > + > + usbss->mux = typec_mux_register(dev, &mux_desc); > + if (IS_ERR(usbss->mux)) { > + typec_switch_unregister(usbss->sw); Already called at the 'err_switch_unregister' label below. > + ret = dev_err_probe(dev, PTR_ERR(usbss->mux), "failed to register typec mux\n"); > + goto err_switch_unregister; > + } > + > + i2c_set_clientdata(client, usbss); > + > + return 0; > + > +err_switch_unregister: > + typec_switch_unregister(usbss->sw); > + > +err_regulator_disable: > + regulator_disable(usbss->vdd_supply); > + > +err_mux_switch: > + typec_switch_put(usbss->codec_switch); > + > +err_mux_put: > + typec_mux_put(usbss->codec); > + > + return ret; > +} > + > +static void wcd939x_usbss_remove(struct i2c_client *client) > +{ > + struct wcd939x_usbss *usbss = i2c_get_clientdata(client); > + > + typec_mux_unregister(usbss->mux); > + typec_switch_unregister(usbss->sw); > + > + regulator_disable(usbss->vdd_supply); Based on error hadling of the probe: typec_switch_put() missing? > + > + typec_mux_put(usbss->codec); > +} CJ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver 2023-12-08 15:27 ` [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver Neil Armstrong 2023-12-09 8:06 ` Krzysztof Kozlowski 2023-12-09 8:42 ` Christophe JAILLET @ 2023-12-10 20:05 ` kernel test robot 2 siblings, 0 replies; 7+ messages in thread From: kernel test robot @ 2023-12-10 20:05 UTC (permalink / raw) To: Neil Armstrong, Andy Gross, Bjorn Andersson, Konrad Dybcio, Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heikki Krogerus, Liam Girdwood, Mark Brown Cc: llvm, oe-kbuild-all, linux-arm-msm, linux-usb, devicetree, linux-kernel, Neil Armstrong Hi Neil, kernel test robot noticed the following build errors: [auto build test ERROR on bc63de6e6ba0b16652c5fb4b9c9916b9e7ca1f23] url: https://github.com/intel-lab-lkp/linux/commits/Neil-Armstrong/dt-bindings-usb-Document-WCD939x-USB-SubSystem-Altmode-Analog-Audio-Switch/20231208-232926 base: bc63de6e6ba0b16652c5fb4b9c9916b9e7ca1f23 patch link: https://lore.kernel.org/r/20231208-topic-sm8650-upstream-wcd939x-usbss-v1-2-91d1ba680fe0%40linaro.org patch subject: [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20231211/202312110337.uzelx86z-lkp@intel.com/config) compiler: clang version 16.0.4 (https://github.com/llvm/llvm-project.git ae42196bc493ffe877a7e3dff8be32035dea4d07) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231211/202312110337.uzelx86z-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202312110337.uzelx86z-lkp@intel.com/ All errors (new ones prefixed by >>): >> drivers/usb/typec/mux/wcd939x-usbss.c:353:7: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, ^ drivers/usb/typec/mux/wcd939x-usbss.c:456:6: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, ^ >> drivers/usb/typec/mux/wcd939x-usbss.c:602:22: error: call to undeclared function 'devm_gpiod_get_optional'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] usbss->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); ^ drivers/usb/typec/mux/wcd939x-usbss.c:602:22: note: did you mean 'devm_regulator_get_optional'? include/linux/regulator/consumer.h:163:32: note: 'devm_regulator_get_optional' declared here struct regulator *__must_check devm_regulator_get_optional(struct device *dev, ^ >> drivers/usb/typec/mux/wcd939x-usbss.c:602:60: error: use of undeclared identifier 'GPIOD_OUT_LOW' usbss->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); ^ >> drivers/usb/typec/mux/wcd939x-usbss.c:627:2: error: call to undeclared function 'gpiod_set_value'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] gpiod_set_value(usbss->reset_gpio, 1); ^ drivers/usb/typec/mux/wcd939x-usbss.c:650:6: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] FIELD_PREP(WCD_USBSS_FUNCTION_ENABLE_SOURCE_SELECT, ^ 6 errors generated. vim +/FIELD_PREP +353 drivers/usb/typec/mux/wcd939x-usbss.c 237 238 static int wcd939x_usbss_set(struct wcd939x_usbss *usbss) 239 { 240 bool reverse = (usbss->orientation == TYPEC_ORIENTATION_REVERSE); 241 bool enable_audio = false; 242 bool enable_usb = false; 243 bool enable_dp = false; 244 int ret; 245 246 /* USB Mode */ 247 if (usbss->mode < TYPEC_STATE_MODAL || 248 (!usbss->svid && (usbss->mode == TYPEC_MODE_USB2 || 249 usbss->mode == TYPEC_MODE_USB3))) { 250 enable_usb = true; 251 } else if (usbss->svid) { 252 switch (usbss->mode) { 253 /* DP Only */ 254 case TYPEC_DP_STATE_C: 255 case TYPEC_DP_STATE_E: 256 enable_dp = true; 257 break; 258 259 /* DP + USB */ 260 case TYPEC_DP_STATE_D: 261 case TYPEC_DP_STATE_F: 262 enable_usb = true; 263 enable_dp = true; 264 break; 265 266 default: 267 return -EOPNOTSUPP; 268 } 269 } else if (usbss->mode == TYPEC_MODE_AUDIO) { 270 enable_audio = true; 271 } else { 272 return -EOPNOTSUPP; 273 } 274 275 /* Disable all switches */ 276 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 277 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES | 278 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES | 279 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES | 280 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES | 281 WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES | 282 WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES | 283 WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES); 284 if (ret) 285 return ret; 286 287 /* Clear switches */ 288 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 289 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | 290 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES | 291 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | 292 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES | 293 WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES | 294 WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES); 295 if (ret) 296 return ret; 297 298 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, 299 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); 300 if (ret) 301 return ret; 302 303 /* Enable OVP_MG1_BIAS PCOMP_DYN_BST_EN */ 304 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG1_BIAS, 305 WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN); 306 if (ret) 307 return ret; 308 309 /* Enable OVP_MG2_BIAS PCOMP_DYN_BST_EN */ 310 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_MG2_BIAS, 311 WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN); 312 if (ret) 313 return ret; 314 315 /* Disable Equalizer in safe mode */ 316 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_EQUALIZER1, 317 WCD_USBSS_EQUALIZER1_EQ_EN); 318 if (ret) 319 return ret; 320 321 /* Start FSM with all disabled, force write */ 322 ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START, 323 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG, 324 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG); 325 326 /* 35us to allow the SBU switch to turn off */ 327 usleep_range(35, 1000); 328 329 /* Setup Audio Accessory mux/switch */ 330 if (enable_audio) { 331 int i; 332 333 /* 334 * AATC switch configuration: 335 * "Normal": 336 * - R: DNR 337 * - L: DNL 338 * - Sense: GSBU2 339 * - Mic: MG1 340 * - AGND: MG2 341 * "Swapped": 342 * - R: DNR 343 * - L: DNL 344 * - Sense: GSBU1 345 * - Mic: MG2 346 * - AGND: MG1 347 * Swapped information is given by the codec MBHC logic 348 */ 349 350 /* Set AATC mode */ 351 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, 352 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, > 353 FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, 354 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_AATC)); 355 if (ret) 356 return ret; 357 358 /* Select L for DNL_SWITCHES and R for DPR_SWITCHES */ 359 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 360 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | 361 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 362 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 363 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_L) | 364 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES, 365 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_R)); 366 if (ret) 367 return ret; 368 369 if (reverse) 370 /* Select MG2 for MIC, SBU1 for Sense */ 371 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 372 WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES, 373 WCD_USBSS_SWITCH_SELECT0_MIC_SWITCHES); 374 else 375 /* Select MG1 for MIC, SBU2 for Sense */ 376 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 377 WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES, 378 WCD_USBSS_SWITCH_SELECT0_SENSE_SWITCHES); 379 if (ret) 380 return ret; 381 382 if (reverse) 383 /* Disable OVP_MG1_BIAS PCOMP_DYN_BST_EN */ 384 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG1_BIAS, 385 WCD_USBSS_MG1_BIAS_PCOMP_DYN_BST_EN); 386 else 387 /* Disable OVP_MG2_BIAS PCOMP_DYN_BST_EN */ 388 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_MG2_BIAS, 389 WCD_USBSS_MG2_BIAS_PCOMP_DYN_BST_EN); 390 if (ret) 391 return ret; 392 393 /* Enable SENSE, MIC switches */ 394 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 395 WCD_USBSS_SWITCH_SETTINGS_ENABLE_SENSE_SWITCHES | 396 WCD_USBSS_SWITCH_SETTINGS_ENABLE_MIC_SWITCHES); 397 if (ret) 398 return ret; 399 400 if (reverse) 401 /* Select MG1 for AGND_SWITCHES */ 402 ret = regmap_clear_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, 403 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); 404 else 405 /* Select MG2 for AGND_SWITCHES */ 406 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT1, 407 WCD_USBSS_SWITCH_SELECT1_AGND_SWITCHES); 408 if (ret) 409 return ret; 410 411 /* Enable AGND switches */ 412 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 413 WCD_USBSS_SWITCH_SETTINGS_ENABLE_AGND_SWITCHES); 414 if (ret) 415 return ret; 416 417 /* Enable DPR, DNL switches */ 418 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 419 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES | 420 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES); 421 if (ret) 422 return ret; 423 424 /* Setup FSM delays */ 425 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_L_SW, 0x02); 426 if (ret) 427 return ret; 428 429 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_R_SW, 0x02); 430 if (ret) 431 return ret; 432 433 ret = regmap_write(usbss->regmap, WCD_USBSS_DELAY_MIC_SW, 0x01); 434 if (ret) 435 return ret; 436 437 /* Start FSM, force write */ 438 ret = regmap_write_bits(usbss->regmap, WCD_USBSS_AUDIO_FSM_START, 439 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG, 440 WCD_USBSS_AUDIO_FSM_START_AUDIO_FSM_AUDIO_TRIG); 441 if (ret) 442 return ret; 443 444 /* Default Linearlizer coefficients */ 445 for (i = 0; i < ARRAY_SIZE(wcd939x_usbss_coeff_init); ++i) 446 regmap_update_bits(usbss->regmap, 447 wcd939x_usbss_coeff_init[i].offset, 448 wcd939x_usbss_coeff_init[i].mask, 449 wcd939x_usbss_coeff_init[i].value); 450 451 return 0; 452 } 453 454 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_USB_SS_CNTL, 455 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, 456 FIELD_PREP(WCD_USBSS_USB_SS_CNTL_USB_SS_MODE, 457 WCD_USBSS_USB_SS_CNTL_USB_SS_MODE_USB)); 458 if (ret) 459 return ret; 460 461 /* Enable USB muxes */ 462 if (enable_usb) { 463 /* Do not enable Equalizer in safe mode */ 464 if (usbss->mode != TYPEC_STATE_SAFE) { 465 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_EQUALIZER1, 466 WCD_USBSS_EQUALIZER1_EQ_EN); 467 if (ret) 468 return ret; 469 } 470 471 /* Select DN for DNL_SWITCHES and DP for DPR_SWITCHES */ 472 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 473 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES | 474 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 475 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DNL_SWITCHES, 476 WCD_USBSS_SWITCH_SELECT0_DNL_SWITCH_DN) | 477 FIELD_PREP(WCD_USBSS_SWITCH_SELECT0_DPR_SWITCHES, 478 WCD_USBSS_SWITCH_SELECT0_DPR_SWITCH_DP)); 479 if (ret) 480 return ret; 481 482 /* Enable DNL_SWITCHES and DPR_SWITCHES */ 483 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 484 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DPR_SWITCHES | 485 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DNL_SWITCHES); 486 if (ret) 487 return ret; 488 } 489 490 /* Enable DP AUX muxes */ 491 if (enable_dp) { 492 /* Update Leakage Canceller Coefficient for AUXP pins */ 493 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_CTL, 494 WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF, 495 FIELD_PREP(WCD_USBSS_DISP_AUXP_CTL_LK_CANCEL_TRK_COEFF, 496 5)); 497 if (ret) 498 return ret; 499 500 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_DISP_AUXP_THRESH, 501 WCD_USBSS_DISP_AUXP_THRESH_DISP_AUXP_OVPON_CM); 502 if (ret) 503 return ret; 504 505 if (reverse) 506 /* Select MG2 for AUXP and MG1 for AUXM */ 507 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 508 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | 509 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES, 510 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES); 511 else 512 /* Select MG1 for AUXP and MG2 for AUXM */ 513 ret = regmap_update_bits(usbss->regmap, WCD_USBSS_SWITCH_SELECT0, 514 WCD_USBSS_SWITCH_SELECT0_DP_AUXP_SWITCHES | 515 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES, 516 WCD_USBSS_SWITCH_SELECT0_DP_AUXM_SWITCHES); 517 if (ret) 518 return ret; 519 520 /* Enable DP_AUXP_TO_MGX and DP_AUXM_TO_MGX switches */ 521 ret = regmap_set_bits(usbss->regmap, WCD_USBSS_SWITCH_SETTINGS_ENABLE, 522 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXP_TO_MGX_SWITCHES | 523 WCD_USBSS_SWITCH_SETTINGS_ENABLE_DP_AUXM_TO_MGX_SWITCHES); 524 525 /* 15us to allow the SBU switch to turn on again */ 526 usleep_range(15, 1000); 527 } 528 529 return 0; 530 } 531 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-12-10 20:06 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-12-08 15:27 [PATCH 0/2] usb: typec: support Qualcomm WCD939X USB SubSystem Altmode Mux Neil Armstrong 2023-12-08 15:27 ` [PATCH 1/2] dt-bindings: usb: Document WCD939x USB SubSystem Altmode/Analog Audio Switch Neil Armstrong 2023-12-09 8:11 ` Krzysztof Kozlowski 2023-12-08 15:27 ` [PATCH 2/2] usb: typec: mux: add Qualcomm WCD939X USB SubSystem Altmode Mux driver Neil Armstrong 2023-12-09 8:06 ` Krzysztof Kozlowski 2023-12-09 8:42 ` Christophe JAILLET 2023-12-10 20:05 ` kernel test robot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).