usb: typec: fsa4480: add support for Audio Accessory Mode
authorNeil Armstrong <neil.armstrong@linaro.org>
Wed, 14 Jun 2023 13:10:41 +0000 (15:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Jun 2023 16:07:55 +0000 (18:07 +0200)
The FSA4480 Type-C switch supports switching the Audio R/L,
AGND and MIC signals to the USB-C DP/DM and SBU1/2 to support
the Audio Accessory Mode.

The FSA4480 has an integrated Audio jack detection mechanism
to automatically mux the AGND, MIX and Sense to the correct
SBU lines to support 3 pole and both 4 pole TRRS pinouts.

Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20230614-topic-sm8550-upstream-type-c-audio-v1-3-15a92565146b@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/typec/mux/fsa4480.c

index ab3ff71..e0ee1f6 100644 (file)
 #define FSA4480_DELAY_L_MIC    0x0e
 #define FSA4480_DELAY_L_SENSE  0x0f
 #define FSA4480_DELAY_L_AGND   0x10
+#define FSA4480_FUNCTION_ENABLE        0x12
 #define FSA4480_RESET          0x1e
 #define FSA4480_MAX_REGISTER   0x1f
 
 #define FSA4480_ENABLE_DEVICE  BIT(7)
 #define FSA4480_ENABLE_SBU     GENMASK(6, 5)
 #define FSA4480_ENABLE_USB     GENMASK(4, 3)
+#define FSA4480_ENABLE_SENSE   BIT(2)
+#define FSA4480_ENABLE_MIC     BIT(1)
+#define FSA4480_ENABLE_AGND    BIT(0)
 
 #define FSA4480_SEL_SBU_REVERSE        GENMASK(6, 5)
 #define FSA4480_SEL_USB                GENMASK(4, 3)
+#define FSA4480_SEL_SENSE      BIT(2)
+#define FSA4480_SEL_MIC                BIT(1)
+#define FSA4480_SEL_AGND       BIT(0)
+
+#define FSA4480_ENABLE_AUTO_JACK_DETECT        BIT(0)
 
 struct fsa4480 {
        struct i2c_client *client;
@@ -95,6 +104,9 @@ static int fsa4480_set(struct fsa4480 *fsa)
                default:
                        return -EOPNOTSUPP;
                }
+       } else if (fsa->mode == TYPEC_MODE_AUDIO) {
+               /* Audio Accessory Mode, setup to auto Jack Detection */
+               enable |= FSA4480_ENABLE_USB | FSA4480_ENABLE_AGND;
        } else
                return -EOPNOTSUPP;
 
@@ -110,6 +122,11 @@ static int fsa4480_set(struct fsa4480 *fsa)
        regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, sel);
        regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, enable);
 
+       /* Start AUDIO JACK DETECTION to setup MIC, AGND & Sense muxes */
+       if (enable & FSA4480_ENABLE_AGND)
+               regmap_write(fsa->regmap, FSA4480_FUNCTION_ENABLE,
+                            FSA4480_ENABLE_AUTO_JACK_DETECT);
+
        if (enable & FSA4480_ENABLE_SBU) {
                /* 15us to allow the SBU switch to turn on again */
                usleep_range(15, 1000);