diff options
129 files changed, 9141 insertions, 1483 deletions
diff --git a/Documentation/devicetree/bindings/sound/ak4458.txt b/Documentation/devicetree/bindings/sound/ak4458.txt index e5820235e0d5..8f6c84f21468 100644 --- a/Documentation/devicetree/bindings/sound/ak4458.txt +++ b/Documentation/devicetree/bindings/sound/ak4458.txt @@ -10,6 +10,8 @@ Required properties: Optional properties: - reset-gpios: A GPIO specifier for the power down & reset pin - mute-gpios: A GPIO specifier for the soft mute pin +- AVDD-supply: Analog power supply +- DVDD-supply: Digital power supply Example: diff --git a/Documentation/devicetree/bindings/sound/ak5558.txt b/Documentation/devicetree/bindings/sound/ak5558.txt index 7d67ca6ced80..36934098170c 100644 --- a/Documentation/devicetree/bindings/sound/ak5558.txt +++ b/Documentation/devicetree/bindings/sound/ak5558.txt @@ -10,6 +10,8 @@ Required properties: Optional properties: - reset-gpios: A GPIO specifier for the power down & reset pin. +- AVDD-supply: Analog power supply +- DVDD-supply: Digital power supply Example: diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml index 55d28268d2f4..67405e6d8168 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml @@ -15,7 +15,11 @@ properties: const: 0 compatible: - const: allwinner,sun8i-a33-codec + oneOf: + - items: + - const: allwinner,sun50i-a64-codec + - const: allwinner,sun8i-a33-codec + - const: allwinner,sun8i-a33-codec reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.txt b/Documentation/devicetree/bindings/sound/fsl,spdif.txt deleted file mode 100644 index e1365b0ee1e9..000000000000 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.txt +++ /dev/null @@ -1,68 +0,0 @@ -Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller - -The Freescale S/PDIF audio block is a stereo transceiver that allows the -processor to receive and transmit digital audio via an coaxial cable or -a fibre cable. - -Required properties: - - - compatible : Compatible list, should contain one of the following - compatibles: - "fsl,imx35-spdif", - "fsl,vf610-spdif", - "fsl,imx6sx-spdif", - - - reg : Offset and length of the register set for the device. - - - interrupts : Contains the spdif interrupt. - - - dmas : Generic dma devicetree binding as described in - Documentation/devicetree/bindings/dma/dma.txt. - - - dma-names : Two dmas have to be defined, "tx" and "rx". - - - clocks : Contains an entry for each entry in clock-names. - - - clock-names : Includes the following entries: - "core" The core clock of spdif controller. - "rxtx<0-7>" Clock source list for tx and rx clock. - This clock list should be identical to the source - list connecting to the spdif clock mux in "SPDIF - Transceiver Clock Diagram" of SoC reference manual. - It can also be referred to TxClk_Source bit of - register SPDIF_STC. - "spba" The spba clock is required when SPDIF is placed as a - bus slave of the Shared Peripheral Bus and when two - or more bus masters (CPU, DMA or DSP) try to access - it. This property is optional depending on the SoC - design. - -Optional properties: - - - big-endian : If this property is absent, the native endian mode - will be in use as default, or the big endian mode - will be in use for all the device registers. - -Example: - -spdif: spdif@2004000 { - compatible = "fsl,imx35-spdif"; - reg = <0x02004000 0x4000>; - interrupts = <0 52 0x04>; - dmas = <&sdma 14 18 0>, - <&sdma 15 18 0>; - dma-names = "rx", "tx"; - - clocks = <&clks 197>, <&clks 3>, - <&clks 197>, <&clks 107>, - <&clks 0>, <&clks 118>, - <&clks 62>, <&clks 139>, - <&clks 0>; - clock-names = "core", "rxtx0", - "rxtx1", "rxtx2", - "rxtx3", "rxtx4", - "rxtx5", "rxtx6", - "rxtx7"; - - big-endian; -}; diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml new file mode 100644 index 000000000000..2ac671f5cb9b --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml @@ -0,0 +1,110 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,spdif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale Sony/Philips Digital Interface Format (S/PDIF) Controller + +maintainers: + - Shengjiu Wang <[email protected]> + +description: | + The Freescale S/PDIF audio block is a stereo transceiver that allows the + processor to receive and transmit digital audio via an coaxial cable or + a fibre cable. + +properties: + compatible: + enum: + - fsl,imx35-spdif + - fsl,vf610-spdif + - fsl,imx6sx-spdif + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + dmas: + items: + - description: DMA controller phandle and request line for RX + - description: DMA controller phandle and request line for TX + + dma-names: + items: + - const: rx + - const: tx + + clocks: + items: + - description: The core clock of spdif controller. + - description: Clock for tx0 and rx0. + - description: Clock for tx1 and rx1. + - description: Clock for tx2 and rx2. + - description: Clock for tx3 and rx3. + - description: Clock for tx4 and rx4. + - description: Clock for tx5 and rx5. + - description: Clock for tx6 and rx6. + - description: Clock for tx7 and rx7. + - description: The spba clock is required when SPDIF is placed as a bus + slave of the Shared Peripheral Bus and when two or more bus masters + (CPU, DMA or DSP) try to access it. This property is optional depending + on the SoC design. + minItems: 9 + + clock-names: + items: + - const: core + - const: rxtx0 + - const: rxtx1 + - const: rxtx2 + - const: rxtx3 + - const: rxtx4 + - const: rxtx5 + - const: rxtx6 + - const: rxtx7 + - const: spba + minItems: 9 + + big-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: | + If this property is absent, the native endian mode will be in use + as default, or the big endian mode will be in use for all the device + registers. Set this flag for HCDs with big endian descriptors and big + endian registers. + +required: + - compatible + - reg + - interrupts + - dmas + - dma-names + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + spdif@2004000 { + compatible = "fsl,imx35-spdif"; + reg = <0x02004000 0x4000>; + interrupts = <0 52 0x04>; + dmas = <&sdma 14 18 0>, + <&sdma 15 18 0>; + dma-names = "rx", "tx"; + clocks = <&clks 197>, <&clks 3>, + <&clks 197>, <&clks 107>, + <&clks 0>, <&clks 118>, + <&clks 62>, <&clks 139>, + <&clks 0>; + clock-names = "core", "rxtx0", + "rxtx1", "rxtx2", + "rxtx3", "rxtx4", + "rxtx5", "rxtx6", + "rxtx7"; + big-endian; + }; diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt index 63ebf52b43e8..f339be62e7e4 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt @@ -38,6 +38,8 @@ The compatible list for this generic sound card currently: "fsl,imx-audio-wm8524" + "fsl,imx-audio-tlv320aic32x4" + Required properties: - compatible : Contains one of entries in the compatible list. diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml index 2e0bbc1c868a..bf4632c0a9b6 100644 --- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -17,6 +17,7 @@ properties: compatible: enum: - intel,keembay-i2s + - intel,keembay-tdm "#sound-dai-cells": const: 0 diff --git a/Documentation/devicetree/bindings/sound/mt6359.yaml b/Documentation/devicetree/bindings/sound/mt6359.yaml new file mode 100644 index 000000000000..a54f466f769d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt6359.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mt6359.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek MT6359 Codec Device Tree Bindings + +maintainers: + - Eason Yen <[email protected]> + - Jiaxin Yu <[email protected]> + - Shane Chien <[email protected]> + +description: | + The communication between MT6359 and SoC is through Mediatek PMIC wrapper. + For more detail, please visit Mediatek PMIC wrapper documentation. + Must be a child node of PMIC wrapper. + +properties: + mediatek,dmic-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Indicates how many data pins are used to transmit two channels of PDM + signal. 0 means two wires, 1 means one wire. Default value is 0. + enum: + - 0 # one wire + - 1 # two wires + + mediatek,mic-type-0: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Specifies the type of mic type connected to adc0 + + enum: + - 0 # IDLE - mic in turn-off status + - 1 # ACC - analog mic with alternating coupling + - 2 # DMIC - digital mic + - 3 # DCC - analog mic with direct couping + - 4 # DCC_ECM_DIFF - analog electret condenser mic with differential mode + - 5 # DCC_ECM_SINGLE - analog electret condenser mic with single mode + + mediatek,mic-type-1: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Specifies the type of mic type connected to adc1 + + mediatek,mic-type-2: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Specifies the type of mic type connected to adc2 + +additionalProperties: false + +examples: + - | + mt6359codec: mt6359codec { + mediatek,dmic-mode = <0>; + mediatek,mic-type-0 = <2>; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt deleted file mode 100644 index 32c2cdb3d32f..000000000000 --- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.txt +++ /dev/null @@ -1,79 +0,0 @@ -* Qualcomm Technologies LPASS CPU DAI - -This node models the Qualcomm Technologies Low-Power Audio SubSystem (LPASS). - -Required properties: - -- compatible : "qcom,lpass-cpu" or "qcom,apq8016-lpass-cpu" -- clocks : Must contain an entry for each entry in clock-names. -- clock-names : A list which must include the following entries: - * "ahbix-clk" - * "mi2s-osr-clk" - * "mi2s-bit-clk" - : required clocks for "qcom,lpass-cpu-apq8016" - * "ahbix-clk" - * "mi2s-bit-clk0" - * "mi2s-bit-clk1" - * "mi2s-bit-clk2" - * "mi2s-bit-clk3" - * "pcnoc-mport-clk" - * "pcnoc-sway-clk" - -- interrupts : Must contain an entry for each entry in - interrupt-names. -- interrupt-names : A list which must include the following entries: - * "lpass-irq-lpaif" -- pinctrl-N : One property must exist for each entry in - pinctrl-names. See ../pinctrl/pinctrl-bindings.txt - for details of the property values. -- pinctrl-names : Must contain a "default" entry. -- reg : Must contain an address for each entry in reg-names. -- reg-names : A list which must include the following entries: - * "lpass-lpaif" -- #address-cells : Must be 1 -- #size-cells : Must be 0 - - - -Optional properties: - -- qcom,adsp : Phandle for the audio DSP node - -By default, the driver uses up to 4 MI2S SD lines, for a total of 8 channels. -The SD lines to use can be configured by adding subnodes for each of the DAIs. - -Required properties for each DAI (represented by a subnode): -- reg : Must be one of the DAI IDs - (usually part of dt-bindings header) -- qcom,playback-sd-lines: List of serial data lines to use for playback - Each SD line should be represented by a number from 0-3. -- qcom,capture-sd-lines : List of serial data lines to use for capture - Each SD line should be represented by a number from 0-3. - -Note that adding a subnode changes the default to "no lines configured", -so both playback and capture lines should be configured when a subnode is added. - -Example: - -lpass@28100000 { - compatible = "qcom,lpass-cpu"; - clocks = <&lcc AHBIX_CLK>, <&lcc MI2S_OSR_CLK>, <&lcc MI2S_BIT_CLK>; - clock-names = "ahbix-clk", "mi2s-osr-clk", "mi2s-bit-clk"; - interrupts = <0 85 1>; - interrupt-names = "lpass-irq-lpaif"; - pinctrl-names = "default", "idle"; - pinctrl-0 = <&mi2s_default>; - pinctrl-1 = <&mi2s_idle>; - reg = <0x28100000 0x10000>; - reg-names = "lpass-lpaif"; - qcom,adsp = <&adsp>; - - #address-cells = <1>; - #size-cells = <0>; - - /* Optional to set different MI2S SD lines */ - dai@3 { - reg = <MI2S_QUATERNARY>; - qcom,playback-sd-lines = <0 1>; - }; -}; diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml new file mode 100644 index 000000000000..09c9bd27fda4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml @@ -0,0 +1,189 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,lpass-cpu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies Inc. LPASS CPU dai driver bindings + +maintainers: + - Srinivas Kandagatla <[email protected]> + - Rohit kumar <[email protected]> + +description: | + Qualcomm Technologies Inc. SOC Low-Power Audio SubSystem (LPASS) that consist + of MI2S interface for audio data transfer on external codecs. LPASS cpu driver + is a module to configure Low-Power Audio Interface(LPAIF) core registers + across different IP versions. + +properties: + compatible: + enum: + - qcom,lpass-cpu + - qcom,apq8016-lpass-cpu + - qcom,sc7180-lpass-cpu + + reg: + maxItems: 1 + description: LPAIF core registers + + clocks: + minItems: 3 + maxItems: 6 + + clock-names: + minItems: 3 + maxItems: 6 + + interrupts: + maxItems: 1 + description: LPAIF DMA buffer interrupt + + qcom,adsp: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle for the audio DSP node + + iommus: + maxItems: 1 + description: Phandle to apps_smmu node with sid mask + + power-domains: + maxItems: 1 + + '#sound-dai-cells': + const: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + +patternProperties: + "(^mi2s-[0-9a-f]$|mi2s)": + type: object + description: Required properties for each DAI + + properties: + reg: + maxItems: 1 + description: Must be one of the DAI ID + + qcom,playback-sd-lines: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: list of MI2S data lines for playback + + qcom,capture-sd-lines: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: list of MI2S data lines for capture + + required: + - reg + + additionalProperties: false + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + - '#sound-dai-cells' + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + const: qcom,lpass-cpu + + then: + properties: + clock-names: + items: + - const: ahbix-clk + - const: mi2s-osr-clk + - const: mi2s-bit-clk + + - if: + properties: + compatible: + contains: + const: qcom,apq8016-lpass-cpu + + then: + properties: + clock-names: + items: + - const: ahbix-clk + - const: mi2s-bit-clk0 + - const: mi2s-bit-clk1 + - const: mi2s-bit-clk2 + - const: mi2s-bit-clk3 + - const: pcnoc-mport-clk + - const: pcnoc-sway-clk + + - if: + properties: + compatible: + contains: + const: qcom,sc7180-lpass-cpu + + then: + properties: + clock-names: + items: + - const: pcnoc-sway-clk + - const: audio-core + - const: mclk0 + - const: pcnoc-mport-clk + - const: mi2s-bit-clk0 + - const: mi2s-bit-clk1 + required: + - iommus + - power-domains + +examples: + - | + #include <dt-bindings/sound/sc7180-lpass.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + lpass@62f00000 { + compatible = "qcom,sc7180-lpass-cpu"; + + reg = <0 0x62f00000 0 0x29000>; + + iommus = <&apps_smmu 0x1020 0>; + power-domains = <&lpass_hm 0>; + + clocks = <&gcc 131>, + <&lpasscorecc 6>, + <&lpasscorecc 7>, + <&lpasscorecc 10>, + <&lpasscorecc 8>, + <&lpasscorecc 9>; + + clock-names = "pcnoc-sway-clk", "audio-core", + "mclk0", "pcnoc-mport-clk", + "mi2s-bit-clk0", "mi2s-bit-clk1"; + + interrupts = <0 160 1>; + + #sound-dai-cells = <1>; + + #address-cells = <1>; + #size-cells = <0>; + /* Optional to set different MI2S SD lines */ + mi2s-primary@0 { + reg = <MI2S_PRIMARY>; + qcom,playback-sd-lines = <1>; + qcom,capture-sd-lines = <0>; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml index 7bad6f16fe60..62a61b68dfef 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml @@ -27,6 +27,7 @@ properties: - enum: - rockchip,rk3188-spdif - rockchip,rk3288-spdif + - rockchip,rk3308-spdif - const: rockchip,rk3066-spdif reg: diff --git a/Documentation/devicetree/bindings/sound/tas2562.txt b/Documentation/devicetree/bindings/sound/tas2562.txt deleted file mode 100644 index dc6d7362ded7..000000000000 --- a/Documentation/devicetree/bindings/sound/tas2562.txt +++ /dev/null @@ -1,37 +0,0 @@ -Texas Instruments TAS2562 Smart PA - -The TAS2562 is a mono, digital input Class-D audio amplifier optimized for -efficiently driving high peak power into small loudspeakers. -Integrated speaker voltage and current sense provides for -real time monitoring of loudspeaker behavior. - -Required properties: - - #address-cells - Should be <1>. - - #size-cells - Should be <0>. - - compatible: - Should contain "ti,tas2562", "ti,tas2563". - - reg: - The i2c address. Should be 0x4c, 0x4d, 0x4e or 0x4f. - - ti,imon-slot-no:- TDM TX current sense time slot. - - ti,vmon-slot-no:- TDM TX voltage sense time slot. This slot must always be - greater then ti,imon-slot-no. - -Optional properties: -- interrupt-parent: phandle to the interrupt controller which provides - the interrupt. -- interrupts: (GPIO) interrupt to which the chip is connected. -- shut-down-gpio: GPIO used to control the state of the device. - -Examples: -tas2562@4c { - #address-cells = <1>; - #size-cells = <0>; - compatible = "ti,tas2562"; - reg = <0x4c>; - - interrupt-parent = <&gpio1>; - interrupts = <14>; - - shut-down-gpio = <&gpio1 15 0>; - ti,imon-slot-no = <0>; - ti,vmon-slot-no = <1>; -}; - diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/tas2562.yaml index 8d75a798740b..c3b7e19a0d44 100644 --- a/Documentation/devicetree/bindings/sound/tas2562.yaml +++ b/Documentation/devicetree/bindings/sound/tas2562.yaml @@ -16,6 +16,10 @@ description: | Integrated speaker voltage and current sense provides for real time monitoring of loudspeaker behavior. + Specifications about the audio amplifier can be found at: + https://www.ti.com/lit/gpn/tas2562 + https://www.ti.com/lit/gpn/tas2563 + properties: compatible: enum: diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c index 594901f3b8e5..526fd0933289 100644 --- a/arch/arm/mach-s3c24xx/mach-gta02.c +++ b/arch/arm/mach-s3c24xx/mach-gta02.c @@ -15,6 +15,7 @@ #include <linux/delay.h> #include <linux/timer.h> #include <linux/init.h> +#include <linux/gpio/machine.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> #include <linux/workqueue.h> @@ -474,6 +475,20 @@ static struct platform_device gta02_buttons_device = { }, }; +static struct gpiod_lookup_table gta02_audio_gpio_table = { + .dev_id = "neo1973-audio", + .table = { + GPIO_LOOKUP("GPIOJ", 2, "amp-shut", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOJ", 1, "hp", GPIO_ACTIVE_HIGH), + { }, + }, +}; + +static struct platform_device gta02_audio = { + .name = "neo1973-audio", + .id = -1, +}; + static void __init gta02_map_io(void) { s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc)); @@ -498,6 +513,7 @@ static struct platform_device *gta02_devices[] __initdata = { >a02_buttons_device, &s3c_device_adc, &s3c_device_ts, + >a02_audio, }; static void gta02_poweroff(void) @@ -524,6 +540,7 @@ static void __init gta02_machine_init(void) i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs)); + gpiod_add_lookup_table(>a02_audio_gpio_table); platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices)); pm_power_off = gta02_poweroff; diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c index f4710052843a..ecb84029e15c 100644 --- a/arch/arm/mach-s3c24xx/mach-h1940.c +++ b/arch/arm/mach-s3c24xx/mach-h1940.c @@ -475,6 +475,22 @@ static struct gpiod_lookup_table h1940_mmc_gpio_table = { }, }; +static struct gpiod_lookup_table h1940_audio_gpio_table = { + .dev_id = "h1940-audio", + .table = { + GPIO_LOOKUP("H1940_LATCH", + H1940_LATCH_AUDIO_POWER - H1940_LATCH_GPIO(0), + "speaker-power", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOG", 4, "hp", GPIO_ACTIVE_HIGH), + { }, + }, +}; + +static struct platform_device h1940_audio = { + .name = "h1940-audio", + .id = -1, +}; + static struct pwm_lookup h1940_pwm_lookup[] = { PWM_LOOKUP("samsung-pwm", 0, "pwm-backlight", NULL, 36296, PWM_POLARITY_NORMAL), @@ -651,6 +667,7 @@ static struct platform_device *h1940_devices[] __initdata = { &s3c_device_ts, &power_supply, &h1940_battery, + &h1940_audio, }; static void __init h1940_map_io(void) @@ -690,6 +707,7 @@ static void __init h1940_init(void) s3c24xx_fb_set_platdata(&h1940_fb_info); gpiod_add_lookup_table(&h1940_mmc_gpio_table); + gpiod_add_lookup_table(&h1940_audio_gpio_table); s3c24xx_mci_set_platdata(&h1940_mmc_cfg); s3c24xx_udc_set_platdata(&h1940_udc_cfg); s3c24xx_ts_set_platdata(&h1940_ts_cfg); diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c index fde98b175c75..e9806bf654b4 100644 --- a/arch/arm/mach-s3c24xx/mach-rx1950.c +++ b/arch/arm/mach-s3c24xx/mach-rx1950.c @@ -728,6 +728,20 @@ static struct i2c_board_info rx1950_i2c_devices[] = { }, }; +static struct gpiod_lookup_table rx1950_audio_gpio_table = { + .dev_id = "rx1950-audio", + .table = { + GPIO_LOOKUP("GPIOG", 12, "hp-gpio", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("GPIOA", 1, "speaker-power", GPIO_ACTIVE_HIGH), + { }, + }, +}; + +static struct platform_device rx1950_audio = { + .name = "rx1950-audio", + .id = -1, +}; + static struct platform_device *rx1950_devices[] __initdata = { &s3c2410_device_dclk, &s3c_device_lcd, @@ -746,6 +760,7 @@ static struct platform_device *rx1950_devices[] __initdata = { &power_supply, &rx1950_battery, &rx1950_leds, + &rx1950_audio, }; static void __init rx1950_map_io(void) @@ -813,6 +828,7 @@ static void __init rx1950_init_machine(void) gpio_direction_output(S3C2410_GPJ(6), 0); pwm_add_table(rx1950_pwm_lookup, ARRAY_SIZE(rx1950_pwm_lookup)); + gpiod_add_lookup_table(&rx1950_audio_gpio_table); platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices)); i2c_register_board_info(0, rx1950_i2c_devices, diff --git a/include/dt-bindings/sound/sc7180-lpass.h b/include/dt-bindings/sound/sc7180-lpass.h new file mode 100644 index 000000000000..7d988f6346a5 --- /dev/null +++ b/include/dt-bindings/sound/sc7180-lpass.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_SC7180_LPASS_H +#define __DT_SC7180_LPASS_H + +#define MI2S_PRIMARY 0 +#define MI2S_SECONDARY 1 + +#define LPASS_MCLK0 0 + +#endif /* __DT_APQ8016_LPASS_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 5e3919ffb00c..a0918d159fd3 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1331,6 +1331,7 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_of_parse_daifmt(struct device_node *np, const char *prefix, struct device_node **bitclkmaster, diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 946a70210f49..e6c71ca0cd9b 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -127,6 +127,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_ML26124 imply SND_SOC_MT6351 imply SND_SOC_MT6358 + imply SND_SOC_MT6359 imply SND_SOC_MT6660 imply SND_SOC_NAU8540 imply SND_SOC_NAU8810 @@ -1724,6 +1725,13 @@ config SND_SOC_MT6358 Enable support for the platform which uses MT6358 as external codec device. +config SND_SOC_MT6359 + tristate "MediaTek MT6359 Codec" + depends on MTK_PMIC_WRAP + help + Enable support for the platform which uses MT6359 as + external codec device. + config SND_SOC_MT6660 tristate "Mediatek MT6660 Speaker Amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 0140c60db695..9a3f58c1069a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -126,6 +126,7 @@ snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o snd-soc-mt6351-objs := mt6351.o snd-soc-mt6358-objs := mt6358.o +snd-soc-mt6359-objs := mt6359.o snd-soc-mt6660-objs := mt6660.o snd-soc-nau8540-objs := nau8540.o snd-soc-nau8810-objs := nau8810.o @@ -431,6 +432,7 @@ obj-$(CONFIG_SND_SOC_MSM8916_WCD_ANALOG) +=snd-soc-msm8916-analog.o obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o obj-$(CONFIG_SND_SOC_MT6358) += snd-soc-mt6358.o +obj-$(CONFIG_SND_SOC_MT6359) += snd-soc-mt6359.o obj-$(CONFIG_SND_SOC_MT6660) += snd-soc-mt6660.o obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index cbe3c782e0ca..763e6839428f 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -12,6 +12,7 @@ #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pm_runtime.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <sound/initval.h> #include <sound/pcm_params.h> @@ -21,6 +22,12 @@ #include "ak4458.h" +#define AK4458_NUM_SUPPLIES 2 +static const char *ak4458_supply_names[AK4458_NUM_SUPPLIES] = { + "DVDD", + "AVDD", +}; + struct ak4458_drvdata { struct snd_soc_dai_driver *dai_drv; const struct snd_soc_component_driver *comp_drv; @@ -28,6 +35,7 @@ struct ak4458_drvdata { /* AK4458 Codec Private Data */ struct ak4458_priv { + struct regulator_bulk_data supplies[AK4458_NUM_SUPPLIES]; struct device *dev; struct regmap *regmap; struct gpio_desc *reset_gpiod; @@ -587,12 +595,22 @@ static int __maybe_unused ak4458_runtime_suspend(struct device *dev) if (ak4458->mute_gpiod) gpiod_set_value_cansleep(ak4458->mute_gpiod, 0); + regulator_bulk_disable(ARRAY_SIZE(ak4458->supplies), + ak4458->supplies); return 0; } static int __maybe_unused ak4458_runtime_resume(struct device *dev) { struct ak4458_priv *ak4458 = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ak4458->supplies), + ak4458->supplies); + if (ret != 0) { + dev_err(ak4458->dev, "Failed to enable supplies: %d\n", ret); + return ret; + } if (ak4458->mute_gpiod) gpiod_set_value_cansleep(ak4458->mute_gpiod, 1); @@ -667,7 +685,7 @@ static int ak4458_i2c_probe(struct i2c_client *i2c) { struct ak4458_priv *ak4458; const struct ak4458_drvdata *drvdata; - int ret; + int ret, i; ak4458 = devm_kzalloc(&i2c->dev, sizeof(*ak4458), GFP_KERNEL); if (!ak4458) @@ -692,6 +710,16 @@ static int ak4458_i2c_probe(struct i2c_client *i2c) if (IS_ERR(ak4458->mute_gpiod)) return PTR_ERR(ak4458->mute_gpiod); + for (i = 0; i < ARRAY_SIZE(ak4458->supplies); i++) + ak4458->supplies[i].supply = ak4458_supply_names[i]; + + ret = devm_regulator_bulk_get(ak4458->dev, ARRAY_SIZE(ak4458->supplies), + ak4458->supplies); + if (ret != 0) { + dev_err(ak4458->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + ret = devm_snd_soc_register_component(ak4458->dev, drvdata->comp_drv, drvdata->dai_drv, 1); if (ret < 0) { @@ -700,6 +728,7 @@ static int ak4458_i2c_probe(struct i2c_client *i2c) } pm_runtime_enable(&i2c->dev); + regcache_cache_only(ak4458->regmap, true); return 0; } diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 8179512129d3..2f076d5ee284 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <sound/initval.h> @@ -22,8 +23,15 @@ #include "ak5558.h" +#define AK5558_NUM_SUPPLIES 2 +static const char *ak5558_supply_names[AK5558_NUM_SUPPLIES] = { + "DVDD", + "AVDD", +}; + /* AK5558 Codec Private Data */ struct ak5558_priv { + struct regulator_bulk_data supplies[AK5558_NUM_SUPPLIES]; struct snd_soc_component component; struct regmap *regmap; struct i2c_client *i2c; @@ -299,12 +307,22 @@ static int __maybe_unused ak5558_runtime_suspend(struct device *dev) regcache_cache_only(ak5558->regmap, true); ak5558_power_off(ak5558); + regulator_bulk_disable(ARRAY_SIZE(ak5558->supplies), + ak5558->supplies); return 0; } static int __maybe_unused ak5558_runtime_resume(struct device *dev) { struct ak5558_priv *ak5558 = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(ak5558->supplies), + ak5558->supplies); + if (ret != 0) { + dev_err(dev, "Failed to enable supplies: %d\n", ret); + return ret; + } ak5558_power_off(ak5558); ak5558_power_on(ak5558); @@ -350,6 +368,7 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) { struct ak5558_priv *ak5558; int ret = 0; + int i; ak5558 = devm_kzalloc(&i2c->dev, sizeof(*ak5558), GFP_KERNEL); if (!ak5558) @@ -367,6 +386,16 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) if (IS_ERR(ak5558->reset_gpiod)) return PTR_ERR(ak5558->reset_gpiod); + for (i = 0; i < ARRAY_SIZE(ak5558->supplies); i++) + ak5558->supplies[i].supply = ak5558_supply_names[i]; + + ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(ak5558->supplies), + ak5558->supplies); + if (ret != 0) { + dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + return ret; + } + ret = devm_snd_soc_register_component(&i2c->dev, &soc_codec_dev_ak5558, &ak5558_dai, 1); @@ -374,6 +403,7 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) return ret; pm_runtime_enable(&i2c->dev); + regcache_cache_only(ak5558->regmap, true); return 0; } diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index b1dfd91609f7..48081d71c22c 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -460,7 +460,7 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) */ static enum da7219_aad_micbias_pulse_lvl - da7219_aad_fw_micbias_pulse_lvl(struct snd_soc_component *component, u32 val) + da7219_aad_fw_micbias_pulse_lvl(struct device *dev, u32 val) { switch (val) { case 2800: @@ -468,13 +468,13 @@ static enum da7219_aad_micbias_pulse_lvl case 2900: return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V; default: - dev_warn(component->dev, "Invalid micbias pulse level"); + dev_warn(dev, "Invalid micbias pulse level"); return DA7219_AAD_MICBIAS_PULSE_LVL_OFF; } } static enum da7219_aad_btn_cfg - da7219_aad_fw_btn_cfg(struct snd_soc_component *component, u32 val) + da7219_aad_fw_btn_cfg(struct device *dev, u32 val) { switch (val) { case 2: @@ -492,13 +492,13 @@ static enum da7219_aad_btn_cfg case 500: return DA7219_AAD_BTN_CFG_500MS; default: - dev_warn(component->dev, "Invalid button config"); + dev_warn(dev, "Invalid button config"); return DA7219_AAD_BTN_CFG_10MS; } } static enum da7219_aad_mic_det_thr - da7219_aad_fw_mic_det_thr(struct snd_soc_component *component, u32 val) + da7219_aad_fw_mic_det_thr(struct device *dev, u32 val) { switch (val) { case 200: @@ -510,13 +510,13 @@ static enum da7219_aad_mic_det_thr case 1000: return DA7219_AAD_MIC_DET_THR_1000_OHMS; default: - dev_warn(component->dev, "Invalid mic detect threshold"); + dev_warn(dev, "Invalid mic detect threshold"); return DA7219_AAD_MIC_DET_THR_500_OHMS; } } static enum da7219_aad_jack_ins_deb - da7219_aad_fw_jack_ins_deb(struct snd_soc_component *component, u32 val) + da7219_aad_fw_jack_ins_deb(struct device *dev, u32 val) { switch (val) { case 5: @@ -536,13 +536,13 @@ static enum da7219_aad_jack_ins_deb case 1000: return DA7219_AAD_JACK_INS_DEB_1S; default: - dev_warn(component->dev, "Invalid jack insert debounce"); + dev_warn(dev, "Invalid jack insert debounce"); return DA7219_AAD_JACK_INS_DEB_20MS; } } static enum da7219_aad_jack_det_rate - da7219_aad_fw_jack_det_rate(struct snd_soc_component *component, const char *str) + da7219_aad_fw_jack_det_rate(struct device *dev, const char *str) { if (!strcmp(str, "32ms_64ms")) { return DA7219_AAD_JACK_DET_RATE_32_64MS; @@ -553,13 +553,13 @@ static enum da7219_aad_jack_det_rate } else if (!strcmp(str, "256ms_512ms")) { return DA7219_AAD_JACK_DET_RATE_256_512MS; } else { - dev_warn(component->dev, "Invalid jack detect rate"); + dev_warn(dev, "Invalid jack detect rate"); return DA7219_AAD_JACK_DET_RATE_256_512MS; } } static enum da7219_aad_jack_rem_deb - da7219_aad_fw_jack_rem_deb(struct snd_soc_component *component, u32 val) + da7219_aad_fw_jack_rem_deb(struct device *dev, u32 val) { switch (val) { case 1: @@ -571,13 +571,13 @@ static enum da7219_aad_jack_rem_deb case 20: return DA7219_AAD_JACK_REM_DEB_20MS; default: - dev_warn(component->dev, "Invalid jack removal debounce"); + dev_warn(dev, "Invalid jack removal debounce"); return DA7219_AAD_JACK_REM_DEB_1MS; } } static enum da7219_aad_btn_avg - da7219_aad_fw_btn_avg(struct snd_soc_component *component, u32 val) + da7219_aad_fw_btn_avg(struct device *dev, u32 val) { switch (val) { case 1: @@ -589,13 +589,13 @@ static enum da7219_aad_btn_avg case 8: return DA7219_AAD_BTN_AVG_8; default: - dev_warn(component->dev, "Invalid button average value"); + dev_warn(dev, "Invalid button average value"); return DA7219_AAD_BTN_AVG_2; } } static enum da7219_aad_adc_1bit_rpt - da7219_aad_fw_adc_1bit_rpt(struct snd_soc_component *component, u32 val) + da7219_aad_fw_adc_1bit_rpt(struct device *dev, u32 val) { switch (val) { case 1: @@ -607,14 +607,13 @@ static enum da7219_aad_adc_1bit_rpt case 8: return DA7219_AAD_ADC_1BIT_RPT_8; default: - dev_warn(component->dev, "Invalid ADC 1-bit repeat value"); + dev_warn(dev, "Invalid ADC 1-bit repeat value"); return DA7219_AAD_ADC_1BIT_RPT_1; } } -static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component *component) +static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev) { - struct device *dev = component->dev; struct i2c_client *i2c = to_i2c_client(dev); struct fwnode_handle *aad_np; struct da7219_aad_pdata *aad_pdata; @@ -634,7 +633,7 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-lvl", &fw_val32) >= 0) aad_pdata->micbias_pulse_lvl = - da7219_aad_fw_micbias_pulse_lvl(component, fw_val32); + da7219_aad_fw_micbias_pulse_lvl(dev, fw_val32); else aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF; @@ -643,31 +642,31 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component aad_pdata->micbias_pulse_time = fw_val32; if (fwnode_property_read_u32(aad_np, "dlg,btn-cfg", &fw_val32) >= 0) - aad_pdata->btn_cfg = da7219_aad_fw_btn_cfg(component, fw_val32); + aad_pdata->btn_cfg = da7219_aad_fw_btn_cfg(dev, fw_val32); else aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS; if (fwnode_property_read_u32(aad_np, "dlg,mic-det-thr", &fw_val32) >= 0) aad_pdata->mic_det_thr = - da7219_aad_fw_mic_det_thr(component, fw_val32); + da7219_aad_fw_mic_det_thr(dev, fw_val32); else aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS; if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0) aad_pdata->jack_ins_deb = - da7219_aad_fw_jack_ins_deb(component, fw_val32); + da7219_aad_fw_jack_ins_deb(dev, fw_val32); else aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS; if (!fwnode_property_read_string(aad_np, "dlg,jack-det-rate", &fw_str)) aad_pdata->jack_det_rate = - da7219_aad_fw_jack_det_rate(component, fw_str); + da7219_aad_fw_jack_det_rate(dev, fw_str); else aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS; if (fwnode_property_read_u32(aad_np, "dlg,jack-rem-deb", &fw_val32) >= 0) aad_pdata->jack_rem_deb = - da7219_aad_fw_jack_rem_deb(component, fw_val32); + da7219_aad_fw_jack_rem_deb(dev, fw_val32); else aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS; @@ -692,13 +691,13 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct snd_soc_component aad_pdata->c_mic_btn_thr = 0x3E; if (fwnode_property_read_u32(aad_np, "dlg,btn-avg", &fw_val32) >= 0) - aad_pdata->btn_avg = da7219_aad_fw_btn_avg(component, fw_val32); + aad_pdata->btn_avg = da7219_aad_fw_btn_avg(dev, fw_val32); else aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2; if (fwnode_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &fw_val32) >= 0) aad_pdata->adc_1bit_rpt = - da7219_aad_fw_adc_1bit_rpt(component, fw_val32); + da7219_aad_fw_adc_1bit_rpt(dev, fw_val32); else aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1; @@ -887,21 +886,13 @@ void da7219_aad_resume(struct snd_soc_component *component) int da7219_aad_init(struct snd_soc_component *component) { struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); - struct da7219_aad_priv *da7219_aad; + struct da7219_aad_priv *da7219_aad = da7219->aad; u8 mask[DA7219_AAD_IRQ_REG_MAX]; int ret; - da7219_aad = devm_kzalloc(component->dev, sizeof(*da7219_aad), GFP_KERNEL); - if (!da7219_aad) - return -ENOMEM; - - da7219->aad = da7219_aad; da7219_aad->component = component; /* Handle any DT/ACPI/platform data */ - if (da7219->pdata && !da7219->pdata->aad_pdata) - da7219->pdata->aad_pdata = da7219_aad_fw_to_pdata(component); - da7219_aad_handle_pdata(component); /* Disable button detection */ @@ -947,6 +938,30 @@ void da7219_aad_exit(struct snd_soc_component *component) } EXPORT_SYMBOL_GPL(da7219_aad_exit); +/* + * AAD related I2C probe handling + */ + +int da7219_aad_probe(struct i2c_client *i2c) +{ + struct da7219_priv *da7219 = i2c_get_clientdata(i2c); + struct device *dev = &i2c->dev; + struct da7219_aad_priv *da7219_aad; + + da7219_aad = devm_kzalloc(dev, sizeof(*da7219_aad), GFP_KERNEL); + if (!da7219_aad) + return -ENOMEM; + + da7219->aad = da7219_aad; + + /* Retrieve any DT/ACPI/platform data */ + if (da7219->pdata && !da7219->pdata->aad_pdata) + da7219->pdata->aad_pdata = da7219_aad_fw_to_pdata(dev); + + return 0; +} +EXPORT_SYMBOL_GPL(da7219_aad_probe); + MODULE_DESCRIPTION("ASoC DA7219 AAD Driver"); MODULE_AUTHOR("Adam Thomson <[email protected]>"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index cfa46fba2390..f48a12012ef3 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -212,4 +212,7 @@ void da7219_aad_resume(struct snd_soc_component *component); int da7219_aad_init(struct snd_soc_component *component); void da7219_aad_exit(struct snd_soc_component *component); +/* I2C Probe */ +int da7219_aad_probe(struct i2c_client *i2c); + #endif /* __DA7219_AAD_H */ diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 153ea30b5a8f..0b3b7909efc9 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1753,9 +1753,8 @@ static enum da7219_mic_amp_in_sel } } -static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_component *component) +static struct da7219_pdata *da7219_fw_to_pdata(struct device *dev) { - struct device *dev = component->dev; struct da7219_pdata *pdata; const char *of_str; u32 of_val32; @@ -1847,45 +1846,43 @@ static const char *da7219_supply_names[DA7219_NUM_SUPPLIES] = { [DA7219_SUPPLY_VDDIO] = "VDDIO", }; -static int da7219_handle_supplies(struct snd_soc_component *component) +static int da7219_handle_supplies(struct snd_soc_component *component, + u8 *io_voltage_lvl) { struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); struct regulator *vddio; - u8 io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V; int i, ret; /* Get required supplies */ for (i = 0; i < DA7219_NUM_SUPPLIES; ++i) da7219->supplies[i].supply = da7219_supply_names[i]; - ret = devm_regulator_bulk_get(component->dev, DA7219_NUM_SUPPLIES, - da7219->supplies); + ret = regulator_bulk_get(component->dev, DA7219_NUM_SUPPLIES, + da7219->supplies); if (ret) { dev_err(component->dev, "Failed to get supplies"); return ret; } + /* Default to upper range */ + *io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_2_5V_3_6V; + /* Determine VDDIO voltage provided */ vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer; ret = regulator_get_voltage(vddio); if (ret < 1200000) dev_warn(component->dev, "Invalid VDDIO voltage\n"); else if (ret < 2800000) - io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V; + *io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V; /* Enable main supplies */ ret = regulator_bulk_enable(DA7219_NUM_SUPPLIES, da7219->supplies); if (ret) { dev_err(component->dev, "Failed to enable supplies"); + regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies); return ret; } - /* Ensure device in active mode */ - snd_soc_component_write(component, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK); - - /* Update IO voltage level range */ - snd_soc_component_write(component, DA7219_IO_CTRL, io_voltage_lvl); - return 0; } @@ -2121,14 +2118,26 @@ static const struct clk_ops da7219_dai_clk_ops[DA7219_DAI_NUM_CLKS] = { static int da7219_register_dai_clks(struct snd_soc_component *component) { struct device *dev = component->dev; + struct device_node *np = dev->of_node; struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); struct da7219_pdata *pdata = da7219->pdata; const char *parent_name; + struct clk_hw_onecell_data *clk_data; int i, ret; + /* For DT platforms allocate onecell data for clock registration */ + if (np) { + clk_data = kzalloc(struct_size(clk_data, hws, DA7219_DAI_NUM_CLKS), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->num = DA7219_DAI_NUM_CLKS; + da7219->clk_hw_data = clk_data; + } + for (i = 0; i < DA7219_DAI_NUM_CLKS; ++i) { struct clk_init_data init = {}; - struct clk *dai_clk; struct clk_lookup *dai_clk_lookup; struct clk_hw *dai_clk_hw = &da7219->dai_clks_hw[i]; @@ -2164,22 +2173,20 @@ static int da7219_register_dai_clks(struct snd_soc_component *component) init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE; dai_clk_hw->init = &init; - dai_clk = devm_clk_register(dev, dai_clk_hw); - if (IS_ERR(dai_clk)) { - dev_warn(dev, "Failed to register %s: %ld\n", - init.name, PTR_ERR(dai_clk)); - ret = PTR_ERR(dai_clk); + ret = clk_hw_register(dev, dai_clk_hw); + if (ret) { + dev_warn(dev, "Failed to register %s: %d\n", init.name, + ret); goto err; } - da7219->dai_clks[i] = dai_clk; + da7219->dai_clks[i] = dai_clk_hw->clk; - /* If we're using DT, then register as provider accordingly */ - if (dev->of_node) { - devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, - dai_clk_hw); + /* For DT setup onecell data, otherwise create lookup */ + if (np) { + da7219->clk_hw_data->hws[i] = dai_clk_hw; } else { - dai_clk_lookup = clkdev_create(dai_clk, init.name, - "%s", dev_name(dev)); + dai_clk_lookup = clkdev_hw_create(dai_clk_hw, init.name, + "%s", dev_name(dev)); if (!dai_clk_lookup) { ret = -ENOMEM; goto err; @@ -2189,21 +2196,58 @@ static int da7219_register_dai_clks(struct snd_soc_component *component) } } + /* If we're using DT, then register as provider accordingly */ + if (np) { + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, + da7219->clk_hw_data); + if (ret) { + dev_err(dev, "Failed to register clock provider\n"); + goto err; + } + } + return 0; err: do { if (da7219->dai_clks_lookup[i]) clkdev_drop(da7219->dai_clks_lookup[i]); + + clk_hw_unregister(&da7219->dai_clks_hw[i]); } while (i-- > 0); + if (np) + kfree(da7219->clk_hw_data); + return ret; } + +static void da7219_free_dai_clks(struct snd_soc_component *component) +{ + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + struct device_node *np = component->dev->of_node; + int i; + + if (np) + of_clk_del_provider(np); + + for (i = DA7219_DAI_NUM_CLKS - 1; i >= 0; --i) { + if (da7219->dai_clks_lookup[i]) + clkdev_drop(da7219->dai_clks_lookup[i]); + + clk_hw_unregister(&da7219->dai_clks_hw[i]); + } + + if (np) + kfree(da7219->clk_hw_data); +} #else static inline int da7219_register_dai_clks(struct snd_soc_component *component) { return 0; } + +static void da7219_free_dai_clks(struct snd_soc_component *component) {} #endif /* CONFIG_COMMON_CLK */ static void da7219_handle_pdata(struct snd_soc_component *component) @@ -2251,6 +2295,142 @@ static void da7219_handle_pdata(struct snd_soc_component *component) } } + +/* + * Regmap configs + */ + +static struct reg_default da7219_reg_defaults[] = { + { DA7219_MIC_1_SELECT, 0x00 }, + { DA7219_CIF_TIMEOUT_CTRL, 0x01 }, + { DA7219_SR_24_48, 0x00 }, + { DA7219_SR, 0x0A }, + { DA7219_CIF_I2C_ADDR_CFG, 0x02 }, + { DA7219_PLL_CTRL, 0x10 }, + { DA7219_PLL_FRAC_TOP, 0x00 }, + { DA7219_PLL_FRAC_BOT, 0x00 }, + { DA7219_PLL_INTEGER, 0x20 }, + { DA7219_DIG_ROUTING_DAI, 0x10 }, + { DA7219_DAI_CLK_MODE, 0x01 }, + { DA7219_DAI_CTRL, 0x28 }, + { DA7219_DAI_TDM_CTRL, 0x40 }, + { DA7219_DIG_ROUTING_DAC, 0x32 }, + { DA7219_DAI_OFFSET_LOWER, 0x00 }, + { DA7219_DAI_OFFSET_UPPER, 0x00 }, + { DA7219_REFERENCES, 0x08 }, + { DA7219_MIXIN_L_SELECT, 0x00 }, + { DA7219_MIXIN_L_GAIN, 0x03 }, + { DA7219_ADC_L_GAIN, 0x6F }, + { DA7219_ADC_FILTERS1, 0x80 }, + { DA7219_MIC_1_GAIN, 0x01 }, + { DA7219_SIDETONE_CTRL, 0x40 }, + { DA7219_SIDETONE_GAIN, 0x0E }, + { DA7219_DROUTING_ST_OUTFILT_1L, 0x01 }, + { DA7219_DROUTING_ST_OUTFILT_1R, 0x02 }, + { DA7219_DAC_FILTERS5, 0x00 }, + { DA7219_DAC_FILTERS2, 0x88 }, + { DA7219_DAC_FILTERS3, 0x88 }, + { DA7219_DAC_FILTERS4, 0x08 }, + { DA7219_DAC_FILTERS1, 0x80 }, + { DA7219_DAC_L_GAIN, 0x6F }, + { DA7219_DAC_R_GAIN, 0x6F }, + { DA7219_CP_CTRL, 0x20 }, + { DA7219_HP_L_GAIN, 0x39 }, + { DA7219_HP_R_GAIN, 0x39 }, + { DA7219_MIXOUT_L_SELECT, 0x00 }, + { DA7219_MIXOUT_R_SELECT, 0x00 }, + { DA7219_MICBIAS_CTRL, 0x03 }, + { DA7219_MIC_1_CTRL, 0x40 }, + { DA7219_MIXIN_L_CTRL, 0x40 }, + { DA7219_ADC_L_CTRL, 0x40 }, + { DA7219_DAC_L_CTRL, 0x40 }, + { DA7219_DAC_R_CTRL, 0x40 }, + { DA7219_HP_L_CTRL, 0x40 }, + { DA7219_HP_R_CTRL, 0x40 }, + { DA7219_MIXOUT_L_CTRL, 0x10 }, + { DA7219_MIXOUT_R_CTRL, 0x10 }, + { DA7219_CHIP_ID1, 0x23 }, + { DA7219_CHIP_ID2, 0x93 }, + { DA7219_IO_CTRL, 0x00 }, + { DA7219_GAIN_RAMP_CTRL, 0x00 }, + { DA7219_PC_COUNT, 0x02 }, + { DA7219_CP_VOL_THRESHOLD1, 0x0E }, + { DA7219_DIG_CTRL, 0x00 }, + { DA7219_ALC_CTRL2, 0x00 }, + { DA7219_ALC_CTRL3, 0x00 }, + { DA7219_ALC_NOISE, 0x3F }, + { DA7219_ALC_TARGET_MIN, 0x3F }, + { DA7219_ALC_TARGET_MAX, 0x00 }, + { DA7219_ALC_GAIN_LIMITS, 0xFF }, + { DA7219_ALC_ANA_GAIN_LIMITS, 0x71 }, + { DA7219_ALC_ANTICLIP_CTRL, 0x00 }, + { DA7219_ALC_ANTICLIP_LEVEL, 0x00 }, + { DA7219_DAC_NG_SETUP_TIME, 0x00 }, + { DA7219_DAC_NG_OFF_THRESH, 0x00 }, + { DA7219_DAC_NG_ON_THRESH, 0x00 }, + { DA7219_DAC_NG_CTRL, 0x00 }, + { DA7219_TONE_GEN_CFG1, 0x00 }, + { DA7219_TONE_GEN_CFG2, 0x00 }, + { DA7219_TONE_GEN_CYCLES, 0x00 }, + { DA7219_TONE_GEN_FREQ1_L, 0x55 }, + { DA7219_TONE_GEN_FREQ1_U, 0x15 }, + { DA7219_TONE_GEN_FREQ2_L, 0x00 }, + { DA7219_TONE_GEN_FREQ2_U, 0x40 }, + { DA7219_TONE_GEN_ON_PER, 0x02 }, + { DA7219_TONE_GEN_OFF_PER, 0x01 }, + { DA7219_ACCDET_IRQ_MASK_A, 0x00 }, + { DA7219_ACCDET_IRQ_MASK_B, 0x00 }, + { DA7219_ACCDET_CONFIG_1, 0xD6 }, + { DA7219_ACCDET_CONFIG_2, 0x34 }, + { DA7219_ACCDET_CONFIG_3, 0x0A }, + { DA7219_ACCDET_CONFIG_4, 0x16 }, + { DA7219_ACCDET_CONFIG_5, 0x21 }, + { DA7219_ACCDET_CONFIG_6, 0x3E }, + { DA7219_ACCDET_CONFIG_7, 0x01 }, + { DA7219_SYSTEM_ACTIVE, 0x00 }, +}; + +static bool da7219_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case DA7219_MIC_1_GAIN_STATUS: + case DA7219_MIXIN_L_GAIN_STATUS: + case DA7219_ADC_L_GAIN_STATUS: + case DA7219_DAC_L_GAIN_STATUS: + case DA7219_DAC_R_GAIN_STATUS: + case DA7219_HP_L_GAIN_STATUS: + case DA7219_HP_R_GAIN_STATUS: + case DA7219_CIF_CTRL: + case DA7219_PLL_SRM_STS: + case DA7219_ALC_CTRL1: + case DA7219_SYSTEM_MODES_INPUT: + case DA7219_SYSTEM_MODES_OUTPUT: + case DA7219_ALC_OFFSET_AUTO_M_L: + case DA7219_ALC_OFFSET_AUTO_U_L: + case DA7219_TONE_GEN_CFG1: + case DA7219_ACCDET_STATUS_A: + case DA7219_ACCDET_STATUS_B: + case DA7219_ACCDET_IRQ_EVENT_A: + case DA7219_ACCDET_IRQ_EVENT_B: + case DA7219_ACCDET_CONFIG_8: + case DA7219_SYSTEM_STATUS: + return true; + default: + return false; + } +} + +static const struct regmap_config da7219_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = DA7219_SYSTEM_ACTIVE, + .reg_defaults = da7219_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(da7219_reg_defaults), + .volatile_reg = da7219_volatile_register, + .cache_type = REGCACHE_RBTREE, +}; + static struct reg_sequence da7219_rev_aa_patch[] = { { DA7219_REFERENCES, 0x08 }, }; @@ -2258,18 +2438,56 @@ static struct reg_sequence da7219_rev_aa_patch[] = { static int da7219_probe(struct snd_soc_component *component) { struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); - unsigned int rev; - int ret; + unsigned int system_active, system_status, rev; + u8 io_voltage_lvl; + int i, ret; da7219->component = component; mutex_init(&da7219->ctrl_lock); mutex_init(&da7219->pll_lock); /* Regulator configuration */ - ret = da7219_handle_supplies(component); + ret = da7219_handle_supplies(component, &io_voltage_lvl); if (ret) return ret; + regcache_cache_bypass(da7219->regmap, true); + + /* Disable audio paths if still active from previous start */ + regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active); + if (system_active) { + regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL, + DA7219_GAIN_RAMP_RATE_NOMINAL); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01); + + for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) { + regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS, + &system_status); + if (!system_status) + break; + + msleep(DA7219_SYS_STAT_CHECK_DELAY); + } + } + + /* Soft reset component */ + regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, 0); + regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL, + DA7219_CIF_REG_SOFT_RESET_MASK, + DA7219_CIF_REG_SOFT_RESET_MASK); + regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, + DA7219_SYSTEM_ACTIVE_MASK, 0); + regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, + DA7219_SYSTEM_ACTIVE_MASK, 1); + + regcache_cache_bypass(da7219->regmap, false); + regmap_reinit_cache(da7219->regmap, &da7219_regmap_config); + + /* Update IO voltage level range based on supply level */ + snd_soc_component_write(component, DA7219_IO_CTRL, io_voltage_lvl); + ret = regmap_read(da7219->regmap, DA7219_CHIP_REVISION, &rev); if (ret) { dev_err(component->dev, "Failed to read chip revision: %d\n", ret); @@ -2291,14 +2509,10 @@ static int da7219_probe(struct snd_soc_component *component) } /* Handle DT/ACPI/Platform data */ - da7219->pdata = dev_get_platdata(component->dev); - if (!da7219->pdata) - da7219->pdata = da7219_fw_to_pdata(component); - da7219_handle_pdata(component); /* Check if MCLK provided */ - da7219->mclk = devm_clk_get(component->dev, "mclk"); + da7219->mclk = clk_get(component->dev, "mclk"); if (IS_ERR(da7219->mclk)) { if (PTR_ERR(da7219->mclk) != -ENOENT) { ret = PTR_ERR(da7219->mclk); @@ -2311,7 +2525,7 @@ static int da7219_probe(struct snd_soc_component *component) /* Register CCF DAI clock control */ ret = da7219_register_dai_clks(component); if (ret) - return ret; + goto err_put_clk; /* Default PC counter to free-running */ snd_soc_component_update_bits(component, DA7219_PC_COUNT, DA7219_PC_FREERUN_MASK, @@ -2348,12 +2562,19 @@ static int da7219_probe(struct snd_soc_component *component) /* Initialise AAD block */ ret = da7219_aad_init(component); if (ret) - goto err_disable_reg; + goto err_free_dai_clks; return 0; +err_free_dai_clks: + da7219_free_dai_clks(component); + +err_put_clk: + clk_put(da7219->mclk); + err_disable_reg: regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); + regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies); return ret; } @@ -2361,21 +2582,15 @@ err_disable_reg: static void da7219_remove(struct snd_soc_component *component) { struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); -#ifdef CONFIG_COMMON_CLK - int i; -#endif da7219_aad_exit(component); -#ifdef CONFIG_COMMON_CLK - for (i = DA7219_DAI_NUM_CLKS - 1; i >= 0; --i) { - if (da7219->dai_clks_lookup[i]) - clkdev_drop(da7219->dai_clks_lookup[i]); - } -#endif + da7219_free_dai_clks(component); + clk_put(da7219->mclk); /* Supplies */ regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); + regulator_bulk_free(DA7219_NUM_SUPPLIES, da7219->supplies); } #ifdef CONFIG_PM @@ -2429,153 +2644,17 @@ static const struct snd_soc_component_driver soc_component_dev_da7219 = { /* - * Regmap configs - */ - -static struct reg_default da7219_reg_defaults[] = { - { DA7219_MIC_1_SELECT, 0x00 }, - { DA7219_CIF_TIMEOUT_CTRL, 0x01 }, - { DA7219_SR_24_48, 0x00 }, - { DA7219_SR, 0x0A }, - { DA7219_CIF_I2C_ADDR_CFG, 0x02 }, - { DA7219_PLL_CTRL, 0x10 }, - { DA7219_PLL_FRAC_TOP, 0x00 }, - { DA7219_PLL_FRAC_BOT, 0x00 }, - { DA7219_PLL_INTEGER, 0x20 }, - { DA7219_DIG_ROUTING_DAI, 0x10 }, - { DA7219_DAI_CLK_MODE, 0x01 }, - { DA7219_DAI_CTRL, 0x28 }, - { DA7219_DAI_TDM_CTRL, 0x40 }, - { DA7219_DIG_ROUTING_DAC, 0x32 }, - { DA7219_DAI_OFFSET_LOWER, 0x00 }, - { DA7219_DAI_OFFSET_UPPER, 0x00 }, - { DA7219_REFERENCES, 0x08 }, - { DA7219_MIXIN_L_SELECT, 0x00 }, - { DA7219_MIXIN_L_GAIN, 0x03 }, - { DA7219_ADC_L_GAIN, 0x6F }, - { DA7219_ADC_FILTERS1, 0x80 }, - { DA7219_MIC_1_GAIN, 0x01 }, - { DA7219_SIDETONE_CTRL, 0x40 }, - { DA7219_SIDETONE_GAIN, 0x0E }, - { DA7219_DROUTING_ST_OUTFILT_1L, 0x01 }, - { DA7219_DROUTING_ST_OUTFILT_1R, 0x02 }, - { DA7219_DAC_FILTERS5, 0x00 }, - { DA7219_DAC_FILTERS2, 0x88 }, - { DA7219_DAC_FILTERS3, 0x88 }, - { DA7219_DAC_FILTERS4, 0x08 }, - { DA7219_DAC_FILTERS1, 0x80 }, - { DA7219_DAC_L_GAIN, 0x6F }, - { DA7219_DAC_R_GAIN, 0x6F }, - { DA7219_CP_CTRL, 0x20 }, - { DA7219_HP_L_GAIN, 0x39 }, - { DA7219_HP_R_GAIN, 0x39 }, - { DA7219_MIXOUT_L_SELECT, 0x00 }, - { DA7219_MIXOUT_R_SELECT, 0x00 }, - { DA7219_MICBIAS_CTRL, 0x03 }, - { DA7219_MIC_1_CTRL, 0x40 }, - { DA7219_MIXIN_L_CTRL, 0x40 }, - { DA7219_ADC_L_CTRL, 0x40 }, - { DA7219_DAC_L_CTRL, 0x40 }, - { DA7219_DAC_R_CTRL, 0x40 }, - { DA7219_HP_L_CTRL, 0x40 }, - { DA7219_HP_R_CTRL, 0x40 }, - { DA7219_MIXOUT_L_CTRL, 0x10 }, - { DA7219_MIXOUT_R_CTRL, 0x10 }, - { DA7219_CHIP_ID1, 0x23 }, - { DA7219_CHIP_ID2, 0x93 }, - { DA7219_IO_CTRL, 0x00 }, - { DA7219_GAIN_RAMP_CTRL, 0x00 }, - { DA7219_PC_COUNT, 0x02 }, - { DA7219_CP_VOL_THRESHOLD1, 0x0E }, - { DA7219_DIG_CTRL, 0x00 }, - { DA7219_ALC_CTRL2, 0x00 }, - { DA7219_ALC_CTRL3, 0x00 }, - { DA7219_ALC_NOISE, 0x3F }, - { DA7219_ALC_TARGET_MIN, 0x3F }, - { DA7219_ALC_TARGET_MAX, 0x00 }, - { DA7219_ALC_GAIN_LIMITS, 0xFF }, - { DA7219_ALC_ANA_GAIN_LIMITS, 0x71 }, - { DA7219_ALC_ANTICLIP_CTRL, 0x00 }, - { DA7219_ALC_ANTICLIP_LEVEL, 0x00 }, - { DA7219_DAC_NG_SETUP_TIME, 0x00 }, - { DA7219_DAC_NG_OFF_THRESH, 0x00 }, - { DA7219_DAC_NG_ON_THRESH, 0x00 }, - { DA7219_DAC_NG_CTRL, 0x00 }, - { DA7219_TONE_GEN_CFG1, 0x00 }, - { DA7219_TONE_GEN_CFG2, 0x00 }, - { DA7219_TONE_GEN_CYCLES, 0x00 }, - { DA7219_TONE_GEN_FREQ1_L, 0x55 }, - { DA7219_TONE_GEN_FREQ1_U, 0x15 }, - { DA7219_TONE_GEN_FREQ2_L, 0x00 }, - { DA7219_TONE_GEN_FREQ2_U, 0x40 }, - { DA7219_TONE_GEN_ON_PER, 0x02 }, - { DA7219_TONE_GEN_OFF_PER, 0x01 }, - { DA7219_ACCDET_IRQ_MASK_A, 0x00 }, - { DA7219_ACCDET_IRQ_MASK_B, 0x00 }, - { DA7219_ACCDET_CONFIG_1, 0xD6 }, - { DA7219_ACCDET_CONFIG_2, 0x34 }, - { DA7219_ACCDET_CONFIG_3, 0x0A }, - { DA7219_ACCDET_CONFIG_4, 0x16 }, - { DA7219_ACCDET_CONFIG_5, 0x21 }, - { DA7219_ACCDET_CONFIG_6, 0x3E }, - { DA7219_ACCDET_CONFIG_7, 0x01 }, - { DA7219_SYSTEM_ACTIVE, 0x00 }, -}; - -static bool da7219_volatile_register(struct device *dev, unsigned int reg) -{ - switch (reg) { - case DA7219_MIC_1_GAIN_STATUS: - case DA7219_MIXIN_L_GAIN_STATUS: - case DA7219_ADC_L_GAIN_STATUS: - case DA7219_DAC_L_GAIN_STATUS: - case DA7219_DAC_R_GAIN_STATUS: - case DA7219_HP_L_GAIN_STATUS: - case DA7219_HP_R_GAIN_STATUS: - case DA7219_CIF_CTRL: - case DA7219_PLL_SRM_STS: - case DA7219_ALC_CTRL1: - case DA7219_SYSTEM_MODES_INPUT: - case DA7219_SYSTEM_MODES_OUTPUT: - case DA7219_ALC_OFFSET_AUTO_M_L: - case DA7219_ALC_OFFSET_AUTO_U_L: - case DA7219_TONE_GEN_CFG1: - case DA7219_ACCDET_STATUS_A: - case DA7219_ACCDET_STATUS_B: - case DA7219_ACCDET_IRQ_EVENT_A: - case DA7219_ACCDET_IRQ_EVENT_B: - case DA7219_ACCDET_CONFIG_8: - case DA7219_SYSTEM_STATUS: - return true; - default: - return false; - } -} - -static const struct regmap_config da7219_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - - .max_register = DA7219_SYSTEM_ACTIVE, - .reg_defaults = da7219_reg_defaults, - .num_reg_defaults = ARRAY_SIZE(da7219_reg_defaults), - .volatile_reg = da7219_volatile_register, - .cache_type = REGCACHE_RBTREE, -}; - - -/* * I2C layer */ static int da7219_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + struct device *dev = &i2c->dev; struct da7219_priv *da7219; - unsigned int system_active, system_status; - int i, ret; + int ret; - da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), + da7219 = devm_kzalloc(dev, sizeof(struct da7219_priv), GFP_KERNEL); if (!da7219) return -ENOMEM; @@ -2585,47 +2664,24 @@ static int da7219_i2c_probe(struct i2c_client *i2c, da7219->regmap = devm_regmap_init_i2c(i2c, &da7219_regmap_config); if (IS_ERR(da7219->regmap)) { ret = PTR_ERR(da7219->regmap); - dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); + dev_err(dev, "regmap_init() failed: %d\n", ret); return ret; } - regcache_cache_bypass(da7219->regmap, true); - - /* Disable audio paths if still active from previous start */ - regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active); - if (system_active) { - regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL, - DA7219_GAIN_RAMP_RATE_NOMINAL); - regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00); - regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01); - - for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) { - regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS, - &system_status); - if (!system_status) - break; - - msleep(DA7219_SYS_STAT_CHECK_DELAY); - } - } - - /* Soft reset component */ - regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1, - DA7219_ACCDET_EN_MASK, 0); - regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL, - DA7219_CIF_REG_SOFT_RESET_MASK, - DA7219_CIF_REG_SOFT_RESET_MASK); - regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, - DA7219_SYSTEM_ACTIVE_MASK, 0); + /* Retrieve DT/ACPI/Platform data */ + da7219->pdata = dev_get_platdata(dev); + if (!da7219->pdata) + da7219->pdata = da7219_fw_to_pdata(dev); - regcache_cache_bypass(da7219->regmap, false); + /* AAD */ + ret = da7219_aad_probe(i2c); + if (ret) + return ret; - ret = devm_snd_soc_register_component(&i2c->dev, - &soc_component_dev_da7219, - &da7219_dai, 1); + ret = devm_snd_soc_register_component(dev, &soc_component_dev_da7219, + &da7219_dai, 1); if (ret < 0) { - dev_err(&i2c->dev, "Failed to register da7219 component: %d\n", - ret); + dev_err(dev, "Failed to register da7219 component: %d\n", ret); } return ret; } diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 88b67fedd01b..94af88f52589 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -817,6 +817,7 @@ struct da7219_priv { #ifdef CONFIG_COMMON_CLK struct clk_hw dai_clks_hw[DA7219_DAI_NUM_CLKS]; + struct clk_hw_onecell_data *clk_hw_data; #endif struct clk_lookup *dai_clks_lookup[DA7219_DAI_NUM_CLKS]; struct clk *dai_clks[DA7219_DAI_NUM_CLKS]; diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index f26b77faed59..869d1547ae5d 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -9,6 +9,7 @@ * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + #include <linux/init.h> #include <linux/delay.h> #include <linux/module.h> @@ -107,6 +108,7 @@ struct hdac_hdmi_pcm { unsigned char chmap[8]; /* ALSA API channel-map */ struct mutex lock; int jack_event; + struct snd_kcontrol *eld_ctl; }; struct hdac_hdmi_dai_port_map { @@ -1248,6 +1250,7 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, struct hdac_hdmi_pcm *pcm; int size = 0; int port_id = -1; + bool eld_valid, eld_changed; if (!hdmi) return; @@ -1273,6 +1276,8 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, size = -EINVAL; } + eld_valid = port->eld.eld_valid; + if (size > 0) { port->eld.eld_valid = true; port->eld.eld_size = size; @@ -1281,6 +1286,8 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, port->eld.eld_size = 0; } + eld_changed = (eld_valid != port->eld.eld_valid); + pcm = hdac_hdmi_get_pcm(hdev, port); if (!port->eld.monitor_present || !port->eld.eld_valid) { @@ -1313,6 +1320,12 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, } mutex_unlock(&hdmi->pin_mutex); + + if (eld_changed && pcm) + snd_ctl_notify(hdmi->card, + SNDRV_CTL_EVENT_MASK_VALUE | + SNDRV_CTL_EVENT_MASK_INFO, + &pcm->eld_ctl->id); } static int hdac_hdmi_add_ports(struct hdac_device *hdev, @@ -1411,6 +1424,122 @@ static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdev) } +static int hdac_hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_hdmi_pcm *pcm; + struct hdac_hdmi_port *port; + struct hdac_hdmi_eld *eld; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = 0; + + pcm = get_hdmi_pcm_from_id(hdmi, kcontrol->id.device); + if (!pcm) { + dev_dbg(component->dev, "%s: no pcm, device %d\n", __func__, + kcontrol->id.device); + return 0; + } + + if (list_empty(&pcm->port_list)) { + dev_dbg(component->dev, "%s: empty port list, device %d\n", + __func__, kcontrol->id.device); + return 0; + } + + mutex_lock(&hdmi->pin_mutex); + + list_for_each_entry(port, &pcm->port_list, head) { + eld = &port->eld; + + if (eld->eld_valid) { + uinfo->count = eld->eld_size; + break; + } + } + + mutex_unlock(&hdmi->pin_mutex); + + return 0; +} + +static int hdac_hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct hdac_hdmi_priv *hdmi = snd_soc_component_get_drvdata(component); + struct hdac_hdmi_pcm *pcm; + struct hdac_hdmi_port *port; + struct hdac_hdmi_eld *eld; + + memset(ucontrol->value.bytes.data, 0, ARRAY_SIZE(ucontrol->value.bytes.data)); + + pcm = get_hdmi_pcm_from_id(hdmi, kcontrol->id.device); + if (!pcm) { + dev_dbg(component->dev, "%s: no pcm, device %d\n", __func__, + kcontrol->id.device); + return 0; + } + + if (list_empty(&pcm->port_list)) { + dev_dbg(component->dev, "%s: empty port list, device %d\n", + __func__, kcontrol->id.device); + return 0; + } + + mutex_lock(&hdmi->pin_mutex); + + list_for_each_entry(port, &pcm->port_list, head) { + eld = &port->eld; + + if (!eld->eld_valid) + continue; + + if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || + eld->eld_size > ELD_MAX_SIZE) { + mutex_unlock(&hdmi->pin_mutex); + + dev_err(component->dev, "%s: buffer too small, device %d eld_size %d\n", + __func__, kcontrol->id.device, eld->eld_size); + snd_BUG(); + return -EINVAL; + } + + memcpy(ucontrol->value.bytes.data, eld->eld_buffer, + eld->eld_size); + break; + } + + mutex_unlock(&hdmi->pin_mutex); + + return 0; +} + +static int hdac_hdmi_create_eld_ctl(struct snd_soc_component *component, struct hdac_hdmi_pcm *pcm) +{ + struct snd_kcontrol *kctl; + struct snd_kcontrol_new hdmi_eld_ctl = { + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "ELD", + .info = hdac_hdmi_eld_ctl_info, + .get = hdac_hdmi_eld_ctl_get, + .device = pcm->pcm_id, + }; + + /* add ELD ctl with the device number corresponding to the PCM stream */ + kctl = snd_ctl_new1(&hdmi_eld_ctl, component); + if (!kctl) + return -ENOMEM; + + pcm->eld_ctl = kctl; + + return snd_ctl_add(component->card->snd_card, kctl); +} + static const struct snd_soc_dai_ops hdmi_dai_ops = { .startup = hdac_hdmi_pcm_open, .shutdown = hdac_hdmi_pcm_close, @@ -1784,6 +1913,15 @@ int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, } } + /* add control for ELD Bytes */ + err = hdac_hdmi_create_eld_ctl(component, pcm); + if (err < 0) { + dev_err(&hdev->dev, + "eld control add failed with err: %d for pcm: %d\n", + err, device); + return err; + } + list_add_tail(&pcm->head, &hdmi->pcm_list); return 0; diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 5fe724728e84..6469612c42cb 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -256,6 +256,9 @@ static __maybe_unused int max98373_resume(struct device *dev) struct max98373_priv *max98373 = dev_get_drvdata(dev); unsigned long time; + if (!max98373->hw_init) + return 0; + if (!slave->unattach_request) goto regmap_sync; diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c new file mode 100644 index 000000000000..72f05335b420 --- /dev/null +++ b/sound/soc/codecs/mt6359.c @@ -0,0 +1,2753 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt6359.c -- mt6359 ALSA SoC audio codec driver +// +// Copyright (c) 2020 MediaTek Inc. +// Author: KaiChieh Chuang <[email protected]> + +#include <linux/delay.h> +#include <linux/kthread.h> +#include <linux/mfd/mt6397/core.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/regulator/consumer.h> +#include <linux/sched.h> +#include <sound/soc.h> +#include <sound/tlv.h> + +#include "mt6359.h" + +static void mt6359_set_playback_gpio(struct mt6359_priv *priv) +{ + /* set gpio mosi mode, clk / data mosi */ + regmap_write(priv->regmap, MT6359_GPIO_MODE2_CLR, 0x0ffe); + regmap_write(priv->regmap, MT6359_GPIO_MODE2_SET, 0x0249); + + /* sync mosi */ + regmap_write(priv->regmap, MT6359_GPIO_MODE3_CLR, 0x6); + regmap_write(priv->regmap, MT6359_GPIO_MODE3_SET, 0x1); +} + +static void mt6359_reset_playback_gpio(struct mt6359_priv *priv) +{ + /* set pad_aud_*_mosi to GPIO mode and dir input + * reason: + * pad_aud_dat_mosi*, because the pin is used as boot strap + * don't clean clk/sync, for mtkaif protocol 2 + */ + regmap_write(priv->regmap, MT6359_GPIO_MODE2_CLR, 0x0ff8); + regmap_update_bits(priv->regmap, MT6359_GPIO_DIR0, 0x7 << 9, 0x0); +} + +static void mt6359_set_capture_gpio(struct mt6359_priv *priv) +{ + /* set gpio miso mode */ + regmap_write(priv->regmap, MT6359_GPIO_MODE3_CLR, 0x0e00); + regmap_write(priv->regmap, MT6359_GPIO_MODE3_SET, 0x0200); + + regmap_write(priv->regmap, MT6359_GPIO_MODE4_CLR, 0x003f); + regmap_write(priv->regmap, MT6359_GPIO_MODE4_SET, 0x0009); +} + +static void mt6359_reset_capture_gpio(struct mt6359_priv *priv) +{ + /* set pad_aud_*_miso to GPIO mode and dir input + * reason: + * pad_aud_clk_miso, because when playback only the miso_clk + * will also have 26m, so will have power leak + * pad_aud_dat_miso*, because the pin is used as boot strap + */ + regmap_write(priv->regmap, MT6359_GPIO_MODE3_CLR, 0x0e00); + + regmap_write(priv->regmap, MT6359_GPIO_MODE4_CLR, 0x003f); + + regmap_update_bits(priv->regmap, MT6359_GPIO_DIR0, + 0x7 << 13, 0x0); + regmap_update_bits(priv->regmap, MT6359_GPIO_DIR1, + 0x3 << 0, 0x0); +} + +static void mt6359_set_decoder_clk(struct mt6359_priv *priv, bool enable) +{ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON13, + RG_RSTB_DECODER_VA32_MASK_SFT, + (enable ? 1 : 0) << RG_RSTB_DECODER_VA32_SFT); +} + +static void mt6359_mtkaif_tx_enable(struct mt6359_priv *priv) +{ + switch (priv->mtkaif_protocol) { + case MT6359_MTKAIF_PROTOCOL_2_CLK_P2: + /* MTKAIF TX format setting */ + regmap_update_bits(priv->regmap, + MT6359_AFE_ADDA_MTKAIF_CFG0, + 0xffff, 0x0210); + /* enable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, + MT6359_AFE_AUD_PAD_TOP, + 0xff00, 0x3800); + regmap_update_bits(priv->regmap, + MT6359_AFE_AUD_PAD_TOP, + 0xff00, 0x3900); + break; + case MT6359_MTKAIF_PROTOCOL_2: + /* MTKAIF TX format setting */ + regmap_update_bits(priv->regmap, + MT6359_AFE_ADDA_MTKAIF_CFG0, + 0xffff, 0x0210); + /* enable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, + MT6359_AFE_AUD_PAD_TOP, + 0xff00, 0x3100); + break; + case MT6359_MTKAIF_PROTOCOL_1: + default: + /* MTKAIF TX format setting */ + regmap_update_bits(priv->regmap, + MT6359_AFE_ADDA_MTKAIF_CFG0, + 0xffff, 0x0000); + /* enable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, + MT6359_AFE_AUD_PAD_TOP, + 0xff00, 0x3100); + break; + } +} + +static void mt6359_mtkaif_tx_disable(struct mt6359_priv *priv) +{ + /* disable aud_pad TX fifos */ + regmap_update_bits(priv->regmap, MT6359_AFE_AUD_PAD_TOP, + 0xff00, 0x3000); +} + +static void zcd_disable(struct mt6359_priv *priv) +{ + regmap_write(priv->regmap, MT6359_ZCD_CON0, 0x0000); +} + +static void hp_main_output_ramp(struct mt6359_priv *priv, bool up) +{ + int i = 0, stage = 0; + int target = 7; + + /* Enable/Reduce HPL/R main output stage step by step */ + for (i = 0; i <= target; i++) { + stage = up ? i : target - i; + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON1, + RG_HPLOUTSTGCTRL_VAUDP32_MASK_SFT, + stage << RG_HPLOUTSTGCTRL_VAUDP32_SFT); + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON1, + RG_HPROUTSTGCTRL_VAUDP32_MASK_SFT, + stage << RG_HPROUTSTGCTRL_VAUDP32_SFT); + usleep_range(600, 650); + } +} + +static void hp_aux_feedback_loop_gain_ramp(struct mt6359_priv *priv, bool up) +{ + int i = 0, stage = 0; + int target = 0xf; + + /* Enable/Reduce HP aux feedback loop gain step by step */ + for (i = 0; i <= target; i++) { + stage = up ? i : target - i; + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON9, + 0xf << 12, stage << 12); + usleep_range(600, 650); + } +} + +static void hp_in_pair_current(struct mt6359_priv *priv, bool increase) +{ + int i = 0, stage = 0; + int target = 0x3; + + /* Set input diff pair bias select (Hi-Fi mode) */ + if (priv->hp_hifi_mode) { + /* Reduce HP aux feedback loop gain step by step */ + for (i = 0; i <= target; i++) { + stage = increase ? i : target - i; + regmap_update_bits(priv->regmap, + MT6359_AUDDEC_ANA_CON10, + 0x3 << 3, stage << 3); + usleep_range(100, 150); + } + } +} + +static void hp_pull_down(struct mt6359_priv *priv, bool enable) +{ + int i; + + if (enable) { + for (i = 0x0; i <= 0x7; i++) { + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON2, + RG_HPPSHORT2VCM_VAUDP32_MASK_SFT, + i << RG_HPPSHORT2VCM_VAUDP32_SFT); + usleep_range(100, 150); + } + } else { + for (i = 0x7; i >= 0x0; i--) { + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON2, + RG_HPPSHORT2VCM_VAUDP32_MASK_SFT, + i << RG_HPPSHORT2VCM_VAUDP32_SFT); + usleep_range(100, 150); + } + } +} + +static bool is_valid_hp_pga_idx(int reg_idx) +{ + return (reg_idx >= DL_GAIN_8DB && reg_idx <= DL_GAIN_N_22DB) || + reg_idx == DL_GAIN_N_40DB; +} + +static void headset_volume_ramp(struct mt6359_priv *priv, + int from, int to) +{ + int offset = 0, count = 1, reg_idx; + + if (!is_valid_hp_pga_idx(from) || !is_valid_hp_pga_idx(to)) { + dev_warn(priv->dev, "%s(), volume index is not valid, from %d, to %d\n", + __func__, from, to); + return; + } + + dev_dbg(priv->dev, "%s(), from %d, to %d\n", __func__, from, to); + + if (to > from) + offset = to - from; + else + offset = from - to; + + while (offset > 0) { + if (to > from) + reg_idx = from + count; + else + reg_idx = from - count; + + if (is_valid_hp_pga_idx(reg_idx)) { + regmap_update_bits(priv->regmap, + MT6359_ZCD_CON2, + DL_GAIN_REG_MASK, + (reg_idx << 7) | reg_idx); + usleep_range(600, 650); + } + offset--; + count++; + } +} + +static int mt6359_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_kcontrol_component(kcontrol); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + unsigned int reg; + int index = ucontrol->value.integer.value[0]; + int ret; + + ret = snd_soc_put_volsw(kcontrol, ucontrol); + if (ret < 0) + return ret; + + switch (mc->reg) { + case MT6359_ZCD_CON2: + regmap_read(priv->regmap, MT6359_ZCD_CON2, ®); + priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL] = + (reg >> RG_AUDHPLGAIN_SFT) & RG_AUDHPLGAIN_MASK; + priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTR] = + (reg >> RG_AUDHPRGAIN_SFT) & RG_AUDHPRGAIN_MASK; + break; + case MT6359_ZCD_CON1: + regmap_read(priv->regmap, MT6359_ZCD_CON1, ®); + priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTL] = + (reg >> RG_AUDLOLGAIN_SFT) & RG_AUDLOLGAIN_MASK; + priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTR] = + (reg >> RG_AUDLORGAIN_SFT) & RG_AUDLORGAIN_MASK; + break; + case MT6359_ZCD_CON3: + regmap_read(priv->regmap, MT6359_ZCD_CON3, ®); + priv->ana_gain[AUDIO_ANALOG_VOLUME_HSOUTL] = + (reg >> RG_AUDHSGAIN_SFT) & RG_AUDHSGAIN_MASK; + break; + case MT6359_AUDENC_ANA_CON0: + regmap_read(priv->regmap, MT6359_AUDENC_ANA_CON0, ®); + priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP1] = + (reg >> RG_AUDPREAMPLGAIN_SFT) & RG_AUDPREAMPLGAIN_MASK; + break; + case MT6359_AUDENC_ANA_CON1: + regmap_read(priv->regmap, MT6359_AUDENC_ANA_CON1, ®); + priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP2] = + (reg >> RG_AUDPREAMPRGAIN_SFT) & RG_AUDPREAMPRGAIN_MASK; + break; + case MT6359_AUDENC_ANA_CON2: + regmap_read(priv->regmap, MT6359_AUDENC_ANA_CON2, ®); + priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP3] = + (reg >> RG_AUDPREAMP3GAIN_SFT) & RG_AUDPREAMP3GAIN_MASK; + break; + } + + dev_dbg(priv->dev, "%s(), name %s, reg(0x%x) = 0x%x, set index = %x\n", + __func__, kcontrol->id.name, mc->reg, reg, index); + + return ret; +} + +/* MUX */ + +/* LOL MUX */ +static const char * const lo_in_mux_map[] = { + "Open", "Playback_L_DAC", "Playback", "Test Mode" +}; + +static SOC_ENUM_SINGLE_DECL(lo_in_mux_map_enum, SND_SOC_NOPM, 0, lo_in_mux_map); + +static const struct snd_kcontrol_new lo_in_mux_control = + SOC_DAPM_ENUM("LO Select", lo_in_mux_map_enum); + +/*HP MUX */ +static const char * const hp_in_mux_map[] = { + "Open", + "LoudSPK Playback", + "Audio Playback", + "Test Mode", + "HP Impedance", +}; + +static SOC_ENUM_SINGLE_DECL(hp_in_mux_map_enum, + SND_SOC_NOPM, + 0, + hp_in_mux_map); + +static const struct snd_kcontrol_new hp_in_mux_control = + SOC_DAPM_ENUM("HP Select", hp_in_mux_map_enum); + +/* RCV MUX */ +static const char * const rcv_in_mux_map[] = { + "Open", "Mute", "Voice Playback", "Test Mode" +}; + +static SOC_ENUM_SINGLE_DECL(rcv_in_mux_map_enum, + SND_SOC_NOPM, + 0, + rcv_in_mux_map); + +static const struct snd_kcontrol_new rcv_in_mux_control = + SOC_DAPM_ENUM("RCV Select", rcv_in_mux_map_enum); + +/* DAC In MUX */ +static const char * const dac_in_mux_map[] = { + "Normal Path", "Sgen" +}; + +static int dac_in_mux_map_value[] = { + 0x0, 0x1, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(dac_in_mux_map_enum, + MT6359_AFE_TOP_CON0, + DL_SINE_ON_SFT, + DL_SINE_ON_MASK, + dac_in_mux_map, + dac_in_mux_map_value); + +static const struct snd_kcontrol_new dac_in_mux_control = + SOC_DAPM_ENUM("DAC Select", dac_in_mux_map_enum); + +/* AIF Out MUX */ +static SOC_VALUE_ENUM_SINGLE_DECL(aif_out_mux_map_enum, + MT6359_AFE_TOP_CON0, + UL_SINE_ON_SFT, + UL_SINE_ON_MASK, + dac_in_mux_map, + dac_in_mux_map_value); + +static const struct snd_kcontrol_new aif_out_mux_control = + SOC_DAPM_ENUM("AIF Out Select", aif_out_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(aif2_out_mux_map_enum, + MT6359_AFE_TOP_CON0, + ADDA6_UL_SINE_ON_SFT, + ADDA6_UL_SINE_ON_MASK, + dac_in_mux_map, + dac_in_mux_map_value); + +static const struct snd_kcontrol_new aif2_out_mux_control = + SOC_DAPM_ENUM("AIF Out Select", aif2_out_mux_map_enum); + +static const char * const ul_src_mux_map[] = { + "AMIC", + "DMIC", +}; + +static int ul_src_mux_map_value[] = { + UL_SRC_MUX_AMIC, + UL_SRC_MUX_DMIC, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(ul_src_mux_map_enum, + MT6359_AFE_UL_SRC_CON0_L, + UL_SDM_3_LEVEL_CTL_SFT, + UL_SDM_3_LEVEL_CTL_MASK, + ul_src_mux_map, + ul_src_mux_map_value); + +static const struct snd_kcontrol_new ul_src_mux_control = + SOC_DAPM_ENUM("UL_SRC_MUX Select", ul_src_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(ul2_src_mux_map_enum, + MT6359_AFE_ADDA6_UL_SRC_CON0_L, + ADDA6_UL_SDM_3_LEVEL_CTL_SFT, + ADDA6_UL_SDM_3_LEVEL_CTL_MASK, + ul_src_mux_map, + ul_src_mux_map_value); + +static const struct snd_kcontrol_new ul2_src_mux_control = + SOC_DAPM_ENUM("UL_SRC_MUX Select", ul2_src_mux_map_enum); + +static const char * const miso_mux_map[] = { + "UL1_CH1", + "UL1_CH2", + "UL2_CH1", + "UL2_CH2", +}; + +static int miso_mux_map_value[] = { + MISO_MUX_UL1_CH1, + MISO_MUX_UL1_CH2, + MISO_MUX_UL2_CH1, + MISO_MUX_UL2_CH2, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(miso0_mux_map_enum, + MT6359_AFE_MTKAIF_MUX_CFG, + RG_ADDA_CH1_SEL_SFT, + RG_ADDA_CH1_SEL_MASK, + miso_mux_map, + miso_mux_map_value); + +static const struct snd_kcontrol_new miso0_mux_control = + SOC_DAPM_ENUM("MISO_MUX Select", miso0_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(miso1_mux_map_enum, + MT6359_AFE_MTKAIF_MUX_CFG, + RG_ADDA_CH2_SEL_SFT, + RG_ADDA_CH2_SEL_MASK, + miso_mux_map, + miso_mux_map_value); + +static const struct snd_kcontrol_new miso1_mux_control = + SOC_DAPM_ENUM("MISO_MUX Select", miso1_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_DECL(miso2_mux_map_enum, + MT6359_AFE_MTKAIF_MUX_CFG, + RG_ADDA6_CH1_SEL_SFT, + RG_ADDA6_CH1_SEL_MASK, + miso_mux_map, + miso_mux_map_value); + +static const struct snd_kcontrol_new miso2_mux_control = + SOC_DAPM_ENUM("MISO_MUX Select", miso2_mux_map_enum); + +static const char * const dmic_mux_map[] = { + "DMIC_DATA0", + "DMIC_DATA1_L", + "DMIC_DATA1_L_1", + "DMIC_DATA1_R", +}; + +static int dmic_mux_map_value[] = { + DMIC_MUX_DMIC_DATA0, + DMIC_MUX_DMIC_DATA1_L, + DMIC_MUX_DMIC_DATA1_L_1, + DMIC_MUX_DMIC_DATA1_R, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(dmic0_mux_map_enum, + MT6359_AFE_MIC_ARRAY_CFG, + RG_DMIC_ADC1_SOURCE_SEL_SFT, + RG_DMIC_ADC1_SOURCE_SEL_MASK, + dmic_mux_map, + dmic_mux_map_value); + +static const struct snd_kcontrol_new dmic0_mux_control = + SOC_DAPM_ENUM("DMIC_MUX Select", dmic0_mux_map_enum); + +/* ul1 ch2 use RG_DMIC_ADC3_SOURCE_SEL */ +static SOC_VALUE_ENUM_SINGLE_DECL(dmic1_mux_map_enum, + MT6359_AFE_MIC_ARRAY_CFG, + RG_DMIC_ADC3_SOURCE_SEL_SFT, + RG_DMIC_ADC3_SOURCE_SEL_MASK, + dmic_mux_map, + dmic_mux_map_value); + +static const struct snd_kcontrol_new dmic1_mux_control = + SOC_DAPM_ENUM("DMIC_MUX Select", dmic1_mux_map_enum); + +/* ul2 ch1 use RG_DMIC_ADC2_SOURCE_SEL */ +static SOC_VALUE_ENUM_SINGLE_DECL(dmic2_mux_map_enum, + MT6359_AFE_MIC_ARRAY_CFG, + RG_DMIC_ADC2_SOURCE_SEL_SFT, + RG_DMIC_ADC2_SOURCE_SEL_MASK, + dmic_mux_map, + dmic_mux_map_value); + +static const struct snd_kcontrol_new dmic2_mux_control = + SOC_DAPM_ENUM("DMIC_MUX Select", dmic2_mux_map_enum); + +/* ADC L MUX */ +static const char * const adc_left_mux_map[] = { + "Idle", "AIN0", "Left Preamplifier", "Idle_1" +}; + +static int adc_mux_map_value[] = { + ADC_MUX_IDLE, + ADC_MUX_AIN0, + ADC_MUX_PREAMPLIFIER, + ADC_MUX_IDLE1, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(adc_left_mux_map_enum, + MT6359_AUDENC_ANA_CON0, + RG_AUDADCLINPUTSEL_SFT, + RG_AUDADCLINPUTSEL_MASK, + adc_left_mux_map, + adc_mux_map_value); + +static const struct snd_kcontrol_new adc_left_mux_control = + SOC_DAPM_ENUM("ADC L Select", adc_left_mux_map_enum); + +/* ADC R MUX */ +static const char * const adc_right_mux_map[] = { + "Idle", "AIN0", "Right Preamplifier", "Idle_1" +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(adc_right_mux_map_enum, + MT6359_AUDENC_ANA_CON1, + RG_AUDADCRINPUTSEL_SFT, + RG_AUDADCRINPUTSEL_MASK, + adc_right_mux_map, + adc_mux_map_value); + +static const struct snd_kcontrol_new adc_right_mux_control = + SOC_DAPM_ENUM("ADC R Select", adc_right_mux_map_enum); + +/* ADC 3 MUX */ +static const char * const adc_3_mux_map[] = { + "Idle", "AIN0", "Preamplifier", "Idle_1" +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(adc_3_mux_map_enum, + MT6359_AUDENC_ANA_CON2, + RG_AUDADC3INPUTSEL_SFT, + RG_AUDADC3INPUTSEL_MASK, + adc_3_mux_map, + adc_mux_map_value); + +static const struct snd_kcontrol_new adc_3_mux_control = + SOC_DAPM_ENUM("ADC 3 Select", adc_3_mux_map_enum); + +static const char * const pga_l_mux_map[] = { + "None", "AIN0", "AIN1" +}; + +static int pga_l_mux_map_value[] = { + PGA_L_MUX_NONE, + PGA_L_MUX_AIN0, + PGA_L_MUX_AIN1 +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(pga_left_mux_map_enum, + MT6359_AUDENC_ANA_CON0, + RG_AUDPREAMPLINPUTSEL_SFT, + RG_AUDPREAMPLINPUTSEL_MASK, + pga_l_mux_map, + pga_l_mux_map_value); + +static const struct snd_kcontrol_new pga_left_mux_control = + SOC_DAPM_ENUM("PGA L Select", pga_left_mux_map_enum); + +static const char * const pga_r_mux_map[] = { + "None", "AIN2", "AIN3", "AIN0" +}; + +static int pga_r_mux_map_value[] = { + PGA_R_MUX_NONE, + PGA_R_MUX_AIN2, + PGA_R_MUX_AIN3, + PGA_R_MUX_AIN0 +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(pga_right_mux_map_enum, + MT6359_AUDENC_ANA_CON1, + RG_AUDPREAMPRINPUTSEL_SFT, + RG_AUDPREAMPRINPUTSEL_MASK, + pga_r_mux_map, + pga_r_mux_map_value); + +static const struct snd_kcontrol_new pga_right_mux_control = + SOC_DAPM_ENUM("PGA R Select", pga_right_mux_map_enum); + +static const char * const pga_3_mux_map[] = { + "None", "AIN3", "AIN2" +}; + +static int pga_3_mux_map_value[] = { + PGA_3_MUX_NONE, + PGA_3_MUX_AIN3, + PGA_3_MUX_AIN2 +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(pga_3_mux_map_enum, + MT6359_AUDENC_ANA_CON2, + RG_AUDPREAMP3INPUTSEL_SFT, + RG_AUDPREAMP3INPUTSEL_MASK, + pga_3_mux_map, + pga_3_mux_map_value); + +static const struct snd_kcontrol_new pga_3_mux_control = + SOC_DAPM_ENUM("PGA 3 Select", pga_3_mux_map_enum); + +static int mt_sgen_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event = 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* sdm audio fifo clock power on */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON2, 0x0006); + /* scrambler clock on enable */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON0, 0xcba1); + /* sdm power on */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON2, 0x0003); + /* sdm fifo enable */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON2, 0x000b); + + regmap_update_bits(priv->regmap, MT6359_AFE_SGEN_CFG0, + 0xff3f, + 0x0000); + regmap_update_bits(priv->regmap, MT6359_AFE_SGEN_CFG1, + 0xffff, + 0x0001); + break; + case SND_SOC_DAPM_POST_PMD: + /* DL scrambler disabling sequence */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON2, 0x0000); + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON0, 0xcba0); + break; + default: + break; + } + + return 0; +} + +static void mtk_hp_enable(struct mt6359_priv *priv) +{ + if (priv->hp_hifi_mode) { + /* Set HP DR bias current optimization, 010: 6uA */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON11, + DRBIAS_HP_MASK_SFT, + DRBIAS_6UA << DRBIAS_HP_SFT); + /* Set HP & ZCD bias current optimization */ + /* 01: ZCD: 4uA, HP/HS/LO: 5uA */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON12, + IBIAS_ZCD_MASK_SFT, + IBIAS_ZCD_4UA << IBIAS_ZCD_SFT); + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON12, + IBIAS_HP_MASK_SFT, + IBIAS_5UA << IBIAS_HP_SFT); + } else { + /* Set HP DR bias current optimization, 001: 5uA */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON11, + DRBIAS_HP_MASK_SFT, + DRBIAS_5UA << DRBIAS_HP_SFT); + /* Set HP & ZCD bias current optimization */ + /* 00: ZCD: 3uA, HP/HS/LO: 4uA */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON12, + IBIAS_ZCD_MASK_SFT, + IBIAS_ZCD_3UA << IBIAS_ZCD_SFT); + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON12, + IBIAS_HP_MASK_SFT, + IBIAS_4UA << IBIAS_HP_SFT); + } + + /* HP damp circuit enable */ + /* Enable HPRN/HPLN output 4K to VCM */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON10, 0x0087); + + /* HP Feedback Cap select 2'b00: 15pF */ + /* for >= 96KHz sampling rate: 2'b01: 10.5pF */ + if (priv->dl_rate[MT6359_AIF_1] >= 96000) + regmap_update_bits(priv->regmap, + MT6359_AUDDEC_ANA_CON4, + RG_AUDHPHFCOMPBUFGAINSEL_VAUDP32_MASK_SFT, + 0x1 << RG_AUDHPHFCOMPBUFGAINSEL_VAUDP32_SFT); + else + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON4, 0x0000); + + /* Set HPP/N STB enhance circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON2, 0xf133); + + /* Enable HP aux output stage */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x000c); + /* Enable HP aux feedback loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x003c); + /* Enable HP aux CMFB loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0x0c00); + /* Enable HP driver bias circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON0, 0x30c0); + /* Enable HP driver core circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON0, 0x30f0); + /* Short HP main output to HP aux output stage */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x00fc); + + /* Increase HP input pair current to HPM step by step */ + hp_in_pair_current(priv, true); + + /* Enable HP main CMFB loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0x0e00); + /* Disable HP aux CMFB loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0x0200); + + /* Enable HP main output stage */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x00ff); + /* Enable HPR/L main output stage step by step */ + hp_main_output_ramp(priv, true); + + /* Reduce HP aux feedback loop gain */ + hp_aux_feedback_loop_gain_ramp(priv, true); + /* Disable HP aux feedback loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x77cf); + + /* apply volume setting */ + headset_volume_ramp(priv, + DL_GAIN_N_22DB, + priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL]); + + /* Disable HP aux output stage */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x77c3); + /* Unshort HP main output to HP aux output stage */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x7703); + usleep_range(100, 120); + + /* Enable AUD_CLK */ + mt6359_set_decoder_clk(priv, true); + + /* Enable Audio DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON0, 0x30ff); + if (priv->hp_hifi_mode) { + /* Enable low-noise mode of DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0xf201); + } else { + /* Disable low-noise mode of DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0xf200); + } + usleep_range(100, 120); + + /* Switch HPL MUX to audio DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON0, 0x32ff); + /* Switch HPR MUX to audio DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON0, 0x3aff); + + /* Disable Pull-down HPL/R to AVSS28_AUD */ + hp_pull_down(priv, false); +} + +static void mtk_hp_disable(struct mt6359_priv *priv) +{ + /* Pull-down HPL/R to AVSS28_AUD */ + hp_pull_down(priv, true); + + /* HPR/HPL mux to open */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + 0x0f00, 0x0000); + + /* Disable low-noise mode of DAC */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON9, + 0x0001, 0x0000); + + /* Disable Audio DAC */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + 0x000f, 0x0000); + + /* Disable AUD_CLK */ + mt6359_set_decoder_clk(priv, false); + + /* Short HP main output to HP aux output stage */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x77c3); + /* Enable HP aux output stage */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x77cf); + + /* decrease HPL/R gain to normal gain step by step */ + headset_volume_ramp(priv, + priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL], + DL_GAIN_N_22DB); + + /* Enable HP aux feedback loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x77ff); + + /* Reduce HP aux feedback loop gain */ + hp_aux_feedback_loop_gain_ramp(priv, false); + + /* decrease HPR/L main output stage step by step */ + hp_main_output_ramp(priv, false); + + /* Disable HP main output stage */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON1, 0x3, 0x0); + + /* Enable HP aux CMFB loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0x0e01); + + /* Disable HP main CMFB loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0x0c01); + + /* Decrease HP input pair current to 2'b00 step by step */ + hp_in_pair_current(priv, false); + + /* Unshort HP main output to HP aux output stage */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON1, + 0x3 << 6, 0x0); + + /* Disable HP driver core circuits */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + 0x3 << 4, 0x0); + + /* Disable HP driver bias circuits */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + 0x3 << 6, 0x0); + + /* Disable HP aux CMFB loop */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0x201); + + /* Disable HP aux feedback loop */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON1, + 0x3 << 4, 0x0); + + /* Disable HP aux output stage */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON1, + 0x3 << 2, 0x0); +} + +static int mt_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + int device = DEVICE_HP; + + dev_dbg(priv->dev, "%s(), event 0x%x, dev_counter[DEV_HP] %d, mux %u\n", + __func__, event, priv->dev_counter[device], mux); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + priv->dev_counter[device]++; + if (mux == HP_MUX_HP) + mtk_hp_enable(priv); + break; + case SND_SOC_DAPM_PRE_PMD: + priv->dev_counter[device]--; + if (mux == HP_MUX_HP) + mtk_hp_disable(priv); + break; + default: + break; + } + + return 0; +} + +static int mt_rcv_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event 0x%x, mux %u\n", + __func__, event, dapm_kcontrol_get_value(w->kcontrols[0])); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Disable handset short-circuit protection */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON6, 0x0010); + + /* Set RCV DR bias current optimization, 010: 6uA */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON11, + DRBIAS_HS_MASK_SFT, + DRBIAS_6UA << DRBIAS_HS_SFT); + /* Set RCV & ZCD bias current optimization */ + /* 01: ZCD: 4uA, HP/HS/LO: 5uA */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON12, + IBIAS_ZCD_MASK_SFT, + IBIAS_ZCD_4UA << IBIAS_ZCD_SFT); + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON12, + IBIAS_HS_MASK_SFT, + IBIAS_5UA << IBIAS_HS_SFT); + + /* Set HS STB enhance circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON6, 0x0090); + + /* Set HS output stage (3'b111 = 8x) */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON10, 0x7000); + + /* Enable HS driver bias circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON6, 0x0092); + /* Enable HS driver core circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON6, 0x0093); + + /* Set HS gain to normal gain step by step */ + regmap_write(priv->regmap, MT6359_ZCD_CON3, + priv->ana_gain[AUDIO_ANALOG_VOLUME_HSOUTL]); + + /* Enable AUD_CLK */ + mt6359_set_decoder_clk(priv, true); + + /* Enable Audio DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON0, 0x0009); + /* Enable low-noise mode of DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON9, 0x0001); + /* Switch HS MUX to audio DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON6, 0x009b); + break; + case SND_SOC_DAPM_PRE_PMD: + /* HS mux to open */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON6, + RG_AUDHSMUXINPUTSEL_VAUDP32_MASK_SFT, + RCV_MUX_OPEN); + + /* Disable Audio DAC */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + 0x000f, 0x0000); + + /* Disable AUD_CLK */ + mt6359_set_decoder_clk(priv, false); + + /* decrease HS gain to minimum gain step by step */ + regmap_write(priv->regmap, MT6359_ZCD_CON3, DL_GAIN_N_40DB); + + /* Disable HS driver core circuits */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON6, + RG_AUDHSPWRUP_VAUDP32_MASK_SFT, 0x0); + + /* Disable HS driver bias circuits */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON6, + RG_AUDHSPWRUP_IBIAS_VAUDP32_MASK_SFT, 0x0); + break; + default: + break; + } + + return 0; +} + +static int mt_lo_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event 0x%x, mux %u\n", + __func__, event, dapm_kcontrol_get_value(w->kcontrols[0])); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Disable handset short-circuit protection */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON7, 0x0010); + + /* Set LO DR bias current optimization, 010: 6uA */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON11, + DRBIAS_LO_MASK_SFT, + DRBIAS_6UA << DRBIAS_LO_SFT); + /* Set LO & ZCD bias current optimization */ + /* 01: ZCD: 4uA, HP/HS/LO: 5uA */ + if (priv->dev_counter[DEVICE_HP] == 0) + regmap_update_bits(priv->regmap, + MT6359_AUDDEC_ANA_CON12, + IBIAS_ZCD_MASK_SFT, + IBIAS_ZCD_4UA << IBIAS_ZCD_SFT); + + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON12, + IBIAS_LO_MASK_SFT, + IBIAS_5UA << IBIAS_LO_SFT); + + /* Set LO STB enhance circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON7, 0x0110); + + /* Enable LO driver bias circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON7, 0x0112); + /* Enable LO driver core circuits */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON7, 0x0113); + + /* Set LO gain to normal gain step by step */ + regmap_write(priv->regmap, MT6359_ZCD_CON1, + priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTL]); + + /* Enable AUD_CLK */ + mt6359_set_decoder_clk(priv, true); + + /* Enable Audio DAC (3rd DAC) */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON7, 0x3113); + /* Enable low-noise mode of DAC */ + if (priv->dev_counter[DEVICE_HP] == 0) + regmap_write(priv->regmap, + MT6359_AUDDEC_ANA_CON9, 0x0001); + /* Switch LOL MUX to audio 3rd DAC */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON7, 0x311b); + break; + case SND_SOC_DAPM_PRE_PMD: + /* Switch LOL MUX to open */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON7, + RG_AUDLOLMUXINPUTSEL_VAUDP32_MASK_SFT, + LO_MUX_OPEN); + + /* Disable Audio DAC */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + 0x000f, 0x0000); + + /* Disable AUD_CLK */ + mt6359_set_decoder_clk(priv, false); + + /* decrease LO gain to minimum gain step by step */ + regmap_write(priv->regmap, MT6359_ZCD_CON1, DL_GAIN_N_40DB); + + /* Disable LO driver core circuits */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON7, + RG_AUDLOLPWRUP_VAUDP32_MASK_SFT, 0x0); + + /* Disable LO driver bias circuits */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON7, + RG_AUDLOLPWRUP_IBIAS_VAUDP32_MASK_SFT, 0x0); + break; + default: + break; + } + + return 0; +} + +static int mt_adc_clk_gen_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + /* ADC CLK from CLKGEN (6.5MHz) */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKRSTB_MASK_SFT, + 0x1 << RG_AUDADCCLKRSTB_SFT); + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKSOURCE_MASK_SFT, 0x0); + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKSEL_MASK_SFT, 0x0); + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKGENMODE_MASK_SFT, + 0x1 << RG_AUDADCCLKGENMODE_SFT); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKSOURCE_MASK_SFT, 0x0); + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKSEL_MASK_SFT, 0x0); + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKGENMODE_MASK_SFT, 0x0); + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON5, + RG_AUDADCCLKRSTB_MASK_SFT, 0x0); + break; + default: + break; + } + + return 0; +} + +static int mt_dcc_clk_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* DCC 50k CLK (from 26M) */ + /* MT6359_AFE_DCCLK_CFG0, bit 3 for dm ck swap */ + regmap_update_bits(priv->regmap, MT6359_AFE_DCCLK_CFG0, + 0xfff7, 0x2062); + regmap_update_bits(priv->regmap, MT6359_AFE_DCCLK_CFG0, + 0xfff7, 0x2060); + regmap_update_bits(priv->regmap, MT6359_AFE_DCCLK_CFG0, + 0xfff7, 0x2061); + + regmap_write(priv->regmap, MT6359_AFE_DCCLK_CFG1, 0x0100); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(priv->regmap, MT6359_AFE_DCCLK_CFG0, + 0xfff7, 0x2060); + regmap_update_bits(priv->regmap, MT6359_AFE_DCCLK_CFG0, + 0xfff7, 0x2062); + break; + default: + break; + } + + return 0; +} + +static int mt_mic_bias_0_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mic_type = priv->mux_select[MUX_MIC_TYPE_0]; + + dev_dbg(priv->dev, "%s(), event 0x%x, mic_type %d\n", + __func__, event, mic_type); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (mic_type) { + case MIC_TYPE_MUX_DCC_ECM_DIFF: + regmap_update_bits(priv->regmap, + MT6359_AUDENC_ANA_CON15, + 0xff00, 0x7700); + break; + case MIC_TYPE_MUX_DCC_ECM_SINGLE: + regmap_update_bits(priv->regmap, + MT6359_AUDENC_ANA_CON15, + 0xff00, 0x1100); + break; + default: + regmap_update_bits(priv->regmap, + MT6359_AUDENC_ANA_CON15, + 0xff00, 0x0000); + break; + } + + /* DMIC enable */ + regmap_write(priv->regmap, + MT6359_AUDENC_ANA_CON14, 0x0004); + /* MISBIAS0 = 1P9V */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON15, + RG_AUDMICBIAS0VREF_MASK_SFT, + MIC_BIAS_1P9 << RG_AUDMICBIAS0VREF_SFT); + /* normal power select */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON15, + RG_AUDMICBIAS0LOWPEN_MASK_SFT, + 0 << RG_AUDMICBIAS0LOWPEN_SFT); + break; + case SND_SOC_DAPM_POST_PMD: + /* Disable MICBIAS0, MISBIAS0 = 1P7V */ + regmap_write(priv->regmap, MT6359_AUDENC_ANA_CON15, 0x0000); + break; + default: + break; + } + + return 0; +} + +static int mt_mic_bias_1_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mic_type = priv->mux_select[MUX_MIC_TYPE_1]; + + dev_dbg(priv->dev, "%s(), event 0x%x, mic_type %d\n", + __func__, event, mic_type); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* MISBIAS1 = 2P6V */ + if (mic_type == MIC_TYPE_MUX_DCC_ECM_SINGLE) + regmap_write(priv->regmap, + MT6359_AUDENC_ANA_CON16, 0x0160); + else + regmap_write(priv->regmap, + MT6359_AUDENC_ANA_CON16, 0x0060); + + /* normal power select */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON16, + RG_AUDMICBIAS1LOWPEN_MASK_SFT, + 0 << RG_AUDMICBIAS1LOWPEN_SFT); + break; + default: + break; + } + + return 0; +} + +static int mt_mic_bias_2_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mic_type = priv->mux_select[MUX_MIC_TYPE_2]; + + dev_dbg(priv->dev, "%s(), event 0x%x, mic_type %d\n", + __func__, event, mic_type); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (mic_type) { + case MIC_TYPE_MUX_DCC_ECM_DIFF: + regmap_update_bits(priv->regmap, + MT6359_AUDENC_ANA_CON17, + 0xff00, 0x7700); + break; + case MIC_TYPE_MUX_DCC_ECM_SINGLE: + regmap_update_bits(priv->regmap, + MT6359_AUDENC_ANA_CON17, + 0xff00, 0x1100); + break; + default: + regmap_update_bits(priv->regmap, + MT6359_AUDENC_ANA_CON17, + 0xff00, 0x0000); + break; + } + + /* MISBIAS2 = 1P9V */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON17, + RG_AUDMICBIAS2VREF_MASK_SFT, + MIC_BIAS_1P9 << RG_AUDMICBIAS2VREF_SFT); + /* normal power select */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON17, + RG_AUDMICBIAS2LOWPEN_MASK_SFT, + 0 << RG_AUDMICBIAS2LOWPEN_SFT); + break; + case SND_SOC_DAPM_POST_PMD: + /* Disable MICBIAS2, MISBIAS0 = 1P7V */ + regmap_write(priv->regmap, MT6359_AUDENC_ANA_CON17, 0x0000); + break; + default: + break; + } + + return 0; +} + +static int mt_mtkaif_tx_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event = 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt6359_mtkaif_tx_enable(priv); + break; + case SND_SOC_DAPM_POST_PMD: + mt6359_mtkaif_tx_disable(priv); + break; + default: + break; + } + + return 0; +} + +static int mt_ul_src_dmic_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event = 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* UL dmic setting */ + if (priv->dmic_one_wire_mode) + regmap_write(priv->regmap, MT6359_AFE_UL_SRC_CON0_H, + 0x0400); + else + regmap_write(priv->regmap, MT6359_AFE_UL_SRC_CON0_H, + 0x0080); + /* default one wire, 3.25M */ + regmap_update_bits(priv->regmap, MT6359_AFE_UL_SRC_CON0_L, + 0xfffc, 0x0000); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_write(priv->regmap, + MT6359_AFE_UL_SRC_CON0_H, 0x0000); + break; + default: + break; + } + + return 0; +} + +static int mt_ul_src_34_dmic_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event = 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* default two wire, 3.25M */ + regmap_write(priv->regmap, + MT6359_AFE_ADDA6_L_SRC_CON0_H, 0x0080); + regmap_update_bits(priv->regmap, MT6359_AFE_ADDA6_UL_SRC_CON0_L, + 0xfffc, 0x0000); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_write(priv->regmap, + MT6359_AFE_ADDA6_L_SRC_CON0_H, 0x0000); + break; + default: + break; + } + + return 0; +} + +static int mt_adc_l_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event = 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + usleep_range(100, 120); + /* Audio L preamplifier DCC precharge off */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON0, + RG_AUDPREAMPLDCPRECHARGE_MASK_SFT, + 0x0); + break; + default: + break; + } + + return 0; +} + +static int mt_adc_r_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event = 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + usleep_range(100, 120); + /* Audio R preamplifier DCC precharge off */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON1, + RG_AUDPREAMPRDCPRECHARGE_MASK_SFT, + 0x0); + break; + default: + break; + } + + return 0; +} + +static int mt_adc_3_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s(), event = 0x%x\n", __func__, event); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + usleep_range(100, 120); + /* Audio R preamplifier DCC precharge off */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON2, + RG_AUDPREAMP3DCPRECHARGE_MASK_SFT, + 0x0); + break; + default: + break; + } + + return 0; +} + +static int mt_pga_l_mux_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + + dev_dbg(priv->dev, "%s(), mux %d\n", __func__, mux); + priv->mux_select[MUX_PGA_L] = mux >> RG_AUDPREAMPLINPUTSEL_SFT; + return 0; +} + +static int mt_pga_r_mux_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + + dev_dbg(priv->dev, "%s(), mux %d\n", __func__, mux); + priv->mux_select[MUX_PGA_R] = mux >> RG_AUDPREAMPRINPUTSEL_SFT; + return 0; +} + +static int mt_pga_3_mux_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int mux = dapm_kcontrol_get_value(w->kcontrols[0]); + + dev_dbg(priv->dev, "%s(), mux %d\n", __func__, mux); + priv->mux_select[MUX_PGA_3] = mux >> RG_AUDPREAMP3INPUTSEL_SFT; + return 0; +} + +static int mt_pga_l_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + int mic_gain_l = priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP1]; + unsigned int mux_pga = priv->mux_select[MUX_PGA_L]; + unsigned int mic_type; + + switch (mux_pga) { + case PGA_L_MUX_AIN0: + mic_type = priv->mux_select[MUX_MIC_TYPE_0]; + break; + case PGA_L_MUX_AIN1: + mic_type = priv->mux_select[MUX_MIC_TYPE_1]; + break; + default: + dev_err(priv->dev, "%s(), invalid pga mux %d\n", + __func__, mux_pga); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (IS_DCC_BASE(mic_type)) { + /* Audio L preamplifier DCC precharge */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON0, + RG_AUDPREAMPLDCPRECHARGE_MASK_SFT, + 0x1 << RG_AUDPREAMPLDCPRECHARGE_SFT); + } + break; + case SND_SOC_DAPM_POST_PMU: + /* set mic pga gain */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON0, + RG_AUDPREAMPLGAIN_MASK_SFT, + mic_gain_l << RG_AUDPREAMPLGAIN_SFT); + + if (IS_DCC_BASE(mic_type)) { + /* L preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON0, + RG_AUDPREAMPLDCCEN_MASK_SFT, + 0x1 << RG_AUDPREAMPLDCCEN_SFT); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* L preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON0, + RG_AUDPREAMPLDCCEN_MASK_SFT, + 0x0 << RG_AUDPREAMPLDCCEN_SFT); + break; + default: + break; + } + + return 0; +} + +static int mt_pga_r_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + int mic_gain_r = priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP2]; + unsigned int mux_pga = priv->mux_select[MUX_PGA_R]; + unsigned int mic_type; + + switch (mux_pga) { + case PGA_R_MUX_AIN0: + mic_type = priv->mux_select[MUX_MIC_TYPE_0]; + break; + case PGA_R_MUX_AIN2: + case PGA_R_MUX_AIN3: + mic_type = priv->mux_select[MUX_MIC_TYPE_2]; + break; + default: + dev_err(priv->dev, "%s(), invalid pga mux %d\n", + __func__, mux_pga); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (IS_DCC_BASE(mic_type)) { + /* Audio R preamplifier DCC precharge */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON1, + RG_AUDPREAMPRDCPRECHARGE_MASK_SFT, + 0x1 << RG_AUDPREAMPRDCPRECHARGE_SFT); + } + break; + case SND_SOC_DAPM_POST_PMU: + /* set mic pga gain */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON1, + RG_AUDPREAMPRGAIN_MASK_SFT, + mic_gain_r << RG_AUDPREAMPRGAIN_SFT); + + if (IS_DCC_BASE(mic_type)) { + /* R preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON1, + RG_AUDPREAMPRDCCEN_MASK_SFT, + 0x1 << RG_AUDPREAMPRDCCEN_SFT); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* R preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON1, + RG_AUDPREAMPRDCCEN_MASK_SFT, + 0x0 << RG_AUDPREAMPRDCCEN_SFT); + break; + default: + break; + } + + return 0; +} + +static int mt_pga_3_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + int mic_gain_3 = priv->ana_gain[AUDIO_ANALOG_VOLUME_MICAMP3]; + unsigned int mux_pga = priv->mux_select[MUX_PGA_3]; + unsigned int mic_type; + + switch (mux_pga) { + case PGA_3_MUX_AIN2: + case PGA_3_MUX_AIN3: + mic_type = priv->mux_select[MUX_MIC_TYPE_2]; + break; + default: + dev_err(priv->dev, "%s(), invalid pga mux %d\n", + __func__, mux_pga); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (IS_DCC_BASE(mic_type)) { + /* Audio 3 preamplifier DCC precharge */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON2, + RG_AUDPREAMP3DCPRECHARGE_MASK_SFT, + 0x1 << RG_AUDPREAMP3DCPRECHARGE_SFT); + } + break; + case SND_SOC_DAPM_POST_PMU: + /* set mic pga gain */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON2, + RG_AUDPREAMP3GAIN_MASK_SFT, + mic_gain_3 << RG_AUDPREAMP3GAIN_SFT); + + if (IS_DCC_BASE(mic_type)) { + /* 3 preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON2, + RG_AUDPREAMP3DCCEN_MASK_SFT, + 0x1 << RG_AUDPREAMP3DCCEN_SFT); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* 3 preamplifier DCCEN */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON2, + RG_AUDPREAMP3DCCEN_MASK_SFT, + 0x0 << RG_AUDPREAMP3DCCEN_SFT); + break; + default: + break; + } + + return 0; +} + +/* It is based on hw's control sequenece to add some delay when PMU/PMD */ +static int mt_delay_250_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + case SND_SOC_DAPM_PRE_PMD: + usleep_range(250, 270); + break; + default: + break; + } + + return 0; +} + +static int mt_delay_100_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + switch (event) { + case SND_SOC_DAPM_POST_PMU: + case SND_SOC_DAPM_PRE_PMD: + usleep_range(100, 120); + break; + default: + break; + } + + return 0; +} + +static int mt_hp_pull_down_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + hp_pull_down(priv, true); + break; + case SND_SOC_DAPM_POST_PMD: + hp_pull_down(priv, false); + break; + default: + break; + } + + return 0; +} + +static int mt_hp_mute_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Set HPR/HPL gain to -22dB */ + regmap_write(priv->regmap, MT6359_ZCD_CON2, DL_GAIN_N_22DB_REG); + break; + case SND_SOC_DAPM_POST_PMD: + /* Set HPL/HPR gain to mute */ + regmap_write(priv->regmap, MT6359_ZCD_CON2, DL_GAIN_N_40DB_REG); + break; + default: + break; + } + + return 0; +} + +static int mt_hp_damp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_POST_PMD: + /* Disable HP damping circuit & HPN 4K load */ + /* reset CMFB PW level */ + regmap_write(priv->regmap, MT6359_AUDDEC_ANA_CON10, 0x0000); + break; + default: + break; + } + + return 0; +} + +static int mt_esd_resist_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* Reduce ESD resistance of AU_REFN */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON2, + RG_AUDREFN_DERES_EN_VAUDP32_MASK_SFT, + 0x1 << RG_AUDREFN_DERES_EN_VAUDP32_SFT); + usleep_range(250, 270); + break; + case SND_SOC_DAPM_POST_PMD: + /* Increase ESD resistance of AU_REFN */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON2, + RG_AUDREFN_DERES_EN_VAUDP32_MASK_SFT, 0x0); + break; + default: + break; + } + + return 0; +} + +static int mt_sdm_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* sdm audio fifo clock power on */ + regmap_update_bits(priv->regmap, MT6359_AFUNC_AUD_CON2, + 0xfffd, 0x0006); + /* scrambler clock on enable */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON0, 0xcba1); + /* sdm power on */ + regmap_update_bits(priv->regmap, MT6359_AFUNC_AUD_CON2, + 0xfffd, 0x0003); + /* sdm fifo enable */ + regmap_update_bits(priv->regmap, MT6359_AFUNC_AUD_CON2, + 0xfffd, 0x000B); + break; + case SND_SOC_DAPM_POST_PMD: + /* DL scrambler disabling sequence */ + regmap_update_bits(priv->regmap, MT6359_AFUNC_AUD_CON2, + 0xfffd, 0x0000); + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON0, 0xcba0); + break; + default: + break; + } + + return 0; +} + +static int mt_sdm_3rd_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + /* sdm audio fifo clock power on */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON11, 0x0006); + /* scrambler clock on enable */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON9, 0xcba1); + /* sdm power on */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON11, 0x0003); + /* sdm fifo enable */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON11, 0x000b); + break; + case SND_SOC_DAPM_POST_PMD: + /* DL scrambler disabling sequence */ + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON11, 0x0000); + regmap_write(priv->regmap, MT6359_AFUNC_AUD_CON9, 0xcba0); + break; + default: + break; + } + + return 0; +} + +static int mt_ncp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + regmap_write(priv->regmap, MT6359_AFE_NCP_CFG0, 0xc800); + break; + default: + break; + } + + return 0; +} + +/* DAPM Widgets */ +static const struct snd_soc_dapm_widget mt6359_dapm_widgets[] = { + /* Global Supply*/ + SND_SOC_DAPM_SUPPLY_S("CLK_BUF", SUPPLY_SEQ_CLK_BUF, + MT6359_DCXO_CW12, + RG_XO_AUDIO_EN_M_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("LDO_VAUD18", SUPPLY_SEQ_LDO_VAUD18, + MT6359_LDO_VAUD18_CON0, + RG_LDO_VAUD18_EN_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDGLB", SUPPLY_SEQ_AUD_GLB, + MT6359_AUDDEC_ANA_CON13, + RG_AUDGLB_PWRDN_VA32_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("CLKSQ Audio", SUPPLY_SEQ_CLKSQ, + MT6359_AUDENC_ANA_CON23, + RG_CLKSQ_EN_SFT, 0, NULL, SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY_S("AUDNCP_CK", SUPPLY_SEQ_TOP_CK, + MT6359_AUD_TOP_CKPDN_CON0, + RG_AUDNCP_CK_PDN_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ZCD13M_CK", SUPPLY_SEQ_TOP_CK, + MT6359_AUD_TOP_CKPDN_CON0, + RG_ZCD13M_CK_PDN_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUD_CK", SUPPLY_SEQ_TOP_CK_LAST, + MT6359_AUD_TOP_CKPDN_CON0, + RG_AUD_CK_PDN_SFT, 1, mt_delay_250_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY_S("AUDIF_CK", SUPPLY_SEQ_TOP_CK, + MT6359_AUD_TOP_CKPDN_CON0, + RG_AUDIF_CK_PDN_SFT, 1, NULL, 0), + /* Digital Clock */ + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_AFE_CTL", SUPPLY_SEQ_AUD_TOP_LAST, + MT6359_AUDIO_TOP_CON0, + PDN_AFE_CTL_SFT, 1, + mt_delay_250_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_DAC_CTL", SUPPLY_SEQ_AUD_TOP, + MT6359_AUDIO_TOP_CON0, + PDN_DAC_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_ADC_CTL", SUPPLY_SEQ_AUD_TOP, + MT6359_AUDIO_TOP_CON0, + PDN_ADC_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_ADDA6_ADC_CTL", SUPPLY_SEQ_AUD_TOP, + MT6359_AUDIO_TOP_CON0, + PDN_ADDA6_ADC_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_I2S_DL", SUPPLY_SEQ_AUD_TOP, + MT6359_AUDIO_TOP_CON0, + PDN_I2S_DL_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PWR_CLK", SUPPLY_SEQ_AUD_TOP, + MT6359_AUDIO_TOP_CON0, + PWR_CLK_DIS_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PDN_AFE_TESTMODEL", SUPPLY_SEQ_AUD_TOP, + MT6359_AUDIO_TOP_CON0, + PDN_AFE_TESTMODEL_CTL_SFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("AUDIO_TOP_PDN_RESERVED", SUPPLY_SEQ_AUD_TOP, + MT6359_AUDIO_TOP_CON0, + PDN_RESERVED_SFT, 1, NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("SDM", SUPPLY_SEQ_DL_SDM, + SND_SOC_NOPM, 0, 0, + mt_sdm_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("SDM_3RD", SUPPLY_SEQ_DL_SDM, + SND_SOC_NOPM, 0, 0, + mt_sdm_3rd_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* ch123 share SDM FIFO CLK */ + SND_SOC_DAPM_SUPPLY_S("SDM_FIFO_CLK", SUPPLY_SEQ_DL_SDM_FIFO_CLK, + MT6359_AFUNC_AUD_CON2, + CCI_AFIFO_CLK_PWDB_SFT, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("NCP", SUPPLY_SEQ_DL_NCP, + MT6359_AFE_NCP_CFG0, + RG_NCP_ON_SFT, 0, + mt_ncp_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_SUPPLY("DL Digital Clock", SND_SOC_NOPM, + 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DL Digital Clock CH_1_2", SND_SOC_NOPM, + 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DL Digital Clock CH_3", SND_SOC_NOPM, + 0, 0, NULL, 0), + + /* AFE ON */ + SND_SOC_DAPM_SUPPLY_S("AFE_ON", SUPPLY_SEQ_AFE, + MT6359_AFE_UL_DL_CON0, AFE_ON_SFT, 0, + NULL, 0), + + /* AIF Rx*/ + SND_SOC_DAPM_AIF_IN("AIF_RX", "AIF1 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_AIF_IN("AIF2_RX", "AIF2 Playback", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SUPPLY_S("AFE_DL_SRC", SUPPLY_SEQ_DL_SRC, + MT6359_AFE_DL_SRC2_CON0_L, + DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0, + NULL, 0), + + /* DL Supply */ + SND_SOC_DAPM_SUPPLY("DL Power Supply", SND_SOC_NOPM, + 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("ESD_RESIST", SUPPLY_SEQ_DL_ESD_RESIST, + SND_SOC_NOPM, + 0, 0, + mt_esd_resist_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("LDO", SUPPLY_SEQ_DL_LDO, + MT6359_AUDDEC_ANA_CON14, + RG_LCLDO_DEC_EN_VA32_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("LDO_REMOTE", SUPPLY_SEQ_DL_LDO_REMOTE_SENSE, + MT6359_AUDDEC_ANA_CON14, + RG_LCLDO_DEC_REMOTE_SENSE_VA18_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("NV_REGULATOR", SUPPLY_SEQ_DL_NV, + MT6359_AUDDEC_ANA_CON14, + RG_NVREG_EN_VAUDP32_SFT, 0, + mt_delay_100_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY_S("IBIST", SUPPLY_SEQ_DL_IBIST, + MT6359_AUDDEC_ANA_CON12, + RG_AUDIBIASPWRDN_VAUDP32_SFT, 1, + NULL, 0), + + /* DAC */ + SND_SOC_DAPM_MUX("DAC In Mux", SND_SOC_NOPM, 0, 0, &dac_in_mux_control), + + SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_DAC("DAC_3RD", NULL, SND_SOC_NOPM, 0, 0), + + /* Headphone */ + SND_SOC_DAPM_MUX_E("HP Mux", SND_SOC_NOPM, 0, 0, + &hp_in_mux_control, + mt_hp_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY("HP_Supply", SND_SOC_NOPM, + 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("HP_PULL_DOWN", SUPPLY_SEQ_HP_PULL_DOWN, + SND_SOC_NOPM, + 0, 0, + mt_hp_pull_down_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("HP_MUTE", SUPPLY_SEQ_HP_MUTE, + SND_SOC_NOPM, + 0, 0, + mt_hp_mute_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("HP_DAMP", SUPPLY_SEQ_HP_DAMPING_OFF_RESET_CMFB, + SND_SOC_NOPM, + 0, 0, + mt_hp_damp_event, + SND_SOC_DAPM_POST_PMD), + + /* Receiver */ + SND_SOC_DAPM_MUX_E("RCV Mux", SND_SOC_NOPM, 0, 0, + &rcv_in_mux_control, + mt_rcv_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + + /* LOL */ + SND_SOC_DAPM_MUX_E("LOL Mux", SND_SOC_NOPM, 0, 0, + &lo_in_mux_control, + mt_lo_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + + /* Outputs */ + SND_SOC_DAPM_OUTPUT("Receiver"), + SND_SOC_DAPM_OUTPUT("Headphone L"), + SND_SOC_DAPM_OUTPUT("Headphone R"), + SND_SOC_DAPM_OUTPUT("Headphone L Ext Spk Amp"), + SND_SOC_DAPM_OUTPUT("Headphone R Ext Spk Amp"), + SND_SOC_DAPM_OUTPUT("LINEOUT L"), + + /* SGEN */ + SND_SOC_DAPM_SUPPLY("SGEN DL Enable", MT6359_AFE_SGEN_CFG0, + SGEN_DAC_EN_CTL_SFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("SGEN MUTE", MT6359_AFE_SGEN_CFG0, + SGEN_MUTE_SW_CTL_SFT, 1, + mt_sgen_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY("SGEN DL SRC", MT6359_AFE_DL_SRC2_CON0_L, + DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0, NULL, 0), + + SND_SOC_DAPM_INPUT("SGEN DL"), + + /* Uplinks */ + SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("AIF2TX", "AIF2 Capture", 0, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SUPPLY_S("ADC_CLKGEN", SUPPLY_SEQ_ADC_CLKGEN, + SND_SOC_NOPM, 0, 0, + mt_adc_clk_gen_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY_S("DCC_CLK", SUPPLY_SEQ_DCC_CLK, + SND_SOC_NOPM, 0, 0, + mt_dcc_clk_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* Uplinks MUX */ + SND_SOC_DAPM_MUX("AIF Out Mux", SND_SOC_NOPM, 0, 0, + &aif_out_mux_control), + + SND_SOC_DAPM_MUX("AIF2 Out Mux", SND_SOC_NOPM, 0, 0, + &aif2_out_mux_control), + + SND_SOC_DAPM_SUPPLY("AIFTX_Supply", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("MTKAIF_TX", SUPPLY_SEQ_UL_MTKAIF, + SND_SOC_NOPM, 0, 0, + mt_mtkaif_tx_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("UL_SRC", SUPPLY_SEQ_UL_SRC, + MT6359_AFE_UL_SRC_CON0_L, + UL_SRC_ON_TMP_CTL_SFT, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("UL_SRC_DMIC", SUPPLY_SEQ_UL_SRC_DMIC, + SND_SOC_NOPM, 0, 0, + mt_ul_src_dmic_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("UL_SRC_34", SUPPLY_SEQ_UL_SRC, + MT6359_AFE_ADDA6_UL_SRC_CON0_L, + ADDA6_UL_SRC_ON_TMP_CTL_SFT, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("UL_SRC_34_DMIC", SUPPLY_SEQ_UL_SRC_DMIC, + SND_SOC_NOPM, 0, 0, + mt_ul_src_34_dmic_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MUX("MISO0_MUX", SND_SOC_NOPM, 0, 0, &miso0_mux_control), + SND_SOC_DAPM_MUX("MISO1_MUX", SND_SOC_NOPM, 0, 0, &miso1_mux_control), + SND_SOC_DAPM_MUX("MISO2_MUX", SND_SOC_NOPM, 0, 0, &miso2_mux_control), + + SND_SOC_DAPM_MUX("UL_SRC_MUX", SND_SOC_NOPM, 0, 0, + &ul_src_mux_control), + SND_SOC_DAPM_MUX("UL2_SRC_MUX", SND_SOC_NOPM, 0, 0, + &ul2_src_mux_control), + + SND_SOC_DAPM_MUX("DMIC0_MUX", SND_SOC_NOPM, 0, 0, &dmic0_mux_control), + SND_SOC_DAPM_MUX("DMIC1_MUX", SND_SOC_NOPM, 0, 0, &dmic1_mux_control), + SND_SOC_DAPM_MUX("DMIC2_MUX", SND_SOC_NOPM, 0, 0, &dmic2_mux_control), + + SND_SOC_DAPM_MUX_E("ADC_L_Mux", SND_SOC_NOPM, 0, 0, + &adc_left_mux_control, NULL, 0), + SND_SOC_DAPM_MUX_E("ADC_R_Mux", SND_SOC_NOPM, 0, 0, + &adc_right_mux_control, NULL, 0), + SND_SOC_DAPM_MUX_E("ADC_3_Mux", SND_SOC_NOPM, 0, 0, + &adc_3_mux_control, NULL, 0), + + SND_SOC_DAPM_ADC("ADC_L", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC_R", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADC_3", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SUPPLY_S("ADC_L_EN", SUPPLY_SEQ_UL_ADC, + MT6359_AUDENC_ANA_CON0, + RG_AUDADCLPWRUP_SFT, 0, + mt_adc_l_event, + SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY_S("ADC_R_EN", SUPPLY_SEQ_UL_ADC, + MT6359_AUDENC_ANA_CON1, + RG_AUDADCRPWRUP_SFT, 0, + mt_adc_r_event, + SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY_S("ADC_3_EN", SUPPLY_SEQ_UL_ADC, + MT6359_AUDENC_ANA_CON2, + RG_AUDADC3PWRUP_SFT, 0, + mt_adc_3_event, + SND_SOC_DAPM_POST_PMU), + + SND_SOC_DAPM_MUX_E("PGA_L_Mux", SND_SOC_NOPM, 0, 0, + &pga_left_mux_control, + mt_pga_l_mux_event, + SND_SOC_DAPM_WILL_PMU), + SND_SOC_DAPM_MUX_E("PGA_R_Mux", SND_SOC_NOPM, 0, 0, + &pga_right_mux_control, + mt_pga_r_mux_event, + SND_SOC_DAPM_WILL_PMU), + SND_SOC_DAPM_MUX_E("PGA_3_Mux", SND_SOC_NOPM, 0, 0, + &pga_3_mux_control, + mt_pga_3_mux_event, + SND_SOC_DAPM_WILL_PMU), + + SND_SOC_DAPM_PGA("PGA_L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("PGA_R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("PGA_3", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("PGA_L_EN", SUPPLY_SEQ_UL_PGA, + MT6359_AUDENC_ANA_CON0, + RG_AUDPREAMPLON_SFT, 0, + mt_pga_l_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("PGA_R_EN", SUPPLY_SEQ_UL_PGA, + MT6359_AUDENC_ANA_CON1, + RG_AUDPREAMPRON_SFT, 0, + mt_pga_r_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("PGA_3_EN", SUPPLY_SEQ_UL_PGA, + MT6359_AUDENC_ANA_CON2, + RG_AUDPREAMP3ON_SFT, 0, + mt_pga_3_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + + /* UL input */ + SND_SOC_DAPM_INPUT("AIN0"), + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + SND_SOC_DAPM_INPUT("AIN3"), + + SND_SOC_DAPM_INPUT("AIN0_DMIC"), + SND_SOC_DAPM_INPUT("AIN2_DMIC"), + SND_SOC_DAPM_INPUT("AIN3_DMIC"), + + /* mic bias */ + SND_SOC_DAPM_SUPPLY_S("MIC_BIAS_0", SUPPLY_SEQ_MIC_BIAS, + MT6359_AUDENC_ANA_CON15, + RG_AUDPWDBMICBIAS0_SFT, 0, + mt_mic_bias_0_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("MIC_BIAS_1", SUPPLY_SEQ_MIC_BIAS, + MT6359_AUDENC_ANA_CON16, + RG_AUDPWDBMICBIAS1_SFT, 0, + mt_mic_bias_1_event, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY_S("MIC_BIAS_2", SUPPLY_SEQ_MIC_BIAS, + MT6359_AUDENC_ANA_CON17, + RG_AUDPWDBMICBIAS2_SFT, 0, + mt_mic_bias_2_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* dmic */ + SND_SOC_DAPM_SUPPLY_S("DMIC_0", SUPPLY_SEQ_DMIC, + MT6359_AUDENC_ANA_CON13, + RG_AUDDIGMICEN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("DMIC_1", SUPPLY_SEQ_DMIC, + MT6359_AUDENC_ANA_CON14, + RG_AUDDIGMIC1EN_SFT, 0, + NULL, 0), +}; + +static int mt_dcc_clk_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + if (IS_DCC_BASE(priv->mux_select[MUX_MIC_TYPE_0]) || + IS_DCC_BASE(priv->mux_select[MUX_MIC_TYPE_1]) || + IS_DCC_BASE(priv->mux_select[MUX_MIC_TYPE_2])) + return 1; + else + return 0; +} + +static const struct snd_soc_dapm_route mt6359_dapm_routes[] = { + /* Capture */ + {"AIFTX_Supply", NULL, "CLK_BUF"}, + {"AIFTX_Supply", NULL, "LDO_VAUD18"}, + {"AIFTX_Supply", NULL, "AUDGLB"}, + {"AIFTX_Supply", NULL, "CLKSQ Audio"}, + {"AIFTX_Supply", NULL, "AUD_CK"}, + {"AIFTX_Supply", NULL, "AUDIF_CK"}, + {"AIFTX_Supply", NULL, "AUDIO_TOP_AFE_CTL"}, + {"AIFTX_Supply", NULL, "AUDIO_TOP_PWR_CLK"}, + {"AIFTX_Supply", NULL, "AUDIO_TOP_PDN_RESERVED"}, + {"AIFTX_Supply", NULL, "AUDIO_TOP_I2S_DL"}, + /* + * *_ADC_CTL should enable only if UL_SRC in use, + * but dm ck may be needed even UL_SRC_x not in use + */ + {"AIFTX_Supply", NULL, "AUDIO_TOP_ADC_CTL"}, + {"AIFTX_Supply", NULL, "AUDIO_TOP_ADDA6_ADC_CTL"}, + {"AIFTX_Supply", NULL, "AFE_ON"}, + + /* ul ch 12 */ + {"AIF1TX", NULL, "AIF Out Mux"}, + {"AIF1TX", NULL, "AIFTX_Supply"}, + {"AIF1TX", NULL, "MTKAIF_TX"}, + + {"AIF2TX", NULL, "AIF2 Out Mux"}, + {"AIF2TX", NULL, "AIFTX_Supply"}, + {"AIF2TX", NULL, "MTKAIF_TX"}, + + {"AIF Out Mux", "Normal Path", "MISO0_MUX"}, + {"AIF Out Mux", "Normal Path", "MISO1_MUX"}, + {"AIF2 Out Mux", "Normal Path", "MISO2_MUX"}, + + {"MISO0_MUX", "UL1_CH1", "UL_SRC_MUX"}, + {"MISO0_MUX", "UL1_CH2", "UL_SRC_MUX"}, + {"MISO0_MUX", "UL2_CH1", "UL2_SRC_MUX"}, + {"MISO0_MUX", "UL2_CH2", "UL2_SRC_MUX"}, + + {"MISO1_MUX", "UL1_CH1", "UL_SRC_MUX"}, + {"MISO1_MUX", "UL1_CH2", "UL_SRC_MUX"}, + {"MISO1_MUX", "UL2_CH1", "UL2_SRC_MUX"}, + {"MISO1_MUX", "UL2_CH2", "UL2_SRC_MUX"}, + + {"MISO2_MUX", "UL1_CH1", "UL_SRC_MUX"}, + {"MISO2_MUX", "UL1_CH2", "UL_SRC_MUX"}, + {"MISO2_MUX", "UL2_CH1", "UL2_SRC_MUX"}, + {"MISO2_MUX", "UL2_CH2", "UL2_SRC_MUX"}, + + {"UL_SRC_MUX", "AMIC", "ADC_L"}, + {"UL_SRC_MUX", "AMIC", "ADC_R"}, + {"UL_SRC_MUX", "DMIC", "DMIC0_MUX"}, + {"UL_SRC_MUX", "DMIC", "DMIC1_MUX"}, + {"UL_SRC_MUX", NULL, "UL_SRC"}, + + {"UL2_SRC_MUX", "AMIC", "ADC_3"}, + {"UL2_SRC_MUX", "DMIC", "DMIC2_MUX"}, + {"UL2_SRC_MUX", NULL, "UL_SRC_34"}, + + {"DMIC0_MUX", "DMIC_DATA0", "AIN0_DMIC"}, + {"DMIC0_MUX", "DMIC_DATA1_L", "AIN2_DMIC"}, + {"DMIC0_MUX", "DMIC_DATA1_L_1", "AIN2_DMIC"}, + {"DMIC0_MUX", "DMIC_DATA1_R", "AIN3_DMIC"}, + {"DMIC1_MUX", "DMIC_DATA0", "AIN0_DMIC"}, + {"DMIC1_MUX", "DMIC_DATA1_L", "AIN2_DMIC"}, + {"DMIC1_MUX", "DMIC_DATA1_L_1", "AIN2_DMIC"}, + {"DMIC1_MUX", "DMIC_DATA1_R", "AIN3_DMIC"}, + {"DMIC2_MUX", "DMIC_DATA0", "AIN0_DMIC"}, + {"DMIC2_MUX", "DMIC_DATA1_L", "AIN2_DMIC"}, + {"DMIC2_MUX", "DMIC_DATA1_L_1", "AIN2_DMIC"}, + {"DMIC2_MUX", "DMIC_DATA1_R", "AIN3_DMIC"}, + + {"DMIC0_MUX", NULL, "UL_SRC_DMIC"}, + {"DMIC1_MUX", NULL, "UL_SRC_DMIC"}, + {"DMIC2_MUX", NULL, "UL_SRC_34_DMIC"}, + + {"AIN0_DMIC", NULL, "DMIC_0"}, + {"AIN2_DMIC", NULL, "DMIC_1"}, + {"AIN3_DMIC", NULL, "DMIC_1"}, + {"AIN0_DMIC", NULL, "MIC_BIAS_0"}, + {"AIN2_DMIC", NULL, "MIC_BIAS_2"}, + {"AIN3_DMIC", NULL, "MIC_BIAS_2"}, + + /* adc */ + {"ADC_L", NULL, "ADC_L_Mux"}, + {"ADC_L", NULL, "ADC_CLKGEN"}, + {"ADC_L", NULL, "ADC_L_EN"}, + {"ADC_R", NULL, "ADC_R_Mux"}, + {"ADC_R", NULL, "ADC_CLKGEN"}, + {"ADC_R", NULL, "ADC_R_EN"}, + /* + * amic fifo ch1/2 clk from ADC_L, + * enable ADC_L even use ADC_R only + */ + {"ADC_R", NULL, "ADC_L_EN"}, + {"ADC_3", NULL, "ADC_3_Mux"}, + {"ADC_3", NULL, "ADC_CLKGEN"}, + {"ADC_3", NULL, "ADC_3_EN"}, + + {"ADC_L_Mux", "Left Preamplifier", "PGA_L"}, + {"ADC_R_Mux", "Right Preamplifier", "PGA_R"}, + {"ADC_3_Mux", "Preamplifier", "PGA_3"}, + + {"PGA_L", NULL, "PGA_L_Mux"}, + {"PGA_L", NULL, "PGA_L_EN"}, + {"PGA_R", NULL, "PGA_R_Mux"}, + {"PGA_R", NULL, "PGA_R_EN"}, + {"PGA_3", NULL, "PGA_3_Mux"}, + {"PGA_3", NULL, "PGA_3_EN"}, + + {"PGA_L", NULL, "DCC_CLK", mt_dcc_clk_connect}, + {"PGA_R", NULL, "DCC_CLK", mt_dcc_clk_connect}, + {"PGA_3", NULL, "DCC_CLK", mt_dcc_clk_connect}, + + {"PGA_L_Mux", "AIN0", "AIN0"}, + {"PGA_L_Mux", "AIN1", "AIN1"}, + + {"PGA_R_Mux", "AIN0", "AIN0"}, + {"PGA_R_Mux", "AIN2", "AIN2"}, + {"PGA_R_Mux", "AIN3", "AIN3"}, + + {"PGA_3_Mux", "AIN2", "AIN2"}, + {"PGA_3_Mux", "AIN3", "AIN3"}, + + {"AIN0", NULL, "MIC_BIAS_0"}, + {"AIN1", NULL, "MIC_BIAS_1"}, + {"AIN2", NULL, "MIC_BIAS_0"}, + {"AIN2", NULL, "MIC_BIAS_2"}, + {"AIN3", NULL, "MIC_BIAS_2"}, + + /* DL Supply */ + {"DL Power Supply", NULL, "CLK_BUF"}, + {"DL Power Supply", NULL, "LDO_VAUD18"}, + {"DL Power Supply", NULL, "AUDGLB"}, + {"DL Power Supply", NULL, "CLKSQ Audio"}, + {"DL Power Supply", NULL, "AUDNCP_CK"}, + {"DL Power Supply", NULL, "ZCD13M_CK"}, + {"DL Power Supply", NULL, "AUD_CK"}, + {"DL Power Supply", NULL, "AUDIF_CK"}, + {"DL Power Supply", NULL, "ESD_RESIST"}, + {"DL Power Supply", NULL, "LDO"}, + {"DL Power Supply", NULL, "LDO_REMOTE"}, + {"DL Power Supply", NULL, "NV_REGULATOR"}, + {"DL Power Supply", NULL, "IBIST"}, + + /* DL Digital Supply */ + {"DL Digital Clock", NULL, "AUDIO_TOP_AFE_CTL"}, + {"DL Digital Clock", NULL, "AUDIO_TOP_DAC_CTL"}, + {"DL Digital Clock", NULL, "AUDIO_TOP_PWR_CLK"}, + {"DL Digital Clock", NULL, "AUDIO_TOP_PDN_RESERVED"}, + {"DL Digital Clock", NULL, "SDM_FIFO_CLK"}, + {"DL Digital Clock", NULL, "NCP"}, + {"DL Digital Clock", NULL, "AFE_ON"}, + {"DL Digital Clock", NULL, "AFE_DL_SRC"}, + + {"DL Digital Clock CH_1_2", NULL, "DL Digital Clock"}, + {"DL Digital Clock CH_1_2", NULL, "SDM"}, + + {"DL Digital Clock CH_3", NULL, "DL Digital Clock"}, + {"DL Digital Clock CH_3", NULL, "SDM_3RD"}, + + {"AIF_RX", NULL, "DL Digital Clock CH_1_2"}, + + {"AIF2_RX", NULL, "DL Digital Clock CH_3"}, + + /* DL Path */ + {"DAC In Mux", "Normal Path", "AIF_RX"}, + {"DAC In Mux", "Sgen", "SGEN DL"}, + {"SGEN DL", NULL, "SGEN DL SRC"}, + {"SGEN DL", NULL, "SGEN MUTE"}, + {"SGEN DL", NULL, "SGEN DL Enable"}, + {"SGEN DL", NULL, "DL Digital Clock CH_1_2"}, + {"SGEN DL", NULL, "DL Digital Clock CH_3"}, + {"SGEN DL", NULL, "AUDIO_TOP_PDN_AFE_TESTMODEL"}, + + {"DACL", NULL, "DAC In Mux"}, + {"DACL", NULL, "DL Power Supply"}, + + {"DACR", NULL, "DAC In Mux"}, + {"DACR", NULL, "DL Power Supply"}, + + /* DAC 3RD */ + {"DAC In Mux", "Normal Path", "AIF2_RX"}, + {"DAC_3RD", NULL, "DAC In Mux"}, + {"DAC_3RD", NULL, "DL Power Supply"}, + + /* Lineout Path */ + {"LOL Mux", "Playback", "DAC_3RD"}, + {"LINEOUT L", NULL, "LOL Mux"}, + + /* Headphone Path */ + {"HP_Supply", NULL, "HP_PULL_DOWN"}, + {"HP_Supply", NULL, "HP_MUTE"}, + {"HP_Supply", NULL, "HP_DAMP"}, + {"HP Mux", NULL, "HP_Supply"}, + + {"HP Mux", "Audio Playback", "DACL"}, + {"HP Mux", "Audio Playback", "DACR"}, + {"HP Mux", "HP Impedance", "DACL"}, + {"HP Mux", "HP Impedance", "DACR"}, + {"HP Mux", "LoudSPK Playback", "DACL"}, + {"HP Mux", "LoudSPK Playback", "DACR"}, + + {"Headphone L", NULL, "HP Mux"}, + {"Headphone R", NULL, "HP Mux"}, + {"Headphone L Ext Spk Amp", NULL, "HP Mux"}, + {"Headphone R Ext Spk Amp", NULL, "HP Mux"}, + + /* Receiver Path */ + {"RCV Mux", "Voice Playback", "DACL"}, + {"Receiver", NULL, "RCV Mux"}, +}; + +static int mt6359_codec_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *cmpnt = dai->component; + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + unsigned int rate = params_rate(params); + int id = dai->id; + + dev_dbg(priv->dev, "%s(), id %d, substream->stream %d, rate %d, number %d\n", + __func__, id, substream->stream, rate, substream->number); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + priv->dl_rate[id] = rate; + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + priv->ul_rate[id] = rate; + + return 0; +} + +static int mt6359_codec_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *cmpnt = dai->component; + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s stream %d\n", __func__, substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + mt6359_set_playback_gpio(priv); + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + mt6359_set_capture_gpio(priv); + + return 0; +} + +static void mt6359_codec_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *cmpnt = dai->component; + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(priv->dev, "%s stream %d\n", __func__, substream->stream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + mt6359_reset_playback_gpio(priv); + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + mt6359_reset_capture_gpio(priv); +} + +static const struct snd_soc_dai_ops mt6359_codec_dai_ops = { + .hw_params = mt6359_codec_dai_hw_params, + .startup = mt6359_codec_dai_startup, + .shutdown = mt6359_codec_dai_shutdown, +}; + +#define MT6359_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\ + SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |\ + SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE |\ + SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |\ + SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE) + +static struct snd_soc_dai_driver mt6359_dai_driver[] = { + { + .id = MT6359_AIF_1, + .name = "mt6359-snd-codec-aif1", + .playback = { + .stream_name = "AIF1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = MT6359_FORMATS, + }, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = MT6359_FORMATS, + }, + .ops = &mt6359_codec_dai_ops, + }, + { + .id = MT6359_AIF_2, + .name = "mt6359-snd-codec-aif2", + .playback = { + .stream_name = "AIF2 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = MT6359_FORMATS, + }, + .capture = { + .stream_name = "AIF2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000, + .formats = MT6359_FORMATS, + }, + .ops = &mt6359_codec_dai_ops, + }, +}; + +static int mt6359_codec_init_reg(struct snd_soc_component *cmpnt) +{ + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + /* enable clk buf */ + regmap_update_bits(priv->regmap, MT6359_DCXO_CW12, + 0x1 << RG_XO_AUDIO_EN_M_SFT, + 0x1 << RG_XO_AUDIO_EN_M_SFT); + + /* set those not controlled by dapm widget */ + + /* audio clk source from internal dcxo */ + regmap_update_bits(priv->regmap, MT6359_AUDENC_ANA_CON23, + RG_CLKSQ_IN_SEL_TEST_MASK_SFT, + 0x0); + + /* Disable HeadphoneL/HeadphoneR short circuit protection */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + RG_AUDHPLSCDISABLE_VAUDP32_MASK_SFT, + 0x1 << RG_AUDHPLSCDISABLE_VAUDP32_SFT); + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON0, + RG_AUDHPRSCDISABLE_VAUDP32_MASK_SFT, + 0x1 << RG_AUDHPRSCDISABLE_VAUDP32_SFT); + /* Disable voice short circuit protection */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON6, + RG_AUDHSSCDISABLE_VAUDP32_MASK_SFT, + 0x1 << RG_AUDHSSCDISABLE_VAUDP32_SFT); + /* disable LO buffer left short circuit protection */ + regmap_update_bits(priv->regmap, MT6359_AUDDEC_ANA_CON7, + RG_AUDLOLSCDISABLE_VAUDP32_MASK_SFT, + 0x1 << RG_AUDLOLSCDISABLE_VAUDP32_SFT); + + /* set gpio */ + mt6359_reset_playback_gpio(priv); + mt6359_reset_capture_gpio(priv); + + /* hp hifi mode, default normal mode */ + priv->hp_hifi_mode = 0; + + /* Disable AUD_ZCD */ + zcd_disable(priv); + + /* disable clk buf */ + regmap_update_bits(priv->regmap, MT6359_DCXO_CW12, + 0x1 << RG_XO_AUDIO_EN_M_SFT, + 0x0 << RG_XO_AUDIO_EN_M_SFT); + + return 0; +} + +static int mt6359_codec_probe(struct snd_soc_component *cmpnt) +{ + struct mt6359_priv *priv = snd_soc_component_get_drvdata(cmpnt); + + snd_soc_component_init_regmap(cmpnt, priv->regmap); + + return mt6359_codec_init_reg(cmpnt); +} + +static void mt6359_codec_remove(struct snd_soc_component *cmpnt) +{ + snd_soc_component_exit_regmap(cmpnt); +} + +static const DECLARE_TLV_DB_SCALE(hp_playback_tlv, -2200, 100, 0); +static const DECLARE_TLV_DB_SCALE(playback_tlv, -1000, 100, 0); +static const DECLARE_TLV_DB_SCALE(capture_tlv, 0, 600, 0); + +static const struct snd_kcontrol_new mt6359_snd_controls[] = { + /* dl pga gain */ + SOC_DOUBLE_EXT_TLV("Headset Volume", + MT6359_ZCD_CON2, 0, 7, 0x1E, 0, + snd_soc_get_volsw, mt6359_put_volsw, + hp_playback_tlv), + SOC_DOUBLE_EXT_TLV("Lineout Volume", + MT6359_ZCD_CON1, 0, 7, 0x12, 0, + snd_soc_get_volsw, mt6359_put_volsw, playback_tlv), + SOC_SINGLE_EXT_TLV("Handset Volume", + MT6359_ZCD_CON3, 0, 0x12, 0, + snd_soc_get_volsw, mt6359_put_volsw, playback_tlv), + + /* ul pga gain */ + SOC_SINGLE_EXT_TLV("PGA1 Volume", + MT6359_AUDENC_ANA_CON0, RG_AUDPREAMPLGAIN_SFT, 4, 0, + snd_soc_get_volsw, mt6359_put_volsw, capture_tlv), + SOC_SINGLE_EXT_TLV("PGA2 Volume", + MT6359_AUDENC_ANA_CON1, RG_AUDPREAMPRGAIN_SFT, 4, 0, + snd_soc_get_volsw, mt6359_put_volsw, capture_tlv), + SOC_SINGLE_EXT_TLV("PGA3 Volume", + MT6359_AUDENC_ANA_CON2, RG_AUDPREAMP3GAIN_SFT, 4, 0, + snd_soc_get_volsw, mt6359_put_volsw, capture_tlv), +}; + +static const struct snd_soc_component_driver mt6359_soc_component_driver = { + .name = CODEC_MT6359_NAME, + .probe = mt6359_codec_probe, + .remove = mt6359_codec_remove, + .controls = mt6359_snd_controls, + .num_controls = ARRAY_SIZE(mt6359_snd_controls), + .dapm_widgets = mt6359_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt6359_dapm_widgets), + .dapm_routes = mt6359_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(mt6359_dapm_routes), +}; + +static int mt6359_parse_dt(struct mt6359_priv *priv) +{ + int ret; + struct device *dev = priv->dev; + + ret = of_property_read_u32(dev->of_node, "mediatek,dmic-mode", + &priv->dmic_one_wire_mode); + if (ret) { + dev_warn(priv->dev, "%s() failed to read dmic-mode\n", + __func__); + priv->dmic_one_wire_mode = 0; + } + + ret = of_property_read_u32(dev->of_node, "mediatek,mic-type-0", + &priv->mux_select[MUX_MIC_TYPE_0]); + if (ret) { + dev_warn(priv->dev, "%s() failed to read mic-type-0\n", + __func__); + priv->mux_select[MUX_MIC_TYPE_0] = MIC_TYPE_MUX_IDLE; + } + + ret = of_property_read_u32(dev->of_node, "mediatek,mic-type-1", + &priv->mux_select[MUX_MIC_TYPE_1]); + if (ret) { + dev_warn(priv->dev, "%s() failed to read mic-type-1\n", + __func__); + priv->mux_select[MUX_MIC_TYPE_1] = MIC_TYPE_MUX_IDLE; + } + + ret = of_property_read_u32(dev->of_node, "mediatek,mic-type-2", + &priv->mux_select[MUX_MIC_TYPE_2]); + if (ret) { + dev_warn(priv->dev, "%s() failed to read mic-type-2\n", + __func__); + priv->mux_select[MUX_MIC_TYPE_2] = MIC_TYPE_MUX_IDLE; + } + + return 0; +} + +static int mt6359_platform_driver_probe(struct platform_device *pdev) +{ + struct mt6359_priv *priv; + int ret; + struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent); + + dev_dbg(&pdev->dev, "%s(), dev name %s\n", + __func__, dev_name(&pdev->dev)); + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->regmap = mt6397->regmap; + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + dev_set_drvdata(&pdev->dev, priv); + priv->dev = &pdev->dev; + + priv->avdd_reg = devm_regulator_get(&pdev->dev, "vaud18"); + if (IS_ERR(priv->avdd_reg)) { + dev_err(&pdev->dev, "%s(), have no vaud18 supply: %ld", + __func__, PTR_ERR(priv->avdd_reg)); + return PTR_ERR(priv->avdd_reg); + } + + ret = regulator_enable(priv->avdd_reg); + if (ret) { + dev_err(&pdev->dev, "%s(), failed to enable regulator!\n", + __func__); + return ret; + } + + ret = mt6359_parse_dt(priv); + if (ret) { + dev_warn(&pdev->dev, "%s() failed to parse dts\n", __func__); + return ret; + } + + return devm_snd_soc_register_component(&pdev->dev, + &mt6359_soc_component_driver, + mt6359_dai_driver, + ARRAY_SIZE(mt6359_dai_driver)); +} + +static int mt6359_platform_driver_remove(struct platform_device *pdev) +{ + struct mt6359_priv *priv = dev_get_drvdata(&pdev->dev); + int ret; + + dev_dbg(&pdev->dev, "%s(), dev name %s\n", + __func__, dev_name(&pdev->dev)); + + ret = regulator_disable(priv->avdd_reg); + if (ret) { + dev_err(&pdev->dev, "%s(), failed to disable regulator!\n", + __func__); + return ret; + } + + return 0; +} + +static struct platform_driver mt6359_platform_driver = { + .driver = { + .name = "mt6359-sound", + }, + .probe = mt6359_platform_driver_probe, + .remove = mt6359_platform_driver_remove, +}; + +module_platform_driver(mt6359_platform_driver) + +/* Module information */ +MODULE_DESCRIPTION("MT6359 ALSA SoC codec driver"); +MODULE_AUTHOR("KaiChieh Chuang <[email protected]>"); +MODULE_AUTHOR("Eason Yen <[email protected]>"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/mt6359.h b/sound/soc/codecs/mt6359.h new file mode 100644 index 000000000000..3792e534a91b --- /dev/null +++ b/sound/soc/codecs/mt6359.h @@ -0,0 +1,2640 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 MediaTek Inc. + * Author: Argus Lin <[email protected]> + */ + +#ifndef _MT6359_H_ +#define _MT6359_H_ + +/*************Register Bit Define*************/ +#define PMIC_ACCDET_IRQ_SHIFT 0 +#define PMIC_ACCDET_EINT0_IRQ_SHIFT 2 +#define PMIC_ACCDET_EINT1_IRQ_SHIFT 3 +#define PMIC_ACCDET_IRQ_CLR_SHIFT 8 +#define PMIC_ACCDET_EINT0_IRQ_CLR_SHIFT 10 +#define PMIC_ACCDET_EINT1_IRQ_CLR_SHIFT 11 +#define PMIC_RG_INT_STATUS_ACCDET_SHIFT 5 +#define PMIC_RG_INT_STATUS_ACCDET_EINT0_SHIFT 6 +#define PMIC_RG_INT_STATUS_ACCDET_EINT1_SHIFT 7 +#define PMIC_RG_EINT0CONFIGACCDET_SHIFT 11 +#define PMIC_RG_EINT1CONFIGACCDET_SHIFT 0 +#define PMIC_ACCDET_EINT0_INVERTER_SW_EN_SHIFT 6 +#define PMIC_ACCDET_EINT1_INVERTER_SW_EN_SHIFT 8 +#define PMIC_RG_MTEST_EN_SHIFT 8 +#define PMIC_RG_MTEST_SEL_SHIFT 9 +#define PMIC_ACCDET_EINT0_M_SW_EN_SHIFT 10 +#define PMIC_ACCDET_EINT1_M_SW_EN_SHIFT 11 +#define PMIC_ACCDET_EINT0_CEN_STABLE_SHIFT 5 +#define PMIC_ACCDET_EINT1_CEN_STABLE_SHIFT 10 +#define PMIC_ACCDET_DA_STABLE_SHIFT 0 +#define PMIC_ACCDET_EINT0_EN_STABLE_SHIFT 1 +#define PMIC_ACCDET_EINT0_CMPEN_STABLE_SHIFT 2 +#define PMIC_ACCDET_EINT1_EN_STABLE_SHIFT 6 +#define PMIC_ACCDET_EINT1_CMPEN_STABLE_SHIFT 7 +#define PMIC_ACCDET_EINT_CTURBO_SEL_SHIFT 7 +#define PMIC_ACCDET_EINT0_CTURBO_SW_SHIFT 7 +#define PMIC_RG_EINTCOMPVTH_SHIFT 4 +#define PMIC_RG_EINT0HIRENB_SHIFT 12 +#define PMIC_RG_EINT0NOHYS_SHIFT 10 +#define PMIC_ACCDET_SW_EN_SHIFT 0 +#define PMIC_ACCDET_EINT0_MEM_IN_SHIFT 6 +#define PMIC_ACCDET_MEM_IN_SHIFT 6 +#define PMIC_ACCDET_EINT_DEBOUNCE0_SHIFT 0 +#define PMIC_ACCDET_EINT_DEBOUNCE1_SHIFT 4 +#define PMIC_ACCDET_EINT_DEBOUNCE2_SHIFT 8 +#define PMIC_ACCDET_EINT_DEBOUNCE3_SHIFT 12 +#define PMIC_RG_ACCDET2AUXSWEN_SHIFT 14 +#define PMIC_AUDACCDETAUXADCSWCTRL_SEL_SHIFT 9 +#define PMIC_AUDACCDETAUXADCSWCTRL_SW_SHIFT 10 +#define PMIC_RG_EINT0CTURBO_SHIFT 5 +#define PMIC_RG_EINT1CTURBO_SHIFT 13 +#define PMIC_ACCDET_EINT_M_PLUG_IN_NUM_SHIFT 12 +#define PMIC_ACCDET_EINT_M_DETECT_EN_SHIFT 12 +#define PMIC_ACCDET_EINT0_SW_EN_SHIFT 2 +#define PMIC_ACCDET_EINT1_SW_EN_SHIFT 4 +#define PMIC_ACCDET_EINT_CMPMOUT_SEL_SHIFT 12 +#define PMIC_ACCDET_EINT_CMPMEN_SEL_SHIFT 6 +#define PMIC_RG_HPLOUTPUTSTBENH_VAUDP32_SHIFT 0 +#define PMIC_RG_HPROUTPUTSTBENH_VAUDP32_SHIFT 4 +#define PMIC_RG_EINT0EN_SHIFT 2 +#define PMIC_RG_EINT1EN_SHIFT 10 +#define PMIC_RG_NCP_PDDIS_EN_SHIFT 0 +#define PMIC_RG_ACCDETSPARE_SHIFT 0 +#define PMIC_RG_ACCDET_RST_SHIFT 1 +#define PMIC_RG_AUDMICBIAS1HVEN_SHIFT 12 +#define PMIC_RG_AUDMICBIAS1VREF_SHIFT 4 +#define PMIC_RG_ANALOGFDEN_SHIFT 12 +#define PMIC_RG_AUDMICBIAS1DCSW1PEN_SHIFT 8 +#define PMIC_RG_AUDMICBIAS1LOWPEN_SHIFT 2 +#define PMIC_ACCDET_SEQ_INIT_SHIFT 1 +#define PMIC_RG_EINTCOMPVTH_MASK 0xf +#define PMIC_ACCDET_EINT0_MEM_IN_MASK 0x3 +#define PMIC_ACCDET_EINT_DEBOUNCE0_MASK 0xf +#define PMIC_ACCDET_EINT_DEBOUNCE1_MASK 0xf +#define PMIC_ACCDET_EINT_DEBOUNCE2_MASK 0xf +#define PMIC_ACCDET_EINT_DEBOUNCE3_MASK 0xf +#define PMIC_ACCDET_EINT0_IRQ_SHIFT 2 +#define PMIC_ACCDET_EINT1_IRQ_SHIFT 3 + +/* AUDENC_ANA_CON16: */ +#define RG_AUD_MICBIAS1_LOWP_EN BIT(PMIC_RG_AUDMICBIAS1LOWPEN_SHIFT) + +/* AUDENC_ANA_CON18: */ +#define RG_ACCDET_MODE_ANA11_MODE1 (0x000f) +#define RG_ACCDET_MODE_ANA11_MODE2 (0x008f) +#define RG_ACCDET_MODE_ANA11_MODE6 (0x008f) + +/* AUXADC_ADC5: Auxadc CH5 read data */ +#define AUXADC_DATA_RDY_CH5 BIT(15) +#define AUXADC_DATA_PROCEED_CH5 BIT(15) +#define AUXADC_DATA_MASK (0x0fff) + +/* AUXADC_RQST0_SET: Auxadc CH5 request, relevant 0x07EC */ +#define AUXADC_RQST_CH5_SET BIT(5) +/* AUXADC_RQST0_CLR: Auxadc CH5 request, relevant 0x07EC */ +#define AUXADC_RQST_CH5_CLR BIT(5) + +#define ACCDET_CALI_MASK0 (0xff) +#define ACCDET_CALI_MASK1 (0xff << 8) +#define ACCDET_CALI_MASK2 (0xff) +#define ACCDET_CALI_MASK3 (0xff << 8) +#define ACCDET_CALI_MASK4 (0xff) + +#define ACCDET_EINT1_IRQ_CLR_B11 BIT(PMIC_ACCDET_EINT1_IRQ_CLR_SHIFT) +#define ACCDET_EINT0_IRQ_CLR_B10 BIT(PMIC_ACCDET_EINT0_IRQ_CLR_SHIFT) +#define ACCDET_EINT_IRQ_CLR_B10_11 (0x03 << \ + PMIC_ACCDET_EINT0_IRQ_CLR_SHIFT) +#define ACCDET_IRQ_CLR_B8 BIT(PMIC_ACCDET_IRQ_CLR_SHIFT) + +#define ACCDET_EINT1_IRQ_B3 BIT(PMIC_ACCDET_EINT1_IRQ_SHIFT) +#define ACCDET_EINT0_IRQ_B2 BIT(PMIC_ACCDET_EINT0_IRQ_SHIFT) +#define ACCDET_EINT_IRQ_B2_B3 (0x03 << PMIC_ACCDET_EINT0_IRQ_SHIFT) +#define ACCDET_IRQ_B0 BIT(PMIC_ACCDET_IRQ_SHIFT) + +/* ACCDET_CON25: RO, accdet FSM state,etc.*/ +#define ACCDET_STATE_MEM_IN_OFFSET (PMIC_ACCDET_MEM_IN_SHIFT) +#define ACCDET_STATE_AB_MASK (0x03) +#define ACCDET_STATE_AB_00 (0x00) +#define ACCDET_STATE_AB_01 (0x01) +#define ACCDET_STATE_AB_10 (0x02) +#define ACCDET_STATE_AB_11 (0x03) + +/* ACCDET_CON19 */ +#define ACCDET_EINT0_STABLE_VAL ((1 << PMIC_ACCDET_DA_STABLE_SHIFT) | \ + (1 << PMIC_ACCDET_EINT0_EN_STABLE_SHIFT) | \ + (1 << PMIC_ACCDET_EINT0_CMPEN_STABLE_SHIFT) | \ + (1 << PMIC_ACCDET_EINT0_CEN_STABLE_SHIFT)) + +#define ACCDET_EINT1_STABLE_VAL ((1 << PMIC_ACCDET_DA_STABLE_SHIFT) | \ + (1 << PMIC_ACCDET_EINT1_EN_STABLE_SHIFT) | \ + (1 << PMIC_ACCDET_EINT1_CMPEN_STABLE_SHIFT) | \ + (1 << PMIC_ACCDET_EINT1_CEN_STABLE_SHIFT)) + +/* The following are used for mt6359.c */ +/* MT6359_DCXO_CW12 */ +#define RG_XO_AUDIO_EN_M_SFT 13 + +/* LDO_VAUD18_CON0 */ +#define RG_LDO_VAUD18_EN_SFT 0 +#define RG_LDO_VAUD18_EN_MASK 0x1 +#define RG_LDO_VAUD18_EN_MASK_SFT (0x1 << 0) + +/* AUD_TOP_CKPDN_CON0 */ +#define RG_VOW13M_CK_PDN_SFT 13 +#define RG_VOW13M_CK_PDN_MASK 0x1 +#define RG_VOW13M_CK_PDN_MASK_SFT (0x1 << 13) +#define RG_VOW32K_CK_PDN_SFT 12 +#define RG_VOW32K_CK_PDN_MASK 0x1 +#define RG_VOW32K_CK_PDN_MASK_SFT (0x1 << 12) +#define RG_AUD_INTRP_CK_PDN_SFT 8 +#define RG_AUD_INTRP_CK_PDN_MASK 0x1 +#define RG_AUD_INTRP_CK_PDN_MASK_SFT (0x1 << 8) +#define RG_PAD_AUD_CLK_MISO_CK_PDN_SFT 7 +#define RG_PAD_AUD_CLK_MISO_CK_PDN_MASK 0x1 +#define RG_PAD_AUD_CLK_MISO_CK_PDN_MASK_SFT (0x1 << 7) +#define RG_AUDNCP_CK_PDN_SFT 6 +#define RG_AUDNCP_CK_PDN_MASK 0x1 +#define RG_AUDNCP_CK_PDN_MASK_SFT (0x1 << 6) +#define RG_ZCD13M_CK_PDN_SFT 5 +#define RG_ZCD13M_CK_PDN_MASK 0x1 +#define RG_ZCD13M_CK_PDN_MASK_SFT (0x1 << 5) +#define RG_AUDIF_CK_PDN_SFT 2 +#define RG_AUDIF_CK_PDN_MASK 0x1 +#define RG_AUDIF_CK_PDN_MASK_SFT (0x1 << 2) +#define RG_AUD_CK_PDN_SFT 1 +#define RG_AUD_CK_PDN_MASK 0x1 +#define RG_AUD_CK_PDN_MASK_SFT (0x1 << 1) +#define RG_ACCDET_CK_PDN_SFT 0 +#define RG_ACCDET_CK_PDN_MASK 0x1 +#define RG_ACCDET_CK_PDN_MASK_SFT (0x1 << 0) + +/* AUD_TOP_CKPDN_CON0_SET */ +#define RG_AUD_TOP_CKPDN_CON0_SET_SFT 0 +#define RG_AUD_TOP_CKPDN_CON0_SET_MASK 0x3fff +#define RG_AUD_TOP_CKPDN_CON0_SET_MASK_SFT (0x3fff << 0) + +/* AUD_TOP_CKPDN_CON0_CLR */ +#define RG_AUD_TOP_CKPDN_CON0_CLR_SFT 0 +#define RG_AUD_TOP_CKPDN_CON0_CLR_MASK 0x3fff +#define RG_AUD_TOP_CKPDN_CON0_CLR_MASK_SFT (0x3fff << 0) + +/* AUD_TOP_CKSEL_CON0 */ +#define RG_AUDIF_CK_CKSEL_SFT 3 +#define RG_AUDIF_CK_CKSEL_MASK 0x1 +#define RG_AUDIF_CK_CKSEL_MASK_SFT (0x1 << 3) +#define RG_AUD_CK_CKSEL_SFT 2 +#define RG_AUD_CK_CKSEL_MASK 0x1 +#define RG_AUD_CK_CKSEL_MASK_SFT (0x1 << 2) + +/* AUD_TOP_CKSEL_CON0_SET */ +#define RG_AUD_TOP_CKSEL_CON0_SET_SFT 0 +#define RG_AUD_TOP_CKSEL_CON0_SET_MASK 0xf +#define RG_AUD_TOP_CKSEL_CON0_SET_MASK_SFT (0xf << 0) + +/* AUD_TOP_CKSEL_CON0_CLR */ +#define RG_AUD_TOP_CKSEL_CON0_CLR_SFT 0 +#define RG_AUD_TOP_CKSEL_CON0_CLR_MASK 0xf +#define RG_AUD_TOP_CKSEL_CON0_CLR_MASK_SFT (0xf << 0) + +/* AUD_TOP_CKTST_CON0 */ +#define RG_VOW13M_CK_TSTSEL_SFT 9 +#define RG_VOW13M_CK_TSTSEL_MASK 0x1 +#define RG_VOW13M_CK_TSTSEL_MASK_SFT (0x1 << 9) +#define RG_VOW13M_CK_TST_DIS_SFT 8 +#define RG_VOW13M_CK_TST_DIS_MASK 0x1 +#define RG_VOW13M_CK_TST_DIS_MASK_SFT (0x1 << 8) +#define RG_AUD26M_CK_TSTSEL_SFT 4 +#define RG_AUD26M_CK_TSTSEL_MASK 0x1 +#define RG_AUD26M_CK_TSTSEL_MASK_SFT (0x1 << 4) +#define RG_AUDIF_CK_TSTSEL_SFT 3 +#define RG_AUDIF_CK_TSTSEL_MASK 0x1 +#define RG_AUDIF_CK_TSTSEL_MASK_SFT (0x1 << 3) +#define RG_AUD_CK_TSTSEL_SFT 2 +#define RG_AUD_CK_TSTSEL_MASK 0x1 +#define RG_AUD_CK_TSTSEL_MASK_SFT (0x1 << 2) +#define RG_AUD26M_CK_TST_DIS_SFT 0 +#define RG_AUD26M_CK_TST_DIS_MASK 0x1 +#define RG_AUD26M_CK_TST_DIS_MASK_SFT (0x1 << 0) + +/* AUD_TOP_CLK_HWEN_CON0 */ +#define RG_AUD_INTRP_CK_PDN_HWEN_SFT 0 +#define RG_AUD_INTRP_CK_PDN_HWEN_MASK 0x1 +#define RG_AUD_INTRP_CK_PDN_HWEN_MASK_SFT (0x1 << 0) + +/* AUD_TOP_CLK_HWEN_CON0_SET */ +#define RG_AUD_INTRP_CK_PND_HWEN_CON0_SET_SFT 0 +#define RG_AUD_INTRP_CK_PND_HWEN_CON0_SET_MASK 0xffff +#define RG_AUD_INTRP_CK_PND_HWEN_CON0_SET_MASK_SFT (0xffff << 0) + +/* AUD_TOP_CLK_HWEN_CON0_CLR */ +#define RG_AUD_INTRP_CLK_PDN_HWEN_CON0_CLR_SFT 0 +#define RG_AUD_INTRP_CLK_PDN_HWEN_CON0_CLR_MASK 0xffff +#define RG_AUD_INTRP_CLK_PDN_HWEN_CON0_CLR_MASK_SFT (0xffff << 0) + +/* AUD_TOP_RST_CON0 */ +#define RG_AUDNCP_RST_SFT 3 +#define RG_AUDNCP_RST_MASK 0x1 +#define RG_AUDNCP_RST_MASK_SFT (0x1 << 3) +#define RG_ZCD_RST_SFT 2 +#define RG_ZCD_RST_MASK 0x1 +#define RG_ZCD_RST_MASK_SFT (0x1 << 2) +#define RG_ACCDET_RST_SFT 1 +#define RG_ACCDET_RST_MASK 0x1 +#define RG_ACCDET_RST_MASK_SFT (0x1 << 1) +#define RG_AUDIO_RST_SFT 0 +#define RG_AUDIO_RST_MASK 0x1 +#define RG_AUDIO_RST_MASK_SFT (0x1 << 0) + +/* AUD_TOP_RST_CON0_SET */ +#define RG_AUD_TOP_RST_CON0_SET_SFT 0 +#define RG_AUD_TOP_RST_CON0_SET_MASK 0xf +#define RG_AUD_TOP_RST_CON0_SET_MASK_SFT (0xf << 0) + +/* AUD_TOP_RST_CON0_CLR */ +#define RG_AUD_TOP_RST_CON0_CLR_SFT 0 +#define RG_AUD_TOP_RST_CON0_CLR_MASK 0xf +#define RG_AUD_TOP_RST_CON0_CLR_MASK_SFT (0xf << 0) + +/* AUD_TOP_RST_BANK_CON0 */ +#define BANK_AUDZCD_SWRST_SFT 2 +#define BANK_AUDZCD_SWRST_MASK 0x1 +#define BANK_AUDZCD_SWRST_MASK_SFT (0x1 << 2) +#define BANK_AUDIO_SWRST_SFT 1 +#define BANK_AUDIO_SWRST_MASK 0x1 +#define BANK_AUDIO_SWRST_MASK_SFT (0x1 << 1) +#define BANK_ACCDET_SWRST_SFT 0 +#define BANK_ACCDET_SWRST_MASK 0x1 +#define BANK_ACCDET_SWRST_MASK_SFT (0x1 << 0) + +/* AFE_UL_DL_CON0 */ +#define AFE_UL_LR_SWAP_SFT 15 +#define AFE_UL_LR_SWAP_MASK 0x1 +#define AFE_UL_LR_SWAP_MASK_SFT (0x1 << 15) +#define AFE_DL_LR_SWAP_SFT 14 +#define AFE_DL_LR_SWAP_MASK 0x1 +#define AFE_DL_LR_SWAP_MASK_SFT (0x1 << 14) +#define AFE_ON_SFT 0 +#define AFE_ON_MASK 0x1 +#define AFE_ON_MASK_SFT (0x1 << 0) + +/* AFE_DL_SRC2_CON0_L */ +#define DL_2_SRC_ON_TMP_CTL_PRE_SFT 0 +#define DL_2_SRC_ON_TMP_CTL_PRE_MASK 0x1 +#define DL_2_SRC_ON_TMP_CTL_PRE_MASK_SFT (0x1 << 0) + +/* AFE_UL_SRC_CON0_H */ +#define C_DIGMIC_PHASE_SEL_CH1_CTL_SFT 11 +#define C_DIGMIC_PHASE_SEL_CH1_CTL_MASK 0x7 +#define C_DIGMIC_PHASE_SEL_CH1_CTL_MASK_SFT (0x7 << 11) +#define C_DIGMIC_PHASE_SEL_CH2_CTL_SFT 8 +#define C_DIGMIC_PHASE_SEL_CH2_CTL_MASK 0x7 +#define C_DIGMIC_PHASE_SEL_CH2_CTL_MASK_SFT (0x7 << 8) +#define C_TWO_DIGITAL_MIC_CTL_SFT 7 +#define C_TWO_DIGITAL_MIC_CTL_MASK 0x1 +#define C_TWO_DIGITAL_MIC_CTL_MASK_SFT (0x1 << 7) + +/* AFE_UL_SRC_CON0_L */ +#define DMIC_LOW_POWER_MODE_CTL_SFT 14 +#define DMIC_LOW_POWER_MODE_CTL_MASK 0x3 +#define DMIC_LOW_POWER_MODE_CTL_MASK_SFT (0x3 << 14) +#define DIGMIC_4P33M_SEL_CTL_SFT 6 +#define DIGMIC_4P33M_SEL_CTL_MASK 0x1 +#define DIGMIC_4P33M_SEL_CTL_MASK_SFT (0x1 << 6) +#define DIGMIC_3P25M_1P625M_SEL_CTL_SFT 5 +#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK 0x1 +#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT (0x1 << 5) +#define UL_LOOP_BACK_MODE_CTL_SFT 2 +#define UL_LOOP_BACK_MODE_CTL_MASK 0x1 +#define UL_LOOP_BACK_MODE_CTL_MASK_SFT (0x1 << 2) +#define UL_SDM_3_LEVEL_CTL_SFT 1 +#define UL_SDM_3_LEVEL_CTL_MASK 0x1 +#define UL_SDM_3_LEVEL_CTL_MASK_SFT (0x1 << 1) +#define UL_SRC_ON_TMP_CTL_SFT 0 +#define UL_SRC_ON_TMP_CTL_MASK 0x1 +#define UL_SRC_ON_TMP_CTL_MASK_SFT (0x1 << 0) + +/* AFE_ADDA6_L_SRC_CON0_H */ +#define ADDA6_C_DIGMIC_PHASE_SEL_CH1_CTL_SFT 11 +#define ADDA6_C_DIGMIC_PHASE_SEL_CH1_CTL_MASK 0x7 +#define ADDA6_C_DIGMIC_PHASE_SEL_CH1_CTL_MASK_SFT (0x7 << 11) +#define ADDA6_C_DIGMIC_PHASE_SEL_CH2_CTL_SFT 8 +#define ADDA6_C_DIGMIC_PHASE_SEL_CH2_CTL_MASK 0x7 +#define ADDA6_C_DIGMIC_PHASE_SEL_CH2_CTL_MASK_SFT (0x7 << 8) +#define ADDA6_C_TWO_DIGITAL_MIC_CTL_SFT 7 +#define ADDA6_C_TWO_DIGITAL_MIC_CTL_MASK 0x1 +#define ADDA6_C_TWO_DIGITAL_MIC_CTL_MASK_SFT (0x1 << 7) + +/* AFE_ADDA6_UL_SRC_CON0_L */ +#define ADDA6_DMIC_LOW_POWER_MODE_CTL_SFT 14 +#define ADDA6_DMIC_LOW_POWER_MODE_CTL_MASK 0x3 +#define ADDA6_DMIC_LOW_POWER_MODE_CTL_MASK_SFT (0x3 << 14) +#define ADDA6_DIGMIC_4P33M_SEL_CTL_SFT 6 +#define ADDA6_DIGMIC_4P33M_SEL_CTL_MASK 0x1 +#define ADDA6_DIGMIC_4P33M_SEL_CTL_MASK_SFT (0x1 << 6) +#define ADDA6_DIGMIC_3P25M_1P625M_SEL_CTL_SFT 5 +#define ADDA6_DIGMIC_3P25M_1P625M_SEL_CTL_MASK 0x1 +#define ADDA6_DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT (0x1 << 5) +#define ADDA6_UL_LOOP_BACK_MODE_CTL_SFT 2 +#define ADDA6_UL_LOOP_BACK_MODE_CTL_MASK 0x1 +#define ADDA6_UL_LOOP_BACK_MODE_CTL_MASK_SFT (0x1 << 2) +#define ADDA6_UL_SDM_3_LEVEL_CTL_SFT 1 +#define ADDA6_UL_SDM_3_LEVEL_CTL_MASK 0x1 +#define ADDA6_UL_SDM_3_LEVEL_CTL_MASK_SFT (0x1 << 1) +#define ADDA6_UL_SRC_ON_TMP_CTL_SFT 0 +#define ADDA6_UL_SRC_ON_TMP_CTL_MASK 0x1 +#define ADDA6_UL_SRC_ON_TMP_CTL_MASK_SFT (0x1 << 0) + +/* AFE_TOP_CON0 */ +#define ADDA6_MTKAIF_SINE_ON_SFT 4 +#define ADDA6_MTKAIF_SINE_ON_MASK 0x1 +#define ADDA6_MTKAIF_SINE_ON_MASK_SFT (0x1 << 4) +#define ADDA6_UL_SINE_ON_SFT 3 +#define ADDA6_UL_SINE_ON_MASK 0x1 +#define ADDA6_UL_SINE_ON_MASK_SFT (0x1 << 3) +#define MTKAIF_SINE_ON_SFT 2 +#define MTKAIF_SINE_ON_MASK 0x1 +#define MTKAIF_SINE_ON_MASK_SFT (0x1 << 2) +#define UL_SINE_ON_SFT 1 +#define UL_SINE_ON_MASK 0x1 +#define UL_SINE_ON_MASK_SFT (0x1 << 1) +#define DL_SINE_ON_SFT 0 +#define DL_SINE_ON_MASK 0x1 +#define DL_SINE_ON_MASK_SFT (0x1 << 0) + +/* AUDIO_TOP_CON0 */ +#define PDN_AFE_CTL_SFT 7 +#define PDN_AFE_CTL_MASK 0x1 +#define PDN_AFE_CTL_MASK_SFT (0x1 << 7) +#define PDN_DAC_CTL_SFT 6 +#define PDN_DAC_CTL_MASK 0x1 +#define PDN_DAC_CTL_MASK_SFT (0x1 << 6) +#define PDN_ADC_CTL_SFT 5 +#define PDN_ADC_CTL_MASK 0x1 +#define PDN_ADC_CTL_MASK_SFT (0x1 << 5) +#define PDN_ADDA6_ADC_CTL_SFT 4 +#define PDN_ADDA6_ADC_CTL_MASK 0x1 +#define PDN_ADDA6_ADC_CTL_MASK_SFT (0x1 << 4) +#define PDN_I2S_DL_CTL_SFT 3 +#define PDN_I2S_DL_CTL_MASK 0x1 +#define PDN_I2S_DL_CTL_MASK_SFT (0x1 << 3) +#define PWR_CLK_DIS_CTL_SFT 2 +#define PWR_CLK_DIS_CTL_MASK 0x1 +#define PWR_CLK_DIS_CTL_MASK_SFT (0x1 << 2) +#define PDN_AFE_TESTMODEL_CTL_SFT 1 +#define PDN_AFE_TESTMODEL_CTL_MASK 0x1 +#define PDN_AFE_TESTMODEL_CTL_MASK_SFT (0x1 << 1) +#define PDN_RESERVED_SFT 0 +#define PDN_RESERVED_MASK 0x1 +#define PDN_RESERVED_MASK_SFT (0x1 << 0) + +/* AFE_MON_DEBUG0 */ +#define AUDIO_SYS_TOP_MON_SWAP_SFT 14 +#define AUDIO_SYS_TOP_MON_SWAP_MASK 0x3 +#define AUDIO_SYS_TOP_MON_SWAP_MASK_SFT (0x3 << 14) +#define AUDIO_SYS_TOP_MON_SEL_SFT 8 +#define AUDIO_SYS_TOP_MON_SEL_MASK 0x1f +#define AUDIO_SYS_TOP_MON_SEL_MASK_SFT (0x1f << 8) +#define AFE_MON_SEL_SFT 0 +#define AFE_MON_SEL_MASK 0xff +#define AFE_MON_SEL_MASK_SFT (0xff << 0) + +/* AFUNC_AUD_CON0 */ +#define CCI_AUD_ANACK_SEL_SFT 15 +#define CCI_AUD_ANACK_SEL_MASK 0x1 +#define CCI_AUD_ANACK_SEL_MASK_SFT (0x1 << 15) +#define CCI_AUDIO_FIFO_WPTR_SFT 12 +#define CCI_AUDIO_FIFO_WPTR_MASK 0x7 +#define CCI_AUDIO_FIFO_WPTR_MASK_SFT (0x7 << 12) +#define CCI_SCRAMBLER_CG_EN_SFT 11 +#define CCI_SCRAMBLER_CG_EN_MASK 0x1 +#define CCI_SCRAMBLER_CG_EN_MASK_SFT (0x1 << 11) +#define CCI_LCH_INV_SFT 10 +#define CCI_LCH_INV_MASK 0x1 +#define CCI_LCH_INV_MASK_SFT (0x1 << 10) +#define CCI_RAND_EN_SFT 9 +#define CCI_RAND_EN_MASK 0x1 +#define CCI_RAND_EN_MASK_SFT (0x1 << 9) +#define CCI_SPLT_SCRMB_CLK_ON_SFT 8 +#define CCI_SPLT_SCRMB_CLK_ON_MASK 0x1 +#define CCI_SPLT_SCRMB_CLK_ON_MASK_SFT (0x1 << 8) +#define CCI_SPLT_SCRMB_ON_SFT 7 +#define CCI_SPLT_SCRMB_ON_MASK 0x1 +#define CCI_SPLT_SCRMB_ON_MASK_SFT (0x1 << 7) +#define CCI_AUD_IDAC_TEST_EN_SFT 6 +#define CCI_AUD_IDAC_TEST_EN_MASK 0x1 +#define CCI_AUD_IDAC_TEST_EN_MASK_SFT (0x1 << 6) +#define CCI_ZERO_PAD_DISABLE_SFT 5 +#define CCI_ZERO_PAD_DISABLE_MASK 0x1 +#define CCI_ZERO_PAD_DISABLE_MASK_SFT (0x1 << 5) +#define CCI_AUD_SPLIT_TEST_EN_SFT 4 +#define CCI_AUD_SPLIT_TEST_EN_MASK 0x1 +#define CCI_AUD_SPLIT_TEST_EN_MASK_SFT (0x1 << 4) +#define CCI_AUD_SDM_MUTEL_SFT 3 +#define CCI_AUD_SDM_MUTEL_MASK 0x1 +#define CCI_AUD_SDM_MUTEL_MASK_SFT (0x1 << 3) +#define CCI_AUD_SDM_MUTER_SFT 2 +#define CCI_AUD_SDM_MUTER_MASK 0x1 +#define CCI_AUD_SDM_MUTER_MASK_SFT (0x1 << 2) +#define CCI_AUD_SDM_7BIT_SEL_SFT 1 +#define CCI_AUD_SDM_7BIT_SEL_MASK 0x1 +#define CCI_AUD_SDM_7BIT_SEL_MASK_SFT (0x1 << 1) +#define CCI_SCRAMBLER_EN_SFT 0 +#define CCI_SCRAMBLER_EN_MASK 0x1 +#define CCI_SCRAMBLER_EN_MASK_SFT (0x1 << 0) + +/* AFUNC_AUD_CON1 */ +#define AUD_SDM_TEST_L_SFT 8 +#define AUD_SDM_TEST_L_MASK 0xff +#define AUD_SDM_TEST_L_MASK_SFT (0xff << 8) +#define AUD_SDM_TEST_R_SFT 0 +#define AUD_SDM_TEST_R_MASK 0xff +#define AUD_SDM_TEST_R_MASK_SFT (0xff << 0) + +/* AFUNC_AUD_CON2 */ +#define CCI_AUD_DAC_ANA_MUTE_SFT 7 +#define CCI_AUD_DAC_ANA_MUTE_MASK 0x1 +#define CCI_AUD_DAC_ANA_MUTE_MASK_SFT (0x1 << 7) +#define CCI_AUD_DAC_ANA_RSTB_SEL_SFT 6 +#define CCI_AUD_DAC_ANA_RSTB_SEL_MASK 0x1 +#define CCI_AUD_DAC_ANA_RSTB_SEL_MASK_SFT (0x1 << 6) +#define CCI_AUDIO_FIFO_CLKIN_INV_SFT 4 +#define CCI_AUDIO_FIFO_CLKIN_INV_MASK 0x1 +#define CCI_AUDIO_FIFO_CLKIN_INV_MASK_SFT (0x1 << 4) +#define CCI_AUDIO_FIFO_ENABLE_SFT 3 +#define CCI_AUDIO_FIFO_ENABLE_MASK 0x1 +#define CCI_AUDIO_FIFO_ENABLE_MASK_SFT (0x1 << 3) +#define CCI_ACD_MODE_SFT 2 +#define CCI_ACD_MODE_MASK 0x1 +#define CCI_ACD_MODE_MASK_SFT (0x1 << 2) +#define CCI_AFIFO_CLK_PWDB_SFT 1 +#define CCI_AFIFO_CLK_PWDB_MASK 0x1 +#define CCI_AFIFO_CLK_PWDB_MASK_SFT (0x1 << 1) +#define CCI_ACD_FUNC_RSTB_SFT 0 +#define CCI_ACD_FUNC_RSTB_MASK 0x1 +#define CCI_ACD_FUNC_RSTB_MASK_SFT (0x1 << 0) + +/* AFUNC_AUD_CON3 */ +#define SDM_ANA13M_TESTCK_SEL_SFT 15 +#define SDM_ANA13M_TESTCK_SEL_MASK 0x1 +#define SDM_ANA13M_TESTCK_SEL_MASK_SFT (0x1 << 15) +#define SDM_ANA13M_TESTCK_SRC_SEL_SFT 12 +#define SDM_ANA13M_TESTCK_SRC_SEL_MASK 0x7 +#define SDM_ANA13M_TESTCK_SRC_SEL_MASK_SFT (0x7 << 12) +#define SDM_TESTCK_SRC_SEL_SFT 8 +#define SDM_TESTCK_SRC_SEL_MASK 0x7 +#define SDM_TESTCK_SRC_SEL_MASK_SFT (0x7 << 8) +#define DIGMIC_TESTCK_SRC_SEL_SFT 4 +#define DIGMIC_TESTCK_SRC_SEL_MASK 0x7 +#define DIGMIC_TESTCK_SRC_SEL_MASK_SFT (0x7 << 4) +#define DIGMIC_TESTCK_SEL_SFT 0 +#define DIGMIC_TESTCK_SEL_MASK 0x1 +#define DIGMIC_TESTCK_SEL_MASK_SFT (0x1 << 0) + +/* AFUNC_AUD_CON4 */ +#define UL_FIFO_WCLK_INV_SFT 8 +#define UL_FIFO_WCLK_INV_MASK 0x1 +#define UL_FIFO_WCLK_INV_MASK_SFT (0x1 << 8) +#define UL_FIFO_DIGMIC_WDATA_TESTSRC_SEL_SFT 6 +#define UL_FIFO_DIGMIC_WDATA_TESTSRC_SEL_MASK 0x1 +#define UL_FIFO_DIGMIC_WDATA_TESTSRC_SEL_MASK_SFT (0x1 << 6) +#define UL_FIFO_WDATA_TESTEN_SFT 5 +#define UL_FIFO_WDATA_TESTEN_MASK 0x1 +#define UL_FIFO_WDATA_TESTEN_MASK_SFT (0x1 << 5) +#define UL_FIFO_WDATA_TESTSRC_SEL_SFT 4 +#define UL_FIFO_WDATA_TESTSRC_SEL_MASK 0x1 +#define UL_FIFO_WDATA_TESTSRC_SEL_MASK_SFT (0x1 << 4) +#define UL_FIFO_WCLK_6P5M_TESTCK_SEL_SFT 3 +#define UL_FIFO_WCLK_6P5M_TESTCK_SEL_MASK 0x1 +#define UL_FIFO_WCLK_6P5M_TESTCK_SEL_MASK_SFT (0x1 << 3) +#define UL_FIFO_WCLK_6P5M_TESTCK_SRC_SEL_SFT 0 +#define UL_FIFO_WCLK_6P5M_TESTCK_SRC_SEL_MASK 0x7 +#define UL_FIFO_WCLK_6P5M_TESTCK_SRC_SEL_MASK_SFT (0x7 << 0) + +/* AFUNC_AUD_CON5 */ +#define R_AUD_DAC_POS_LARGE_MONO_SFT 8 +#define R_AUD_DAC_POS_LARGE_MONO_MASK 0xff +#define R_AUD_DAC_POS_LARGE_MONO_MASK_SFT (0xff << 8) +#define R_AUD_DAC_NEG_LARGE_MONO_SFT 0 +#define R_AUD_DAC_NEG_LARGE_MONO_MASK 0xff +#define R_AUD_DAC_NEG_LARGE_MONO_MASK_SFT (0xff << 0) + +/* AFUNC_AUD_CON6 */ +#define R_AUD_DAC_POS_SMALL_MONO_SFT 12 +#define R_AUD_DAC_POS_SMALL_MONO_MASK 0xf +#define R_AUD_DAC_POS_SMALL_MONO_MASK_SFT (0xf << 12) +#define R_AUD_DAC_NEG_SMALL_MONO_SFT 8 +#define R_AUD_DAC_NEG_SMALL_MONO_MASK 0xf +#define R_AUD_DAC_NEG_SMALL_MONO_MASK_SFT (0xf << 8) +#define R_AUD_DAC_POS_TINY_MONO_SFT 6 +#define R_AUD_DAC_POS_TINY_MONO_MASK 0x3 +#define R_AUD_DAC_POS_TINY_MONO_MASK_SFT (0x3 << 6) +#define R_AUD_DAC_NEG_TINY_MONO_SFT 4 +#define R_AUD_DAC_NEG_TINY_MONO_MASK 0x3 +#define R_AUD_DAC_NEG_TINY_MONO_MASK_SFT (0x3 << 4) +#define R_AUD_DAC_MONO_SEL_SFT 3 +#define R_AUD_DAC_MONO_SEL_MASK 0x1 +#define R_AUD_DAC_MONO_SEL_MASK_SFT (0x1 << 3) +#define R_AUD_DAC_3TH_SEL_SFT 1 +#define R_AUD_DAC_3TH_SEL_MASK 0x1 +#define R_AUD_DAC_3TH_SEL_MASK_SFT (0x1 << 1) +#define R_AUD_DAC_SW_RSTB_SFT 0 +#define R_AUD_DAC_SW_RSTB_MASK 0x1 +#define R_AUD_DAC_SW_RSTB_MASK_SFT (0x1 << 0) + +/* AFUNC_AUD_CON7 */ +#define UL2_DIGMIC_TESTCK_SRC_SEL_SFT 10 +#define UL2_DIGMIC_TESTCK_SRC_SEL_MASK 0x7 +#define UL2_DIGMIC_TESTCK_SRC_SEL_MASK_SFT (0x7 << 10) +#define UL2_DIGMIC_TESTCK_SEL_SFT 9 +#define UL2_DIGMIC_TESTCK_SEL_MASK 0x1 +#define UL2_DIGMIC_TESTCK_SEL_MASK_SFT (0x1 << 9) +#define UL2_FIFO_WCLK_INV_SFT 8 +#define UL2_FIFO_WCLK_INV_MASK 0x1 +#define UL2_FIFO_WCLK_INV_MASK_SFT (0x1 << 8) +#define UL2_FIFO_DIGMIC_WDATA_TESTSRC_SEL_SFT 6 +#define UL2_FIFO_DIGMIC_WDATA_TESTSRC_SEL_MASK 0x1 +#define UL2_FIFO_DIGMIC_WDATA_TESTSRC_SEL_MASK_SFT (0x1 << 6) +#define UL2_FIFO_WDATA_TESTEN_SFT 5 +#define UL2_FIFO_WDATA_TESTEN_MASK 0x1 +#define UL2_FIFO_WDATA_TESTEN_MASK_SFT (0x1 << 5) +#define UL2_FIFO_WDATA_TESTSRC_SEL_SFT 4 +#define UL2_FIFO_WDATA_TESTSRC_SEL_MASK 0x1 +#define UL2_FIFO_WDATA_TESTSRC_SEL_MASK_SFT (0x1 << 4) +#define UL2_FIFO_WCLK_6P5M_TESTCK_SEL_SFT 3 +#define UL2_FIFO_WCLK_6P5M_TESTCK_SEL_MASK 0x1 +#define UL2_FIFO_WCLK_6P5M_TESTCK_SEL_MASK_SFT (0x1 << 3) +#define UL2_FIFO_WCLK_6P5M_TESTCK_SRC_SEL_SFT 0 +#define UL2_FIFO_WCLK_6P5M_TESTCK_SRC_SEL_MASK 0x7 +#define UL2_FIFO_WCLK_6P5M_TESTCK_SRC_SEL_MASK_SFT (0x7 << 0) + +/* AFUNC_AUD_CON8 */ +#define SPLITTER2_DITHER_EN_SFT 9 +#define SPLITTER2_DITHER_EN_MASK 0x1 +#define SPLITTER2_DITHER_EN_MASK_SFT (0x1 << 9) +#define SPLITTER1_DITHER_EN_SFT 8 +#define SPLITTER1_DITHER_EN_MASK 0x1 +#define SPLITTER1_DITHER_EN_MASK_SFT (0x1 << 8) +#define SPLITTER2_DITHER_GAIN_SFT 4 +#define SPLITTER2_DITHER_GAIN_MASK 0xf +#define SPLITTER2_DITHER_GAIN_MASK_SFT (0xf << 4) +#define SPLITTER1_DITHER_GAIN_SFT 0 +#define SPLITTER1_DITHER_GAIN_MASK 0xf +#define SPLITTER1_DITHER_GAIN_MASK_SFT (0xf << 0) + +/* AFUNC_AUD_CON9 */ +#define CCI_AUD_ANACK_SEL_2ND_SFT 15 +#define CCI_AUD_ANACK_SEL_2ND_MASK 0x1 +#define CCI_AUD_ANACK_SEL_2ND_MASK_SFT (0x1 << 15) +#define CCI_AUDIO_FIFO_WPTR_2ND_SFT 12 +#define CCI_AUDIO_FIFO_WPTR_2ND_MASK 0x7 +#define CCI_AUDIO_FIFO_WPTR_2ND_MASK_SFT (0x7 << 12) +#define CCI_SCRAMBLER_CG_EN_2ND_SFT 11 +#define CCI_SCRAMBLER_CG_EN_2ND_MASK 0x1 +#define CCI_SCRAMBLER_CG_EN_2ND_MASK_SFT (0x1 << 11) +#define CCI_LCH_INV_2ND_SFT 10 +#define CCI_LCH_INV_2ND_MASK 0x1 +#define CCI_LCH_INV_2ND_MASK_SFT (0x1 << 10) +#define CCI_RAND_EN_2ND_SFT 9 +#define CCI_RAND_EN_2ND_MASK 0x1 +#define CCI_RAND_EN_2ND_MASK_SFT (0x1 << 9) +#define CCI_SPLT_SCRMB_CLK_ON_2ND_SFT 8 +#define CCI_SPLT_SCRMB_CLK_ON_2ND_MASK 0x1 +#define CCI_SPLT_SCRMB_CLK_ON_2ND_MASK_SFT (0x1 << 8) +#define CCI_SPLT_SCRMB_ON_2ND_SFT 7 +#define CCI_SPLT_SCRMB_ON_2ND_MASK 0x1 +#define CCI_SPLT_SCRMB_ON_2ND_MASK_SFT (0x1 << 7) +#define CCI_AUD_IDAC_TEST_EN_2ND_SFT 6 +#define CCI_AUD_IDAC_TEST_EN_2ND_MASK 0x1 +#define CCI_AUD_IDAC_TEST_EN_2ND_MASK_SFT (0x1 << 6) +#define CCI_ZERO_PAD_DISABLE_2ND_SFT 5 +#define CCI_ZERO_PAD_DISABLE_2ND_MASK 0x1 +#define CCI_ZERO_PAD_DISABLE_2ND_MASK_SFT (0x1 << 5) +#define CCI_AUD_SPLIT_TEST_EN_2ND_SFT 4 +#define CCI_AUD_SPLIT_TEST_EN_2ND_MASK 0x1 +#define CCI_AUD_SPLIT_TEST_EN_2ND_MASK_SFT (0x1 << 4) +#define CCI_AUD_SDM_MUTEL_2ND_SFT 3 +#define CCI_AUD_SDM_MUTEL_2ND_MASK 0x1 +#define CCI_AUD_SDM_MUTEL_2ND_MASK_SFT (0x1 << 3) +#define CCI_AUD_SDM_MUTER_2ND_SFT 2 +#define CCI_AUD_SDM_MUTER_2ND_MASK 0x1 +#define CCI_AUD_SDM_MUTER_2ND_MASK_SFT (0x1 << 2) +#define CCI_AUD_SDM_7BIT_SEL_2ND_SFT 1 +#define CCI_AUD_SDM_7BIT_SEL_2ND_MASK 0x1 +#define CCI_AUD_SDM_7BIT_SEL_2ND_MASK_SFT (0x1 << 1) +#define CCI_SCRAMBLER_EN_2ND_SFT 0 +#define CCI_SCRAMBLER_EN_2ND_MASK 0x1 +#define CCI_SCRAMBLER_EN_2ND_MASK_SFT (0x1 << 0) + +/* AFUNC_AUD_CON10 */ +#define AUD_SDM_TEST_L_2ND_SFT 8 +#define AUD_SDM_TEST_L_2ND_MASK 0xff +#define AUD_SDM_TEST_L_2ND_MASK_SFT (0xff << 8) +#define AUD_SDM_TEST_R_2ND_SFT 0 +#define AUD_SDM_TEST_R_2ND_MASK 0xff +#define AUD_SDM_TEST_R_2ND_MASK_SFT (0xff << 0) + +/* AFUNC_AUD_CON11 */ +#define CCI_AUD_DAC_ANA_MUTE_2ND_SFT 7 +#define CCI_AUD_DAC_ANA_MUTE_2ND_MASK 0x1 +#define CCI_AUD_DAC_ANA_MUTE_2ND_MASK_SFT (0x1 << 7) +#define CCI_AUD_DAC_ANA_RSTB_SEL_2ND_SFT 6 +#define CCI_AUD_DAC_ANA_RSTB_SEL_2ND_MASK 0x1 +#define CCI_AUD_DAC_ANA_RSTB_SEL_2ND_MASK_SFT (0x1 << 6) +#define CCI_AUDIO_FIFO_CLKIN_INV_2ND_SFT 4 +#define CCI_AUDIO_FIFO_CLKIN_INV_2ND_MASK 0x1 +#define CCI_AUDIO_FIFO_CLKIN_INV_2ND_MASK_SFT (0x1 << 4) +#define CCI_AUDIO_FIFO_ENABLE_2ND_SFT 3 +#define CCI_AUDIO_FIFO_ENABLE_2ND_MASK 0x1 +#define CCI_AUDIO_FIFO_ENABLE_2ND_MASK_SFT (0x1 << 3) +#define CCI_ACD_MODE_2ND_SFT 2 +#define CCI_ACD_MODE_2ND_MASK 0x1 +#define CCI_ACD_MODE_2ND_MASK_SFT (0x1 << 2) +#define CCI_AFIFO_CLK_PWDB_2ND_SFT 1 +#define CCI_AFIFO_CLK_PWDB_2ND_MASK 0x1 +#define CCI_AFIFO_CLK_PWDB_2ND_MASK_SFT (0x1 << 1) +#define CCI_ACD_FUNC_RSTB_2ND_SFT 0 +#define CCI_ACD_FUNC_RSTB_2ND_MASK 0x1 +#define CCI_ACD_FUNC_RSTB_2ND_MASK_SFT (0x1 << 0) + +/* AFUNC_AUD_CON12 */ +#define SPLITTER2_DITHER_EN_2ND_SFT 9 +#define SPLITTER2_DITHER_EN_2ND_MASK 0x1 +#define SPLITTER2_DITHER_EN_2ND_MASK_SFT (0x1 << 9) +#define SPLITTER1_DITHER_EN_2ND_SFT 8 +#define SPLITTER1_DITHER_EN_2ND_MASK 0x1 +#define SPLITTER1_DITHER_EN_2ND_MASK_SFT (0x1 << 8) +#define SPLITTER2_DITHER_GAIN_2ND_SFT 4 +#define SPLITTER2_DITHER_GAIN_2ND_MASK 0xf +#define SPLITTER2_DITHER_GAIN_2ND_MASK_SFT (0xf << 4) +#define SPLITTER1_DITHER_GAIN_2ND_SFT 0 +#define SPLITTER1_DITHER_GAIN_2ND_MASK 0xf +#define SPLITTER1_DITHER_GAIN_2ND_MASK_SFT (0xf << 0) + +/* AFUNC_AUD_MON0 */ +#define AUD_SCR_OUT_L_SFT 8 +#define AUD_SCR_OUT_L_MASK 0xff +#define AUD_SCR_OUT_L_MASK_SFT (0xff << 8) +#define AUD_SCR_OUT_R_SFT 0 +#define AUD_SCR_OUT_R_MASK 0xff +#define AUD_SCR_OUT_R_MASK_SFT (0xff << 0) + +/* AFUNC_AUD_MON1 */ +#define AUD_SCR_OUT_L_2ND_SFT 8 +#define AUD_SCR_OUT_L_2ND_MASK 0xff +#define AUD_SCR_OUT_L_2ND_MASK_SFT (0xff << 8) +#define AUD_SCR_OUT_R_2ND_SFT 0 +#define AUD_SCR_OUT_R_2ND_MASK 0xff +#define AUD_SCR_OUT_R_2ND_MASK_SFT (0xff << 0) + +/* AUDRC_TUNE_MON0 */ +#define ASYNC_TEST_OUT_BCK_SFT 15 +#define ASYNC_TEST_OUT_BCK_MASK 0x1 +#define ASYNC_TEST_OUT_BCK_MASK_SFT (0x1 << 15) +#define RGS_AUDRCTUNE1READ_SFT 8 +#define RGS_AUDRCTUNE1READ_MASK 0x1f +#define RGS_AUDRCTUNE1READ_MASK_SFT (0x1f << 8) +#define RGS_AUDRCTUNE0READ_SFT 0 +#define RGS_AUDRCTUNE0READ_MASK 0x1f +#define RGS_AUDRCTUNE0READ_MASK_SFT (0x1f << 0) + +/* AFE_ADDA_MTKAIF_FIFO_CFG0 */ +#define AFE_RESERVED_SFT 1 +#define AFE_RESERVED_MASK 0x7fff +#define AFE_RESERVED_MASK_SFT (0x7fff << 1) +#define RG_MTKAIF_RXIF_FIFO_INTEN_SFT 0 +#define RG_MTKAIF_RXIF_FIFO_INTEN_MASK 0x1 +#define RG_MTKAIF_RXIF_FIFO_INTEN_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_MTKAIF_FIFO_LOG_MON1 */ +#define MTKAIF_RXIF_WR_FULL_STATUS_SFT 1 +#define MTKAIF_RXIF_WR_FULL_STATUS_MASK 0x1 +#define MTKAIF_RXIF_WR_FULL_STATUS_MASK_SFT (0x1 << 1) +#define MTKAIF_RXIF_RD_EMPTY_STATUS_SFT 0 +#define MTKAIF_RXIF_RD_EMPTY_STATUS_MASK 0x1 +#define MTKAIF_RXIF_RD_EMPTY_STATUS_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_MTKAIF_MON0 */ +#define MTKAIFTX_V3_SYNC_OUT_SFT 15 +#define MTKAIFTX_V3_SYNC_OUT_MASK 0x1 +#define MTKAIFTX_V3_SYNC_OUT_MASK_SFT (0x1 << 15) +#define MTKAIFTX_V3_SDATA_OUT3_SFT 14 +#define MTKAIFTX_V3_SDATA_OUT3_MASK 0x1 +#define MTKAIFTX_V3_SDATA_OUT3_MASK_SFT (0x1 << 14) +#define MTKAIFTX_V3_SDATA_OUT2_SFT 13 +#define MTKAIFTX_V3_SDATA_OUT2_MASK 0x1 +#define MTKAIFTX_V3_SDATA_OUT2_MASK_SFT (0x1 << 13) +#define MTKAIFTX_V3_SDATA_OUT1_SFT 12 +#define MTKAIFTX_V3_SDATA_OUT1_MASK 0x1 +#define MTKAIFTX_V3_SDATA_OUT1_MASK_SFT (0x1 << 12) +#define MTKAIF_RXIF_FIFO_STATUS_SFT 0 +#define MTKAIF_RXIF_FIFO_STATUS_MASK 0xfff +#define MTKAIF_RXIF_FIFO_STATUS_MASK_SFT (0xfff << 0) + +/* AFE_ADDA_MTKAIF_MON1 */ +#define MTKAIFRX_V3_SYNC_IN_SFT 15 +#define MTKAIFRX_V3_SYNC_IN_MASK 0x1 +#define MTKAIFRX_V3_SYNC_IN_MASK_SFT (0x1 << 15) +#define MTKAIFRX_V3_SDATA_IN3_SFT 14 +#define MTKAIFRX_V3_SDATA_IN3_MASK 0x1 +#define MTKAIFRX_V3_SDATA_IN3_MASK_SFT (0x1 << 14) +#define MTKAIFRX_V3_SDATA_IN2_SFT 13 +#define MTKAIFRX_V3_SDATA_IN2_MASK 0x1 +#define MTKAIFRX_V3_SDATA_IN2_MASK_SFT (0x1 << 13) +#define MTKAIFRX_V3_SDATA_IN1_SFT 12 +#define MTKAIFRX_V3_SDATA_IN1_MASK 0x1 +#define MTKAIFRX_V3_SDATA_IN1_MASK_SFT (0x1 << 12) +#define MTKAIF_RXIF_SEARCH_FAIL_FLAG_SFT 11 +#define MTKAIF_RXIF_SEARCH_FAIL_FLAG_MASK 0x1 +#define MTKAIF_RXIF_SEARCH_FAIL_FLAG_MASK_SFT (0x1 << 11) +#define MTKAIF_RXIF_INVALID_FLAG_SFT 8 +#define MTKAIF_RXIF_INVALID_FLAG_MASK 0x1 +#define MTKAIF_RXIF_INVALID_FLAG_MASK_SFT (0x1 << 8) +#define MTKAIF_RXIF_INVALID_CYCLE_SFT 0 +#define MTKAIF_RXIF_INVALID_CYCLE_MASK 0xff +#define MTKAIF_RXIF_INVALID_CYCLE_MASK_SFT (0xff << 0) + +/* AFE_ADDA_MTKAIF_MON2 */ +#define MTKAIF_TXIF_IN_CH2_SFT 8 +#define MTKAIF_TXIF_IN_CH2_MASK 0xff +#define MTKAIF_TXIF_IN_CH2_MASK_SFT (0xff << 8) +#define MTKAIF_TXIF_IN_CH1_SFT 0 +#define MTKAIF_TXIF_IN_CH1_MASK 0xff +#define MTKAIF_TXIF_IN_CH1_MASK_SFT (0xff << 0) + +/* AFE_ADDA6_MTKAIF_MON3 */ +#define ADDA6_MTKAIF_TXIF_IN_CH2_SFT 8 +#define ADDA6_MTKAIF_TXIF_IN_CH2_MASK 0xff +#define ADDA6_MTKAIF_TXIF_IN_CH2_MASK_SFT (0xff << 8) +#define ADDA6_MTKAIF_TXIF_IN_CH1_SFT 0 +#define ADDA6_MTKAIF_TXIF_IN_CH1_MASK 0xff +#define ADDA6_MTKAIF_TXIF_IN_CH1_MASK_SFT (0xff << 0) + +/* AFE_ADDA_MTKAIF_MON4 */ +#define MTKAIF_RXIF_OUT_CH2_SFT 8 +#define MTKAIF_RXIF_OUT_CH2_MASK 0xff +#define MTKAIF_RXIF_OUT_CH2_MASK_SFT (0xff << 8) +#define MTKAIF_RXIF_OUT_CH1_SFT 0 +#define MTKAIF_RXIF_OUT_CH1_MASK 0xff +#define MTKAIF_RXIF_OUT_CH1_MASK_SFT (0xff << 0) + +/* AFE_ADDA_MTKAIF_MON5 */ +#define MTKAIF_RXIF_OUT_CH3_SFT 0 +#define MTKAIF_RXIF_OUT_CH3_MASK 0xff +#define MTKAIF_RXIF_OUT_CH3_MASK_SFT (0xff << 0) + +/* AFE_ADDA_MTKAIF_CFG0 */ +#define RG_MTKAIF_RXIF_CLKINV_SFT 15 +#define RG_MTKAIF_RXIF_CLKINV_MASK 0x1 +#define RG_MTKAIF_RXIF_CLKINV_MASK_SFT (0x1 << 15) +#define RG_ADDA6_MTKAIF_TXIF_PROTOCOL2_SFT 9 +#define RG_ADDA6_MTKAIF_TXIF_PROTOCOL2_MASK 0x1 +#define RG_ADDA6_MTKAIF_TXIF_PROTOCOL2_MASK_SFT (0x1 << 9) +#define RG_MTKAIF_RXIF_PROTOCOL2_SFT 8 +#define RG_MTKAIF_RXIF_PROTOCOL2_MASK 0x1 +#define RG_MTKAIF_RXIF_PROTOCOL2_MASK_SFT (0x1 << 8) +#define RG_MTKAIF_BYPASS_SRC_MODE_SFT 6 +#define RG_MTKAIF_BYPASS_SRC_MODE_MASK 0x3 +#define RG_MTKAIF_BYPASS_SRC_MODE_MASK_SFT (0x3 << 6) +#define RG_MTKAIF_BYPASS_SRC_TEST_SFT 5 +#define RG_MTKAIF_BYPASS_SRC_TEST_MASK 0x1 +#define RG_MTKAIF_BYPASS_SRC_TEST_MASK_SFT (0x1 << 5) +#define RG_MTKAIF_TXIF_PROTOCOL2_SFT 4 +#define RG_MTKAIF_TXIF_PROTOCOL2_MASK 0x1 +#define RG_MTKAIF_TXIF_PROTOCOL2_MASK_SFT (0x1 << 4) +#define RG_ADDA6_MTKAIF_PMIC_TXIF_8TO5_SFT 3 +#define RG_ADDA6_MTKAIF_PMIC_TXIF_8TO5_MASK 0x1 +#define RG_ADDA6_MTKAIF_PMIC_TXIF_8TO5_MASK_SFT (0x1 << 3) +#define RG_MTKAIF_PMIC_TXIF_8TO5_SFT 2 +#define RG_MTKAIF_PMIC_TXIF_8TO5_MASK 0x1 +#define RG_MTKAIF_PMIC_TXIF_8TO5_MASK_SFT (0x1 << 2) +#define RG_MTKAIF_LOOPBACK_TEST2_SFT 1 +#define RG_MTKAIF_LOOPBACK_TEST2_MASK 0x1 +#define RG_MTKAIF_LOOPBACK_TEST2_MASK_SFT (0x1 << 1) +#define RG_MTKAIF_LOOPBACK_TEST1_SFT 0 +#define RG_MTKAIF_LOOPBACK_TEST1_MASK 0x1 +#define RG_MTKAIF_LOOPBACK_TEST1_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_MTKAIF_RX_CFG0 */ +#define RG_MTKAIF_RXIF_VOICE_MODE_SFT 12 +#define RG_MTKAIF_RXIF_VOICE_MODE_MASK 0xf +#define RG_MTKAIF_RXIF_VOICE_MODE_MASK_SFT (0xf << 12) +#define RG_MTKAIF_RXIF_DATA_BIT_SFT 8 +#define RG_MTKAIF_RXIF_DATA_BIT_MASK 0x7 +#define RG_MTKAIF_RXIF_DATA_BIT_MASK_SFT (0x7 << 8) +#define RG_MTKAIF_RXIF_FIFO_RSP_SFT 4 +#define RG_MTKAIF_RXIF_FIFO_RSP_MASK 0x7 +#define RG_MTKAIF_RXIF_FIFO_RSP_MASK_SFT (0x7 << 4) +#define RG_MTKAIF_RXIF_DETECT_ON_SFT 3 +#define RG_MTKAIF_RXIF_DETECT_ON_MASK 0x1 +#define RG_MTKAIF_RXIF_DETECT_ON_MASK_SFT (0x1 << 3) +#define RG_MTKAIF_RXIF_DATA_MODE_SFT 0 +#define RG_MTKAIF_RXIF_DATA_MODE_MASK 0x1 +#define RG_MTKAIF_RXIF_DATA_MODE_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_MTKAIF_RX_CFG1 */ +#define RG_MTKAIF_RXIF_SYNC_SEARCH_TABLE_SFT 12 +#define RG_MTKAIF_RXIF_SYNC_SEARCH_TABLE_MASK 0xf +#define RG_MTKAIF_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0xf << 12) +#define RG_MTKAIF_RXIF_INVALID_SYNC_CHECK_ROUND_SFT 8 +#define RG_MTKAIF_RXIF_INVALID_SYNC_CHECK_ROUND_MASK 0xf +#define RG_MTKAIF_RXIF_INVALID_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8) +#define RG_MTKAIF_RXIF_SYNC_CHECK_ROUND_SFT 4 +#define RG_MTKAIF_RXIF_SYNC_CHECK_ROUND_MASK 0xf +#define RG_MTKAIF_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4) +#define RG_MTKAIF_RXIF_VOICE_MODE_PROTOCOL2_SFT 0 +#define RG_MTKAIF_RXIF_VOICE_MODE_PROTOCOL2_MASK 0xf +#define RG_MTKAIF_RXIF_VOICE_MODE_PROTOCOL2_MASK_SFT (0xf << 0) + +/* AFE_ADDA_MTKAIF_RX_CFG2 */ +#define RG_MTKAIF_RXIF_P2_INPUT_SEL_SFT 15 +#define RG_MTKAIF_RXIF_P2_INPUT_SEL_MASK 0x1 +#define RG_MTKAIF_RXIF_P2_INPUT_SEL_MASK_SFT (0x1 << 15) +#define RG_MTKAIF_RXIF_SYNC_WORD2_DISABLE_SFT 14 +#define RG_MTKAIF_RXIF_SYNC_WORD2_DISABLE_MASK 0x1 +#define RG_MTKAIF_RXIF_SYNC_WORD2_DISABLE_MASK_SFT (0x1 << 14) +#define RG_MTKAIF_RXIF_SYNC_WORD1_DISABLE_SFT 13 +#define RG_MTKAIF_RXIF_SYNC_WORD1_DISABLE_MASK 0x1 +#define RG_MTKAIF_RXIF_SYNC_WORD1_DISABLE_MASK_SFT (0x1 << 13) +#define RG_MTKAIF_RXIF_CLEAR_SYNC_FAIL_SFT 12 +#define RG_MTKAIF_RXIF_CLEAR_SYNC_FAIL_MASK 0x1 +#define RG_MTKAIF_RXIF_CLEAR_SYNC_FAIL_MASK_SFT (0x1 << 12) +#define RG_MTKAIF_RXIF_SYNC_CNT_TABLE_SFT 0 +#define RG_MTKAIF_RXIF_SYNC_CNT_TABLE_MASK 0xfff +#define RG_MTKAIF_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 0) + +/* AFE_ADDA_MTKAIF_RX_CFG3 */ +#define RG_MTKAIF_RXIF_LOOPBACK_USE_NLE_SFT 7 +#define RG_MTKAIF_RXIF_LOOPBACK_USE_NLE_MASK 0x1 +#define RG_MTKAIF_RXIF_LOOPBACK_USE_NLE_MASK_SFT (0x1 << 7) +#define RG_MTKAIF_RXIF_FIFO_RSP_PROTOCOL2_SFT 4 +#define RG_MTKAIF_RXIF_FIFO_RSP_PROTOCOL2_MASK 0x7 +#define RG_MTKAIF_RXIF_FIFO_RSP_PROTOCOL2_MASK_SFT (0x7 << 4) +#define RG_MTKAIF_RXIF_DETECT_ON_PROTOCOL2_SFT 3 +#define RG_MTKAIF_RXIF_DETECT_ON_PROTOCOL2_MASK 0x1 +#define RG_MTKAIF_RXIF_DETECT_ON_PROTOCOL2_MASK_SFT (0x1 << 3) + +/* AFE_ADDA_MTKAIF_SYNCWORD_CFG0 */ +#define RG_MTKAIF_RX_SYNC_WORD2_SFT 4 +#define RG_MTKAIF_RX_SYNC_WORD2_MASK 0x7 +#define RG_MTKAIF_RX_SYNC_WORD2_MASK_SFT (0x7 << 4) +#define RG_MTKAIF_RX_SYNC_WORD1_SFT 0 +#define RG_MTKAIF_RX_SYNC_WORD1_MASK 0x7 +#define RG_MTKAIF_RX_SYNC_WORD1_MASK_SFT (0x7 << 0) + +/* AFE_ADDA_MTKAIF_SYNCWORD_CFG1 */ +#define RG_ADDA6_MTKAIF_TX_SYNC_WORD2_SFT 12 +#define RG_ADDA6_MTKAIF_TX_SYNC_WORD2_MASK 0x7 +#define RG_ADDA6_MTKAIF_TX_SYNC_WORD2_MASK_SFT (0x7 << 12) +#define RG_ADDA6_MTKAIF_TX_SYNC_WORD1_SFT 8 +#define RG_ADDA6_MTKAIF_TX_SYNC_WORD1_MASK 0x7 +#define RG_ADDA6_MTKAIF_TX_SYNC_WORD1_MASK_SFT (0x7 << 8) +#define RG_ADDA_MTKAIF_TX_SYNC_WORD2_SFT 4 +#define RG_ADDA_MTKAIF_TX_SYNC_WORD2_MASK 0x7 +#define RG_ADDA_MTKAIF_TX_SYNC_WORD2_MASK_SFT (0x7 << 4) +#define RG_ADDA_MTKAIF_TX_SYNC_WORD1_SFT 0 +#define RG_ADDA_MTKAIF_TX_SYNC_WORD1_MASK 0x7 +#define RG_ADDA_MTKAIF_TX_SYNC_WORD1_MASK_SFT (0x7 << 0) + +/* AFE_SGEN_CFG0 */ +#define SGEN_AMP_DIV_CH1_CTL_SFT 12 +#define SGEN_AMP_DIV_CH1_CTL_MASK 0xf +#define SGEN_AMP_DIV_CH1_CTL_MASK_SFT (0xf << 12) +#define SGEN_DAC_EN_CTL_SFT 7 +#define SGEN_DAC_EN_CTL_MASK 0x1 +#define SGEN_DAC_EN_CTL_MASK_SFT (0x1 << 7) +#define SGEN_MUTE_SW_CTL_SFT 6 +#define SGEN_MUTE_SW_CTL_MASK 0x1 +#define SGEN_MUTE_SW_CTL_MASK_SFT (0x1 << 6) +#define R_AUD_SDM_MUTE_L_SFT 5 +#define R_AUD_SDM_MUTE_L_MASK 0x1 +#define R_AUD_SDM_MUTE_L_MASK_SFT (0x1 << 5) +#define R_AUD_SDM_MUTE_R_SFT 4 +#define R_AUD_SDM_MUTE_R_MASK 0x1 +#define R_AUD_SDM_MUTE_R_MASK_SFT (0x1 << 4) +#define R_AUD_SDM_MUTE_L_2ND_SFT 3 +#define R_AUD_SDM_MUTE_L_2ND_MASK 0x1 +#define R_AUD_SDM_MUTE_L_2ND_MASK_SFT (0x1 << 3) +#define R_AUD_SDM_MUTE_R_2ND_SFT 2 +#define R_AUD_SDM_MUTE_R_2ND_MASK 0x1 +#define R_AUD_SDM_MUTE_R_2ND_MASK_SFT (0x1 << 2) + +/* AFE_SGEN_CFG1 */ +#define C_SGEN_RCH_INV_5BIT_SFT 15 +#define C_SGEN_RCH_INV_5BIT_MASK 0x1 +#define C_SGEN_RCH_INV_5BIT_MASK_SFT (0x1 << 15) +#define C_SGEN_RCH_INV_8BIT_SFT 14 +#define C_SGEN_RCH_INV_8BIT_MASK 0x1 +#define C_SGEN_RCH_INV_8BIT_MASK_SFT (0x1 << 14) +#define SGEN_FREQ_DIV_CH1_CTL_SFT 0 +#define SGEN_FREQ_DIV_CH1_CTL_MASK 0x1f +#define SGEN_FREQ_DIV_CH1_CTL_MASK_SFT (0x1f << 0) + +/* AFE_ADC_ASYNC_FIFO_CFG */ +#define RG_UL_ASYNC_FIFO_SOFT_RST_EN_SFT 5 +#define RG_UL_ASYNC_FIFO_SOFT_RST_EN_MASK 0x1 +#define RG_UL_ASYNC_FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 5) +#define RG_UL_ASYNC_FIFO_SOFT_RST_SFT 4 +#define RG_UL_ASYNC_FIFO_SOFT_RST_MASK 0x1 +#define RG_UL_ASYNC_FIFO_SOFT_RST_MASK_SFT (0x1 << 4) +#define RG_AMIC_UL_ADC_CLK_SEL_SFT 1 +#define RG_AMIC_UL_ADC_CLK_SEL_MASK 0x1 +#define RG_AMIC_UL_ADC_CLK_SEL_MASK_SFT (0x1 << 1) + +/* AFE_ADC_ASYNC_FIFO_CFG1 */ +#define RG_UL2_ASYNC_FIFO_SOFT_RST_EN_SFT 5 +#define RG_UL2_ASYNC_FIFO_SOFT_RST_EN_MASK 0x1 +#define RG_UL2_ASYNC_FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 5) +#define RG_UL2_ASYNC_FIFO_SOFT_RST_SFT 4 +#define RG_UL2_ASYNC_FIFO_SOFT_RST_MASK 0x1 +#define RG_UL2_ASYNC_FIFO_SOFT_RST_MASK_SFT (0x1 << 4) + +/* AFE_DCCLK_CFG0 */ +#define DCCLK_DIV_SFT 5 +#define DCCLK_DIV_MASK 0x7ff +#define DCCLK_DIV_MASK_SFT (0x7ff << 5) +#define DCCLK_INV_SFT 4 +#define DCCLK_INV_MASK 0x1 +#define DCCLK_INV_MASK_SFT (0x1 << 4) +#define DCCLK_REF_CK_SEL_SFT 2 +#define DCCLK_REF_CK_SEL_MASK 0x3 +#define DCCLK_REF_CK_SEL_MASK_SFT (0x3 << 2) +#define DCCLK_PDN_SFT 1 +#define DCCLK_PDN_MASK 0x1 +#define DCCLK_PDN_MASK_SFT (0x1 << 1) +#define DCCLK_GEN_ON_SFT 0 +#define DCCLK_GEN_ON_MASK 0x1 +#define DCCLK_GEN_ON_MASK_SFT (0x1 << 0) + +/* AFE_DCCLK_CFG1 */ +#define RESYNC_SRC_SEL_SFT 10 +#define RESYNC_SRC_SEL_MASK 0x3 +#define RESYNC_SRC_SEL_MASK_SFT (0x3 << 10) +#define RESYNC_SRC_CK_INV_SFT 9 +#define RESYNC_SRC_CK_INV_MASK 0x1 +#define RESYNC_SRC_CK_INV_MASK_SFT (0x1 << 9) +#define DCCLK_RESYNC_BYPASS_SFT 8 +#define DCCLK_RESYNC_BYPASS_MASK 0x1 +#define DCCLK_RESYNC_BYPASS_MASK_SFT (0x1 << 8) +#define DCCLK_PHASE_SEL_SFT 4 +#define DCCLK_PHASE_SEL_MASK 0xf +#define DCCLK_PHASE_SEL_MASK_SFT (0xf << 4) + +/* AUDIO_DIG_CFG */ +#define RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_SFT 15 +#define RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK 0x1 +#define RG_AUD_PAD_TOP_DAT_MISO2_LOOPBACK_MASK_SFT (0x1 << 15) +#define RG_AUD_PAD_TOP_PHASE_MODE2_SFT 8 +#define RG_AUD_PAD_TOP_PHASE_MODE2_MASK 0x7f +#define RG_AUD_PAD_TOP_PHASE_MODE2_MASK_SFT (0x7f << 8) +#define RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_SFT 7 +#define RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK 0x1 +#define RG_AUD_PAD_TOP_DAT_MISO_LOOPBACK_MASK_SFT (0x1 << 7) +#define RG_AUD_PAD_TOP_PHASE_MODE_SFT 0 +#define RG_AUD_PAD_TOP_PHASE_MODE_MASK 0x7f +#define RG_AUD_PAD_TOP_PHASE_MODE_MASK_SFT (0x7f << 0) + +/* AUDIO_DIG_CFG1 */ +#define RG_AUD_PAD_TOP_DAT_MISO3_LOOPBACK_SFT 7 +#define RG_AUD_PAD_TOP_DAT_MISO3_LOOPBACK_MASK 0x1 +#define RG_AUD_PAD_TOP_DAT_MISO3_LOOPBACK_MASK_SFT (0x1 << 7) +#define RG_AUD_PAD_TOP_PHASE_MODE3_SFT 0 +#define RG_AUD_PAD_TOP_PHASE_MODE3_MASK 0x7f +#define RG_AUD_PAD_TOP_PHASE_MODE3_MASK_SFT (0x7f << 0) + +/* AFE_AUD_PAD_TOP */ +#define RG_AUD_PAD_TOP_TX_FIFO_RSP_SFT 12 +#define RG_AUD_PAD_TOP_TX_FIFO_RSP_MASK 0x7 +#define RG_AUD_PAD_TOP_TX_FIFO_RSP_MASK_SFT (0x7 << 12) +#define RG_AUD_PAD_TOP_MTKAIF_CLK_PROTOCOL2_SFT 11 +#define RG_AUD_PAD_TOP_MTKAIF_CLK_PROTOCOL2_MASK 0x1 +#define RG_AUD_PAD_TOP_MTKAIF_CLK_PROTOCOL2_MASK_SFT (0x1 << 11) +#define RG_AUD_PAD_TOP_TX_FIFO_ON_SFT 8 +#define RG_AUD_PAD_TOP_TX_FIFO_ON_MASK 0x1 +#define RG_AUD_PAD_TOP_TX_FIFO_ON_MASK_SFT (0x1 << 8) + +/* AFE_AUD_PAD_TOP_MON */ +#define ADDA_AUD_PAD_TOP_MON_SFT 0 +#define ADDA_AUD_PAD_TOP_MON_MASK 0xffff +#define ADDA_AUD_PAD_TOP_MON_MASK_SFT (0xffff << 0) + +/* AFE_AUD_PAD_TOP_MON1 */ +#define ADDA_AUD_PAD_TOP_MON1_SFT 0 +#define ADDA_AUD_PAD_TOP_MON1_MASK 0xffff +#define ADDA_AUD_PAD_TOP_MON1_MASK_SFT (0xffff << 0) + +/* AFE_AUD_PAD_TOP_MON2 */ +#define ADDA_AUD_PAD_TOP_MON2_SFT 0 +#define ADDA_AUD_PAD_TOP_MON2_MASK 0xffff +#define ADDA_AUD_PAD_TOP_MON2_MASK_SFT (0xffff << 0) + +/* AFE_DL_NLE_CFG */ +#define NLE_RCH_HPGAIN_SEL_SFT 10 +#define NLE_RCH_HPGAIN_SEL_MASK 0x1 +#define NLE_RCH_HPGAIN_SEL_MASK_SFT (0x1 << 10) +#define NLE_RCH_CH_SEL_SFT 9 +#define NLE_RCH_CH_SEL_MASK 0x1 +#define NLE_RCH_CH_SEL_MASK_SFT (0x1 << 9) +#define NLE_RCH_ON_SFT 8 +#define NLE_RCH_ON_MASK 0x1 +#define NLE_RCH_ON_MASK_SFT (0x1 << 8) +#define NLE_LCH_HPGAIN_SEL_SFT 2 +#define NLE_LCH_HPGAIN_SEL_MASK 0x1 +#define NLE_LCH_HPGAIN_SEL_MASK_SFT (0x1 << 2) +#define NLE_LCH_CH_SEL_SFT 1 +#define NLE_LCH_CH_SEL_MASK 0x1 +#define NLE_LCH_CH_SEL_MASK_SFT (0x1 << 1) +#define NLE_LCH_ON_SFT 0 +#define NLE_LCH_ON_MASK 0x1 +#define NLE_LCH_ON_MASK_SFT (0x1 << 0) + +/* AFE_DL_NLE_MON */ +#define NLE_MONITOR_SFT 0 +#define NLE_MONITOR_MASK 0x3fff +#define NLE_MONITOR_MASK_SFT (0x3fff << 0) + +/* AFE_CG_EN_MON */ +#define CK_CG_EN_MON_SFT 0 +#define CK_CG_EN_MON_MASK 0x3f +#define CK_CG_EN_MON_MASK_SFT (0x3f << 0) + +/* AFE_MIC_ARRAY_CFG */ +#define RG_AMIC_ADC1_SOURCE_SEL_SFT 10 +#define RG_AMIC_ADC1_SOURCE_SEL_MASK 0x3 +#define RG_AMIC_ADC1_SOURCE_SEL_MASK_SFT (0x3 << 10) +#define RG_AMIC_ADC2_SOURCE_SEL_SFT 8 +#define RG_AMIC_ADC2_SOURCE_SEL_MASK 0x3 +#define RG_AMIC_ADC2_SOURCE_SEL_MASK_SFT (0x3 << 8) +#define RG_AMIC_ADC3_SOURCE_SEL_SFT 6 +#define RG_AMIC_ADC3_SOURCE_SEL_MASK 0x3 +#define RG_AMIC_ADC3_SOURCE_SEL_MASK_SFT (0x3 << 6) +#define RG_DMIC_ADC1_SOURCE_SEL_SFT 4 +#define RG_DMIC_ADC1_SOURCE_SEL_MASK 0x3 +#define RG_DMIC_ADC1_SOURCE_SEL_MASK_SFT (0x3 << 4) +#define RG_DMIC_ADC2_SOURCE_SEL_SFT 2 +#define RG_DMIC_ADC2_SOURCE_SEL_MASK 0x3 +#define RG_DMIC_ADC2_SOURCE_SEL_MASK_SFT (0x3 << 2) +#define RG_DMIC_ADC3_SOURCE_SEL_SFT 0 +#define RG_DMIC_ADC3_SOURCE_SEL_MASK 0x3 +#define RG_DMIC_ADC3_SOURCE_SEL_MASK_SFT (0x3 << 0) + +/* AFE_CHOP_CFG0 */ +#define RG_CHOP_DIV_SEL_SFT 4 +#define RG_CHOP_DIV_SEL_MASK 0x1f +#define RG_CHOP_DIV_SEL_MASK_SFT (0x1f << 4) +#define RG_CHOP_DIV_EN_SFT 0 +#define RG_CHOP_DIV_EN_MASK 0x1 +#define RG_CHOP_DIV_EN_MASK_SFT (0x1 << 0) + +/* AFE_MTKAIF_MUX_CFG */ +#define RG_ADDA6_EN_SEL_SFT 12 +#define RG_ADDA6_EN_SEL_MASK 0x1 +#define RG_ADDA6_EN_SEL_MASK_SFT (0x1 << 12) +#define RG_ADDA6_CH2_SEL_SFT 10 +#define RG_ADDA6_CH2_SEL_MASK 0x3 +#define RG_ADDA6_CH2_SEL_MASK_SFT (0x3 << 10) +#define RG_ADDA6_CH1_SEL_SFT 8 +#define RG_ADDA6_CH1_SEL_MASK 0x3 +#define RG_ADDA6_CH1_SEL_MASK_SFT (0x3 << 8) +#define RG_ADDA_EN_SEL_SFT 4 +#define RG_ADDA_EN_SEL_MASK 0x1 +#define RG_ADDA_EN_SEL_MASK_SFT (0x1 << 4) +#define RG_ADDA_CH2_SEL_SFT 2 +#define RG_ADDA_CH2_SEL_MASK 0x3 +#define RG_ADDA_CH2_SEL_MASK_SFT (0x3 << 2) +#define RG_ADDA_CH1_SEL_SFT 0 +#define RG_ADDA_CH1_SEL_MASK 0x3 +#define RG_ADDA_CH1_SEL_MASK_SFT (0x3 << 0) + +/* AFE_PMIC_NEWIF_CFG3 */ +#define RG_UP8X_SYNC_WORD_SFT 0 +#define RG_UP8X_SYNC_WORD_MASK 0xffff +#define RG_UP8X_SYNC_WORD_MASK_SFT (0xffff << 0) + +/* AFE_NCP_CFG0 */ +#define RG_NCP_CK1_VALID_CNT_SFT 9 +#define RG_NCP_CK1_VALID_CNT_MASK 0x7f +#define RG_NCP_CK1_VALID_CNT_MASK_SFT (0x7f << 9) +#define RG_NCP_ADITH_SFT 8 +#define RG_NCP_ADITH_MASK 0x1 +#define RG_NCP_ADITH_MASK_SFT (0x1 << 8) +#define RG_NCP_DITHER_EN_SFT 7 +#define RG_NCP_DITHER_EN_MASK 0x1 +#define RG_NCP_DITHER_EN_MASK_SFT (0x1 << 7) +#define RG_NCP_DITHER_FIXED_CK0_ACK1_2P_SFT 4 +#define RG_NCP_DITHER_FIXED_CK0_ACK1_2P_MASK 0x7 +#define RG_NCP_DITHER_FIXED_CK0_ACK1_2P_MASK_SFT (0x7 << 4) +#define RG_NCP_DITHER_FIXED_CK0_ACK2_2P_SFT 1 +#define RG_NCP_DITHER_FIXED_CK0_ACK2_2P_MASK 0x7 +#define RG_NCP_DITHER_FIXED_CK0_ACK2_2P_MASK_SFT (0x7 << 1) +#define RG_NCP_ON_SFT 0 +#define RG_NCP_ON_MASK 0x1 +#define RG_NCP_ON_MASK_SFT (0x1 << 0) + +/* AFE_NCP_CFG1 */ +#define RG_XY_VAL_CFG_EN_SFT 15 +#define RG_XY_VAL_CFG_EN_MASK 0x1 +#define RG_XY_VAL_CFG_EN_MASK_SFT (0x1 << 15) +#define RG_X_VAL_CFG_SFT 8 +#define RG_X_VAL_CFG_MASK 0x7f +#define RG_X_VAL_CFG_MASK_SFT (0x7f << 8) +#define RG_Y_VAL_CFG_SFT 0 +#define RG_Y_VAL_CFG_MASK 0x7f +#define RG_Y_VAL_CFG_MASK_SFT (0x7f << 0) + +/* AFE_NCP_CFG2 */ +#define RG_NCP_NONCLK_SET_SFT 1 +#define RG_NCP_NONCLK_SET_MASK 0x1 +#define RG_NCP_NONCLK_SET_MASK_SFT (0x1 << 1) +#define RG_NCP_PDDIS_EN_SFT 0 +#define RG_NCP_PDDIS_EN_MASK 0x1 +#define RG_NCP_PDDIS_EN_MASK_SFT (0x1 << 0) + +/* AUDENC_ANA_CON0 */ +#define RG_AUDPREAMPLON_SFT 0 +#define RG_AUDPREAMPLON_MASK 0x1 +#define RG_AUDPREAMPLON_MASK_SFT (0x1 << 0) +#define RG_AUDPREAMPLDCCEN_SFT 1 +#define RG_AUDPREAMPLDCCEN_MASK 0x1 +#define RG_AUDPREAMPLDCCEN_MASK_SFT (0x1 << 1) +#define RG_AUDPREAMPLDCPRECHARGE_SFT 2 +#define RG_AUDPREAMPLDCPRECHARGE_MASK 0x1 +#define RG_AUDPREAMPLDCPRECHARGE_MASK_SFT (0x1 << 2) +#define RG_AUDPREAMPLPGATEST_SFT 3 +#define RG_AUDPREAMPLPGATEST_MASK 0x1 +#define RG_AUDPREAMPLPGATEST_MASK_SFT (0x1 << 3) +#define RG_AUDPREAMPLVSCALE_SFT 4 +#define RG_AUDPREAMPLVSCALE_MASK 0x3 +#define RG_AUDPREAMPLVSCALE_MASK_SFT (0x3 << 4) +#define RG_AUDPREAMPLINPUTSEL_SFT 6 +#define RG_AUDPREAMPLINPUTSEL_MASK 0x3 +#define RG_AUDPREAMPLINPUTSEL_MASK_SFT (0x3 << 6) +#define RG_AUDPREAMPLGAIN_SFT 8 +#define RG_AUDPREAMPLGAIN_MASK 0x7 +#define RG_AUDPREAMPLGAIN_MASK_SFT (0x7 << 8) +#define RG_BULKL_VCM_EN_SFT 11 +#define RG_BULKL_VCM_EN_MASK 0x1 +#define RG_BULKL_VCM_EN_MASK_SFT (0x1 << 11) +#define RG_AUDADCLPWRUP_SFT 12 +#define RG_AUDADCLPWRUP_MASK 0x1 +#define RG_AUDADCLPWRUP_MASK_SFT (0x1 << 12) +#define RG_AUDADCLINPUTSEL_SFT 13 +#define RG_AUDADCLINPUTSEL_MASK 0x3 +#define RG_AUDADCLINPUTSEL_MASK_SFT (0x3 << 13) + +/* AUDENC_ANA_CON1 */ +#define RG_AUDPREAMPRON_SFT 0 +#define RG_AUDPREAMPRON_MASK 0x1 +#define RG_AUDPREAMPRON_MASK_SFT (0x1 << 0) +#define RG_AUDPREAMPRDCCEN_SFT 1 +#define RG_AUDPREAMPRDCCEN_MASK 0x1 +#define RG_AUDPREAMPRDCCEN_MASK_SFT (0x1 << 1) +#define RG_AUDPREAMPRDCPRECHARGE_SFT 2 +#define RG_AUDPREAMPRDCPRECHARGE_MASK 0x1 +#define RG_AUDPREAMPRDCPRECHARGE_MASK_SFT (0x1 << 2) +#define RG_AUDPREAMPRPGATEST_SFT 3 +#define RG_AUDPREAMPRPGATEST_MASK 0x1 +#define RG_AUDPREAMPRPGATEST_MASK_SFT (0x1 << 3) +#define RG_AUDPREAMPRVSCALE_SFT 4 +#define RG_AUDPREAMPRVSCALE_MASK 0x3 +#define RG_AUDPREAMPRVSCALE_MASK_SFT (0x3 << 4) +#define RG_AUDPREAMPRINPUTSEL_SFT 6 +#define RG_AUDPREAMPRINPUTSEL_MASK 0x3 +#define RG_AUDPREAMPRINPUTSEL_MASK_SFT (0x3 << 6) +#define RG_AUDPREAMPRGAIN_SFT 8 +#define RG_AUDPREAMPRGAIN_MASK 0x7 +#define RG_AUDPREAMPRGAIN_MASK_SFT (0x7 << 8) +#define RG_BULKR_VCM_EN_SFT 11 +#define RG_BULKR_VCM_EN_MASK 0x1 +#define RG_BULKR_VCM_EN_MASK_SFT (0x1 << 11) +#define RG_AUDADCRPWRUP_SFT 12 +#define RG_AUDADCRPWRUP_MASK 0x1 +#define RG_AUDADCRPWRUP_MASK_SFT (0x1 << 12) +#define RG_AUDADCRINPUTSEL_SFT 13 +#define RG_AUDADCRINPUTSEL_MASK 0x3 +#define RG_AUDADCRINPUTSEL_MASK_SFT (0x3 << 13) + +/* AUDENC_ANA_CON2 */ +#define RG_AUDPREAMP3ON_SFT 0 +#define RG_AUDPREAMP3ON_MASK 0x1 +#define RG_AUDPREAMP3ON_MASK_SFT (0x1 << 0) +#define RG_AUDPREAMP3DCCEN_SFT 1 +#define RG_AUDPREAMP3DCCEN_MASK 0x1 +#define RG_AUDPREAMP3DCCEN_MASK_SFT (0x1 << 1) +#define RG_AUDPREAMP3DCPRECHARGE_SFT 2 +#define RG_AUDPREAMP3DCPRECHARGE_MASK 0x1 +#define RG_AUDPREAMP3DCPRECHARGE_MASK_SFT (0x1 << 2) +#define RG_AUDPREAMP3PGATEST_SFT 3 +#define RG_AUDPREAMP3PGATEST_MASK 0x1 +#define RG_AUDPREAMP3PGATEST_MASK_SFT (0x1 << 3) +#define RG_AUDPREAMP3VSCALE_SFT 4 +#define RG_AUDPREAMP3VSCALE_MASK 0x3 +#define RG_AUDPREAMP3VSCALE_MASK_SFT (0x3 << 4) +#define RG_AUDPREAMP3INPUTSEL_SFT 6 +#define RG_AUDPREAMP3INPUTSEL_MASK 0x3 +#define RG_AUDPREAMP3INPUTSEL_MASK_SFT (0x3 << 6) +#define RG_AUDPREAMP3GAIN_SFT 8 +#define RG_AUDPREAMP3GAIN_MASK 0x7 +#define RG_AUDPREAMP3GAIN_MASK_SFT (0x7 << 8) +#define RG_BULK3_VCM_EN_SFT 11 +#define RG_BULK3_VCM_EN_MASK 0x1 +#define RG_BULK3_VCM_EN_MASK_SFT (0x1 << 11) +#define RG_AUDADC3PWRUP_SFT 12 +#define RG_AUDADC3PWRUP_MASK 0x1 +#define RG_AUDADC3PWRUP_MASK_SFT (0x1 << 12) +#define RG_AUDADC3INPUTSEL_SFT 13 +#define RG_AUDADC3INPUTSEL_MASK 0x3 +#define RG_AUDADC3INPUTSEL_MASK_SFT (0x3 << 13) + +/* AUDENC_ANA_CON3 */ +#define RG_AUDULHALFBIAS_SFT 0 +#define RG_AUDULHALFBIAS_MASK 0x1 +#define RG_AUDULHALFBIAS_MASK_SFT (0x1 << 0) +#define RG_AUDGLBVOWLPWEN_SFT 1 +#define RG_AUDGLBVOWLPWEN_MASK 0x1 +#define RG_AUDGLBVOWLPWEN_MASK_SFT (0x1 << 1) +#define RG_AUDPREAMPLPEN_SFT 2 +#define RG_AUDPREAMPLPEN_MASK 0x1 +#define RG_AUDPREAMPLPEN_MASK_SFT (0x1 << 2) +#define RG_AUDADC1STSTAGELPEN_SFT 3 +#define RG_AUDADC1STSTAGELPEN_MASK 0x1 +#define RG_AUDADC1STSTAGELPEN_MASK_SFT (0x1 << 3) +#define RG_AUDADC2NDSTAGELPEN_SFT 4 +#define RG_AUDADC2NDSTAGELPEN_MASK 0x1 +#define RG_AUDADC2NDSTAGELPEN_MASK_SFT (0x1 << 4) +#define RG_AUDADCFLASHLPEN_SFT 5 +#define RG_AUDADCFLASHLPEN_MASK 0x1 +#define RG_AUDADCFLASHLPEN_MASK_SFT (0x1 << 5) +#define RG_AUDPREAMPIDDTEST_SFT 6 +#define RG_AUDPREAMPIDDTEST_MASK 0x3 +#define RG_AUDPREAMPIDDTEST_MASK_SFT (0x3 << 6) +#define RG_AUDADC1STSTAGEIDDTEST_SFT 8 +#define RG_AUDADC1STSTAGEIDDTEST_MASK 0x3 +#define RG_AUDADC1STSTAGEIDDTEST_MASK_SFT (0x3 << 8) +#define RG_AUDADC2NDSTAGEIDDTEST_SFT 10 +#define RG_AUDADC2NDSTAGEIDDTEST_MASK 0x3 +#define RG_AUDADC2NDSTAGEIDDTEST_MASK_SFT (0x3 << 10) +#define RG_AUDADCREFBUFIDDTEST_SFT 12 +#define RG_AUDADCREFBUFIDDTEST_MASK 0x3 +#define RG_AUDADCREFBUFIDDTEST_MASK_SFT (0x3 << 12) +#define RG_AUDADCFLASHIDDTEST_SFT 14 +#define RG_AUDADCFLASHIDDTEST_MASK 0x3 +#define RG_AUDADCFLASHIDDTEST_MASK_SFT (0x3 << 14) + +/* AUDENC_ANA_CON4 */ +#define RG_AUDRULHALFBIAS_SFT 0 +#define RG_AUDRULHALFBIAS_MASK 0x1 +#define RG_AUDRULHALFBIAS_MASK_SFT (0x1 << 0) +#define RG_AUDGLBRVOWLPWEN_SFT 1 +#define RG_AUDGLBRVOWLPWEN_MASK 0x1 +#define RG_AUDGLBRVOWLPWEN_MASK_SFT (0x1 << 1) +#define RG_AUDRPREAMPLPEN_SFT 2 +#define RG_AUDRPREAMPLPEN_MASK 0x1 +#define RG_AUDRPREAMPLPEN_MASK_SFT (0x1 << 2) +#define RG_AUDRADC1STSTAGELPEN_SFT 3 +#define RG_AUDRADC1STSTAGELPEN_MASK 0x1 +#define RG_AUDRADC1STSTAGELPEN_MASK_SFT (0x1 << 3) +#define RG_AUDRADC2NDSTAGELPEN_SFT 4 +#define RG_AUDRADC2NDSTAGELPEN_MASK 0x1 +#define RG_AUDRADC2NDSTAGELPEN_MASK_SFT (0x1 << 4) +#define RG_AUDRADCFLASHLPEN_SFT 5 +#define RG_AUDRADCFLASHLPEN_MASK 0x1 +#define RG_AUDRADCFLASHLPEN_MASK_SFT (0x1 << 5) +#define RG_AUDRPREAMPIDDTEST_SFT 6 +#define RG_AUDRPREAMPIDDTEST_MASK 0x3 +#define RG_AUDRPREAMPIDDTEST_MASK_SFT (0x3 << 6) +#define RG_AUDRADC1STSTAGEIDDTEST_SFT 8 +#define RG_AUDRADC1STSTAGEIDDTEST_MASK 0x3 +#define RG_AUDRADC1STSTAGEIDDTEST_MASK_SFT (0x3 << 8) +#define RG_AUDRADC2NDSTAGEIDDTEST_SFT 10 +#define RG_AUDRADC2NDSTAGEIDDTEST_MASK 0x3 +#define RG_AUDRADC2NDSTAGEIDDTEST_MASK_SFT (0x3 << 10) +#define RG_AUDRADCREFBUFIDDTEST_SFT 12 +#define RG_AUDRADCREFBUFIDDTEST_MASK 0x3 +#define RG_AUDRADCREFBUFIDDTEST_MASK_SFT (0x3 << 12) +#define RG_AUDRADCFLASHIDDTEST_SFT 14 +#define RG_AUDRADCFLASHIDDTEST_MASK 0x3 +#define RG_AUDRADCFLASHIDDTEST_MASK_SFT (0x3 << 14) + +/* AUDENC_ANA_CON5 */ +#define RG_AUDADCCLKRSTB_SFT 0 +#define RG_AUDADCCLKRSTB_MASK 0x1 +#define RG_AUDADCCLKRSTB_MASK_SFT (0x1 << 0) +#define RG_AUDADCCLKSEL_SFT 1 +#define RG_AUDADCCLKSEL_MASK 0x3 +#define RG_AUDADCCLKSEL_MASK_SFT (0x3 << 1) +#define RG_AUDADCCLKSOURCE_SFT 3 +#define RG_AUDADCCLKSOURCE_MASK 0x3 +#define RG_AUDADCCLKSOURCE_MASK_SFT (0x3 << 3) +#define RG_AUDADCCLKGENMODE_SFT 5 +#define RG_AUDADCCLKGENMODE_MASK 0x3 +#define RG_AUDADCCLKGENMODE_MASK_SFT (0x3 << 5) +#define RG_AUDPREAMP_ACCFS_SFT 7 +#define RG_AUDPREAMP_ACCFS_MASK 0x1 +#define RG_AUDPREAMP_ACCFS_MASK_SFT (0x1 << 7) +#define RG_AUDPREAMPAAFEN_SFT 8 +#define RG_AUDPREAMPAAFEN_MASK 0x1 +#define RG_AUDPREAMPAAFEN_MASK_SFT (0x1 << 8) +#define RG_DCCVCMBUFLPMODSEL_SFT 9 +#define RG_DCCVCMBUFLPMODSEL_MASK 0x1 +#define RG_DCCVCMBUFLPMODSEL_MASK_SFT (0x1 << 9) +#define RG_DCCVCMBUFLPSWEN_SFT 10 +#define RG_DCCVCMBUFLPSWEN_MASK 0x1 +#define RG_DCCVCMBUFLPSWEN_MASK_SFT (0x1 << 10) +#define RG_AUDSPAREPGA_SFT 11 +#define RG_AUDSPAREPGA_MASK 0x1f +#define RG_AUDSPAREPGA_MASK_SFT (0x1f << 11) + +/* AUDENC_ANA_CON6 */ +#define RG_AUDADC1STSTAGESDENB_SFT 0 +#define RG_AUDADC1STSTAGESDENB_MASK 0x1 +#define RG_AUDADC1STSTAGESDENB_MASK_SFT (0x1 << 0) +#define RG_AUDADC2NDSTAGERESET_SFT 1 +#define RG_AUDADC2NDSTAGERESET_MASK 0x1 +#define RG_AUDADC2NDSTAGERESET_MASK_SFT (0x1 << 1) +#define RG_AUDADC3RDSTAGERESET_SFT 2 +#define RG_AUDADC3RDSTAGERESET_MASK 0x1 +#define RG_AUDADC3RDSTAGERESET_MASK_SFT (0x1 << 2) +#define RG_AUDADCFSRESET_SFT 3 +#define RG_AUDADCFSRESET_MASK 0x1 +#define RG_AUDADCFSRESET_MASK_SFT (0x1 << 3) +#define RG_AUDADCWIDECM_SFT 4 +#define RG_AUDADCWIDECM_MASK 0x1 +#define RG_AUDADCWIDECM_MASK_SFT (0x1 << 4) +#define RG_AUDADCNOPATEST_SFT 5 +#define RG_AUDADCNOPATEST_MASK 0x1 +#define RG_AUDADCNOPATEST_MASK_SFT (0x1 << 5) +#define RG_AUDADCBYPASS_SFT 6 +#define RG_AUDADCBYPASS_MASK 0x1 +#define RG_AUDADCBYPASS_MASK_SFT (0x1 << 6) +#define RG_AUDADCFFBYPASS_SFT 7 +#define RG_AUDADCFFBYPASS_MASK 0x1 +#define RG_AUDADCFFBYPASS_MASK_SFT (0x1 << 7) +#define RG_AUDADCDACFBCURRENT_SFT 8 +#define RG_AUDADCDACFBCURRENT_MASK 0x1 +#define RG_AUDADCDACFBCURRENT_MASK_SFT (0x1 << 8) +#define RG_AUDADCDACIDDTEST_SFT 9 +#define RG_AUDADCDACIDDTEST_MASK 0x3 +#define RG_AUDADCDACIDDTEST_MASK_SFT (0x3 << 9) +#define RG_AUDADCDACNRZ_SFT 11 +#define RG_AUDADCDACNRZ_MASK 0x1 +#define RG_AUDADCDACNRZ_MASK_SFT (0x1 << 11) +#define RG_AUDADCNODEM_SFT 12 +#define RG_AUDADCNODEM_MASK 0x1 +#define RG_AUDADCNODEM_MASK_SFT (0x1 << 12) +#define RG_AUDADCDACTEST_SFT 13 +#define RG_AUDADCDACTEST_MASK 0x1 +#define RG_AUDADCDACTEST_MASK_SFT (0x1 << 13) +#define RG_AUDADCDAC0P25FS_SFT 14 +#define RG_AUDADCDAC0P25FS_MASK 0x1 +#define RG_AUDADCDAC0P25FS_MASK_SFT (0x1 << 14) +#define RG_AUDADCRDAC0P25FS_SFT 15 +#define RG_AUDADCRDAC0P25FS_MASK 0x1 +#define RG_AUDADCRDAC0P25FS_MASK_SFT (0x1 << 15) + +/* AUDENC_ANA_CON7 */ +#define RG_AUDADCTESTDATA_SFT 0 +#define RG_AUDADCTESTDATA_MASK 0xffff +#define RG_AUDADCTESTDATA_MASK_SFT (0xffff << 0) + +/* AUDENC_ANA_CON8 */ +#define RG_AUDRCTUNEL_SFT 0 +#define RG_AUDRCTUNEL_MASK 0x1f +#define RG_AUDRCTUNEL_MASK_SFT (0x1f << 0) +#define RG_AUDRCTUNELSEL_SFT 5 +#define RG_AUDRCTUNELSEL_MASK 0x1 +#define RG_AUDRCTUNELSEL_MASK_SFT (0x1 << 5) +#define RG_AUDRCTUNER_SFT 8 +#define RG_AUDRCTUNER_MASK 0x1f +#define RG_AUDRCTUNER_MASK_SFT (0x1f << 8) +#define RG_AUDRCTUNERSEL_SFT 13 +#define RG_AUDRCTUNERSEL_MASK 0x1 +#define RG_AUDRCTUNERSEL_MASK_SFT (0x1 << 13) + +/* AUDENC_ANA_CON9 */ +#define RG_AUD3CTUNEL_SFT 0 +#define RG_AUD3CTUNEL_MASK 0x1f +#define RG_AUD3CTUNEL_MASK_SFT (0x1f << 0) +#define RG_AUD3CTUNELSEL_SFT 5 +#define RG_AUD3CTUNELSEL_MASK 0x1 +#define RG_AUD3CTUNELSEL_MASK_SFT (0x1 << 5) +#define RGS_AUDRCTUNE3READ_SFT 6 +#define RGS_AUDRCTUNE3READ_MASK 0x1f +#define RGS_AUDRCTUNE3READ_MASK_SFT (0x1f << 6) +#define RG_AUD3SPARE_SFT 11 +#define RG_AUD3SPARE_MASK 0x1f +#define RG_AUD3SPARE_MASK_SFT (0x1f << 11) + +/* AUDENC_ANA_CON10 */ +#define RGS_AUDRCTUNELREAD_SFT 0 +#define RGS_AUDRCTUNELREAD_MASK 0x1f +#define RGS_AUDRCTUNELREAD_MASK_SFT (0x1f << 0) +#define RGS_AUDRCTUNERREAD_SFT 8 +#define RGS_AUDRCTUNERREAD_MASK 0x1f +#define RGS_AUDRCTUNERREAD_MASK_SFT (0x1f << 8) + +/* AUDENC_ANA_CON11 */ +#define RG_AUDSPAREVA30_SFT 0 +#define RG_AUDSPAREVA30_MASK 0xff +#define RG_AUDSPAREVA30_MASK_SFT (0xff << 0) +#define RG_AUDSPAREVA18_SFT 8 +#define RG_AUDSPAREVA18_MASK 0xff +#define RG_AUDSPAREVA18_MASK_SFT (0xff << 8) + +/* AUDENC_ANA_CON12 */ +#define RG_AUDPGA_DECAP_SFT 0 +#define RG_AUDPGA_DECAP_MASK 0x1 +#define RG_AUDPGA_DECAP_MASK_SFT (0x1 << 0) +#define RG_AUDPGA_CAPRA_SFT 1 +#define RG_AUDPGA_CAPRA_MASK 0x1 +#define RG_AUDPGA_CAPRA_MASK_SFT (0x1 << 1) +#define RG_AUDPGA_ACCCMP_SFT 2 +#define RG_AUDPGA_ACCCMP_MASK 0x1 +#define RG_AUDPGA_ACCCMP_MASK_SFT (0x1 << 2) +#define RG_AUDENC_SPARE2_SFT 3 +#define RG_AUDENC_SPARE2_MASK 0x1fff +#define RG_AUDENC_SPARE2_MASK_SFT (0x1fff << 3) + +/* AUDENC_ANA_CON13 */ +#define RG_AUDDIGMICEN_SFT 0 +#define RG_AUDDIGMICEN_MASK 0x1 +#define RG_AUDDIGMICEN_MASK_SFT (0x1 << 0) +#define RG_AUDDIGMICBIAS_SFT 1 +#define RG_AUDDIGMICBIAS_MASK 0x3 +#define RG_AUDDIGMICBIAS_MASK_SFT (0x3 << 1) +#define RG_DMICHPCLKEN_SFT 3 +#define RG_DMICHPCLKEN_MASK 0x1 +#define RG_DMICHPCLKEN_MASK_SFT (0x1 << 3) +#define RG_AUDDIGMICPDUTY_SFT 4 +#define RG_AUDDIGMICPDUTY_MASK 0x3 +#define RG_AUDDIGMICPDUTY_MASK_SFT (0x3 << 4) +#define RG_AUDDIGMICNDUTY_SFT 6 +#define RG_AUDDIGMICNDUTY_MASK 0x3 +#define RG_AUDDIGMICNDUTY_MASK_SFT (0x3 << 6) +#define RG_DMICMONEN_SFT 8 +#define RG_DMICMONEN_MASK 0x1 +#define RG_DMICMONEN_MASK_SFT (0x1 << 8) +#define RG_DMICMONSEL_SFT 9 +#define RG_DMICMONSEL_MASK 0x7 +#define RG_DMICMONSEL_MASK_SFT (0x7 << 9) + +/* AUDENC_ANA_CON14 */ +#define RG_AUDDIGMIC1EN_SFT 0 +#define RG_AUDDIGMIC1EN_MASK 0x1 +#define RG_AUDDIGMIC1EN_MASK_SFT (0x1 << 0) +#define RG_AUDDIGMICBIAS1_SFT 1 +#define RG_AUDDIGMICBIAS1_MASK 0x3 +#define RG_AUDDIGMICBIAS1_MASK_SFT (0x3 << 1) +#define RG_DMIC1HPCLKEN_SFT 3 +#define RG_DMIC1HPCLKEN_MASK 0x1 +#define RG_DMIC1HPCLKEN_MASK_SFT (0x1 << 3) +#define RG_AUDDIGMIC1PDUTY_SFT 4 +#define RG_AUDDIGMIC1PDUTY_MASK 0x3 +#define RG_AUDDIGMIC1PDUTY_MASK_SFT (0x3 << 4) +#define RG_AUDDIGMIC1NDUTY_SFT 6 +#define RG_AUDDIGMIC1NDUTY_MASK 0x3 +#define RG_AUDDIGMIC1NDUTY_MASK_SFT (0x3 << 6) +#define RG_DMIC1MONEN_SFT 8 +#define RG_DMIC1MONEN_MASK 0x1 +#define RG_DMIC1MONEN_MASK_SFT (0x1 << 8) +#define RG_DMIC1MONSEL_SFT 9 +#define RG_DMIC1MONSEL_MASK 0x7 +#define RG_DMIC1MONSEL_MASK_SFT (0x7 << 9) +#define RG_AUDSPAREVMIC_SFT 12 +#define RG_AUDSPAREVMIC_MASK 0xf +#define RG_AUDSPAREVMIC_MASK_SFT (0xf << 12) + +/* AUDENC_ANA_CON15 */ +#define RG_AUDPWDBMICBIAS0_SFT 0 +#define RG_AUDPWDBMICBIAS0_MASK 0x1 +#define RG_AUDPWDBMICBIAS0_MASK_SFT (0x1 << 0) +#define RG_AUDMICBIAS0BYPASSEN_SFT 1 +#define RG_AUDMICBIAS0BYPASSEN_MASK 0x1 +#define RG_AUDMICBIAS0BYPASSEN_MASK_SFT (0x1 << 1) +#define RG_AUDMICBIAS0LOWPEN_SFT 2 +#define RG_AUDMICBIAS0LOWPEN_MASK 0x1 +#define RG_AUDMICBIAS0LOWPEN_MASK_SFT (0x1 << 2) +#define RG_AUDPWDBMICBIAS3_SFT 3 +#define RG_AUDPWDBMICBIAS3_MASK 0x1 +#define RG_AUDPWDBMICBIAS3_MASK_SFT (0x1 << 3) +#define RG_AUDMICBIAS0VREF_SFT 4 +#define RG_AUDMICBIAS0VREF_MASK 0x7 +#define RG_AUDMICBIAS0VREF_MASK_SFT (0x7 << 4) +#define RG_AUDMICBIAS0DCSW0P1EN_SFT 8 +#define RG_AUDMICBIAS0DCSW0P1EN_MASK 0x1 +#define RG_AUDMICBIAS0DCSW0P1EN_MASK_SFT (0x1 << 8) +#define RG_AUDMICBIAS0DCSW0P2EN_SFT 9 +#define RG_AUDMICBIAS0DCSW0P2EN_MASK 0x1 +#define RG_AUDMICBIAS0DCSW0P2EN_MASK_SFT (0x1 << 9) +#define RG_AUDMICBIAS0DCSW0NEN_SFT 10 +#define RG_AUDMICBIAS0DCSW0NEN_MASK 0x1 +#define RG_AUDMICBIAS0DCSW0NEN_MASK_SFT (0x1 << 10) +#define RG_AUDMICBIAS0DCSW2P1EN_SFT 12 +#define RG_AUDMICBIAS0DCSW2P1EN_MASK 0x1 +#define RG_AUDMICBIAS0DCSW2P1EN_MASK_SFT (0x1 << 12) +#define RG_AUDMICBIAS0DCSW2P2EN_SFT 13 +#define RG_AUDMICBIAS0DCSW2P2EN_MASK 0x1 +#define RG_AUDMICBIAS0DCSW2P2EN_MASK_SFT (0x1 << 13) +#define RG_AUDMICBIAS0DCSW2NEN_SFT 14 +#define RG_AUDMICBIAS0DCSW2NEN_MASK 0x1 +#define RG_AUDMICBIAS0DCSW2NEN_MASK_SFT (0x1 << 14) + +/* AUDENC_ANA_CON16 */ +#define RG_AUDPWDBMICBIAS1_SFT 0 +#define RG_AUDPWDBMICBIAS1_MASK 0x1 +#define RG_AUDPWDBMICBIAS1_MASK_SFT (0x1 << 0) +#define RG_AUDMICBIAS1BYPASSEN_SFT 1 +#define RG_AUDMICBIAS1BYPASSEN_MASK 0x1 +#define RG_AUDMICBIAS1BYPASSEN_MASK_SFT (0x1 << 1) +#define RG_AUDMICBIAS1LOWPEN_SFT 2 +#define RG_AUDMICBIAS1LOWPEN_MASK 0x1 +#define RG_AUDMICBIAS1LOWPEN_MASK_SFT (0x1 << 2) +#define RG_AUDMICBIAS1VREF_SFT 4 +#define RG_AUDMICBIAS1VREF_MASK 0x7 +#define RG_AUDMICBIAS1VREF_MASK_SFT (0x7 << 4) +#define RG_AUDMICBIAS1DCSW1PEN_SFT 8 +#define RG_AUDMICBIAS1DCSW1PEN_MASK 0x1 +#define RG_AUDMICBIAS1DCSW1PEN_MASK_SFT (0x1 << 8) +#define RG_AUDMICBIAS1DCSW1NEN_SFT 9 +#define RG_AUDMICBIAS1DCSW1NEN_MASK 0x1 +#define RG_AUDMICBIAS1DCSW1NEN_MASK_SFT (0x1 << 9) +#define RG_BANDGAPGEN_SFT 10 +#define RG_BANDGAPGEN_MASK 0x1 +#define RG_BANDGAPGEN_MASK_SFT (0x1 << 10) +#define RG_AUDMICBIAS1HVEN_SFT 12 +#define RG_AUDMICBIAS1HVEN_MASK 0x1 +#define RG_AUDMICBIAS1HVEN_MASK_SFT (0x1 << 12) +#define RG_AUDMICBIAS1HVVREF_SFT 13 +#define RG_AUDMICBIAS1HVVREF_MASK 0x1 +#define RG_AUDMICBIAS1HVVREF_MASK_SFT (0x1 << 13) + +/* AUDENC_ANA_CON17 */ +#define RG_AUDPWDBMICBIAS2_SFT 0 +#define RG_AUDPWDBMICBIAS2_MASK 0x1 +#define RG_AUDPWDBMICBIAS2_MASK_SFT (0x1 << 0) +#define RG_AUDMICBIAS2BYPASSEN_SFT 1 +#define RG_AUDMICBIAS2BYPASSEN_MASK 0x1 +#define RG_AUDMICBIAS2BYPASSEN_MASK_SFT (0x1 << 1) +#define RG_AUDMICBIAS2LOWPEN_SFT 2 +#define RG_AUDMICBIAS2LOWPEN_MASK 0x1 +#define RG_AUDMICBIAS2LOWPEN_MASK_SFT (0x1 << 2) +#define RG_AUDMICBIAS2VREF_SFT 4 +#define RG_AUDMICBIAS2VREF_MASK 0x7 +#define RG_AUDMICBIAS2VREF_MASK_SFT (0x7 << 4) +#define RG_AUDMICBIAS2DCSW3P1EN_SFT 8 +#define RG_AUDMICBIAS2DCSW3P1EN_MASK 0x1 +#define RG_AUDMICBIAS2DCSW3P1EN_MASK_SFT (0x1 << 8) +#define RG_AUDMICBIAS2DCSW3P2EN_SFT 9 +#define RG_AUDMICBIAS2DCSW3P2EN_MASK 0x1 +#define RG_AUDMICBIAS2DCSW3P2EN_MASK_SFT (0x1 << 9) +#define RG_AUDMICBIAS2DCSW3NEN_SFT 10 +#define RG_AUDMICBIAS2DCSW3NEN_MASK 0x1 +#define RG_AUDMICBIAS2DCSW3NEN_MASK_SFT (0x1 << 10) +#define RG_AUDMICBIASSPARE_SFT 12 +#define RG_AUDMICBIASSPARE_MASK 0xf +#define RG_AUDMICBIASSPARE_MASK_SFT (0xf << 12) + +/* AUDENC_ANA_CON18 */ +#define RG_AUDACCDETMICBIAS0PULLLOW_SFT 0 +#define RG_AUDACCDETMICBIAS0PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS0PULLLOW_MASK_SFT (0x1 << 0) +#define RG_AUDACCDETMICBIAS1PULLLOW_SFT 1 +#define RG_AUDACCDETMICBIAS1PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS1PULLLOW_MASK_SFT (0x1 << 1) +#define RG_AUDACCDETMICBIAS2PULLLOW_SFT 2 +#define RG_AUDACCDETMICBIAS2PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS2PULLLOW_MASK_SFT (0x1 << 2) +#define RG_AUDACCDETVIN1PULLLOW_SFT 3 +#define RG_AUDACCDETVIN1PULLLOW_MASK 0x1 +#define RG_AUDACCDETVIN1PULLLOW_MASK_SFT (0x1 << 3) +#define RG_AUDACCDETVTHACAL_SFT 4 +#define RG_AUDACCDETVTHACAL_MASK 0x1 +#define RG_AUDACCDETVTHACAL_MASK_SFT (0x1 << 4) +#define RG_AUDACCDETVTHBCAL_SFT 5 +#define RG_AUDACCDETVTHBCAL_MASK 0x1 +#define RG_AUDACCDETVTHBCAL_MASK_SFT (0x1 << 5) +#define RG_AUDACCDETTVDET_SFT 6 +#define RG_AUDACCDETTVDET_MASK 0x1 +#define RG_AUDACCDETTVDET_MASK_SFT (0x1 << 6) +#define RG_ACCDETSEL_SFT 7 +#define RG_ACCDETSEL_MASK 0x1 +#define RG_ACCDETSEL_MASK_SFT (0x1 << 7) +#define RG_SWBUFMODSEL_SFT 8 +#define RG_SWBUFMODSEL_MASK 0x1 +#define RG_SWBUFMODSEL_MASK_SFT (0x1 << 8) +#define RG_SWBUFSWEN_SFT 9 +#define RG_SWBUFSWEN_MASK 0x1 +#define RG_SWBUFSWEN_MASK_SFT (0x1 << 9) +#define RG_EINT0NOHYS_SFT 10 +#define RG_EINT0NOHYS_MASK 0x1 +#define RG_EINT0NOHYS_MASK_SFT (0x1 << 10) +#define RG_EINT0CONFIGACCDET_SFT 11 +#define RG_EINT0CONFIGACCDET_MASK 0x1 +#define RG_EINT0CONFIGACCDET_MASK_SFT (0x1 << 11) +#define RG_EINT0HIRENB_SFT 12 +#define RG_EINT0HIRENB_MASK 0x1 +#define RG_EINT0HIRENB_MASK_SFT (0x1 << 12) +#define RG_ACCDET2AUXRESBYPASS_SFT 13 +#define RG_ACCDET2AUXRESBYPASS_MASK 0x1 +#define RG_ACCDET2AUXRESBYPASS_MASK_SFT (0x1 << 13) +#define RG_ACCDET2AUXSWEN_SFT 14 +#define RG_ACCDET2AUXSWEN_MASK 0x1 +#define RG_ACCDET2AUXSWEN_MASK_SFT (0x1 << 14) +#define RG_AUDACCDETMICBIAS3PULLLOW_SFT 15 +#define RG_AUDACCDETMICBIAS3PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS3PULLLOW_MASK_SFT (0x1 << 15) + +/* AUDENC_ANA_CON19 */ +#define RG_EINT1CONFIGACCDET_SFT 0 +#define RG_EINT1CONFIGACCDET_MASK 0x1 +#define RG_EINT1CONFIGACCDET_MASK_SFT (0x1 << 0) +#define RG_EINT1HIRENB_SFT 1 +#define RG_EINT1HIRENB_MASK 0x1 +#define RG_EINT1HIRENB_MASK_SFT (0x1 << 1) +#define RG_EINT1NOHYS_SFT 2 +#define RG_EINT1NOHYS_MASK 0x1 +#define RG_EINT1NOHYS_MASK_SFT (0x1 << 2) +#define RG_EINTCOMPVTH_SFT 4 +#define RG_EINTCOMPVTH_MASK 0xf +#define RG_EINTCOMPVTH_MASK_SFT (0xf << 4) +#define RG_MTEST_EN_SFT 8 +#define RG_MTEST_EN_MASK 0x1 +#define RG_MTEST_EN_MASK_SFT (0x1 << 8) +#define RG_MTEST_SEL_SFT 9 +#define RG_MTEST_SEL_MASK 0x1 +#define RG_MTEST_SEL_MASK_SFT (0x1 << 9) +#define RG_MTEST_CURRENT_SFT 10 +#define RG_MTEST_CURRENT_MASK 0x1 +#define RG_MTEST_CURRENT_MASK_SFT (0x1 << 10) +#define RG_ANALOGFDEN_SFT 12 +#define RG_ANALOGFDEN_MASK 0x1 +#define RG_ANALOGFDEN_MASK_SFT (0x1 << 12) +#define RG_FDVIN1PPULLLOW_SFT 13 +#define RG_FDVIN1PPULLLOW_MASK 0x1 +#define RG_FDVIN1PPULLLOW_MASK_SFT (0x1 << 13) +#define RG_FDEINT0TYPE_SFT 14 +#define RG_FDEINT0TYPE_MASK 0x1 +#define RG_FDEINT0TYPE_MASK_SFT (0x1 << 14) +#define RG_FDEINT1TYPE_SFT 15 +#define RG_FDEINT1TYPE_MASK 0x1 +#define RG_FDEINT1TYPE_MASK_SFT (0x1 << 15) + +/* AUDENC_ANA_CON20 */ +#define RG_EINT0CMPEN_SFT 0 +#define RG_EINT0CMPEN_MASK 0x1 +#define RG_EINT0CMPEN_MASK_SFT (0x1 << 0) +#define RG_EINT0CMPMEN_SFT 1 +#define RG_EINT0CMPMEN_MASK 0x1 +#define RG_EINT0CMPMEN_MASK_SFT (0x1 << 1) +#define RG_EINT0EN_SFT 2 +#define RG_EINT0EN_MASK 0x1 +#define RG_EINT0EN_MASK_SFT (0x1 << 2) +#define RG_EINT0CEN_SFT 3 +#define RG_EINT0CEN_MASK 0x1 +#define RG_EINT0CEN_MASK_SFT (0x1 << 3) +#define RG_EINT0INVEN_SFT 4 +#define RG_EINT0INVEN_MASK 0x1 +#define RG_EINT0INVEN_MASK_SFT (0x1 << 4) +#define RG_EINT0CTURBO_SFT 5 +#define RG_EINT0CTURBO_MASK 0x7 +#define RG_EINT0CTURBO_MASK_SFT (0x7 << 5) +#define RG_EINT1CMPEN_SFT 8 +#define RG_EINT1CMPEN_MASK 0x1 +#define RG_EINT1CMPEN_MASK_SFT (0x1 << 8) +#define RG_EINT1CMPMEN_SFT 9 +#define RG_EINT1CMPMEN_MASK 0x1 +#define RG_EINT1CMPMEN_MASK_SFT (0x1 << 9) +#define RG_EINT1EN_SFT 10 +#define RG_EINT1EN_MASK 0x1 +#define RG_EINT1EN_MASK_SFT (0x1 << 10) +#define RG_EINT1CEN_SFT 11 +#define RG_EINT1CEN_MASK 0x1 +#define RG_EINT1CEN_MASK_SFT (0x1 << 11) +#define RG_EINT1INVEN_SFT 12 +#define RG_EINT1INVEN_MASK 0x1 +#define RG_EINT1INVEN_MASK_SFT (0x1 << 12) +#define RG_EINT1CTURBO_SFT 13 +#define RG_EINT1CTURBO_MASK 0x7 +#define RG_EINT1CTURBO_MASK_SFT (0x7 << 13) + +/* AUDENC_ANA_CON21 */ +#define RG_ACCDETSPARE_SFT 0 +#define RG_ACCDETSPARE_MASK 0xffff +#define RG_ACCDETSPARE_MASK_SFT (0xffff << 0) + +/* AUDENC_ANA_CON22 */ +#define RG_AUDENCSPAREVA30_SFT 0 +#define RG_AUDENCSPAREVA30_MASK 0xff +#define RG_AUDENCSPAREVA30_MASK_SFT (0xff << 0) +#define RG_AUDENCSPAREVA18_SFT 8 +#define RG_AUDENCSPAREVA18_MASK 0xff +#define RG_AUDENCSPAREVA18_MASK_SFT (0xff << 8) + +/* AUDENC_ANA_CON23 */ +#define RG_CLKSQ_EN_SFT 0 +#define RG_CLKSQ_EN_MASK 0x1 +#define RG_CLKSQ_EN_MASK_SFT (0x1 << 0) +#define RG_CLKSQ_IN_SEL_TEST_SFT 1 +#define RG_CLKSQ_IN_SEL_TEST_MASK 0x1 +#define RG_CLKSQ_IN_SEL_TEST_MASK_SFT (0x1 << 1) +#define RG_CM_REFGENSEL_SFT 2 +#define RG_CM_REFGENSEL_MASK 0x1 +#define RG_CM_REFGENSEL_MASK_SFT (0x1 << 2) +#define RG_AUDIO_VOW_EN_SFT 3 +#define RG_AUDIO_VOW_EN_MASK 0x1 +#define RG_AUDIO_VOW_EN_MASK_SFT (0x1 << 3) +#define RG_CLKSQ_EN_VOW_SFT 4 +#define RG_CLKSQ_EN_VOW_MASK 0x1 +#define RG_CLKSQ_EN_VOW_MASK_SFT (0x1 << 4) +#define RG_CLKAND_EN_VOW_SFT 5 +#define RG_CLKAND_EN_VOW_MASK 0x1 +#define RG_CLKAND_EN_VOW_MASK_SFT (0x1 << 5) +#define RG_VOWCLK_SEL_EN_VOW_SFT 6 +#define RG_VOWCLK_SEL_EN_VOW_MASK 0x1 +#define RG_VOWCLK_SEL_EN_VOW_MASK_SFT (0x1 << 6) +#define RG_SPARE_VOW_SFT 7 +#define RG_SPARE_VOW_MASK 0x7 +#define RG_SPARE_VOW_MASK_SFT (0x7 << 7) + +/* AUDDEC_ANA_CON0 */ +#define RG_AUDDACLPWRUP_VAUDP32_SFT 0 +#define RG_AUDDACLPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDDACLPWRUP_VAUDP32_MASK_SFT (0x1 << 0) +#define RG_AUDDACRPWRUP_VAUDP32_SFT 1 +#define RG_AUDDACRPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDDACRPWRUP_VAUDP32_MASK_SFT (0x1 << 1) +#define RG_AUD_DAC_PWR_UP_VA32_SFT 2 +#define RG_AUD_DAC_PWR_UP_VA32_MASK 0x1 +#define RG_AUD_DAC_PWR_UP_VA32_MASK_SFT (0x1 << 2) +#define RG_AUD_DAC_PWL_UP_VA32_SFT 3 +#define RG_AUD_DAC_PWL_UP_VA32_MASK 0x1 +#define RG_AUD_DAC_PWL_UP_VA32_MASK_SFT (0x1 << 3) +#define RG_AUDHPLPWRUP_VAUDP32_SFT 4 +#define RG_AUDHPLPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDHPLPWRUP_VAUDP32_MASK_SFT (0x1 << 4) +#define RG_AUDHPRPWRUP_VAUDP32_SFT 5 +#define RG_AUDHPRPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDHPRPWRUP_VAUDP32_MASK_SFT (0x1 << 5) +#define RG_AUDHPLPWRUP_IBIAS_VAUDP32_SFT 6 +#define RG_AUDHPLPWRUP_IBIAS_VAUDP32_MASK 0x1 +#define RG_AUDHPLPWRUP_IBIAS_VAUDP32_MASK_SFT (0x1 << 6) +#define RG_AUDHPRPWRUP_IBIAS_VAUDP32_SFT 7 +#define RG_AUDHPRPWRUP_IBIAS_VAUDP32_MASK 0x1 +#define RG_AUDHPRPWRUP_IBIAS_VAUDP32_MASK_SFT (0x1 << 7) +#define RG_AUDHPLMUXINPUTSEL_VAUDP32_SFT 8 +#define RG_AUDHPLMUXINPUTSEL_VAUDP32_MASK 0x3 +#define RG_AUDHPLMUXINPUTSEL_VAUDP32_MASK_SFT (0x3 << 8) +#define RG_AUDHPRMUXINPUTSEL_VAUDP32_SFT 10 +#define RG_AUDHPRMUXINPUTSEL_VAUDP32_MASK 0x3 +#define RG_AUDHPRMUXINPUTSEL_VAUDP32_MASK_SFT (0x3 << 10) +#define RG_AUDHPLSCDISABLE_VAUDP32_SFT 12 +#define RG_AUDHPLSCDISABLE_VAUDP32_MASK 0x1 +#define RG_AUDHPLSCDISABLE_VAUDP32_MASK_SFT (0x1 << 12) +#define RG_AUDHPRSCDISABLE_VAUDP32_SFT 13 +#define RG_AUDHPRSCDISABLE_VAUDP32_MASK 0x1 +#define RG_AUDHPRSCDISABLE_VAUDP32_MASK_SFT (0x1 << 13) +#define RG_AUDHPLBSCCURRENT_VAUDP32_SFT 14 +#define RG_AUDHPLBSCCURRENT_VAUDP32_MASK 0x1 +#define RG_AUDHPLBSCCURRENT_VAUDP32_MASK_SFT (0x1 << 14) +#define RG_AUDHPRBSCCURRENT_VAUDP32_SFT 15 +#define RG_AUDHPRBSCCURRENT_VAUDP32_MASK 0x1 +#define RG_AUDHPRBSCCURRENT_VAUDP32_MASK_SFT (0x1 << 15) + +/* AUDDEC_ANA_CON1 */ +#define RG_AUDHPLOUTPWRUP_VAUDP32_SFT 0 +#define RG_AUDHPLOUTPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDHPLOUTPWRUP_VAUDP32_MASK_SFT (0x1 << 0) +#define RG_AUDHPROUTPWRUP_VAUDP32_SFT 1 +#define RG_AUDHPROUTPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDHPROUTPWRUP_VAUDP32_MASK_SFT (0x1 << 1) +#define RG_AUDHPLOUTAUXPWRUP_VAUDP32_SFT 2 +#define RG_AUDHPLOUTAUXPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDHPLOUTAUXPWRUP_VAUDP32_MASK_SFT (0x1 << 2) +#define RG_AUDHPROUTAUXPWRUP_VAUDP32_SFT 3 +#define RG_AUDHPROUTAUXPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDHPROUTAUXPWRUP_VAUDP32_MASK_SFT (0x1 << 3) +#define RG_HPLAUXFBRSW_EN_VAUDP32_SFT 4 +#define RG_HPLAUXFBRSW_EN_VAUDP32_MASK 0x1 +#define RG_HPLAUXFBRSW_EN_VAUDP32_MASK_SFT (0x1 << 4) +#define RG_HPRAUXFBRSW_EN_VAUDP32_SFT 5 +#define RG_HPRAUXFBRSW_EN_VAUDP32_MASK 0x1 +#define RG_HPRAUXFBRSW_EN_VAUDP32_MASK_SFT (0x1 << 5) +#define RG_HPLSHORT2HPLAUX_EN_VAUDP32_SFT 6 +#define RG_HPLSHORT2HPLAUX_EN_VAUDP32_MASK 0x1 +#define RG_HPLSHORT2HPLAUX_EN_VAUDP32_MASK_SFT (0x1 << 6) +#define RG_HPRSHORT2HPRAUX_EN_VAUDP32_SFT 7 +#define RG_HPRSHORT2HPRAUX_EN_VAUDP32_MASK 0x1 +#define RG_HPRSHORT2HPRAUX_EN_VAUDP32_MASK_SFT (0x1 << 7) +#define RG_HPLOUTSTGCTRL_VAUDP32_SFT 8 +#define RG_HPLOUTSTGCTRL_VAUDP32_MASK 0x7 +#define RG_HPLOUTSTGCTRL_VAUDP32_MASK_SFT (0x7 << 8) +#define RG_HPROUTSTGCTRL_VAUDP32_SFT 12 +#define RG_HPROUTSTGCTRL_VAUDP32_MASK 0x7 +#define RG_HPROUTSTGCTRL_VAUDP32_MASK_SFT (0x7 << 12) + +/* AUDDEC_ANA_CON2 */ +#define RG_HPLOUTPUTSTBENH_VAUDP32_SFT 0 +#define RG_HPLOUTPUTSTBENH_VAUDP32_MASK 0x7 +#define RG_HPLOUTPUTSTBENH_VAUDP32_MASK_SFT (0x7 << 0) +#define RG_HPROUTPUTSTBENH_VAUDP32_SFT 4 +#define RG_HPROUTPUTSTBENH_VAUDP32_MASK 0x7 +#define RG_HPROUTPUTSTBENH_VAUDP32_MASK_SFT (0x7 << 4) +#define RG_AUDHPSTARTUP_VAUDP32_SFT 7 +#define RG_AUDHPSTARTUP_VAUDP32_MASK 0x1 +#define RG_AUDHPSTARTUP_VAUDP32_MASK_SFT (0x1 << 7) +#define RG_AUDREFN_DERES_EN_VAUDP32_SFT 8 +#define RG_AUDREFN_DERES_EN_VAUDP32_MASK 0x1 +#define RG_AUDREFN_DERES_EN_VAUDP32_MASK_SFT (0x1 << 8) +#define RG_HPINPUTSTBENH_VAUDP32_SFT 9 +#define RG_HPINPUTSTBENH_VAUDP32_MASK 0x1 +#define RG_HPINPUTSTBENH_VAUDP32_MASK_SFT (0x1 << 9) +#define RG_HPINPUTRESET0_VAUDP32_SFT 10 +#define RG_HPINPUTRESET0_VAUDP32_MASK 0x1 +#define RG_HPINPUTRESET0_VAUDP32_MASK_SFT (0x1 << 10) +#define RG_HPOUTPUTRESET0_VAUDP32_SFT 11 +#define RG_HPOUTPUTRESET0_VAUDP32_MASK 0x1 +#define RG_HPOUTPUTRESET0_VAUDP32_MASK_SFT (0x1 << 11) +#define RG_HPPSHORT2VCM_VAUDP32_SFT 12 +#define RG_HPPSHORT2VCM_VAUDP32_MASK 0x7 +#define RG_HPPSHORT2VCM_VAUDP32_MASK_SFT (0x7 << 12) +#define RG_AUDHPTRIM_EN_VAUDP32_SFT 15 +#define RG_AUDHPTRIM_EN_VAUDP32_MASK 0x1 +#define RG_AUDHPTRIM_EN_VAUDP32_MASK_SFT (0x1 << 15) + +/* AUDDEC_ANA_CON3 */ +#define RG_AUDHPLTRIM_VAUDP32_SFT 0 +#define RG_AUDHPLTRIM_VAUDP32_MASK 0x1f +#define RG_AUDHPLTRIM_VAUDP32_MASK_SFT (0x1f << 0) +#define RG_AUDHPLFINETRIM_VAUDP32_SFT 5 +#define RG_AUDHPLFINETRIM_VAUDP32_MASK 0x7 +#define RG_AUDHPLFINETRIM_VAUDP32_MASK_SFT (0x7 << 5) +#define RG_AUDHPRTRIM_VAUDP32_SFT 8 +#define RG_AUDHPRTRIM_VAUDP32_MASK 0x1f +#define RG_AUDHPRTRIM_VAUDP32_MASK_SFT (0x1f << 8) +#define RG_AUDHPRFINETRIM_VAUDP32_SFT 13 +#define RG_AUDHPRFINETRIM_VAUDP32_MASK 0x7 +#define RG_AUDHPRFINETRIM_VAUDP32_MASK_SFT (0x7 << 13) + +/* AUDDEC_ANA_CON4 */ +#define RG_AUDHPDIFFINPBIASADJ_VAUDP32_SFT 0 +#define RG_AUDHPDIFFINPBIASADJ_VAUDP32_MASK 0x7 +#define RG_AUDHPDIFFINPBIASADJ_VAUDP32_MASK_SFT (0x7 << 0) +#define RG_AUDHPLFCOMPRESSEL_VAUDP32_SFT 4 +#define RG_AUDHPLFCOMPRESSEL_VAUDP32_MASK 0x7 +#define RG_AUDHPLFCOMPRESSEL_VAUDP32_MASK_SFT (0x7 << 4) +#define RG_AUDHPHFCOMPRESSEL_VAUDP32_SFT 8 +#define RG_AUDHPHFCOMPRESSEL_VAUDP32_MASK 0x7 +#define RG_AUDHPHFCOMPRESSEL_VAUDP32_MASK_SFT (0x7 << 8) +#define RG_AUDHPHFCOMPBUFGAINSEL_VAUDP32_SFT 12 +#define RG_AUDHPHFCOMPBUFGAINSEL_VAUDP32_MASK 0x3 +#define RG_AUDHPHFCOMPBUFGAINSEL_VAUDP32_MASK_SFT (0x3 << 12) +#define RG_AUDHPCOMP_EN_VAUDP32_SFT 15 +#define RG_AUDHPCOMP_EN_VAUDP32_MASK 0x1 +#define RG_AUDHPCOMP_EN_VAUDP32_MASK_SFT (0x1 << 15) + +/* AUDDEC_ANA_CON5 */ +#define RG_AUDHPDECMGAINADJ_VAUDP32_SFT 0 +#define RG_AUDHPDECMGAINADJ_VAUDP32_MASK 0x7 +#define RG_AUDHPDECMGAINADJ_VAUDP32_MASK_SFT (0x7 << 0) +#define RG_AUDHPDEDMGAINADJ_VAUDP32_SFT 4 +#define RG_AUDHPDEDMGAINADJ_VAUDP32_MASK 0x7 +#define RG_AUDHPDEDMGAINADJ_VAUDP32_MASK_SFT (0x7 << 4) + +/* AUDDEC_ANA_CON6 */ +#define RG_AUDHSPWRUP_VAUDP32_SFT 0 +#define RG_AUDHSPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDHSPWRUP_VAUDP32_MASK_SFT (0x1 << 0) +#define RG_AUDHSPWRUP_IBIAS_VAUDP32_SFT 1 +#define RG_AUDHSPWRUP_IBIAS_VAUDP32_MASK 0x1 +#define RG_AUDHSPWRUP_IBIAS_VAUDP32_MASK_SFT (0x1 << 1) +#define RG_AUDHSMUXINPUTSEL_VAUDP32_SFT 2 +#define RG_AUDHSMUXINPUTSEL_VAUDP32_MASK 0x3 +#define RG_AUDHSMUXINPUTSEL_VAUDP32_MASK_SFT (0x3 << 2) +#define RG_AUDHSSCDISABLE_VAUDP32_SFT 4 +#define RG_AUDHSSCDISABLE_VAUDP32_MASK 0x1 +#define RG_AUDHSSCDISABLE_VAUDP32_MASK_SFT (0x1 << 4) +#define RG_AUDHSBSCCURRENT_VAUDP32_SFT 5 +#define RG_AUDHSBSCCURRENT_VAUDP32_MASK 0x1 +#define RG_AUDHSBSCCURRENT_VAUDP32_MASK_SFT (0x1 << 5) +#define RG_AUDHSSTARTUP_VAUDP32_SFT 6 +#define RG_AUDHSSTARTUP_VAUDP32_MASK 0x1 +#define RG_AUDHSSTARTUP_VAUDP32_MASK_SFT (0x1 << 6) +#define RG_HSOUTPUTSTBENH_VAUDP32_SFT 7 +#define RG_HSOUTPUTSTBENH_VAUDP32_MASK 0x1 +#define RG_HSOUTPUTSTBENH_VAUDP32_MASK_SFT (0x1 << 7) +#define RG_HSINPUTSTBENH_VAUDP32_SFT 8 +#define RG_HSINPUTSTBENH_VAUDP32_MASK 0x1 +#define RG_HSINPUTSTBENH_VAUDP32_MASK_SFT (0x1 << 8) +#define RG_HSINPUTRESET0_VAUDP32_SFT 9 +#define RG_HSINPUTRESET0_VAUDP32_MASK 0x1 +#define RG_HSINPUTRESET0_VAUDP32_MASK_SFT (0x1 << 9) +#define RG_HSOUTPUTRESET0_VAUDP32_SFT 10 +#define RG_HSOUTPUTRESET0_VAUDP32_MASK 0x1 +#define RG_HSOUTPUTRESET0_VAUDP32_MASK_SFT (0x1 << 10) +#define RG_HSOUT_SHORTVCM_VAUDP32_SFT 11 +#define RG_HSOUT_SHORTVCM_VAUDP32_MASK 0x1 +#define RG_HSOUT_SHORTVCM_VAUDP32_MASK_SFT (0x1 << 11) + +/* AUDDEC_ANA_CON7 */ +#define RG_AUDLOLPWRUP_VAUDP32_SFT 0 +#define RG_AUDLOLPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDLOLPWRUP_VAUDP32_MASK_SFT (0x1 << 0) +#define RG_AUDLOLPWRUP_IBIAS_VAUDP32_SFT 1 +#define RG_AUDLOLPWRUP_IBIAS_VAUDP32_MASK 0x1 +#define RG_AUDLOLPWRUP_IBIAS_VAUDP32_MASK_SFT (0x1 << 1) +#define RG_AUDLOLMUXINPUTSEL_VAUDP32_SFT 2 +#define RG_AUDLOLMUXINPUTSEL_VAUDP32_MASK 0x3 +#define RG_AUDLOLMUXINPUTSEL_VAUDP32_MASK_SFT (0x3 << 2) +#define RG_AUDLOLSCDISABLE_VAUDP32_SFT 4 +#define RG_AUDLOLSCDISABLE_VAUDP32_MASK 0x1 +#define RG_AUDLOLSCDISABLE_VAUDP32_MASK_SFT (0x1 << 4) +#define RG_AUDLOLBSCCURRENT_VAUDP32_SFT 5 +#define RG_AUDLOLBSCCURRENT_VAUDP32_MASK 0x1 +#define RG_AUDLOLBSCCURRENT_VAUDP32_MASK_SFT (0x1 << 5) +#define RG_AUDLOSTARTUP_VAUDP32_SFT 6 +#define RG_AUDLOSTARTUP_VAUDP32_MASK 0x1 +#define RG_AUDLOSTARTUP_VAUDP32_MASK_SFT (0x1 << 6) +#define RG_LOINPUTSTBENH_VAUDP32_SFT 7 +#define RG_LOINPUTSTBENH_VAUDP32_MASK 0x1 +#define RG_LOINPUTSTBENH_VAUDP32_MASK_SFT (0x1 << 7) +#define RG_LOOUTPUTSTBENH_VAUDP32_SFT 8 +#define RG_LOOUTPUTSTBENH_VAUDP32_MASK 0x1 +#define RG_LOOUTPUTSTBENH_VAUDP32_MASK_SFT (0x1 << 8) +#define RG_LOINPUTRESET0_VAUDP32_SFT 9 +#define RG_LOINPUTRESET0_VAUDP32_MASK 0x1 +#define RG_LOINPUTRESET0_VAUDP32_MASK_SFT (0x1 << 9) +#define RG_LOOUTPUTRESET0_VAUDP32_SFT 10 +#define RG_LOOUTPUTRESET0_VAUDP32_MASK 0x1 +#define RG_LOOUTPUTRESET0_VAUDP32_MASK_SFT (0x1 << 10) +#define RG_LOOUT_SHORTVCM_VAUDP32_SFT 11 +#define RG_LOOUT_SHORTVCM_VAUDP32_MASK 0x1 +#define RG_LOOUT_SHORTVCM_VAUDP32_MASK_SFT (0x1 << 11) +#define RG_AUDDACTPWRUP_VAUDP32_SFT 12 +#define RG_AUDDACTPWRUP_VAUDP32_MASK 0x1 +#define RG_AUDDACTPWRUP_VAUDP32_MASK_SFT (0x1 << 12) +#define RG_AUD_DAC_PWT_UP_VA32_SFT 13 +#define RG_AUD_DAC_PWT_UP_VA32_MASK 0x1 +#define RG_AUD_DAC_PWT_UP_VA32_MASK_SFT (0x1 << 13) + +/* AUDDEC_ANA_CON8 */ +#define RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_SFT 0 +#define RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_MASK 0xf +#define RG_AUDTRIMBUF_INPUTMUXSEL_VAUDP32_MASK_SFT (0xf << 0) +#define RG_AUDTRIMBUF_GAINSEL_VAUDP32_SFT 4 +#define RG_AUDTRIMBUF_GAINSEL_VAUDP32_MASK 0x3 +#define RG_AUDTRIMBUF_GAINSEL_VAUDP32_MASK_SFT (0x3 << 4) +#define RG_AUDTRIMBUF_EN_VAUDP32_SFT 6 +#define RG_AUDTRIMBUF_EN_VAUDP32_MASK 0x1 +#define RG_AUDTRIMBUF_EN_VAUDP32_MASK_SFT (0x1 << 6) +#define RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_SFT 8 +#define RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_MASK 0x3 +#define RG_AUDHPSPKDET_INPUTMUXSEL_VAUDP32_MASK_SFT (0x3 << 8) +#define RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_SFT 10 +#define RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_MASK 0x3 +#define RG_AUDHPSPKDET_OUTPUTMUXSEL_VAUDP32_MASK_SFT (0x3 << 10) +#define RG_AUDHPSPKDET_EN_VAUDP32_SFT 12 +#define RG_AUDHPSPKDET_EN_VAUDP32_MASK 0x1 +#define RG_AUDHPSPKDET_EN_VAUDP32_MASK_SFT (0x1 << 12) + +/* AUDDEC_ANA_CON9 */ +#define RG_ABIDEC_RSVD0_VA32_SFT 0 +#define RG_ABIDEC_RSVD0_VA32_MASK 0xff +#define RG_ABIDEC_RSVD0_VA32_MASK_SFT (0xff << 0) +#define RG_ABIDEC_RSVD0_VAUDP32_SFT 8 +#define RG_ABIDEC_RSVD0_VAUDP32_MASK 0xff +#define RG_ABIDEC_RSVD0_VAUDP32_MASK_SFT (0xff << 8) + +/* AUDDEC_ANA_CON10 */ +#define RG_ABIDEC_RSVD1_VAUDP32_SFT 0 +#define RG_ABIDEC_RSVD1_VAUDP32_MASK 0xff +#define RG_ABIDEC_RSVD1_VAUDP32_MASK_SFT (0xff << 0) +#define RG_ABIDEC_RSVD2_VAUDP32_SFT 8 +#define RG_ABIDEC_RSVD2_VAUDP32_MASK 0xff +#define RG_ABIDEC_RSVD2_VAUDP32_MASK_SFT (0xff << 8) + +/* AUDDEC_ANA_CON11 */ +#define RG_AUDZCDMUXSEL_VAUDP32_SFT 0 +#define RG_AUDZCDMUXSEL_VAUDP32_MASK 0x7 +#define RG_AUDZCDMUXSEL_VAUDP32_MASK_SFT (0x7 << 0) +#define RG_AUDZCDCLKSEL_VAUDP32_SFT 3 +#define RG_AUDZCDCLKSEL_VAUDP32_MASK 0x1 +#define RG_AUDZCDCLKSEL_VAUDP32_MASK_SFT (0x1 << 3) +#define RG_AUDBIASADJ_0_VAUDP32_SFT 7 +#define RG_AUDBIASADJ_0_VAUDP32_MASK 0x1ff +#define RG_AUDBIASADJ_0_VAUDP32_MASK_SFT (0x1ff << 7) + +/* AUDDEC_ANA_CON12 */ +#define RG_AUDBIASADJ_1_VAUDP32_SFT 0 +#define RG_AUDBIASADJ_1_VAUDP32_MASK 0xff +#define RG_AUDBIASADJ_1_VAUDP32_MASK_SFT (0xff << 0) +#define RG_AUDIBIASPWRDN_VAUDP32_SFT 8 +#define RG_AUDIBIASPWRDN_VAUDP32_MASK 0x1 +#define RG_AUDIBIASPWRDN_VAUDP32_MASK_SFT (0x1 << 8) + +/* AUDDEC_ANA_CON13 */ +#define RG_RSTB_DECODER_VA32_SFT 0 +#define RG_RSTB_DECODER_VA32_MASK 0x1 +#define RG_RSTB_DECODER_VA32_MASK_SFT (0x1 << 0) +#define RG_SEL_DECODER_96K_VA32_SFT 1 +#define RG_SEL_DECODER_96K_VA32_MASK 0x1 +#define RG_SEL_DECODER_96K_VA32_MASK_SFT (0x1 << 1) +#define RG_SEL_DELAY_VCORE_SFT 2 +#define RG_SEL_DELAY_VCORE_MASK 0x1 +#define RG_SEL_DELAY_VCORE_MASK_SFT (0x1 << 2) +#define RG_AUDGLB_PWRDN_VA32_SFT 4 +#define RG_AUDGLB_PWRDN_VA32_MASK 0x1 +#define RG_AUDGLB_PWRDN_VA32_MASK_SFT (0x1 << 4) +#define RG_AUDGLB_LP_VOW_EN_VA32_SFT 5 +#define RG_AUDGLB_LP_VOW_EN_VA32_MASK 0x1 +#define RG_AUDGLB_LP_VOW_EN_VA32_MASK_SFT (0x1 << 5) +#define RG_AUDGLB_LP2_VOW_EN_VA32_SFT 6 +#define RG_AUDGLB_LP2_VOW_EN_VA32_MASK 0x1 +#define RG_AUDGLB_LP2_VOW_EN_VA32_MASK_SFT (0x1 << 6) + +/* AUDDEC_ANA_CON14 */ +#define RG_LCLDO_DEC_EN_VA32_SFT 0 +#define RG_LCLDO_DEC_EN_VA32_MASK 0x1 +#define RG_LCLDO_DEC_EN_VA32_MASK_SFT (0x1 << 0) +#define RG_LCLDO_DEC_PDDIS_EN_VA18_SFT 1 +#define RG_LCLDO_DEC_PDDIS_EN_VA18_MASK 0x1 +#define RG_LCLDO_DEC_PDDIS_EN_VA18_MASK_SFT (0x1 << 1) +#define RG_LCLDO_DEC_REMOTE_SENSE_VA18_SFT 2 +#define RG_LCLDO_DEC_REMOTE_SENSE_VA18_MASK 0x1 +#define RG_LCLDO_DEC_REMOTE_SENSE_VA18_MASK_SFT (0x1 << 2) +#define RG_NVREG_EN_VAUDP32_SFT 4 +#define RG_NVREG_EN_VAUDP32_MASK 0x1 +#define RG_NVREG_EN_VAUDP32_MASK_SFT (0x1 << 4) +#define RG_NVREG_PULL0V_VAUDP32_SFT 5 +#define RG_NVREG_PULL0V_VAUDP32_MASK 0x1 +#define RG_NVREG_PULL0V_VAUDP32_MASK_SFT (0x1 << 5) +#define RG_AUDPMU_RSVD_VA18_SFT 8 +#define RG_AUDPMU_RSVD_VA18_MASK 0xff +#define RG_AUDPMU_RSVD_VA18_MASK_SFT (0xff << 8) + +/* MT6359_ZCD_CON0 */ +#define RG_AUDZCDENABLE_SFT 0 +#define RG_AUDZCDENABLE_MASK 0x1 +#define RG_AUDZCDENABLE_MASK_SFT (0x1 << 0) +#define RG_AUDZCDGAINSTEPTIME_SFT 1 +#define RG_AUDZCDGAINSTEPTIME_MASK 0x7 +#define RG_AUDZCDGAINSTEPTIME_MASK_SFT (0x7 << 1) +#define RG_AUDZCDGAINSTEPSIZE_SFT 4 +#define RG_AUDZCDGAINSTEPSIZE_MASK 0x3 +#define RG_AUDZCDGAINSTEPSIZE_MASK_SFT (0x3 << 4) +#define RG_AUDZCDTIMEOUTMODESEL_SFT 6 +#define RG_AUDZCDTIMEOUTMODESEL_MASK 0x1 +#define RG_AUDZCDTIMEOUTMODESEL_MASK_SFT (0x1 << 6) + +/* MT6359_ZCD_CON1 */ +#define RG_AUDLOLGAIN_SFT 0 +#define RG_AUDLOLGAIN_MASK 0x1f +#define RG_AUDLOLGAIN_MASK_SFT (0x1f << 0) +#define RG_AUDLORGAIN_SFT 7 +#define RG_AUDLORGAIN_MASK 0x1f +#define RG_AUDLORGAIN_MASK_SFT (0x1f << 7) + +/* MT6359_ZCD_CON2 */ +#define RG_AUDHPLGAIN_SFT 0 +#define RG_AUDHPLGAIN_MASK 0x1f +#define RG_AUDHPLGAIN_MASK_SFT (0x1f << 0) +#define RG_AUDHPRGAIN_SFT 7 +#define RG_AUDHPRGAIN_MASK 0x1f +#define RG_AUDHPRGAIN_MASK_SFT (0x1f << 7) + +/* MT6359_ZCD_CON3 */ +#define RG_AUDHSGAIN_SFT 0 +#define RG_AUDHSGAIN_MASK 0x1f +#define RG_AUDHSGAIN_MASK_SFT (0x1f << 0) + +/* MT6359_ZCD_CON4 */ +#define RG_AUDIVLGAIN_SFT 0 +#define RG_AUDIVLGAIN_MASK 0x7 +#define RG_AUDIVLGAIN_MASK_SFT (0x7 << 0) +#define RG_AUDIVRGAIN_SFT 8 +#define RG_AUDIVRGAIN_MASK 0x7 +#define RG_AUDIVRGAIN_MASK_SFT (0x7 << 8) + +/* MT6359_ZCD_CON5 */ +#define RG_AUDINTGAIN1_SFT 0 +#define RG_AUDINTGAIN1_MASK 0x3f +#define RG_AUDINTGAIN1_MASK_SFT (0x3f << 0) +#define RG_AUDINTGAIN2_SFT 8 +#define RG_AUDINTGAIN2_MASK 0x3f +#define RG_AUDINTGAIN2_MASK_SFT (0x3f << 8) + +/* audio register */ +#define MT6359_GPIO_DIR0 0x88 +#define MT6359_GPIO_DIR0_SET 0x8a +#define MT6359_GPIO_DIR0_CLR 0x8c +#define MT6359_GPIO_DIR1 0x8e +#define MT6359_GPIO_DIR1_SET 0x90 +#define MT6359_GPIO_DIR1_CLR 0x92 + +#define MT6359_DCXO_CW11 0x7a6 +#define MT6359_DCXO_CW12 0x7a8 +#define MT6359_LDO_VAUD18_CON0 0x1c98 + +#define MT6359_GPIO_MODE0 0xcc +#define MT6359_GPIO_MODE0_SET 0xce +#define MT6359_GPIO_MODE0_CLR 0xd0 +#define MT6359_GPIO_MODE1 0xd2 +#define MT6359_GPIO_MODE1_SET 0xd4 +#define MT6359_GPIO_MODE1_CLR 0xd6 +#define MT6359_GPIO_MODE2 0xd8 +#define MT6359_GPIO_MODE2_SET 0xda +#define MT6359_GPIO_MODE2_CLR 0xdc +#define MT6359_GPIO_MODE3 0xde +#define MT6359_GPIO_MODE3_SET 0xe0 +#define MT6359_GPIO_MODE3_CLR 0xe2 +#define MT6359_GPIO_MODE4 0xe4 +#define MT6359_GPIO_MODE4_SET 0xe6 +#define MT6359_GPIO_MODE4_CLR 0xe8 + +#define MT6359_AUD_TOP_ID 0x2300 +#define MT6359_AUD_TOP_REV0 0x2302 +#define MT6359_AUD_TOP_DBI 0x2304 +#define MT6359_AUD_TOP_DXI 0x2306 +#define MT6359_AUD_TOP_CKPDN_TPM0 0x2308 +#define MT6359_AUD_TOP_CKPDN_TPM1 0x230a +#define MT6359_AUD_TOP_CKPDN_CON0 0x230c +#define MT6359_AUD_TOP_CKPDN_CON0_SET 0x230e +#define MT6359_AUD_TOP_CKPDN_CON0_CLR 0x2310 +#define MT6359_AUD_TOP_CKSEL_CON0 0x2312 +#define MT6359_AUD_TOP_CKSEL_CON0_SET 0x2314 +#define MT6359_AUD_TOP_CKSEL_CON0_CLR 0x2316 +#define MT6359_AUD_TOP_CKTST_CON0 0x2318 +#define MT6359_AUD_TOP_CLK_HWEN_CON0 0x231a +#define MT6359_AUD_TOP_CLK_HWEN_CON0_SET 0x231c +#define MT6359_AUD_TOP_CLK_HWEN_CON0_CLR 0x231e +#define MT6359_AUD_TOP_RST_CON0 0x2320 +#define MT6359_AUD_TOP_RST_CON0_SET 0x2322 +#define MT6359_AUD_TOP_RST_CON0_CLR 0x2324 +#define MT6359_AUD_TOP_RST_BANK_CON0 0x2326 +#define MT6359_AUD_TOP_INT_CON0 0x2328 +#define MT6359_AUD_TOP_INT_CON0_SET 0x232a +#define MT6359_AUD_TOP_INT_CON0_CLR 0x232c +#define MT6359_AUD_TOP_INT_MASK_CON0 0x232e +#define MT6359_AUD_TOP_INT_MASK_CON0_SET 0x2330 +#define MT6359_AUD_TOP_INT_MASK_CON0_CLR 0x2332 +#define MT6359_AUD_TOP_INT_STATUS0 0x2334 +#define MT6359_AUD_TOP_INT_RAW_STATUS0 0x2336 +#define MT6359_AUD_TOP_INT_MISC_CON0 0x2338 +#define MT6359_AUD_TOP_MON_CON0 0x233a +#define MT6359_AUDIO_DIG_DSN_ID 0x2380 +#define MT6359_AUDIO_DIG_DSN_REV0 0x2382 +#define MT6359_AUDIO_DIG_DSN_DBI 0x2384 +#define MT6359_AUDIO_DIG_DSN_DXI 0x2386 +#define MT6359_AFE_UL_DL_CON0 0x2388 +#define MT6359_AFE_DL_SRC2_CON0_L 0x238a +#define MT6359_AFE_UL_SRC_CON0_H 0x238c +#define MT6359_AFE_UL_SRC_CON0_L 0x238e +#define MT6359_AFE_ADDA6_L_SRC_CON0_H 0x2390 +#define MT6359_AFE_ADDA6_UL_SRC_CON0_L 0x2392 +#define MT6359_AFE_TOP_CON0 0x2394 +#define MT6359_AUDIO_TOP_CON0 0x2396 +#define MT6359_AFE_MON_DEBUG0 0x2398 +#define MT6359_AFUNC_AUD_CON0 0x239a +#define MT6359_AFUNC_AUD_CON1 0x239c +#define MT6359_AFUNC_AUD_CON2 0x239e +#define MT6359_AFUNC_AUD_CON3 0x23a0 +#define MT6359_AFUNC_AUD_CON4 0x23a2 +#define MT6359_AFUNC_AUD_CON5 0x23a4 +#define MT6359_AFUNC_AUD_CON6 0x23a6 +#define MT6359_AFUNC_AUD_CON7 0x23a8 +#define MT6359_AFUNC_AUD_CON8 0x23aa +#define MT6359_AFUNC_AUD_CON9 0x23ac +#define MT6359_AFUNC_AUD_CON10 0x23ae +#define MT6359_AFUNC_AUD_CON11 0x23b0 +#define MT6359_AFUNC_AUD_CON12 0x23b2 +#define MT6359_AFUNC_AUD_MON0 0x23b4 +#define MT6359_AFUNC_AUD_MON1 0x23b6 +#define MT6359_AUDRC_TUNE_MON0 0x23b8 +#define MT6359_AFE_ADDA_MTKAIF_FIFO_CFG0 0x23ba +#define MT6359_AFE_ADDA_MTKAIF_FIFO_LOG_MON1 0x23bc +#define MT6359_AFE_ADDA_MTKAIF_MON0 0x23be +#define MT6359_AFE_ADDA_MTKAIF_MON1 0x23c0 +#define MT6359_AFE_ADDA_MTKAIF_MON2 0x23c2 +#define MT6359_AFE_ADDA6_MTKAIF_MON3 0x23c4 +#define MT6359_AFE_ADDA_MTKAIF_MON4 0x23c6 +#define MT6359_AFE_ADDA_MTKAIF_MON5 0x23c8 +#define MT6359_AFE_ADDA_MTKAIF_CFG0 0x23ca +#define MT6359_AFE_ADDA_MTKAIF_RX_CFG0 0x23cc +#define MT6359_AFE_ADDA_MTKAIF_RX_CFG1 0x23ce +#define MT6359_AFE_ADDA_MTKAIF_RX_CFG2 0x23d0 +#define MT6359_AFE_ADDA_MTKAIF_RX_CFG3 0x23d2 +#define MT6359_AFE_ADDA_MTKAIF_SYNCWORD_CFG0 0x23d4 +#define MT6359_AFE_ADDA_MTKAIF_SYNCWORD_CFG1 0x23d6 +#define MT6359_AFE_SGEN_CFG0 0x23d8 +#define MT6359_AFE_SGEN_CFG1 0x23da +#define MT6359_AFE_ADC_ASYNC_FIFO_CFG 0x23dc +#define MT6359_AFE_ADC_ASYNC_FIFO_CFG1 0x23de +#define MT6359_AFE_DCCLK_CFG0 0x23e0 +#define MT6359_AFE_DCCLK_CFG1 0x23e2 +#define MT6359_AUDIO_DIG_CFG 0x23e4 +#define MT6359_AUDIO_DIG_CFG1 0x23e6 +#define MT6359_AFE_AUD_PAD_TOP 0x23e8 +#define MT6359_AFE_AUD_PAD_TOP_MON 0x23ea +#define MT6359_AFE_AUD_PAD_TOP_MON1 0x23ec +#define MT6359_AFE_AUD_PAD_TOP_MON2 0x23ee +#define MT6359_AFE_DL_NLE_CFG 0x23f0 +#define MT6359_AFE_DL_NLE_MON 0x23f2 +#define MT6359_AFE_CG_EN_MON 0x23f4 +#define MT6359_AFE_MIC_ARRAY_CFG 0x23f6 +#define MT6359_AFE_CHOP_CFG0 0x23f8 +#define MT6359_AFE_MTKAIF_MUX_CFG 0x23fa +#define MT6359_AUDIO_DIG_2ND_DSN_ID 0x2400 +#define MT6359_AUDIO_DIG_2ND_DSN_REV0 0x2402 +#define MT6359_AUDIO_DIG_2ND_DSN_DBI 0x2404 +#define MT6359_AUDIO_DIG_2ND_DSN_DXI 0x2406 +#define MT6359_AFE_PMIC_NEWIF_CFG3 0x2408 +#define MT6359_AUDIO_DIG_3RD_DSN_ID 0x2480 +#define MT6359_AUDIO_DIG_3RD_DSN_REV0 0x2482 +#define MT6359_AUDIO_DIG_3RD_DSN_DBI 0x2484 +#define MT6359_AUDIO_DIG_3RD_DSN_DXI 0x2486 +#define MT6359_AFE_NCP_CFG0 0x24de +#define MT6359_AFE_NCP_CFG1 0x24e0 +#define MT6359_AFE_NCP_CFG2 0x24e2 +#define MT6359_AUDENC_DSN_ID 0x2500 +#define MT6359_AUDENC_DSN_REV0 0x2502 +#define MT6359_AUDENC_DSN_DBI 0x2504 +#define MT6359_AUDENC_DSN_FPI 0x2506 +#define MT6359_AUDENC_ANA_CON0 0x2508 +#define MT6359_AUDENC_ANA_CON1 0x250a +#define MT6359_AUDENC_ANA_CON2 0x250c +#define MT6359_AUDENC_ANA_CON3 0x250e +#define MT6359_AUDENC_ANA_CON4 0x2510 +#define MT6359_AUDENC_ANA_CON5 0x2512 +#define MT6359_AUDENC_ANA_CON6 0x2514 +#define MT6359_AUDENC_ANA_CON7 0x2516 +#define MT6359_AUDENC_ANA_CON8 0x2518 +#define MT6359_AUDENC_ANA_CON9 0x251a +#define MT6359_AUDENC_ANA_CON10 0x251c +#define MT6359_AUDENC_ANA_CON11 0x251e +#define MT6359_AUDENC_ANA_CON12 0x2520 +#define MT6359_AUDENC_ANA_CON13 0x2522 +#define MT6359_AUDENC_ANA_CON14 0x2524 +#define MT6359_AUDENC_ANA_CON15 0x2526 +#define MT6359_AUDENC_ANA_CON16 0x2528 +#define MT6359_AUDENC_ANA_CON17 0x252a +#define MT6359_AUDENC_ANA_CON18 0x252c +#define MT6359_AUDENC_ANA_CON19 0x252e +#define MT6359_AUDENC_ANA_CON20 0x2530 +#define MT6359_AUDENC_ANA_CON21 0x2532 +#define MT6359_AUDENC_ANA_CON22 0x2534 +#define MT6359_AUDENC_ANA_CON23 0x2536 +#define MT6359_AUDDEC_DSN_ID 0x2580 +#define MT6359_AUDDEC_DSN_REV0 0x2582 +#define MT6359_AUDDEC_DSN_DBI 0x2584 +#define MT6359_AUDDEC_DSN_FPI 0x2586 +#define MT6359_AUDDEC_ANA_CON0 0x2588 +#define MT6359_AUDDEC_ANA_CON1 0x258a +#define MT6359_AUDDEC_ANA_CON2 0x258c +#define MT6359_AUDDEC_ANA_CON3 0x258e +#define MT6359_AUDDEC_ANA_CON4 0x2590 +#define MT6359_AUDDEC_ANA_CON5 0x2592 +#define MT6359_AUDDEC_ANA_CON6 0x2594 +#define MT6359_AUDDEC_ANA_CON7 0x2596 +#define MT6359_AUDDEC_ANA_CON8 0x2598 +#define MT6359_AUDDEC_ANA_CON9 0x259a +#define MT6359_AUDDEC_ANA_CON10 0x259c +#define MT6359_AUDDEC_ANA_CON11 0x259e +#define MT6359_AUDDEC_ANA_CON12 0x25a0 +#define MT6359_AUDDEC_ANA_CON13 0x25a2 +#define MT6359_AUDDEC_ANA_CON14 0x25a4 +#define MT6359_AUDZCD_DSN_ID 0x2600 +#define MT6359_AUDZCD_DSN_REV0 0x2602 +#define MT6359_AUDZCD_DSN_DBI 0x2604 +#define MT6359_AUDZCD_DSN_FPI 0x2606 +#define MT6359_ZCD_CON0 0x2608 +#define MT6359_ZCD_CON1 0x260a +#define MT6359_ZCD_CON2 0x260c +#define MT6359_ZCD_CON3 0x260e +#define MT6359_ZCD_CON4 0x2610 +#define MT6359_ZCD_CON5 0x2612 +#define MT6359_ACCDET_DSN_DIG_ID 0x2680 +#define MT6359_ACCDET_DSN_DIG_REV0 0x2682 +#define MT6359_ACCDET_DSN_DBI 0x2684 +#define MT6359_ACCDET_DSN_FPI 0x2686 +#define MT6359_ACCDET_CON0 0x2688 +#define MT6359_ACCDET_CON1 0x268a +#define MT6359_ACCDET_CON2 0x268c +#define MT6359_ACCDET_CON3 0x268e +#define MT6359_ACCDET_CON4 0x2690 +#define MT6359_ACCDET_CON5 0x2692 +#define MT6359_ACCDET_CON6 0x2694 +#define MT6359_ACCDET_CON7 0x2696 +#define MT6359_ACCDET_CON8 0x2698 +#define MT6359_ACCDET_CON9 0x269a +#define MT6359_ACCDET_CON10 0x269c +#define MT6359_ACCDET_CON11 0x269e +#define MT6359_ACCDET_CON12 0x26a0 +#define MT6359_ACCDET_CON13 0x26a2 +#define MT6359_ACCDET_CON14 0x26a4 +#define MT6359_ACCDET_CON15 0x26a6 +#define MT6359_ACCDET_CON16 0x26a8 +#define MT6359_ACCDET_CON17 0x26aa +#define MT6359_ACCDET_CON18 0x26ac +#define MT6359_ACCDET_CON19 0x26ae +#define MT6359_ACCDET_CON20 0x26b0 +#define MT6359_ACCDET_CON21 0x26b2 +#define MT6359_ACCDET_CON22 0x26b4 +#define MT6359_ACCDET_CON23 0x26b6 +#define MT6359_ACCDET_CON24 0x26b8 +#define MT6359_ACCDET_CON25 0x26ba +#define MT6359_ACCDET_CON26 0x26bc +#define MT6359_ACCDET_CON27 0x26be +#define MT6359_ACCDET_CON28 0x26c0 +#define MT6359_ACCDET_CON29 0x26c2 +#define MT6359_ACCDET_CON30 0x26c4 +#define MT6359_ACCDET_CON31 0x26c6 +#define MT6359_ACCDET_CON32 0x26c8 +#define MT6359_ACCDET_CON33 0x26ca +#define MT6359_ACCDET_CON34 0x26cc +#define MT6359_ACCDET_CON35 0x26ce +#define MT6359_ACCDET_CON36 0x26d0 +#define MT6359_ACCDET_CON37 0x26d2 +#define MT6359_ACCDET_CON38 0x26d4 +#define MT6359_ACCDET_CON39 0x26d6 +#define MT6359_ACCDET_CON40 0x26d8 +#define MT6359_MAX_REGISTER MT6359_ZCD_CON5 + +/* dl bias */ +#define DRBIAS_MASK 0x7 +#define DRBIAS_HP_SFT (RG_AUDBIASADJ_0_VAUDP32_SFT + 0) +#define DRBIAS_HP_MASK_SFT (DRBIAS_MASK << DRBIAS_HP_SFT) +#define DRBIAS_HS_SFT (RG_AUDBIASADJ_0_VAUDP32_SFT + 3) +#define DRBIAS_HS_MASK_SFT (DRBIAS_MASK << DRBIAS_HS_SFT) +#define DRBIAS_LO_SFT (RG_AUDBIASADJ_0_VAUDP32_SFT + 6) +#define DRBIAS_LO_MASK_SFT (DRBIAS_MASK << DRBIAS_LO_SFT) +#define IBIAS_MASK 0x3 +#define IBIAS_HP_SFT (RG_AUDBIASADJ_1_VAUDP32_SFT + 0) +#define IBIAS_HP_MASK_SFT (IBIAS_MASK << IBIAS_HP_SFT) +#define IBIAS_HS_SFT (RG_AUDBIASADJ_1_VAUDP32_SFT + 2) +#define IBIAS_HS_MASK_SFT (IBIAS_MASK << IBIAS_HS_SFT) +#define IBIAS_LO_SFT (RG_AUDBIASADJ_1_VAUDP32_SFT + 4) +#define IBIAS_LO_MASK_SFT (IBIAS_MASK << IBIAS_LO_SFT) +#define IBIAS_ZCD_SFT (RG_AUDBIASADJ_1_VAUDP32_SFT + 6) +#define IBIAS_ZCD_MASK_SFT (IBIAS_MASK << IBIAS_ZCD_SFT) + +/* dl gain */ +#define DL_GAIN_N_10DB_REG (DL_GAIN_N_10DB << 7 | DL_GAIN_N_10DB) +#define DL_GAIN_N_22DB_REG (DL_GAIN_N_22DB << 7 | DL_GAIN_N_22DB) +#define DL_GAIN_N_40DB_REG (DL_GAIN_N_40DB << 7 | DL_GAIN_N_40DB) +#define DL_GAIN_REG_MASK 0x0f9f + +/* mic type mux */ +#define MT_SOC_ENUM_EXT_ID(xname, xenum, xhandler_get, xhandler_put, id) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .device = id,\ + .info = snd_soc_info_enum_double, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = (unsigned long)&(xenum) } + +enum { + MT6359_MTKAIF_PROTOCOL_1 = 0, + MT6359_MTKAIF_PROTOCOL_2, + MT6359_MTKAIF_PROTOCOL_2_CLK_P2, +}; + +enum { + MT6359_AIF_1 = 0, /* dl: hp, rcv, hp+lo */ + MT6359_AIF_2, /* dl: lo only */ + MT6359_AIF_NUM, +}; + +enum { + AUDIO_ANALOG_VOLUME_HSOUTL, + AUDIO_ANALOG_VOLUME_HSOUTR, + AUDIO_ANALOG_VOLUME_HPOUTL, + AUDIO_ANALOG_VOLUME_HPOUTR, + AUDIO_ANALOG_VOLUME_LINEOUTL, + AUDIO_ANALOG_VOLUME_LINEOUTR, + AUDIO_ANALOG_VOLUME_MICAMP1, + AUDIO_ANALOG_VOLUME_MICAMP2, + AUDIO_ANALOG_VOLUME_MICAMP3, + AUDIO_ANALOG_VOLUME_TYPE_MAX +}; + +enum { + MUX_MIC_TYPE_0, /* ain0, micbias 0 */ + MUX_MIC_TYPE_1, /* ain1, micbias 1 */ + MUX_MIC_TYPE_2, /* ain2/3, micbias 2 */ + MUX_PGA_L, + MUX_PGA_R, + MUX_PGA_3, + MUX_HP, + MUX_NUM, +}; + +enum { + DEVICE_HP, + DEVICE_LO, + DEVICE_RCV, + DEVICE_MIC1, + DEVICE_MIC2, + DEVICE_NUM +}; + +enum { + HP_GAIN_CTL_ZCD = 0, + HP_GAIN_CTL_NLE, + HP_GAIN_CTL_NUM, +}; + +enum { + HP_MUX_OPEN = 0, + HP_MUX_HPSPK, + HP_MUX_HP, + HP_MUX_TEST_MODE, + HP_MUX_HP_IMPEDANCE, + HP_MUX_MASK = 0x7, +}; + +enum { + RCV_MUX_OPEN = 0, + RCV_MUX_MUTE, + RCV_MUX_VOICE_PLAYBACK, + RCV_MUX_TEST_MODE, + RCV_MUX_MASK = 0x3, +}; + +enum { + LO_MUX_OPEN = 0, + LO_MUX_L_DAC, + LO_MUX_3RD_DAC, + LO_MUX_TEST_MODE, + LO_MUX_MASK = 0x3, +}; + +/* Supply widget subseq */ +enum { + /* common */ + SUPPLY_SEQ_CLK_BUF, + SUPPLY_SEQ_LDO_VAUD18, + SUPPLY_SEQ_AUD_GLB, + SUPPLY_SEQ_HP_PULL_DOWN, + SUPPLY_SEQ_CLKSQ, + SUPPLY_SEQ_ADC_CLKGEN, + SUPPLY_SEQ_TOP_CK, + SUPPLY_SEQ_TOP_CK_LAST, + SUPPLY_SEQ_DCC_CLK, + SUPPLY_SEQ_MIC_BIAS, + SUPPLY_SEQ_DMIC, + SUPPLY_SEQ_AUD_TOP, + SUPPLY_SEQ_AUD_TOP_LAST, + SUPPLY_SEQ_DL_SDM_FIFO_CLK, + SUPPLY_SEQ_DL_SDM, + SUPPLY_SEQ_DL_NCP, + SUPPLY_SEQ_AFE, + /* playback */ + SUPPLY_SEQ_DL_SRC, + SUPPLY_SEQ_DL_ESD_RESIST, + SUPPLY_SEQ_HP_DAMPING_OFF_RESET_CMFB, + SUPPLY_SEQ_HP_MUTE, + SUPPLY_SEQ_DL_LDO_REMOTE_SENSE, + SUPPLY_SEQ_DL_LDO, + SUPPLY_SEQ_DL_NV, + SUPPLY_SEQ_HP_ANA_TRIM, + SUPPLY_SEQ_DL_IBIST, + /* capture */ + SUPPLY_SEQ_UL_PGA, + SUPPLY_SEQ_UL_ADC, + SUPPLY_SEQ_UL_MTKAIF, + SUPPLY_SEQ_UL_SRC_DMIC, + SUPPLY_SEQ_UL_SRC, +}; + +enum { + CH_L = 0, + CH_R, + NUM_CH, +}; + +enum { + DRBIAS_4UA = 0, + DRBIAS_5UA, + DRBIAS_6UA, + DRBIAS_7UA, + DRBIAS_8UA, + DRBIAS_9UA, + DRBIAS_10UA, + DRBIAS_11UA, +}; + +enum { + IBIAS_4UA = 0, + IBIAS_5UA, + IBIAS_6UA, + IBIAS_7UA, +}; + +enum { + IBIAS_ZCD_3UA = 0, + IBIAS_ZCD_4UA, + IBIAS_ZCD_5UA, + IBIAS_ZCD_6UA, +}; + +enum { + MIC_BIAS_1P7 = 0, + MIC_BIAS_1P8, + MIC_BIAS_1P9, + MIC_BIAS_2P0, + MIC_BIAS_2P1, + MIC_BIAS_2P5, + MIC_BIAS_2P6, + MIC_BIAS_2P7, +}; + +/* dl pga gain */ +enum { + DL_GAIN_8DB = 0, + DL_GAIN_0DB = 8, + DL_GAIN_N_1DB = 9, + DL_GAIN_N_10DB = 18, + DL_GAIN_N_22DB = 30, + DL_GAIN_N_40DB = 0x1f, +}; + +/* Mic Type MUX */ +enum { + MIC_TYPE_MUX_IDLE = 0, + MIC_TYPE_MUX_ACC, + MIC_TYPE_MUX_DMIC, + MIC_TYPE_MUX_DCC, + MIC_TYPE_MUX_DCC_ECM_DIFF, + MIC_TYPE_MUX_DCC_ECM_SINGLE, +}; + +/* UL SRC MUX */ +enum { + UL_SRC_MUX_AMIC = 0, + UL_SRC_MUX_DMIC, +}; + +/* MISO MUX */ +enum { + MISO_MUX_UL1_CH1 = 0, + MISO_MUX_UL1_CH2, + MISO_MUX_UL2_CH1, + MISO_MUX_UL2_CH2, +}; + +/* DMIC MUX */ +enum { + DMIC_MUX_DMIC_DATA0 = 0, + DMIC_MUX_DMIC_DATA1_L, + DMIC_MUX_DMIC_DATA1_L_1, + DMIC_MUX_DMIC_DATA1_R, +}; + +/* ADC L MUX */ +enum { + ADC_MUX_IDLE = 0, + ADC_MUX_AIN0, + ADC_MUX_PREAMPLIFIER, + ADC_MUX_IDLE1, +}; + +/* PGA L MUX */ +enum { + PGA_L_MUX_NONE = 0, + PGA_L_MUX_AIN0, + PGA_L_MUX_AIN1, +}; + +/* PGA R MUX */ +enum { + PGA_R_MUX_NONE = 0, + PGA_R_MUX_AIN2, + PGA_R_MUX_AIN3, + PGA_R_MUX_AIN0, +}; + +/* PGA 3 MUX */ +enum { + PGA_3_MUX_NONE = 0, + PGA_3_MUX_AIN3, + PGA_3_MUX_AIN2, +}; + +struct mt6359_priv { + struct device *dev; + struct regmap *regmap; + unsigned int dl_rate[MT6359_AIF_NUM]; + unsigned int ul_rate[MT6359_AIF_NUM]; + int ana_gain[AUDIO_ANALOG_VOLUME_TYPE_MAX]; + unsigned int mux_select[MUX_NUM]; + unsigned int dmic_one_wire_mode; + int dev_counter[DEVICE_NUM]; + int hp_gain_ctl; + int hp_hifi_mode; + int mtkaif_protocol; + struct regulator *avdd_reg; +}; + +#define CODEC_MT6359_NAME "mtk-codec-mt6359" +#define IS_DCC_BASE(type) ((type) == MIC_TYPE_MUX_DCC || \ + (type) == MIC_TYPE_MUX_DCC_ECM_DIFF || \ + (type) == MIC_TYPE_MUX_DCC_ECM_SINGLE) + +#endif/* end _MT6359_H_ */ diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 9f5aee7de686..f0cba7b5758b 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -251,7 +251,7 @@ static const unsigned short logtable[256] = { * * Acquires the semaphore without jiffies. Try to acquire the semaphore * atomically. Returns 0 if the semaphore has been acquired successfully - * or 1 if it it cannot be acquired. + * or 1 if it cannot be acquired. */ static int nau8825_sema_acquire(struct nau8825 *nau8825, long timeout) { diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index b0ba0d2acbdd..6a2318e04bb7 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -693,7 +693,7 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, } static const struct sdw_device_id rt1308_id[] = { - SDW_SLAVE_ENTRY(0x025d, 0x1308, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt1308_id); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 94bf6bee78e6..b0386f592290 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -717,7 +717,7 @@ static int rt5682_sdw_remove(struct sdw_slave *slave) } static const struct sdw_device_id rt5682_id[] = { - SDW_SLAVE_ENTRY(0x025d, 0x5682, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x5682, 0x2, 0, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt5682_id); diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index a4713bd6508d..93ebf0279b62 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2481,7 +2481,7 @@ static int rt5682_set_bias_level(struct snd_soc_component *component, static bool rt5682_clk_check(struct rt5682_priv *rt5682) { if (!rt5682->master[RT5682_AIF1]) { - dev_err(rt5682->component->dev, "sysclk/dai not set correctly\n"); + dev_dbg(rt5682->component->dev, "sysclk/dai not set correctly\n"); return false; } return true; @@ -2559,7 +2559,7 @@ static unsigned long rt5682_wclk_recalc_rate(struct clk_hw *hw, container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); struct snd_soc_component *component = rt5682->component; - const char * const clk_name = __clk_get_name(hw->clk); + const char * const clk_name = clk_hw_get_name(hw); if (!rt5682_clk_check(rt5682)) return 0; @@ -2583,7 +2583,7 @@ static long rt5682_wclk_round_rate(struct clk_hw *hw, unsigned long rate, container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); struct snd_soc_component *component = rt5682->component; - const char * const clk_name = __clk_get_name(hw->clk); + const char * const clk_name = clk_hw_get_name(hw); if (!rt5682_clk_check(rt5682)) return -EINVAL; @@ -2608,7 +2608,7 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, dai_clks_hw[RT5682_DAI_WCLK_IDX]); struct snd_soc_component *component = rt5682->component; struct clk *parent_clk; - const char * const clk_name = __clk_get_name(hw->clk); + const char * const clk_name = clk_hw_get_name(hw); int pre_div; unsigned int clk_pll2_out; @@ -2766,39 +2766,34 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) struct device *dev = component->dev; struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct rt5682_platform_data *pdata = &rt5682->pdata; - struct clk_init_data init; - struct clk *dai_clk; - struct clk_lookup *dai_clk_lookup; struct clk_hw *dai_clk_hw; - const char *parent_name; int i, ret; for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) { + struct clk_init_data init = { }; + dai_clk_hw = &rt5682->dai_clks_hw[i]; switch (i) { case RT5682_DAI_WCLK_IDX: /* Make MCLK the parent of WCLK */ if (rt5682->mclk) { - parent_name = __clk_get_name(rt5682->mclk); - init.parent_names = &parent_name; + init.parent_data = &(struct clk_parent_data){ + .fw_name = "mclk", + }; init.num_parents = 1; - } else { - init.parent_names = NULL; - init.num_parents = 0; } break; case RT5682_DAI_BCLK_IDX: /* Make WCLK the parent of BCLK */ - parent_name = __clk_get_name( - rt5682->dai_clks[RT5682_DAI_WCLK_IDX]); - init.parent_names = &parent_name; + init.parent_hws = &(const struct clk_hw *){ + &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX] + }; init.num_parents = 1; break; default: dev_err(dev, "Invalid clock index\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } init.name = pdata->dai_clk_names[i]; @@ -2806,39 +2801,26 @@ static int rt5682_register_dai_clks(struct snd_soc_component *component) init.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_GATE; dai_clk_hw->init = &init; - dai_clk = devm_clk_register(dev, dai_clk_hw); - if (IS_ERR(dai_clk)) { - dev_warn(dev, "Failed to register %s: %ld\n", - init.name, PTR_ERR(dai_clk)); - ret = PTR_ERR(dai_clk); - goto err; + ret = devm_clk_hw_register(dev, dai_clk_hw); + if (ret) { + dev_warn(dev, "Failed to register %s: %d\n", + init.name, ret); + return ret; } - rt5682->dai_clks[i] = dai_clk; if (dev->of_node) { devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); } else { - dai_clk_lookup = clkdev_create(dai_clk, init.name, - "%s", dev_name(dev)); - if (!dai_clk_lookup) { - ret = -ENOMEM; - goto err; - } else { - rt5682->dai_clks_lookup[i] = dai_clk_lookup; - } + ret = devm_clk_hw_register_clkdev(dev, dai_clk_hw, + init.name, + dev_name(dev)); + if (ret) + return ret; } } return 0; - -err: - do { - if (rt5682->dai_clks_lookup[i]) - clkdev_drop(rt5682->dai_clks_lookup[i]); - } while (i-- > 0); - - return ret; } #endif /* CONFIG_COMMON_CLK */ @@ -2895,15 +2877,6 @@ static void rt5682_remove(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); -#ifdef CONFIG_COMMON_CLK - int i; - - for (i = RT5682_DAI_NUM_CLKS - 1; i >= 0; --i) { - if (rt5682->dai_clks_lookup[i]) - clkdev_drop(rt5682->dai_clks_lookup[i]); - } -#endif - rt5682_reset(rt5682); } diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 6d94327beae5..354acd735ef4 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1411,8 +1411,6 @@ struct rt5682_priv { #ifdef CONFIG_COMMON_CLK struct clk_hw dai_clks_hw[RT5682_DAI_NUM_CLKS]; - struct clk_lookup *dai_clks_lookup[RT5682_DAI_NUM_CLKS]; - struct clk *dai_clks[RT5682_DAI_NUM_CLKS]; struct clk *mclk; #endif diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 4d14048d1197..5430941cb2da 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -478,7 +478,7 @@ static int rt700_sdw_remove(struct sdw_slave *slave) } static const struct sdw_device_id rt700_id[] = { - SDW_SLAVE_ENTRY(0x025d, 0x700, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x700, 0x1, 0, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt700_id); diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 45b928954b58..dff098ddde01 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -479,7 +479,7 @@ static int rt711_sdw_remove(struct sdw_slave *slave) } static const struct sdw_device_id rt711_id[] = { - SDW_SLAVE_ENTRY(0x025d, 0x711, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x711, 0x2, 0, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt711_id); diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index d11b23d6b240..00e441560f00 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -541,7 +541,7 @@ static int rt715_sdw_probe(struct sdw_slave *slave, } static const struct sdw_device_id rt715_id[] = { - SDW_SLAVE_ENTRY(0x025d, 0x715, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt715_id); diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 0250b94c8f65..7831c96d0d83 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -487,7 +487,7 @@ static int tas5086_init(struct device *dev, struct tas5086_private *priv) /* * If any of the channels is configured to start in Mid-Z mode, * configure 'part 1' of the PWM starts to use Mid-Z, and tell - * all configured mid-z channels to start start under 'part 1'. + * all configured mid-z channels to start under 'part 1'. */ if (priv->pwm_start_mid_z) regmap_write(priv->regmap, TAS5086_PWM_START, diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 467802875c13..8dcea566b375 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -50,6 +50,28 @@ struct aic32x4_priv { struct device *dev; }; +static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u32 adc_reg; + + /* + * Workaround: the datasheet does not mention a required programming + * sequence but experiments show the ADC needs to be reset after each + * capture to avoid audible artifacts. + */ + switch (event) { + case SND_SOC_DAPM_POST_PMD: + adc_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP); + snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg | + AIC32X4_LADC_EN | AIC32X4_RADC_EN); + snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg); + break; + } + return 0; +}; + static int mic_bias_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -434,6 +456,7 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_POST("ADC Reset", aic32x4_reset_adc), SND_SOC_DAPM_OUTPUT("HPL"), SND_SOC_DAPM_OUTPUT("HPR"), @@ -665,7 +688,8 @@ static int aic32x4_set_processing_blocks(struct snd_soc_component *component, } static int aic32x4_setup_clocks(struct snd_soc_component *component, - unsigned int sample_rate) + unsigned int sample_rate, unsigned int channel, + unsigned int bit_depth) { u8 aosr; u16 dosr; @@ -753,7 +777,8 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, dosr); clk_set_rate(clocks[5].clk, - sample_rate * 32); + sample_rate * channel * + bit_depth); return 0; } } @@ -775,9 +800,11 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream, u8 iface1_reg = 0; u8 dacsetup_reg = 0; - aic32x4_setup_clocks(component, params_rate(params)); + aic32x4_setup_clocks(component, params_rate(params), + params_channels(params), + params_physical_width(params)); - switch (params_width(params)) { + switch (params_physical_width(params)) { case 16: iface1_reg |= (AIC32X4_WORD_LEN_16BITS << AIC32X4_IFACE1_DATALEN_SHIFT); @@ -862,7 +889,8 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, #define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000 #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ - | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE \ + | SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops aic32x4_ops = { .hw_params = aic32x4_hw_params, @@ -883,7 +911,7 @@ static struct snd_soc_dai_driver aic32x4_dai = { .capture = { .stream_name = "Capture", .channels_min = 1, - .channels_max = 2, + .channels_max = 8, .rates = AIC32X4_RATES, .formats = AIC32X4_FORMATS,}, .ops = &aic32x4_ops, @@ -953,12 +981,6 @@ static int aic32x4_component_probe(struct snd_soc_component *component) if (ret) return ret; - if (gpio_is_valid(aic32x4->rstn_gpio)) { - ndelay(10); - gpio_set_value(aic32x4->rstn_gpio, 1); - mdelay(1); - } - snd_soc_component_write(component, AIC32X4_RESET, 0x01); if (aic32x4->setup) @@ -1191,10 +1213,6 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) aic32x4->mclk_name = "mclk"; } - ret = aic32x4_register_clocks(dev, aic32x4->mclk_name); - if (ret) - return ret; - if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); @@ -1216,6 +1234,16 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) return ret; } + if (gpio_is_valid(aic32x4->rstn_gpio)) { + ndelay(10); + gpio_set_value_cansleep(aic32x4->rstn_gpio, 1); + mdelay(1); + } + + ret = aic32x4_register_clocks(dev, aic32x4->mclk_name); + if (ret) + return ret; + return 0; } EXPORT_SYMBOL(aic32x4_probe); diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 2f2b2f5d55e4..28b4656c4e14 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c @@ -346,7 +346,7 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_component *comp struct list_head xfer_list; struct wm0010_boot_xfer *xfer; int ret; - struct completion done; + DECLARE_COMPLETION_ONSTACK(done); const struct firmware *fw; const struct dfw_binrec *rec; const struct dfw_inforec *inforec; @@ -370,7 +370,6 @@ static int wm0010_firmware_load(const char *name, struct snd_soc_component *comp wm0010->boot_failed = false; if (WARN_ON(!list_empty(&xfer_list))) return -EINVAL; - init_completion(&done); /* First record should be INFO */ if (rec->command != DFW_CMD_INFO) { diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 0623a2251084..0bd3bbc2aacf 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1702,6 +1702,8 @@ SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME, SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0), SOC_SINGLE("DAC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 5, 1, 0), SOC_SINGLE("ADC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 8, 1, 0), +SOC_SINGLE("DAC Monomix Switch", WM8962_DAC_DSP_MIXING_1, WM8962_DAC_MONOMIX_SHIFT, 1, 0), +SOC_SINGLE("ADC Monomix Switch", WM8962_THREED1, WM8962_ADC_MONOMIX_SHIFT, 1, 0), SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1, 5, 1, 0), diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 7072ffacbdfd..f333e2ff4a16 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -755,7 +755,7 @@ static void pll_factors(struct snd_soc_component *component, u64 Kpart; unsigned int K, Ndiv, Nmod, target; - /* The the PLL output is always 98.304MHz. */ + /* The PLL output is always 98.304MHz. */ target = 98304000; /* If the input frequency is over 14.4MHz then scale it down. */ diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 410cca57da52..4ff0c6cfa32d 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -199,7 +199,7 @@ #define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR 0x7C #define ADSP2_REGION_LOCK_ERR_MASK 0x8000 -#define ADSP2_SLAVE_ERR_MASK 0x4000 +#define ADSP2_ADDR_ERR_MASK 0x4000 #define ADSP2_WDT_TIMEOUT_STS_MASK 0x2000 #define ADSP2_CTRL_ERR_PAUSE_ENA 0x0002 #define ADSP2_CTRL_ERR_EINT 0x0001 @@ -4364,9 +4364,9 @@ irqreturn_t wm_adsp2_bus_error(int irq, void *data) wm_adsp_fatal_error(dsp); } - if (val & (ADSP2_SLAVE_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) { - if (val & ADSP2_SLAVE_ERR_MASK) - adsp_err(dsp, "bus error: slave error\n"); + if (val & (ADSP2_ADDR_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) { + if (val & ADSP2_ADDR_ERR_MASK) + adsp_err(dsp, "bus error: address error\n"); else adsp_err(dsp, "bus error: region lock error\n"); diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 1c4ca5ec8caf..3f76ff71ea47 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -324,7 +324,7 @@ config SND_SOC_FSL_ASOC_CARD help ALSA SoC Audio support with ASRC feature for Freescale SoCs that have ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888, - CS4271, CS4272 and SGTL5000. + CS4271, CS4272, SGTL5000 and TLV320AIC32x4. Say Y if you want to add support for Freescale Generic ASoC Sound Card. config SND_SOC_IMX_AUDMIX diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 52adedc03245..a2dd3b6b7fec 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -617,6 +617,9 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) codec_dai_name = "sgtl5000"; priv->codec_priv.mclk_id = SGTL5000_SYSCLK; priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; + } else if (of_device_is_compatible(np, "fsl,imx-audio-tlv320aic32x4")) { + codec_dai_name = "tlv320aic32x4-hifi"; + priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8962")) { codec_dai_name = "wm8962"; priv->codec_priv.mclk_id = WM8962_SYSCLK_MCLK; @@ -696,6 +699,17 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto asrc_fail; } } else if (of_node_name_eq(cpu_np, "esai")) { + struct clk *esai_clk = clk_get(&cpu_pdev->dev, "extal"); + + if (!IS_ERR(esai_clk)) { + priv->cpu_priv.sysclk_freq[TX] = clk_get_rate(esai_clk); + priv->cpu_priv.sysclk_freq[RX] = clk_get_rate(esai_clk); + clk_put(esai_clk); + } else if (PTR_ERR(esai_clk) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto asrc_fail; + } + priv->cpu_priv.sysclk_id[1] = ESAI_HCKT_EXTAL; priv->cpu_priv.sysclk_id[0] = ESAI_HCKR_EXTAL; } else if (of_node_name_eq(cpu_np, "sai")) { @@ -849,6 +863,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-ac97", }, { .compatible = "fsl,imx-audio-cs42888", }, { .compatible = "fsl,imx-audio-cs427x", }, + { .compatible = "fsl,imx-audio-tlv320aic32x4", }, { .compatible = "fsl,imx-audio-sgtl5000", }, { .compatible = "fsl,imx-audio-wm8962", }, { .compatible = "fsl,imx-audio-wm8960", }, diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index be021250d6e9..e0c39c5f4854 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -154,7 +154,7 @@ static void fsl_dma_abort_stream(struct snd_pcm_substream *substream) /** * fsl_dma_update_pointers - update LD pointers to point to the next period * - * As each period is completed, this function changes the the link + * As each period is completed, this function changes the link * descriptor pointers for that period to point to the next period. */ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index cdff739924e2..62c5fdb678fc 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -37,6 +37,24 @@ static const struct snd_pcm_hw_constraint_list fsl_sai_rate_constraints = { .list = fsl_sai_rates, }; +/** + * fsl_sai_dir_is_synced - Check if stream is synced by the opposite stream + * + * SAI supports synchronous mode using bit/frame clocks of either Transmitter's + * or Receiver's for both streams. This function is used to check if clocks of + * the stream's are synced by the opposite stream. + * + * @sai: SAI context + * @dir: stream direction + */ +static inline bool fsl_sai_dir_is_synced(struct fsl_sai *sai, int dir) +{ + int adir = (dir == TX) ? RX : TX; + + /* current dir in async mode while opposite dir in sync mode */ + return !sai->synchronous[dir] && sai->synchronous[adir]; +} + static irqreturn_t fsl_sai_isr(int irq, void *devid) { struct fsl_sai *sai = (struct fsl_sai *)devid; @@ -332,6 +350,8 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) unsigned int ofs = sai->soc_data->reg_offset; unsigned long clk_rate; u32 savediv = 0, ratio, savesub = freq; + int adir = tx ? RX : TX; + int dir = tx ? TX : RX; u32 id; int ret = 0; @@ -390,19 +410,17 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) * 4) For Tx and Rx are both Synchronous with another SAI, we just * ignore it. */ - if ((sai->synchronous[TX] && !sai->synchronous[RX]) || - (!tx && !sai->synchronous[RX])) { - regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), + if (fsl_sai_dir_is_synced(sai, adir)) { + regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs), FSL_SAI_CR2_MSEL_MASK, FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); - regmap_update_bits(sai->regmap, FSL_SAI_RCR2(ofs), + regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs), FSL_SAI_CR2_DIV_MASK, savediv - 1); - } else if ((sai->synchronous[RX] && !sai->synchronous[TX]) || - (tx && !sai->synchronous[TX])) { - regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), + } else if (!sai->synchronous[dir]) { + regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), FSL_SAI_CR2_MSEL_MASK, FSL_SAI_CR2_MSEL(sai->mclk_id[tx])); - regmap_update_bits(sai->regmap, FSL_SAI_TCR2(ofs), + regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), FSL_SAI_CR2_DIV_MASK, savediv - 1); } @@ -424,6 +442,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, u32 val_cr4 = 0, val_cr5 = 0; u32 slots = (channels == 1) ? 2 : channels; u32 slot_width = word_width; + int adir = tx ? RX : TX; int ret; if (sai->slots) @@ -470,30 +489,16 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream, /* * For SAI master mode, when Tx(Rx) sync with Rx(Tx) clock, Rx(Tx) will * generate bclk and frame clock for Tx(Rx), we should set RCR4(TCR4), - * RCR5(TCR5) and RMR(TMR) for playback(capture), or there will be sync - * error. + * RCR5(TCR5) for playback(capture), or there will be sync error. */ - if (!sai->is_slave_mode) { - if (!sai->synchronous[TX] && sai->synchronous[RX] && !tx) { - regmap_update_bits(sai->regmap, FSL_SAI_TCR4(ofs), - FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, - val_cr4); - regmap_update_bits(sai->regmap, FSL_SAI_TCR5(ofs), - FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | - FSL_SAI_CR5_FBT_MASK, val_cr5); - regmap_write(sai->regmap, FSL_SAI_TMR, - ~0UL - ((1 << channels) - 1)); - } else if (!sai->synchronous[RX] && sai->synchronous[TX] && tx) { - regmap_update_bits(sai->regmap, FSL_SAI_RCR4(ofs), - FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, - val_cr4); - regmap_update_bits(sai->regmap, FSL_SAI_RCR5(ofs), - FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | - FSL_SAI_CR5_FBT_MASK, val_cr5); - regmap_write(sai->regmap, FSL_SAI_RMR, - ~0UL - ((1 << channels) - 1)); - } + if (!sai->is_slave_mode && fsl_sai_dir_is_synced(sai, adir)) { + regmap_update_bits(sai->regmap, FSL_SAI_xCR4(!tx, ofs), + FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK, + val_cr4); + regmap_update_bits(sai->regmap, FSL_SAI_xCR5(!tx, ofs), + FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK | + FSL_SAI_CR5_FBT_MASK, val_cr5); } regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), @@ -522,6 +527,38 @@ static int fsl_sai_hw_free(struct snd_pcm_substream *substream, return 0; } +static void fsl_sai_config_disable(struct fsl_sai *sai, int dir) +{ + unsigned int ofs = sai->soc_data->reg_offset; + bool tx = dir == TX; + u32 xcsr, count = 100; + + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), + FSL_SAI_CSR_TERE, 0); + + /* TERE will remain set till the end of current frame */ + do { + udelay(10); + regmap_read(sai->regmap, FSL_SAI_xCSR(tx, ofs), &xcsr); + } while (--count && xcsr & FSL_SAI_CSR_TERE); + + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), + FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); + + /* + * For sai master mode, after several open/close sai, + * there will be no frame clock, and can't recover + * anymore. Add software reset to fix this issue. + * This is a hardware bug, and will be fix in the + * next sai version. + */ + if (!sai->is_slave_mode) { + /* Software Reset */ + regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR); + /* Clear SR bit to finish the reset */ + regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0); + } +} static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) @@ -530,7 +567,9 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, unsigned int ofs = sai->soc_data->reg_offset; bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - u32 xcsr, count = 100; + int adir = tx ? RX : TX; + int dir = tx ? TX : RX; + u32 xcsr; /* * Asynchronous mode: Clear SYNC for both Tx and Rx. @@ -553,10 +592,22 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); - regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), - FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); - regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), + regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); + /* + * Enable the opposite direction for synchronous mode + * 1. Tx sync with Rx: only set RE for Rx; set TE & RE for Tx + * 2. Rx sync with Tx: only set TE for Tx; set RE & TE for Rx + * + * RM recommends to enable RE after TE for case 1 and to enable + * TE after RE for case 2, but we here may not always guarantee + * that happens: "arecord 1.wav; aplay 2.wav" in case 1 enables + * TE after RE, which is against what RM recommends but should + * be safe to do, judging by years of testing results. + */ + if (fsl_sai_dir_is_synced(sai, adir)) + regmap_update_bits(sai->regmap, FSL_SAI_xCSR((!tx), ofs), + FSL_SAI_CSR_TERE, FSL_SAI_CSR_TERE); regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_xIE_MASK, FSL_SAI_FLAGS); @@ -571,43 +622,23 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, /* Check if the opposite FRDE is also disabled */ regmap_read(sai->regmap, FSL_SAI_xCSR(!tx, ofs), &xcsr); - if (!(xcsr & FSL_SAI_CSR_FRDE)) { - /* Disable both directions and reset their FIFOs */ - regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), - FSL_SAI_CSR_TERE, 0); - regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), - FSL_SAI_CSR_TERE, 0); - - /* TERE will remain set till the end of current frame */ - do { - udelay(10); - regmap_read(sai->regmap, - FSL_SAI_xCSR(tx, ofs), &xcsr); - } while (--count && xcsr & FSL_SAI_CSR_TERE); - - regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), - FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); - regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), - FSL_SAI_CSR_FR, FSL_SAI_CSR_FR); - - /* - * For sai master mode, after several open/close sai, - * there will be no frame clock, and can't recover - * anymore. Add software reset to fix this issue. - * This is a hardware bug, and will be fix in the - * next sai version. - */ - if (!sai->is_slave_mode) { - /* Software Reset for both Tx and Rx */ - regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), - FSL_SAI_CSR_SR); - regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), - FSL_SAI_CSR_SR); - /* Clear SR bit to finish the reset */ - regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); - regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); - } - } + + /* + * If opposite stream provides clocks for synchronous mode and + * it is inactive, disable it before disabling the current one + */ + if (fsl_sai_dir_is_synced(sai, adir) && !(xcsr & FSL_SAI_CSR_FRDE)) + fsl_sai_config_disable(sai, adir); + + /* + * Disable current stream if either of: + * 1. current stream doesn't provide clocks for synchronous mode + * 2. current stream provides clocks for synchronous mode but no + * more stream is active. + */ + if (!fsl_sai_dir_is_synced(sai, dir) || !(xcsr & FSL_SAI_CSR_FRDE)) + fsl_sai_config_disable(sai, dir); + break; default: return -EINVAL; @@ -928,7 +959,7 @@ static int fsl_sai_probe(struct platform_device *pdev) "bus", base, &fsl_sai_regmap_config); /* Compatible with old DTB cases */ - if (IS_ERR(sai->regmap)) + if (IS_ERR(sai->regmap) && PTR_ERR(sai->regmap) != -EPROBE_DEFER) sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "sai", base, &fsl_sai_regmap_config); if (IS_ERR(sai->regmap)) { diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 04d4d28ed511..75365c7bb393 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -424,37 +424,6 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, return ret; } -static int simple_parse_aux_devs(struct device_node *node, - struct asoc_simple_priv *priv) -{ - struct device *dev = simple_priv_to_dev(priv); - struct device_node *aux_node; - struct snd_soc_card *card = simple_priv_to_card(priv); - int i, n, len; - - if (!of_find_property(node, PREFIX "aux-devs", &len)) - return 0; /* Ok to have no aux-devs */ - - n = len / sizeof(__be32); - if (n <= 0) - return -EINVAL; - - card->aux_dev = devm_kcalloc(dev, - n, sizeof(*card->aux_dev), GFP_KERNEL); - if (!card->aux_dev) - return -ENOMEM; - - for (i = 0; i < n; i++) { - aux_node = of_parse_phandle(node, PREFIX "aux-devs", i); - if (!aux_node) - return -EINVAL; - card->aux_dev[i].dlc.of_node = aux_node; - } - - card->num_aux_devs = n; - return 0; -} - static int simple_parse_of(struct asoc_simple_priv *priv) { struct device *dev = simple_priv_to_dev(priv); @@ -504,7 +473,7 @@ static int simple_parse_of(struct asoc_simple_priv *priv) if (ret < 0) return ret; - ret = simple_parse_aux_devs(top, priv); + ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs"); return ret; } diff --git a/sound/soc/intel/atom/sst-atom-controls.c b/sound/soc/intel/atom/sst-atom-controls.c index ff42f629b035..6b5a34a15acb 100644 --- a/sound/soc/intel/atom/sst-atom-controls.c +++ b/sound/soc/intel/atom/sst-atom-controls.c @@ -299,7 +299,7 @@ static int sst_find_and_send_pipe_algo(struct sst_data *drv, { int ret = 0; struct sst_algo_control *bc; - struct sst_module *algo = NULL; + struct sst_module *algo; dev_dbg(&drv->pdev->dev, "Enter: widget=%s\n", pipe); @@ -602,7 +602,7 @@ static int sst_set_pipe_gain(struct sst_ids *ids, int ret = 0; struct sst_gain_mixer_control *mc; struct sst_gain_value *gv; - struct sst_module *gain = NULL; + struct sst_module *gain; list_for_each_entry(gain, &ids->gain_list, node) { struct snd_kcontrol *kctl = gain->kctl; diff --git a/sound/soc/intel/atom/sst-mfld-platform-compress.c b/sound/soc/intel/atom/sst-mfld-platform-compress.c index 1595e01a7e12..89c9c5ad6b21 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-compress.c +++ b/sound/soc/intel/atom/sst-mfld-platform-compress.c @@ -42,8 +42,7 @@ static void sst_drain_notify(void *arg) static int sst_platform_compr_open(struct snd_soc_component *component, struct snd_compr_stream *cstream) { - - int ret_val = 0; + int ret_val; struct snd_compr_runtime *runtime = cstream->runtime; struct sst_runtime_stream *stream; diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index b1cac7abdc0a..6add70500ed8 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -366,7 +366,7 @@ static int sst_media_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct sst_runtime_stream *stream; - int ret_val = 0, str_id; + int ret_val, str_id; stream = substream->runtime->private_data; str_id = stream->stream_info.str_id; @@ -385,7 +385,7 @@ static int sst_media_prepare(struct snd_pcm_substream *substream, if (ret_val) return ret_val; substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER; - return ret_val; + return 0; } static int sst_enable_ssp(struct snd_pcm_substream *substream, diff --git a/sound/soc/intel/atom/sst-mfld-platform.h b/sound/soc/intel/atom/sst-mfld-platform.h index 10c9ecfa7038..8b5777d3229a 100644 --- a/sound/soc/intel/atom/sst-mfld-platform.h +++ b/sound/soc/intel/atom/sst-mfld-platform.h @@ -173,6 +173,6 @@ struct sst_data { struct snd_soc_card *soc_card; struct sst_cmd_sba_hw_set_ssp ssp_cmd; }; -int sst_register_dsp(struct sst_device *sst); -int sst_unregister_dsp(struct sst_device *sst); +int sst_register_dsp(struct sst_device *dev); +int sst_unregister_dsp(struct sst_device *dev); #endif diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c index d6563985e008..d450b9848028 100644 --- a/sound/soc/intel/atom/sst/sst.c +++ b/sound/soc/intel/atom/sst/sst.c @@ -49,7 +49,7 @@ static irqreturn_t intel_sst_interrupt_mrfld(int irq, void *context) union ipc_header_mrfld header; union sst_imr_reg_mrfld imr; struct ipc_post *msg = NULL; - unsigned int size = 0; + unsigned int size; struct intel_sst_drv *drv = (struct intel_sst_drv *) context; irqreturn_t retval = IRQ_HANDLED; @@ -370,7 +370,6 @@ void sst_context_cleanup(struct intel_sst_drv *ctx) kfree(ctx->fw_in_mem); ctx->fw_in_mem = NULL; sst_memcpy_free_resources(ctx); - ctx = NULL; } EXPORT_SYMBOL_GPL(sst_context_cleanup); @@ -424,7 +423,7 @@ static int intel_sst_suspend(struct device *dev) { struct intel_sst_drv *ctx = dev_get_drvdata(dev); struct sst_fw_save *fw_save; - int i, ret = 0; + int i, ret; /* check first if we are already in SW reset */ if (ctx->sst_state == SST_RESET) diff --git a/sound/soc/intel/atom/sst/sst.h b/sound/soc/intel/atom/sst/sst.h index 50441cf6f77d..2bee646e81b8 100644 --- a/sound/soc/intel/atom/sst/sst.h +++ b/sound/soc/intel/atom/sst/sst.h @@ -428,34 +428,34 @@ struct intel_sst_ops { }; int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id); -int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int id); -int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int id); -int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int id); -int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int id); +int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id); +int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id); +int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id); +int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id); int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id); -int sst_send_byte_stream_mrfld(struct intel_sst_drv *ctx, - struct snd_sst_bytes_v2 *sbytes); +int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, + struct snd_sst_bytes_v2 *bytes); int sst_set_stream_param(int str_id, struct snd_sst_params *str_param); int sst_set_metadata(int str_id, char *params); -int sst_get_stream(struct intel_sst_drv *sst_drv_ctx, +int sst_get_stream(struct intel_sst_drv *ctx, struct snd_sst_params *str_param); int sst_get_stream_allocated(struct intel_sst_drv *ctx, struct snd_sst_params *str_param, struct snd_sst_lib_download **lib_dnld); int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx, int str_id, bool partial_drain); -int sst_post_message_mrfld(struct intel_sst_drv *ctx, - struct ipc_post *msg, bool sync); -void sst_process_reply_mrfld(struct intel_sst_drv *ctx, struct ipc_post *msg); -int sst_start_mrfld(struct intel_sst_drv *ctx); -int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *ctx); -void intel_sst_clear_intr_mrfld(struct intel_sst_drv *ctx); - -int sst_load_fw(struct intel_sst_drv *ctx); +int sst_post_message_mrfld(struct intel_sst_drv *sst_drv_ctx, + struct ipc_post *ipc_msg, bool sync); +void sst_process_reply_mrfld(struct intel_sst_drv *sst_drv_ctx, struct ipc_post *msg); +int sst_start_mrfld(struct intel_sst_drv *sst_drv_ctx); +int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx); +void intel_sst_clear_intr_mrfld(struct intel_sst_drv *sst_drv_ctx); + +int sst_load_fw(struct intel_sst_drv *sst_drv_ctx); int sst_load_library(struct snd_sst_lib_download *lib, u8 ops); void sst_post_download_mrfld(struct intel_sst_drv *ctx); int sst_get_block_stream(struct intel_sst_drv *sst_drv_ctx); -void sst_memcpy_free_resources(struct intel_sst_drv *ctx); +void sst_memcpy_free_resources(struct intel_sst_drv *sst_drv_ctx); int sst_wait_interruptible(struct intel_sst_drv *sst_drv_ctx, struct sst_block *block); @@ -490,7 +490,7 @@ int sst_prepare_and_post_msg(struct intel_sst_drv *sst, bool large, bool fill_dsp, bool sync, bool response); void sst_process_pending_msg(struct work_struct *work); -int sst_assign_pvt_id(struct intel_sst_drv *sst_drv_ctx); +int sst_assign_pvt_id(struct intel_sst_drv *drv); int sst_validate_strid(struct intel_sst_drv *sst_drv_ctx, int str_id); struct stream_info *get_stream_info(struct intel_sst_drv *sst_drv_ctx, int str_id); diff --git a/sound/soc/intel/atom/sst/sst_loader.c b/sound/soc/intel/atom/sst/sst_loader.c index fc91a304256b..5c42cce90ce2 100644 --- a/sound/soc/intel/atom/sst/sst_loader.c +++ b/sound/soc/intel/atom/sst/sst_loader.c @@ -398,8 +398,7 @@ int sst_load_fw(struct intel_sst_drv *sst_drv_ctx) dev_dbg(sst_drv_ctx->dev, "sst_load_fw\n"); - if (sst_drv_ctx->sst_state != SST_RESET || - sst_drv_ctx->sst_state == SST_SHUTDOWN) + if (sst_drv_ctx->sst_state != SST_RESET) return -EAGAIN; if (!sst_drv_ctx->fw_in_mem) { diff --git a/sound/soc/intel/atom/sst/sst_pvt.c b/sound/soc/intel/atom/sst/sst_pvt.c index 053c27707147..c099f7df6168 100644 --- a/sound/soc/intel/atom/sst/sst_pvt.c +++ b/sound/soc/intel/atom/sst/sst_pvt.c @@ -188,7 +188,7 @@ int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large, struct intel_sst_drv *sst_drv_ctx, struct sst_block **block, u32 msg_id, u32 drv_id) { - int retval = 0; + int retval; retval = sst_create_ipc_msg(arg, large); if (retval) @@ -198,7 +198,7 @@ int sst_create_block_and_ipc_msg(struct ipc_post **arg, bool large, kfree(*arg); return -ENOMEM; } - return retval; + return 0; } /* diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.h b/sound/soc/intel/baytrail/sst-baytrail-ipc.h index 755098509327..cc960b79e9e1 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.h +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.h @@ -26,8 +26,7 @@ extern struct sst_ops sst_byt_ops; /* stream API */ struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id, - uint32_t (*get_write_position)(struct sst_byt_stream *stream, - void *data), + uint32_t (*notify_position)(struct sst_byt_stream *stream, void *data), void *data); /* stream configuration */ diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index d96fc1313434..12dd41796e82 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -569,9 +569,12 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_MAX98373_SDW select SND_SOC_RT700_SDW select SND_SOC_RT711_SDW + select SND_SOC_RT711_SDCA_SDW select SND_SOC_RT1308_SDW select SND_SOC_RT1308 + select SND_SOC_RT1316_SDW select SND_SOC_RT715_SDW + select SND_SOC_RT715_SDCA_SDW select SND_SOC_RT5682_SDW select SND_SOC_DMIC help diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index dc04acb911b6..de7cc9b86354 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -35,9 +35,10 @@ snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o hda_dsp_common.o snd-soc-ehl-rt5660-objs := ehl_rt5660.o hda_dsp_common.o snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_max98373.o \ - sof_sdw_rt711.o sof_sdw_rt700.o \ - sof_sdw_rt1308.o sof_sdw_rt715.o \ - sof_sdw_rt5682.o \ + sof_sdw_rt1308.o sof_sdw_rt1316.o \ + sof_sdw_rt5682.o sof_sdw_rt700.o \ + sof_sdw_rt711.o sof_sdw_rt711_sdca.o \ + sof_sdw_rt715.o sof_sdw_rt715_sdca.o \ sof_maxim_common.o \ sof_sdw_dmic.o sof_sdw_hdmi.o hda_dsp_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index ce7320916b22..1412a9941ed4 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -87,14 +87,14 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *chan = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); /* The ADSP will covert the FE rate to 48k, max 4-channels */ rate->min = rate->max = 48000; - channels->min = 2; - channels->max = 4; + chan->min = 2; + chan->max = 4; /* set SSP0 to 24 bit */ snd_mask_set_format(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 86e427e3822f..297871bcaf5d 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -140,13 +140,13 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *chan = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); /* The ADSP will covert the FE rate to 48k, stereo */ rate->min = rate->max = 48000; - channels->min = channels->max = 2; + chan->min = chan->max = 2; /* set SSP0 to 16 bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index f6399077d291..56972af13b6f 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -87,13 +87,13 @@ static int broadwell_ssp0_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *chan = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); /* The ADSP will covert the FE rate to 48k, stereo */ rate->min = rate->max = 48000; - channels->min = channels->max = 2; + chan->min = chan->max = 2; /* set SSP0 to 16 bit */ params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 9cb42ba40c07..0b50b3646d55 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -99,7 +99,7 @@ static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), 50); - return ret; + return 0; } static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd, diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 1a6961592029..b6e63ea13d64 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -66,6 +66,10 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd) int j; int ret = 0; + /* set spk pin by playback only */ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + return 0; + for_each_rtd_codec_dais(rtd, j, codec_dai) { struct snd_soc_component *component = codec_dai->component; struct snd_soc_dapm_context *dapm = @@ -86,9 +90,6 @@ int max98373_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - /* Make sure no streams are active before disable pin */ - if (snd_soc_dai_active(codec_dai) != 1) - break; ret = snd_soc_dapm_disable_pin(dapm, pin_name); if (!ret) snd_soc_dapm_sync(dapm); diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 0129d23694ed..9a6f10ede427 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -119,6 +119,19 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { .driver_data = (void *)(SOF_RT5682_MCLK_EN | SOF_RT5682_SSP_CODEC(0)), }, + { + .callback = sof_rt5682_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Terrador"), + }, + .driver_data = (void *)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98373_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(2) | + SOF_RT5682_NUM_HDMIDEV(4)), + }, {} }; diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 2463d432bf4d..00d10e83872a 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -123,6 +123,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + SOF_SDW_FOUR_SPK), + }, {} }; @@ -132,6 +141,10 @@ static struct snd_soc_codec_conf codec_conf[] = { .dlc = COMP_CODEC_CONF("sdw:0:25d:711:0"), .name_prefix = "rt711", }, + { + .dlc = COMP_CODEC_CONF("sdw:0:25d:711:1"), + .name_prefix = "rt711", + }, /* rt1308 w/ I2S connection */ { .dlc = COMP_CODEC_CONF("i2c-10EC1308:00"), @@ -173,6 +186,23 @@ static struct snd_soc_codec_conf codec_conf[] = { .dlc = COMP_CODEC_CONF("sdw:0:25d:5682:0"), .name_prefix = "rt5682", }, + /* rt5682 on link2 */ + { + .dlc = COMP_CODEC_CONF("sdw:2:25d:5682:0"), + .name_prefix = "rt5682", + }, + { + .dlc = COMP_CODEC_CONF("sdw:1:25d:1316:1"), + .name_prefix = "rt1316-1", + }, + { + .dlc = COMP_CODEC_CONF("sdw:2:25d:1316:1"), + .name_prefix = "rt1316-2", + }, + { + .dlc = COMP_CODEC_CONF("sdw:3:25d:714:1"), + .name_prefix = "rt714", + }, }; static struct snd_soc_dai_link_component dmic_component[] = { @@ -207,20 +237,29 @@ static const struct snd_soc_ops sdw_ops = { static struct sof_sdw_codec_info codec_info_list[] = { { - .id = 0x700, + .part_id = 0x700, .direction = {true, true}, .dai_name = "rt700-aif1", .init = sof_sdw_rt700_init, }, { - .id = 0x711, + .part_id = 0x711, + .version_id = 3, + .direction = {true, true}, + .dai_name = "rt711-sdca-aif1", + .init = sof_sdw_rt711_sdca_init, + .exit = sof_sdw_rt711_sdca_exit, + }, + { + .part_id = 0x711, + .version_id = 2, .direction = {true, true}, .dai_name = "rt711-aif1", .init = sof_sdw_rt711_init, .exit = sof_sdw_rt711_exit, }, { - .id = 0x1308, + .part_id = 0x1308, .acpi_id = "10EC1308", .direction = {true, false}, .dai_name = "rt1308-aif", @@ -228,38 +267,57 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt1308_init, }, { - .id = 0x715, + .part_id = 0x1316, + .direction = {true, true}, + .dai_name = "rt1316-aif", + .init = sof_sdw_rt1316_init, + }, + { + .part_id = 0x714, + .direction = {false, true}, + .dai_name = "rt715-aif2", + .init = sof_sdw_rt715_sdca_init, + }, + { + .part_id = 0x715, .direction = {false, true}, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_init, }, { - .id = 0x8373, + .part_id = 0x8373, .direction = {true, true}, .dai_name = "max98373-aif1", .init = sof_sdw_mx8373_init, .codec_card_late_probe = sof_sdw_mx8373_late_probe, }, { - .id = 0x5682, + .part_id = 0x5682, .direction = {true, true}, .dai_name = "rt5682-sdw", .init = sof_sdw_rt5682_init, }, }; -static inline int find_codec_info_part(unsigned int part_id) +static inline int find_codec_info_part(u64 adr) { + unsigned int part_id, sdw_version; int i; + part_id = SDW_PART_ID(adr); + sdw_version = SDW_VERSION(adr); for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) - if (part_id == codec_info_list[i].id) - break; + /* + * A codec info is for all sdw version with the part id if + * version_id is not specified in the codec info. + */ + if (part_id == codec_info_list[i].part_id && + (!codec_info_list[i].version_id || + sdw_version == codec_info_list[i].version_id)) + return i; - if (i == ARRAY_SIZE(codec_info_list)) - return -EINVAL; + return -EINVAL; - return i; } static inline int find_codec_info_acpi(const u8 *acpi_id) @@ -305,13 +363,12 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links, for (link = links; link->num_adr; link++) { const struct snd_soc_acpi_endpoint *endpoint; - int part_id, codec_index; + int codec_index; int stream; u64 adr; adr = link->adr_d->adr; - part_id = SDW_PART_ID(adr); - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; @@ -439,7 +496,7 @@ static int create_codec_dai_name(struct device *dev, if (!codec[comp_index].name) return -ENOMEM; - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; @@ -463,11 +520,9 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, * same group. */ for (i = 0; i < link->num_adr; i++) { - unsigned int part_id; int codec_index; - part_id = SDW_PART_ID(link->adr_d[i].adr); - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(link->adr_d[i].adr); if (codec_index < 0) return codec_index; @@ -571,7 +626,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, struct snd_soc_dai_link_component *codecs; int cpu_dai_id[SDW_MAX_CPU_DAIS]; int cpu_dai_num, cpu_dai_index; - unsigned int part_id, group_id; + unsigned int group_id; int codec_idx = 0; int i = 0, j = 0; int codec_index; @@ -613,8 +668,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, } /* find codec info to create BE DAI */ - part_id = SDW_PART_ID(link->adr_d[0].adr); - codec_index = find_codec_info_part(part_id); + codec_index = find_codec_info_part(link->adr_d[0].adr); if (codec_index < 0) return codec_index; @@ -1032,12 +1086,43 @@ static int mc_probe(struct platform_device *pdev) return ret; } +static int mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_dai_link *link; + int ret; + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (!codec_info_list[i].exit) + continue; + /* + * We don't need to call .exit function if there is no matched + * dai link found. + */ + for_each_card_prelinks(card, j, link) { + if (!strcmp(link->codecs[0].dai_name, + codec_info_list[i].dai_name)) { + ret = codec_info_list[i].exit(&pdev->dev, link); + if (ret) + dev_warn(&pdev->dev, + "codec exit failed %d\n", + ret); + break; + } + } + } + + return 0; +} + static struct platform_driver sof_sdw_driver = { .driver = { .name = "sof_sdw", .pm = &snd_soc_pm_ops, }, .probe = mc_probe, + .remove = mc_remove, }; module_platform_driver(sof_sdw_driver); diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 12e32439ba46..6a5d46589baf 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -51,7 +51,8 @@ enum { #define SOF_SDW_NO_AGGREGATION BIT(12) struct sof_sdw_codec_info { - const int id; + const int part_id; + const int version_id; int amp_num; const u8 acpi_id[ACPI_ID_LEN]; const bool direction[2]; // playback & capture support @@ -63,6 +64,7 @@ struct sof_sdw_codec_info { struct sof_sdw_codec_info *info, bool playback); + int (*exit)(struct device *dev, struct snd_soc_dai_link *dai_link); bool late_probe; int (*codec_card_late_probe)(struct snd_soc_card *card); }; @@ -94,6 +96,13 @@ int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, bool playback); int sof_sdw_rt711_exit(struct device *dev, struct snd_soc_dai_link *dai_link); +/* RT711-SDCA support */ +int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); +int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link); + /* RT700 support */ int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, @@ -108,12 +117,24 @@ int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link, struct sof_sdw_codec_info *info, bool playback); +/* RT1316 support */ +int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + /* RT715 support */ int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); +/* RT715-SDCA support */ +int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + /* MAX98373 support */ int sof_sdw_mx8373_init(const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, diff --git a/sound/soc/intel/boards/sof_sdw_dmic.c b/sound/soc/intel/boards/sof_sdw_dmic.c index 89b0824b2381..19df0f7a1d85 100644 --- a/sound/soc/intel/boards/sof_sdw_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_dmic.c @@ -7,6 +7,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget dmic_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_max98373.c b/sound/soc/intel/boards/sof_sdw_max98373.c index 6437872a9b3d..905582aaf58c 100644 --- a/sound/soc/intel/boards/sof_sdw_max98373.c +++ b/sound/soc/intel/boards/sof_sdw_max98373.c @@ -6,8 +6,10 @@ #include <linux/device.h> #include <linux/errno.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include "sof_sdw_common.h" #include "sof_maxim_common.h" diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c index 3655e890acec..dba2fd28d77f 100644 --- a/sound/soc/intel/boards/sof_sdw_rt1308.c +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -7,8 +7,10 @@ #include <linux/device.h> #include <linux/errno.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include "sof_sdw_common.h" #include "../../codecs/rt1308.h" diff --git a/sound/soc/intel/boards/sof_sdw_rt1316.c b/sound/soc/intel/boards/sof_sdw_rt1316.c new file mode 100644 index 000000000000..2c566330f236 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt1316.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt1316 - Helpers to handle RT1316 from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <sound/control.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> +#include "sof_sdw_common.h" + +static const struct snd_soc_dapm_widget rt1316_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +/* + * dapm routes for rt1316 will be registered dynamically according + * to the number of rt1316 used. The first two entries will be registered + * for one codec case, and the last two entries are also registered + * if two 1316s are used. + */ +static const struct snd_soc_dapm_route rt1316_map[] = { + { "Speaker", NULL, "rt1316-1 SPOL" }, + { "Speaker", NULL, "rt1316-1 SPOR" }, + { "Speaker", NULL, "rt1316-2 SPOL" }, + { "Speaker", NULL, "rt1316-2 SPOR" }, +}; + +static const struct snd_kcontrol_new rt1316_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static int first_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_add_card_controls(card, rt1316_controls, + ARRAY_SIZE(rt1316_controls)); + if (ret) { + dev_err(card->dev, "rt1316 controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt1316_widgets, + ARRAY_SIZE(rt1316_widgets)); + if (ret) { + dev_err(card->dev, "rt1316 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map, 2); + if (ret) + dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); + + return ret; +} + +static int second_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1316_map + 2, 2); + if (ret) + dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); + + return ret; +} + +static int all_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + ret = first_spk_init(rtd); + if (ret) + return ret; + + return second_spk_init(rtd); +} + +int sof_sdw_rt1316_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* Count amp number and do init on playback link only. */ + if (!playback) + return 0; + + info->amp_num++; + if (info->amp_num == 1) + dai_links->init = first_spk_init; + + if (info->amp_num == 2) { + /* + * if two 1316s are in one dai link, the init function + * in this dai link will be first set for the first speaker, + * and it should be reset to initialize all speakers when + * the second speaker is found. + */ + if (dai_links->init) + dai_links->init = all_spk_init; + else + dai_links->init = second_spk_init; + } + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index da354ba83939..5fa1a59615b6 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -10,8 +10,10 @@ #include <linux/input.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include <sound/jack.h> #include "sof_sdw_common.h" diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 5f50491ba5ee..bff69cfe27f4 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -8,8 +8,10 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/input.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include <sound/jack.h> #include "sof_sdw_common.h" diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 606009fa3901..04074c09dded 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -10,8 +10,10 @@ #include <linux/input.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> +#include <sound/control.h> #include <sound/soc.h> #include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> #include <sound/jack.h> #include "sof_sdw_common.h" diff --git a/sound/soc/intel/boards/sof_sdw_rt711_sdca.c b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c new file mode 100644 index 000000000000..19496f0f9110 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt711_sdca.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt711_sdca - Helpers to handle RT711-SDCA from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/input.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/control.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/soc-dapm.h> +#include <sound/jack.h> +#include "sof_sdw_common.h" + +/* + * Note this MUST be called before snd_soc_register_card(), so that the props + * are in place before the codec component driver's probe function parses them. + */ +static int rt711_sdca_add_codec_device_props(const char *sdw_dev_name) +{ + struct property_entry props[MAX_NO_PROPS] = {}; + struct device *sdw_dev; + int ret; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name); + if (!sdw_dev) + return -EPROBE_DEFER; + + if (SOF_RT711_JDSRC(sof_sdw_quirk)) { + props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", + SOF_RT711_JDSRC(sof_sdw_quirk)); + } + + ret = device_add_properties(sdw_dev, props); + put_device(sdw_dev); + + return ret; +} + +static const struct snd_soc_dapm_widget rt711_sdca_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route rt711_sdca_map[] = { + /* Headphones */ + { "Headphone", NULL, "rt711 HP" }, + { "rt711 MIC2", NULL, "Headset Mic" }, +}; + +static const struct snd_kcontrol_new rt711_sdca_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_jack_pin rt711_sdca_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int rt711_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + struct snd_soc_jack *jack; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s hs:rt711-sdca", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt711_sdca_controls, + ARRAY_SIZE(rt711_sdca_controls)); + if (ret) { + dev_err(card->dev, "rt711-sdca controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt711_sdca_widgets, + ARRAY_SIZE(rt711_sdca_widgets)); + if (ret) { + dev_err(card->dev, "rt711-sdca widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt711_sdca_map, + ARRAY_SIZE(rt711_sdca_map)); + + if (ret) { + dev_err(card->dev, "rt711-sdca map addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + &ctx->sdw_headset, + rt711_sdca_jack_pins, + ARRAY_SIZE(rt711_sdca_jack_pins)); + if (ret) { + dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n", + ret); + return ret; + } + + jack = &ctx->sdw_headset; + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, jack, NULL); + + if (ret) + dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n", + ret); + + return ret; +} + +int sof_sdw_rt711_sdca_exit(struct device *dev, struct snd_soc_dai_link *dai_link) +{ + struct device *sdw_dev; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, + dai_link->codecs[0].name); + if (!sdw_dev) + return -EINVAL; + + device_remove_properties(sdw_dev); + put_device(sdw_dev); + + return 0; +} + +int sof_sdw_rt711_sdca_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + int ret; + + /* + * headset should be initialized once. + * Do it with dai link for playback. + */ + if (!playback) + return 0; + + ret = rt711_sdca_add_codec_device_props(dai_links->codecs[0].name); + if (ret < 0) + return ret; + + dai_links->init = rt711_sdca_rtd_init; + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c new file mode 100644 index 000000000000..c056e56a139b --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt715_sdca - Helpers to handle RT715-SDCA from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "sof_sdw_common.h" + +static int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:rt715-sdca", + card->components); + if (!card->components) + return -ENOMEM; + + return 0; +} + +int sof_sdw_rt715_sdca_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* + * DAI ID is fixed at SDW_DMIC_DAI_ID for 715-SDCA to + * keep sdw DMIC and HDMI setting static in UCM + */ + if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX) + dai_links->id = SDW_DMIC_DAI_ID; + + dai_links->init = rt715_sdca_rtd_init; + + return 0; +} diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index dee1f0fa998b..ec01884ef93d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -112,15 +112,15 @@ static const struct snd_soc_acpi_link_adr cml_rvp[] = { static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { { - .adr = 0x000010025D071100, + .adr = 0x000020025D071100, .num_endpoints = 1, .endpoints = &single_endpoint, } }; -static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { +static const struct snd_soc_acpi_adr_device rt1308_1_single_adr[] = { { - .adr = 0x000110025D130800, + .adr = 0x000120025D130800, .num_endpoints = 1, .endpoints = &single_endpoint, } @@ -128,7 +128,7 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = { { - .adr = 0x000110025D130800, + .adr = 0x000120025D130800, .num_endpoints = 1, .endpoints = &spk_l_endpoint, } @@ -136,7 +136,7 @@ static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = { static const struct snd_soc_acpi_adr_device rt1308_2_group1_adr[] = { { - .adr = 0x000210025D130800, + .adr = 0x000220025D130800, .num_endpoints = 1, .endpoints = &spk_r_endpoint, } @@ -144,7 +144,39 @@ static const struct snd_soc_acpi_adr_device rt1308_2_group1_adr[] = { static const struct snd_soc_acpi_adr_device rt715_3_adr[] = { { - .adr = 0x000310025D071500, + .adr = 0x000320025D071500, + .num_endpoints = 1, + .endpoints = &single_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { + { + .adr = 0x000030025D071101, + .num_endpoints = 1, + .endpoints = &single_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt1316_1_group1_adr[] = { + { + .adr = 0x000131025D131601, /* unique ID is set for some reason */ + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt1316_2_group1_adr[] = { + { + .adr = 0x000230025D131601, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt714_3_adr[] = { + { + .adr = 0x000330025D071401, .num_endpoints = 1, .endpoints = &single_endpoint, } @@ -182,8 +214,8 @@ static const struct snd_soc_acpi_link_adr cml_3_in_1_mono_amp[] = { }, { .mask = BIT(1), - .num_adr = ARRAY_SIZE(rt1308_1_adr), - .adr_d = rt1308_1_adr, + .num_adr = ARRAY_SIZE(rt1308_1_single_adr), + .adr_d = rt1308_1_single_adr, }, { .mask = BIT(3), @@ -193,6 +225,30 @@ static const struct snd_soc_acpi_link_adr cml_3_in_1_mono_amp[] = { {} }; +static const struct snd_soc_acpi_link_adr cml_3_in_1_sdca[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1316_1_group1_adr), + .adr_d = rt1316_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1316_2_group1_adr), + .adr_d = rt1316_2_group1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt714_3_adr), + .adr_d = rt714_3_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[] = { { .link_mask = 0xF, /* 4 active links required */ @@ -202,6 +258,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[] = { .sof_tplg_filename = "sof-cml-rt711-rt1308-rt715.tplg", }, { + .link_mask = 0xF, /* 4 active links required */ + .links = cml_3_in_1_sdca, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-cml.ri", + .sof_tplg_filename = "sof-cml-rt711-rt1316-rt714.tplg", + }, + { /* * link_mask should be 0xB, but all links are enabled by BIOS. * This entry will be selected if there is no rt1308 exposed diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c index 6a0bcc1a8429..7d61e0da808b 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c @@ -27,8 +27,39 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_machines[] = { }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_machines); +static const struct snd_soc_acpi_endpoint single_endpoint = { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, +}; + +static const struct snd_soc_acpi_adr_device rt5682_2_adr[] = { + { + .adr = 0x000220025D568200, + .num_endpoints = 1, + .endpoints = &single_endpoint, + } +}; + +static const struct snd_soc_acpi_link_adr up_extreme_rt5682_2[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt5682_2_adr), + .adr_d = rt5682_2_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[] = { - {}, + { + .link_mask = BIT(2), + .links = up_extreme_rt5682_2, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-cnl.ri", + .sof_tplg_filename = "sof-cnl-rt5682-sdw2.tplg" + }, + {} }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cnl_sdw_machines); diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index 6927bbbc66fc..ebe13197410f 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -73,7 +73,7 @@ static const struct snd_soc_acpi_link_adr icl_rvp[] = { static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { { - .adr = 0x000010025D071100, + .adr = 0x000020025D071100, .num_endpoints = 1, .endpoints = &single_endpoint, } @@ -81,7 +81,7 @@ static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { { - .adr = 0x000110025D130800, + .adr = 0x000120025D130800, .num_endpoints = 1, .endpoints = &single_endpoint, } @@ -89,7 +89,7 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = { { - .adr = 0x000110025D130800, + .adr = 0x000120025D130800, .num_endpoints = 1, .endpoints = &spk_l_endpoint, } @@ -97,7 +97,7 @@ static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = { static const struct snd_soc_acpi_adr_device rt1308_2_group1_adr[] = { { - .adr = 0x000210025D130800, + .adr = 0x000220025D130800, .num_endpoints = 1, .endpoints = &spk_r_endpoint, } @@ -105,7 +105,7 @@ static const struct snd_soc_acpi_adr_device rt1308_2_group1_adr[] = { static const struct snd_soc_acpi_adr_device rt715_3_adr[] = { { - .adr = 0x000310025D071500, + .adr = 0x000320025D071500, .num_endpoints = 1, .endpoints = &single_endpoint, } diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 2ffa608d987d..6816847bee40 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -37,13 +37,13 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = { static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { { - .adr = 0x000010025D071100, + .adr = 0x000020025D071100, .num_endpoints = 1, .endpoints = &single_endpoint, } }; -static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { +static const struct snd_soc_acpi_adr_device rt1308_1_dual_adr[] = { { .adr = 0x000120025D130800, .num_endpoints = 1, @@ -56,6 +56,38 @@ static const struct snd_soc_acpi_adr_device rt1308_1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1308_1_single_adr[] = { + { + .adr = 0x000120025D130800, + .num_endpoints = 1, + .endpoints = &single_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = { + { + .adr = 0x000120025D130800, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt1308_2_group1_adr[] = { + { + .adr = 0x000220025D130800, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt715_3_adr[] = { + { + .adr = 0x000320025D071500, + .num_endpoints = 1, + .endpoints = &single_endpoint, + } +}; + static const struct snd_soc_acpi_adr_device mx8373_1_adr[] = { { .adr = 0x000123019F837300, @@ -77,6 +109,38 @@ static const struct snd_soc_acpi_adr_device rt5682_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { + { + .adr = 0x000030025D071101, + .num_endpoints = 1, + .endpoints = &single_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt1316_1_group1_adr[] = { + { + .adr = 0x000131025D131601, /* unique ID is set for some reason */ + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt1316_2_group1_adr[] = { + { + .adr = 0x000230025D131601, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + } +}; + +static const struct snd_soc_acpi_adr_device rt714_3_adr[] = { + { + .adr = 0x000330025D071401, + .num_endpoints = 1, + .endpoints = &single_endpoint, + } +}; + static const struct snd_soc_acpi_link_adr tgl_i2s_rt1308[] = { { .mask = BIT(0), @@ -94,8 +158,8 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = { }, { .mask = BIT(1), - .num_adr = ARRAY_SIZE(rt1308_1_adr), - .adr_d = rt1308_1_adr, + .num_adr = ARRAY_SIZE(rt1308_1_dual_adr), + .adr_d = rt1308_1_dual_adr, }, {} }; @@ -114,6 +178,73 @@ static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = { {} }; +static const struct snd_soc_acpi_link_adr tgl_3_in_1_default[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_0_adr), + .adr_d = rt711_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1308_1_group1_adr), + .adr_d = rt1308_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1308_2_group1_adr), + .adr_d = rt1308_2_group1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt715_3_adr), + .adr_d = rt715_3_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr tgl_3_in_1_mono_amp[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_0_adr), + .adr_d = rt711_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1308_1_single_adr), + .adr_d = rt1308_1_single_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt715_3_adr), + .adr_d = rt715_3_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1316_1_group1_adr), + .adr_d = rt1316_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1316_2_group1_adr), + .adr_d = rt1316_2_group1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt714_3_adr), + .adr_d = rt714_3_adr, + }, + {} +}; + static struct snd_soc_acpi_codecs tgl_max98373_amp = { .num_codecs = 1, .codecs = {"MX98373"} @@ -151,6 +282,32 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines); /* this table is used when there is no I2S codec present */ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { { + .link_mask = 0xF, /* 4 active links required */ + .links = tgl_3_in_1_default, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-rt711-rt1308-rt715.tplg", + }, + { + /* + * link_mask should be 0xB, but all links are enabled by BIOS. + * This entry will be selected if there is no rt1308 exposed + * on link2 since it will fail to match the above entry. + */ + .link_mask = 0xF, + .links = tgl_3_in_1_mono_amp, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-rt711-rt1308-mono-rt715.tplg", + }, + { + .link_mask = 0xF, /* 4 active links required */ + .links = tgl_3_in_1_sdca, + .drv_name = "sof_sdw", + .sof_fw_filename = "sof-tgl.ri", + .sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg", + }, + { .link_mask = 0x3, /* rt711 on link 0 and 2 rt1308s on link 1 */ .links = tgl_rvp, .drv_name = "sof_sdw", diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index 3d8765ce3e0d..9a760123b46f 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h @@ -344,7 +344,7 @@ void sst_fw_unload(struct sst_fw *sst_fw); /* Create/Free firmware modules */ struct sst_module *sst_module_new(struct sst_fw *sst_fw, struct sst_module_template *template, void *private); -void sst_module_free(struct sst_module *module); +void sst_module_free(struct sst_module *sst_module); struct sst_module *sst_module_get_from_id(struct sst_dsp *dsp, u32 id); int sst_module_alloc_blocks(struct sst_module *module); int sst_module_free_blocks(struct sst_module *module); diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h index 604a80c5859b..d55014587415 100644 --- a/sound/soc/intel/common/sst-dsp.h +++ b/sound/soc/intel/common/sst-dsp.h @@ -268,15 +268,14 @@ void sst_dsp_ipc_msg_tx(struct sst_dsp *dsp, u32 msg); u32 sst_dsp_ipc_msg_rx(struct sst_dsp *dsp); /* Mailbox management */ -int sst_dsp_mailbox_init(struct sst_dsp *dsp, u32 inbox_offset, +int sst_dsp_mailbox_init(struct sst_dsp *sst, u32 inbox_offset, size_t inbox_size, u32 outbox_offset, size_t outbox_size); -void sst_dsp_inbox_write(struct sst_dsp *dsp, void *message, size_t bytes); -void sst_dsp_inbox_read(struct sst_dsp *dsp, void *message, size_t bytes); -void sst_dsp_outbox_write(struct sst_dsp *dsp, void *message, size_t bytes); -void sst_dsp_outbox_read(struct sst_dsp *dsp, void *message, size_t bytes); -void sst_dsp_mailbox_dump(struct sst_dsp *dsp, size_t bytes); -int sst_dsp_register_poll(struct sst_dsp *dsp, u32 offset, u32 mask, - u32 expected_value, u32 timeout, char *operation); +void sst_dsp_inbox_write(struct sst_dsp *sst, void *message, size_t bytes); +void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes); +void sst_dsp_outbox_write(struct sst_dsp *sst, void *message, size_t bytes); +void sst_dsp_outbox_read(struct sst_dsp *sst, void *message, size_t bytes); +int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask, + u32 target, u32 time, char *operation); /* Debug */ void sst_dsp_dump(struct sst_dsp *sst); diff --git a/sound/soc/intel/common/sst-firmware.c b/sound/soc/intel/common/sst-firmware.c index 0594f89ea7f2..1189ec37134e 100644 --- a/sound/soc/intel/common/sst-firmware.c +++ b/sound/soc/intel/common/sst-firmware.c @@ -130,7 +130,7 @@ static void block_list_remove(struct sst_dsp *dsp, err = block->ops->disable(block); if (err < 0) dev_err(dsp->dev, - "error: cant disable block %d:%d\n", + "error: can't disable block %d:%d\n", block->type, block->index); } } @@ -158,7 +158,7 @@ static int block_list_prepare(struct sst_dsp *dsp, ret = block->ops->enable(block); if (ret < 0) { dev_err(dsp->dev, - "error: cant disable block %d:%d\n", + "error: can't disable block %d:%d\n", block->type, block->index); goto err; } diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index 0ff89ea96ccf..95a50265dff6 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c @@ -427,7 +427,7 @@ static void hsw_fw_ready(struct sst_hsw *hsw, u32 header) u32 offset; u8 fw_info[IPC_MAX_MAILBOX_BYTES - 5 * sizeof(u32)]; char *tmp[5], *pinfo; - int i = 0; + int i; offset = (header & 0x1FFFFFFF) << 3; @@ -1507,7 +1507,7 @@ static int sst_hsw_dx_state_dump(struct sst_hsw *hsw) ret = sst_dsp_dma_get_channel(sst, 0); if (ret < 0) { - dev_err(hsw->dev, "error: cant allocate dma channel %d\n", ret); + dev_err(hsw->dev, "error: can't allocate dma channel %d\n", ret); return ret; } @@ -1587,7 +1587,7 @@ int sst_hsw_dsp_load(struct sst_hsw *hsw) ret = sst_dsp_dma_get_channel(dsp, 0); if (ret < 0) { - dev_err(hsw->dev, "error: cant allocate dma channel %d\n", ret); + dev_err(hsw->dev, "error: can't allocate dma channel %d\n", ret); return ret; } @@ -1616,7 +1616,7 @@ static int sst_hsw_dsp_restore(struct sst_hsw *hsw) ret = sst_dsp_dma_get_channel(dsp, 0); if (ret < 0) { - dev_err(hsw->dev, "error: cant allocate dma channel %d\n", ret); + dev_err(hsw->dev, "error: can't allocate dma channel %d\n", ret); return ret; } @@ -1789,7 +1789,7 @@ int sst_hsw_store_param_line(struct sst_hsw *hsw, u8 *buf) int sst_hsw_load_param_line(struct sst_hsw *hsw, u8 *buf) { - u8 id = 0; + u8 id; /* read the first matching line from param buffer */ while (hsw->param_idx_r < WAVES_PARAM_LINES) { diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.h b/sound/soc/intel/haswell/sst-haswell-ipc.h index fdc70c77e688..646dbbba327b 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.h +++ b/sound/soc/intel/haswell/sst-haswell-ipc.h @@ -414,7 +414,7 @@ int sst_hsw_mixer_get_volume(struct sst_hsw *hsw, u32 stage_id, u32 channel, /* Stream API */ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id, - u32 (*get_write_position)(struct sst_hsw_stream *stream, void *data), + u32 (*notify_position)(struct sst_hsw_stream *stream, void *data), void *data); int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream); diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 16f9fc4c663d..ca25a6e40cc9 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -8,6 +8,8 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> @@ -17,7 +19,7 @@ #define PERIODS_MAX 48 #define PERIOD_BYTES_MIN 4096 #define BUFFER_BYTES_MAX (PERIODS_MAX * PERIOD_BYTES_MIN) -#define TDM_OPERATION 1 +#define TDM_OPERATION 5 #define I2S_OPERATION 0 #define DATA_WIDTH_CONFIG_BIT 6 #define TDM_CHANNEL_CONFIG_BIT 3 @@ -82,19 +84,25 @@ static unsigned int kmb_pcm_rx_fn(struct kmb_i2s_info *kmb_i2s, { unsigned int period_pos = rx_ptr % runtime->period_size; void __iomem *i2s_base = kmb_i2s->i2s_base; + int chan = kmb_i2s->config.chan_nr; void *buf = runtime->dma_area; - int i; + int i, j; /* KMB i2s uses two separate L/R FIFO */ for (i = 0; i < kmb_i2s->fifo_th; i++) { - if (kmb_i2s->config.data_width == 16) { - ((u16(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0)); - ((u16(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0)); - } else { - ((u32(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0)); - ((u32(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0)); + for (j = 0; j < chan / 2; j++) { + if (kmb_i2s->config.data_width == 16) { + ((u16 *)buf)[rx_ptr * chan + (j * 2)] = + readl(i2s_base + LRBR_LTHR(j)); + ((u16 *)buf)[rx_ptr * chan + ((j * 2) + 1)] = + readl(i2s_base + RRBR_RTHR(j)); + } else { + ((u32 *)buf)[rx_ptr * chan + (j * 2)] = + readl(i2s_base + LRBR_LTHR(j)); + ((u32 *)buf)[rx_ptr * chan + ((j * 2) + 1)] = + readl(i2s_base + RRBR_RTHR(j)); + } } - period_pos++; if (++rx_ptr >= runtime->buffer_size) @@ -238,6 +246,7 @@ static irqreturn_t kmb_i2s_irq_handler(int irq, void *dev_id) struct kmb_i2s_info *kmb_i2s = dev_id; struct i2s_clk_config_data *config = &kmb_i2s->config; irqreturn_t ret = IRQ_NONE; + u32 tx_enabled = 0; u32 isr[4]; int i; @@ -246,22 +255,45 @@ static irqreturn_t kmb_i2s_irq_handler(int irq, void *dev_id) kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK); kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE); + /* Only check TX interrupt if TX is active */ + tx_enabled = readl(kmb_i2s->i2s_base + ITER); + + /* + * Data available. Retrieve samples from FIFO + */ + + /* + * 8 channel audio will have isr[0..2] triggered, + * reading the specific isr based on the audio configuration, + * to avoid reading the buffers too early. + */ + switch (config->chan_nr) { + case 2: + if (isr[0] & ISR_RXDA) + kmb_pcm_operation(kmb_i2s, false); + ret = IRQ_HANDLED; + break; + case 4: + if (isr[1] & ISR_RXDA) + kmb_pcm_operation(kmb_i2s, false); + ret = IRQ_HANDLED; + break; + case 8: + if (isr[3] & ISR_RXDA) + kmb_pcm_operation(kmb_i2s, false); + ret = IRQ_HANDLED; + break; + } for (i = 0; i < config->chan_nr / 2; i++) { /* * Check if TX fifo is empty. If empty fill FIFO with samples */ - if ((isr[i] & ISR_TXFE)) { + if ((isr[i] & ISR_TXFE) && tx_enabled) { kmb_pcm_operation(kmb_i2s, true); ret = IRQ_HANDLED; } - /* - * Data available. Retrieve samples from FIFO - */ - if ((isr[i] & ISR_RXDA)) { - kmb_pcm_operation(kmb_i2s, false); - ret = IRQ_HANDLED; - } + /* Error Handling: TX */ if (isr[i] & ISR_TXFO) { dev_dbg(kmb_i2s->dev, "TX overrun (ch_id=%d)\n", i); @@ -445,7 +477,7 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream, { struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai); struct i2s_clk_config_data *config = &kmb_i2s->config; - u32 register_val, write_val; + u32 write_val; int ret; switch (params_format(hw_params)) { @@ -472,16 +504,34 @@ static int kmb_dai_hw_params(struct snd_pcm_substream *substream, config->chan_nr = params_channels(hw_params); switch (config->chan_nr) { - /* TODO: This switch case will handle up to TDM8 in the near future */ - case TWO_CHANNEL_SUPPORT: + case 8: + case 4: + /* + * Platform is not capable of providing clocks for + * multi channel audio + */ + if (kmb_i2s->master) + return -EINVAL; + write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) | (config->data_width << DATA_WIDTH_CONFIG_BIT) | - MASTER_MODE | I2S_OPERATION; + !MASTER_MODE | TDM_OPERATION; writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0); + break; + case 2: + /* + * Platform is only capable of providing clocks need for + * 2 channel master mode + */ + if (!(kmb_i2s->master)) + return -EINVAL; + + write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) | + (config->data_width << DATA_WIDTH_CONFIG_BIT) | + MASTER_MODE | I2S_OPERATION; - register_val = readl(kmb_i2s->pss_base + I2S_GEN_CFG_0); - dev_dbg(kmb_i2s->dev, "pss register = 0x%X", register_val); + writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0); break; default: dev_dbg(kmb_i2s->dev, "channel not supported\n"); @@ -529,9 +579,9 @@ static struct snd_soc_dai_ops kmb_dai_ops = { .set_fmt = kmb_set_dai_fmt, }; -static struct snd_soc_dai_driver intel_kmb_platform_dai[] = { +static struct snd_soc_dai_driver intel_kmb_i2s_dai[] = { { - .name = "kmb-plat-dai", + .name = "intel_kmb_i2s", .playback = { .channels_min = 2, .channels_max = 2, @@ -547,10 +597,6 @@ static struct snd_soc_dai_driver intel_kmb_platform_dai[] = { .capture = { .channels_min = 2, .channels_max = 2, - /* - * .channels_max will be overwritten - * if provided by Device Tree - */ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000, @@ -564,9 +610,35 @@ static struct snd_soc_dai_driver intel_kmb_platform_dai[] = { }, }; +static struct snd_soc_dai_driver intel_kmb_tdm_dai[] = { + { + .name = "intel_kmb_tdm", + .capture = { + .channels_min = 4, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000, + .rate_min = 8000, + .rate_max = 48000, + .formats = (SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S16_LE), + }, + .ops = &kmb_dai_ops, + }, +}; + +static const struct of_device_id kmb_plat_of_match[] = { + { .compatible = "intel,keembay-i2s", .data = &intel_kmb_i2s_dai}, + { .compatible = "intel,keembay-tdm", .data = &intel_kmb_tdm_dai}, + {} +}; + static int kmb_plat_dai_probe(struct platform_device *pdev) { struct snd_soc_dai_driver *kmb_i2s_dai; + const struct of_device_id *match; struct device *dev = &pdev->dev; struct kmb_i2s_info *kmb_i2s; int ret, irq; @@ -580,7 +652,12 @@ static int kmb_plat_dai_probe(struct platform_device *pdev) if (!kmb_i2s_dai) return -ENOMEM; - kmb_i2s_dai->ops = &kmb_dai_ops; + match = of_match_device(kmb_plat_of_match, &pdev->dev); + if (!match) { + dev_err(&pdev->dev, "Error: No device match found\n"); + return -ENODEV; + } + kmb_i2s_dai = (struct snd_soc_dai_driver *) match->data; /* Prepare the related clocks */ kmb_i2s->clk_apb = devm_clk_get(dev, "apb_clk"); @@ -630,8 +707,7 @@ static int kmb_plat_dai_probe(struct platform_device *pdev) kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2; ret = devm_snd_soc_register_component(dev, &kmb_component, - intel_kmb_platform_dai, - ARRAY_SIZE(intel_kmb_platform_dai)); + kmb_i2s_dai, 1); if (ret) { dev_err(dev, "not able to register dai\n"); return ret; @@ -646,11 +722,6 @@ static int kmb_plat_dai_probe(struct platform_device *pdev) return ret; } -static const struct of_device_id kmb_plat_of_match[] = { - { .compatible = "intel,keembay-i2s", }, - {} -}; - static struct platform_driver kmb_plat_dai_driver = { .driver = { .name = "kmb-plat-dai", diff --git a/sound/soc/intel/skylake/cnl-sst-dsp.h b/sound/soc/intel/skylake/cnl-sst-dsp.h index 7bd4d2a8fdfa..d3cf4bd1a070 100644 --- a/sound/soc/intel/skylake/cnl-sst-dsp.h +++ b/sound/soc/intel/skylake/cnl-sst-dsp.h @@ -82,8 +82,8 @@ struct sst_generic_ipc; #define CNL_ADSPCS_CPA_SHIFT 24 #define CNL_ADSPCS_CPA(x) (x << CNL_ADSPCS_CPA_SHIFT) -int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core); -int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core); +int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask); +int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask); irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id); void cnl_dsp_free(struct sst_dsp *dsp); diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index d9c8f5cb389e..87c891c46291 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -200,7 +200,7 @@ static void skl_get_ssp_clks(struct skl_dev *skl, struct skl_ssp_clk *ssp_clks, struct skl_ssp_clk *sclk, *sclkfs; struct nhlt_fmt_cfg *fmt_cfg; struct wav_fmt_ext *wav_fmt; - unsigned long rate = 0; + unsigned long rate; bool present = false; int rate_index = 0; u16 channels, bps; diff --git a/sound/soc/intel/skylake/skl-sst-cldma.c b/sound/soc/intel/skylake/skl-sst-cldma.c index 36f697c61074..b91f7a652a2b 100644 --- a/sound/soc/intel/skylake/skl-sst-cldma.c +++ b/sound/soc/intel/skylake/skl-sst-cldma.c @@ -245,7 +245,7 @@ static int skl_cldma_copy_to_buf(struct sst_dsp *ctx, const void *bin, u32 total_size, bool wait) { - int ret = 0; + int ret; bool start = true; unsigned int excess_bytes; u32 size; diff --git a/sound/soc/intel/skylake/skl-sst-ipc.h b/sound/soc/intel/skylake/skl-sst-ipc.h index 08ac31778325..aaaab3b3ec42 100644 --- a/sound/soc/intel/skylake/skl-sst-ipc.h +++ b/sound/soc/intel/skylake/skl-sst-ipc.h @@ -107,12 +107,12 @@ struct skl_ipc_d0ix_msg { irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context); -int skl_ipc_create_pipeline(struct sst_generic_ipc *sst_ipc, +int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, u16 ppl_mem_size, u8 ppl_type, u8 instance_id, u8 lp_mode); -int skl_ipc_delete_pipeline(struct sst_generic_ipc *sst_ipc, u8 instance_id); +int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id); -int skl_ipc_set_pipeline_state(struct sst_generic_ipc *sst_ipc, +int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, u8 instance_id, enum skl_ipc_pipeline_state state); int skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, @@ -120,10 +120,10 @@ int skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id); -int skl_ipc_init_instance(struct sst_generic_ipc *sst_ipc, +int skl_ipc_init_instance(struct sst_generic_ipc *ipc, struct skl_ipc_init_instance_msg *msg, void *param_data); -int skl_ipc_bind_unbind(struct sst_generic_ipc *sst_ipc, +int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, struct skl_ipc_bind_unbind_msg *msg); int skl_ipc_load_modules(struct sst_generic_ipc *ipc, @@ -150,12 +150,12 @@ int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, int skl_ipc_check_D0i0(struct sst_dsp *dsp, bool state); -void skl_ipc_int_enable(struct sst_dsp *dsp); +void skl_ipc_int_enable(struct sst_dsp *ctx); void skl_ipc_op_int_enable(struct sst_dsp *ctx); void skl_ipc_op_int_disable(struct sst_dsp *ctx); -void skl_ipc_int_disable(struct sst_dsp *dsp); +void skl_ipc_int_disable(struct sst_dsp *ctx); -bool skl_ipc_int_status(struct sst_dsp *dsp); +bool skl_ipc_int_status(struct sst_dsp *ctx); void skl_ipc_free(struct sst_generic_ipc *ipc); int skl_ipc_init(struct device *dev, struct skl_dev *skl); void skl_clear_module_cnt(struct sst_dsp *ctx); diff --git a/sound/soc/intel/skylake/skl-sst-utils.c b/sound/soc/intel/skylake/skl-sst-utils.c index b233f89517c1..57ea815d3f04 100644 --- a/sound/soc/intel/skylake/skl-sst-utils.c +++ b/sound/soc/intel/skylake/skl-sst-utils.c @@ -237,7 +237,7 @@ int snd_skl_parse_uuids(struct sst_dsp *ctx, const struct firmware *fw, struct uuid_module *module; struct firmware stripped_fw; unsigned int safe_file; - int ret = 0; + int ret; /* Get the FW pointer to derive ADSP header */ stripped_fw.data = fw->data; diff --git a/sound/soc/intel/skylake/skl-sst.c b/sound/soc/intel/skylake/skl-sst.c index 61a8e4756a2b..00a97cea58b4 100644 --- a/sound/soc/intel/skylake/skl-sst.c +++ b/sound/soc/intel/skylake/skl-sst.c @@ -354,7 +354,7 @@ static int skl_transfer_module(struct sst_dsp *ctx, const void *data, /* * if bytes_left > 0 then wait for BDL complete interrupt and * copy the next chunk till bytes_left is 0. if bytes_left is - * is zero, then wait for load module IPC reply + * zero, then wait for load module IPC reply */ while (bytes_left > 0) { curr_pos = size - bytes_left; diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index b7d2d97d12a7..40bee10b0c65 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -550,8 +550,8 @@ static int skl_tplg_unload_pipe_modules(struct skl_dev *skl, struct skl_pipe *pipe) { int ret = 0; - struct skl_pipe_module *w_module = NULL; - struct skl_module_cfg *mconfig = NULL; + struct skl_pipe_module *w_module; + struct skl_module_cfg *mconfig; list_for_each_entry(w_module, &pipe->w_list, node) { guid_t *uuid_mod; @@ -1893,7 +1893,7 @@ static int skl_tplg_be_set_src_pipe_params(struct snd_soc_dai *dai, static int skl_tplg_be_set_sink_pipe_params(struct snd_soc_dai *dai, struct snd_soc_dapm_widget *w, struct skl_pipe_params *params) { - struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dapm_path *p; int ret = -EIO; snd_soc_dapm_widget_for_each_sink_path(w, p) { @@ -2876,7 +2876,7 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, struct skl_module_cfg *mconfig) { struct snd_soc_tplg_vendor_array *array; - int num_blocks, block_size = 0, block_type, off = 0; + int num_blocks, block_size, block_type, off = 0; char *data; int ret; diff --git a/sound/soc/intel/skylake/skl-topology.h b/sound/soc/intel/skylake/skl-topology.h index 5e93ad85e06d..fb011862fb24 100644 --- a/sound/soc/intel/skylake/skl-topology.h +++ b/sound/soc/intel/skylake/skl-topology.h @@ -453,7 +453,7 @@ int skl_dsp_set_dma_control(struct skl_dev *skl, u32 *caps, void skl_tplg_set_be_dmic_config(struct snd_soc_dai *dai, struct skl_pipe_params *params, int stream); int skl_tplg_init(struct snd_soc_component *component, - struct hdac_bus *ebus); + struct hdac_bus *bus); void skl_tplg_exit(struct snd_soc_component *component, struct hdac_bus *bus); struct skl_module_cfg *skl_tplg_fe_get_cpr_module( @@ -476,13 +476,13 @@ int skl_stop_pipe(struct skl_dev *skl, struct skl_pipe *pipe); int skl_reset_pipe(struct skl_dev *skl, struct skl_pipe *pipe); -int skl_init_module(struct skl_dev *skl, struct skl_module_cfg *module_config); +int skl_init_module(struct skl_dev *skl, struct skl_module_cfg *mconfig); int skl_bind_modules(struct skl_dev *skl, struct skl_module_cfg - *src_module, struct skl_module_cfg *dst_module); + *src_mcfg, struct skl_module_cfg *dst_mcfg); int skl_unbind_modules(struct skl_dev *skl, struct skl_module_cfg - *src_module, struct skl_module_cfg *dst_module); + *src_mcfg, struct skl_module_cfg *dst_mcfg); int skl_set_module_params(struct skl_dev *skl, u32 *params, int size, u32 param_id, struct skl_module_cfg *mcfg); diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 26057f38a014..857ea17e3c9f 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -166,7 +166,7 @@ int skl_platform_unregister(struct device *dev); int skl_platform_register(struct device *dev); struct nhlt_specific_cfg *skl_get_ep_blob(struct skl_dev *skl, u32 instance, - u8 link_type, u8 s_fmt, u8 no_ch, + u8 link_type, u8 s_fmt, u8 num_ch, u32 s_rate, u8 dirn, u8 dev_type); int skl_nhlt_update_topology_bin(struct skl_dev *skl); diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index f7e8e9da68a0..cab7fa2851aa 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -398,7 +398,7 @@ void axg_tdm_stream_free(struct axg_tdm_stream *ts) /* * If the list is not empty, it would mean that one of the formatter * widget is still powered and attached to the interface while we - * we are removing the TDM DAI. It should not be possible + * are removing the TDM DAI. It should not be possible */ WARN_ON(!list_empty(&ts->formatter_list)); mutex_destroy(&ts->lock); diff --git a/sound/soc/meson/meson-card-utils.c b/sound/soc/meson/meson-card-utils.c index 6a64ac01b5ca..300ac8be46ef 100644 --- a/sound/soc/meson/meson-card-utils.c +++ b/sound/soc/meson/meson-card-utils.c @@ -254,37 +254,6 @@ static int meson_card_parse_of_optional(struct snd_soc_card *card, return func(card, propname); } -static int meson_card_add_aux_devices(struct snd_soc_card *card) -{ - struct device_node *node = card->dev->of_node; - struct snd_soc_aux_dev *aux; - int num, i; - - num = of_count_phandle_with_args(node, "audio-aux-devs", NULL); - if (num == -ENOENT) { - return 0; - } else if (num < 0) { - dev_err(card->dev, "error getting auxiliary devices: %d\n", - num); - return num; - } - - aux = devm_kcalloc(card->dev, num, sizeof(*aux), GFP_KERNEL); - if (!aux) - return -ENOMEM; - card->aux_dev = aux; - card->num_aux_devs = num; - - for_each_card_pre_auxs(card, i, aux) { - aux->dlc.of_node = - of_parse_phandle(node, "audio-aux-devs", i); - if (!aux->dlc.of_node) - return -EINVAL; - } - - return 0; -} - static void meson_card_clean_references(struct meson_card *priv) { struct snd_soc_card *card = &priv->card; @@ -357,7 +326,7 @@ int meson_card_probe(struct platform_device *pdev) if (ret) goto out_err; - ret = meson_card_add_aux_devices(&priv->card); + ret = snd_soc_of_parse_aux_devs(&priv->card, "audio-aux-devs"); if (ret) goto out_err; diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index 5d6b2466a2f2..a607ace8b089 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -1,11 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-only -config SND_SOC_QCOM +menuconfig SND_SOC_QCOM tristate "ASoC support for QCOM platforms" depends on ARCH_QCOM || COMPILE_TEST help Say Y or M if you want to add support to use audio devices in Qualcomm Technologies SOC-based platforms. +if SND_SOC_QCOM + config SND_SOC_LPASS_CPU tristate select REGMAP_MMIO @@ -24,9 +26,13 @@ config SND_SOC_LPASS_APQ8016 select SND_SOC_LPASS_CPU select SND_SOC_LPASS_PLATFORM +config SND_SOC_LPASS_SC7180 + tristate + select SND_SOC_LPASS_CPU + select SND_SOC_LPASS_PLATFORM + config SND_SOC_STORM tristate "ASoC I2S support for Storm boards" - depends on SND_SOC_QCOM select SND_SOC_LPASS_IPQ806X select SND_SOC_MAX98357A help @@ -35,7 +41,6 @@ config SND_SOC_STORM config SND_SOC_APQ8016_SBC tristate "SoC Audio support for APQ8016 SBC platforms" - depends on SND_SOC_QCOM select SND_SOC_LPASS_APQ8016 select SND_SOC_QCOM_COMMON help @@ -110,3 +115,5 @@ config SND_SOC_SDM845 To add support for audio on Qualcomm Technologies Inc. SDM845 SoC-based systems. Say Y if you want to use audio device on this SoCs. + +endif #SND_SOC_QCOM diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 41b2c7a23a4d..7972c9479ab0 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -4,11 +4,13 @@ snd-soc-lpass-cpu-objs := lpass-cpu.o snd-soc-lpass-platform-objs := lpass-platform.o snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o snd-soc-lpass-apq8016-objs := lpass-apq8016.o +snd-soc-lpass-sc7180-objs := lpass-sc7180.o obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o +obj-$(CONFIG_SND_SOC_LPASS_SC7180) += snd-soc-lpass-sc7180.o # Machine snd-soc-storm-objs := storm.o diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c index b3610d05b651..5c8ae225cd5d 100644 --- a/sound/soc/qcom/lpass-apq8016.c +++ b/sound/soc/qcom/lpass-apq8016.c @@ -161,44 +161,67 @@ static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) static int apq8016_lpass_init(struct platform_device *pdev) { struct lpass_data *drvdata = platform_get_drvdata(pdev); + struct lpass_variant *variant = drvdata->variant; struct device *dev = &pdev->dev; - int ret; + int ret, i; - drvdata->pcnoc_mport_clk = devm_clk_get(dev, "pcnoc-mport-clk"); - if (IS_ERR(drvdata->pcnoc_mport_clk)) { - dev_err(dev, "error getting pcnoc-mport-clk: %ld\n", - PTR_ERR(drvdata->pcnoc_mport_clk)); - return PTR_ERR(drvdata->pcnoc_mport_clk); + + drvdata->clks = devm_kcalloc(dev, variant->num_clks, + sizeof(*drvdata->clks), GFP_KERNEL); + if (!drvdata->clks) + return -ENOMEM; + drvdata->num_clks = variant->num_clks; + + for (i = 0; i < drvdata->num_clks; i++) + drvdata->clks[i].id = variant->clk_name[i]; + + ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "Failed to get clocks %d\n", ret); + return ret; } - ret = clk_prepare_enable(drvdata->pcnoc_mport_clk); + ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); if (ret) { - dev_err(dev, "Error enabling pcnoc-mport-clk: %d\n", ret); + dev_err(dev, "apq8016 clk_enable failed\n"); return ret; } - drvdata->pcnoc_sway_clk = devm_clk_get(dev, "pcnoc-sway-clk"); - if (IS_ERR(drvdata->pcnoc_sway_clk)) { - dev_err(dev, "error getting pcnoc-sway-clk: %ld\n", - PTR_ERR(drvdata->pcnoc_sway_clk)); - return PTR_ERR(drvdata->pcnoc_sway_clk); + drvdata->ahbix_clk = devm_clk_get(dev, "ahbix-clk"); + if (IS_ERR(drvdata->ahbix_clk)) { + dev_err(dev, "error getting ahbix-clk: %ld\n", + PTR_ERR(drvdata->ahbix_clk)); + ret = PTR_ERR(drvdata->ahbix_clk); + goto err_ahbix_clk; } - ret = clk_prepare_enable(drvdata->pcnoc_sway_clk); + ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); if (ret) { - dev_err(dev, "Error enabling pcnoc_sway_clk: %d\n", ret); - return ret; + dev_err(dev, "error setting rate on ahbix_clk: %d\n", ret); + goto err_ahbix_clk; + } + dev_dbg(dev, "set ahbix_clk rate to %lu\n", + clk_get_rate(drvdata->ahbix_clk)); + + ret = clk_prepare_enable(drvdata->ahbix_clk); + if (ret) { + dev_err(dev, "error enabling ahbix_clk: %d\n", ret); + goto err_ahbix_clk; } return 0; + +err_ahbix_clk: + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + return ret; } static int apq8016_lpass_exit(struct platform_device *pdev) { struct lpass_data *drvdata = platform_get_drvdata(pdev); - clk_disable_unprepare(drvdata->pcnoc_mport_clk); - clk_disable_unprepare(drvdata->pcnoc_sway_clk); + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + clk_disable_unprepare(drvdata->ahbix_clk); return 0; } @@ -219,6 +242,35 @@ static struct lpass_variant apq8016_data = { .wrdma_reg_stride = 0x1000, .wrdma_channel_start = 5, .wrdma_channels = 2, + .loopback = REG_FIELD_ID(0x1000, 15, 15, 4, 0x1000), + .spken = REG_FIELD_ID(0x1000, 14, 14, 4, 0x1000), + .spkmode = REG_FIELD_ID(0x1000, 10, 13, 4, 0x1000), + .spkmono = REG_FIELD_ID(0x1000, 9, 9, 4, 0x1000), + .micen = REG_FIELD_ID(0x1000, 8, 8, 4, 0x1000), + .micmode = REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000), + .micmono = REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000), + .wssrc = REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000), + .bitwidth = REG_FIELD_ID(0x1000, 0, 0, 4, 0x1000), + + .rdma_dyncclk = REG_FIELD_ID(0x8400, 12, 12, 2, 0x1000), + .rdma_bursten = REG_FIELD_ID(0x8400, 11, 11, 2, 0x1000), + .rdma_wpscnt = REG_FIELD_ID(0x8400, 8, 10, 2, 0x1000), + .rdma_intf = REG_FIELD_ID(0x8400, 4, 7, 2, 0x1000), + .rdma_fifowm = REG_FIELD_ID(0x8400, 1, 3, 2, 0x1000), + .rdma_enable = REG_FIELD_ID(0x8400, 0, 0, 2, 0x1000), + + .wrdma_dyncclk = REG_FIELD_ID(0xB000, 12, 12, 2, 0x1000), + .wrdma_bursten = REG_FIELD_ID(0xB000, 11, 11, 2, 0x1000), + .wrdma_wpscnt = REG_FIELD_ID(0xB000, 8, 10, 2, 0x1000), + .wrdma_intf = REG_FIELD_ID(0xB000, 4, 7, 2, 0x1000), + .wrdma_fifowm = REG_FIELD_ID(0xB000, 1, 3, 2, 0x1000), + .wrdma_enable = REG_FIELD_ID(0xB000, 0, 0, 2, 0x1000), + + .clk_name = (const char*[]) { + "pcnoc-mport-clk", + "pcnoc-sway-clk", + }, + .num_clks = 2, .dai_driver = apq8016_lpass_cpu_dai_driver, .num_dai = ARRAY_SIZE(apq8016_lpass_cpu_dai_driver), .dai_osr_clk_names = (const char *[]) { diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index e00a4af29c13..1ee6d8b3f550 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -29,6 +29,32 @@ #define LPASS_CPU_I2S_SD0_1_2_MASK GENMASK(2, 0) #define LPASS_CPU_I2S_SD0_1_2_3_MASK GENMASK(3, 0) +static int lpass_cpu_init_i2sctl_bitfields(struct device *dev, + struct lpaif_i2sctl *i2sctl, struct regmap *map) +{ + struct lpass_data *drvdata = dev_get_drvdata(dev); + struct lpass_variant *v = drvdata->variant; + + i2sctl->loopback = devm_regmap_field_alloc(dev, map, v->loopback); + i2sctl->spken = devm_regmap_field_alloc(dev, map, v->spken); + i2sctl->spkmode = devm_regmap_field_alloc(dev, map, v->spkmode); + i2sctl->spkmono = devm_regmap_field_alloc(dev, map, v->spkmono); + i2sctl->micen = devm_regmap_field_alloc(dev, map, v->micen); + i2sctl->micmode = devm_regmap_field_alloc(dev, map, v->micmode); + i2sctl->micmono = devm_regmap_field_alloc(dev, map, v->micmono); + i2sctl->wssrc = devm_regmap_field_alloc(dev, map, v->wssrc); + i2sctl->bitwidth = devm_regmap_field_alloc(dev, map, v->bitwidth); + + if (IS_ERR(i2sctl->loopback) || IS_ERR(i2sctl->spken) || + IS_ERR(i2sctl->spkmode) || IS_ERR(i2sctl->spkmono) || + IS_ERR(i2sctl->micen) || IS_ERR(i2sctl->micmode) || + IS_ERR(i2sctl->micmono) || IS_ERR(i2sctl->wssrc) || + IS_ERR(i2sctl->bitwidth)) + return -EINVAL; + + return 0; +} + static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { @@ -79,6 +105,8 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct lpaif_i2sctl *i2sctl = drvdata->i2sctl; + unsigned int id = dai->driver->id; snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); unsigned int rate = params_rate(params); @@ -92,28 +120,45 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, return bitwidth; } - regval = LPAIF_I2SCTL_LOOPBACK_DISABLE | - LPAIF_I2SCTL_WSSRC_INTERNAL; + ret = regmap_fields_write(i2sctl->loopback, id, + LPAIF_I2SCTL_LOOPBACK_DISABLE); + if (ret) { + dev_err(dai->dev, "error updating loopback field: %d\n", ret); + return ret; + } + + ret = regmap_fields_write(i2sctl->wssrc, id, + LPAIF_I2SCTL_WSSRC_INTERNAL); + if (ret) { + dev_err(dai->dev, "error updating wssrc field: %d\n", ret); + return ret; + } switch (bitwidth) { case 16: - regval |= LPAIF_I2SCTL_BITWIDTH_16; + regval = LPAIF_I2SCTL_BITWIDTH_16; break; case 24: - regval |= LPAIF_I2SCTL_BITWIDTH_24; + regval = LPAIF_I2SCTL_BITWIDTH_24; break; case 32: - regval |= LPAIF_I2SCTL_BITWIDTH_32; + regval = LPAIF_I2SCTL_BITWIDTH_32; break; default: dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth); return -EINVAL; } + ret = regmap_fields_write(i2sctl->bitwidth, id, regval); + if (ret) { + dev_err(dai->dev, "error updating bitwidth field: %d\n", ret); + return ret; + } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - mode = drvdata->mi2s_playback_sd_mode[dai->driver->id]; + mode = drvdata->mi2s_playback_sd_mode[id]; else - mode = drvdata->mi2s_capture_sd_mode[dai->driver->id]; + mode = drvdata->mi2s_capture_sd_mode[id]; if (!mode) { dev_err(dai->dev, "no line is assigned\n"); @@ -175,30 +220,42 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - regval |= LPAIF_I2SCTL_SPKMODE(mode); - + ret = regmap_fields_write(i2sctl->spkmode, id, + LPAIF_I2SCTL_SPKMODE(mode)); + if (ret) { + dev_err(dai->dev, "error writing to i2sctl spkr mode: %d\n", + ret); + return ret; + } if (channels >= 2) - regval |= LPAIF_I2SCTL_SPKMONO_STEREO; + ret = regmap_fields_write(i2sctl->spkmono, id, + LPAIF_I2SCTL_SPKMONO_STEREO); else - regval |= LPAIF_I2SCTL_SPKMONO_MONO; + ret = regmap_fields_write(i2sctl->spkmono, id, + LPAIF_I2SCTL_SPKMONO_MONO); } else { - regval |= LPAIF_I2SCTL_MICMODE(mode); - + ret = regmap_fields_write(i2sctl->micmode, id, + LPAIF_I2SCTL_MICMODE(mode)); + if (ret) { + dev_err(dai->dev, "error writing to i2sctl mic mode: %d\n", + ret); + return ret; + } if (channels >= 2) - regval |= LPAIF_I2SCTL_MICMONO_STEREO; + ret = regmap_fields_write(i2sctl->micmono, id, + LPAIF_I2SCTL_MICMONO_STEREO); else - regval |= LPAIF_I2SCTL_MICMONO_MONO; + ret = regmap_fields_write(i2sctl->micmono, id, + LPAIF_I2SCTL_MICMONO_MONO); } - ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), - regval); if (ret) { - dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); + dev_err(dai->dev, "error writing to i2sctl channels mode: %d\n", + ret); return ret; } - ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], + ret = clk_set_rate(drvdata->mi2s_bit_clk[id], rate * bitwidth * 2); if (ret) { dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n", @@ -209,41 +266,24 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, return 0; } -static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); - int ret; - - ret = regmap_write(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), - 0); - if (ret) - dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); - - return ret; -} - static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct lpaif_i2sctl *i2sctl = drvdata->i2sctl; + unsigned int id = dai->driver->id; int ret; - unsigned int val, mask; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - val = LPAIF_I2SCTL_SPKEN_ENABLE; - mask = LPAIF_I2SCTL_SPKEN_MASK; - } else { - val = LPAIF_I2SCTL_MICEN_ENABLE; - mask = LPAIF_I2SCTL_MICEN_MASK; + ret = regmap_fields_write(i2sctl->spken, id, + LPAIF_I2SCTL_SPKEN_ENABLE); + } else { + ret = regmap_fields_write(i2sctl->micen, id, + LPAIF_I2SCTL_MICEN_ENABLE); } - ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), - mask, val); if (ret) - dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); + dev_err(dai->dev, "error writing to i2sctl enable: %d\n", ret); return ret; } @@ -252,25 +292,21 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); + struct lpaif_i2sctl *i2sctl = drvdata->i2sctl; + unsigned int id = dai->driver->id; int ret = -EINVAL; - unsigned int val, mask; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - val = LPAIF_I2SCTL_SPKEN_ENABLE; - mask = LPAIF_I2SCTL_SPKEN_MASK; + ret = regmap_fields_write(i2sctl->spken, id, + LPAIF_I2SCTL_SPKEN_ENABLE); } else { - val = LPAIF_I2SCTL_MICEN_ENABLE; - mask = LPAIF_I2SCTL_MICEN_MASK; + ret = regmap_fields_write(i2sctl->micen, id, + LPAIF_I2SCTL_MICEN_ENABLE); } - - ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, - dai->driver->id), - mask, val); if (ret) dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); @@ -279,17 +315,12 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - val = LPAIF_I2SCTL_SPKEN_DISABLE; - mask = LPAIF_I2SCTL_SPKEN_MASK; + ret = regmap_fields_write(i2sctl->spken, id, + LPAIF_I2SCTL_SPKEN_DISABLE); } else { - val = LPAIF_I2SCTL_MICEN_DISABLE; - mask = LPAIF_I2SCTL_MICEN_MASK; + ret = regmap_fields_write(i2sctl->micen, id, + LPAIF_I2SCTL_MICEN_DISABLE); } - - ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_I2SCTL_REG(drvdata->variant, - dai->driver->id), - mask, val); if (ret) dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); @@ -304,7 +335,6 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { .startup = lpass_cpu_daiops_startup, .shutdown = lpass_cpu_daiops_shutdown, .hw_params = lpass_cpu_daiops_hw_params, - .hw_free = lpass_cpu_daiops_hw_free, .prepare = lpass_cpu_daiops_prepare, .trigger = lpass_cpu_daiops_trigger, }; @@ -545,7 +575,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) of_lpass_cpu_parse_dai_data(dev, drvdata); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); drvdata->lpaif = devm_ioremap_resource(dev, res); if (IS_ERR((void const __force *)drvdata->lpaif)) { @@ -566,8 +596,13 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) return PTR_ERR(drvdata->lpaif_map); } - if (variant->init) - variant->init(pdev); + if (variant->init) { + ret = variant->init(pdev); + if (ret) { + dev_err(dev, "error initializing variant: %d\n", ret); + return ret; + } + } for (i = 0; i < variant->num_dai; i++) { dai_id = variant->dai_driver[i].id; @@ -594,24 +629,15 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) } } - drvdata->ahbix_clk = devm_clk_get(dev, "ahbix-clk"); - if (IS_ERR(drvdata->ahbix_clk)) { - dev_err(dev, "error getting ahbix-clk: %ld\n", - PTR_ERR(drvdata->ahbix_clk)); - return PTR_ERR(drvdata->ahbix_clk); - } + /* Allocation for i2sctl regmap fields */ + drvdata->i2sctl = devm_kzalloc(&pdev->dev, sizeof(struct lpaif_i2sctl), + GFP_KERNEL); - ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); + /* Initialize bitfields for dai I2SCTL register */ + ret = lpass_cpu_init_i2sctl_bitfields(dev, drvdata->i2sctl, + drvdata->lpaif_map); if (ret) { - dev_err(dev, "error setting rate on ahbix_clk: %d\n", ret); - return ret; - } - dev_dbg(dev, "set ahbix_clk rate to %lu\n", - clk_get_rate(drvdata->ahbix_clk)); - - ret = clk_prepare_enable(drvdata->ahbix_clk); - if (ret) { - dev_err(dev, "error enabling ahbix_clk: %d\n", ret); + dev_err(dev, "error init i2sctl field: %d\n", ret); return ret; } @@ -621,19 +647,16 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) variant->num_dai); if (ret) { dev_err(dev, "error registering cpu driver: %d\n", ret); - goto err_clk; + goto err; } ret = asoc_qcom_lpass_platform_register(pdev); if (ret) { dev_err(dev, "error registering platform driver: %d\n", ret); - goto err_clk; + goto err; } - return 0; - -err_clk: - clk_disable_unprepare(drvdata->ahbix_clk); +err: return ret; } EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe); @@ -645,7 +668,6 @@ int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) if (drvdata->variant->exit) drvdata->variant->exit(pdev); - clk_disable_unprepare(drvdata->ahbix_clk); return 0; } diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c index 1987605482f7..72f09b3a4f6b 100644 --- a/sound/soc/qcom/lpass-ipq806x.c +++ b/sound/soc/qcom/lpass-ipq806x.c @@ -55,6 +55,47 @@ static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = { .ops = &asoc_qcom_lpass_cpu_dai_ops, }; +static int ipq806x_lpass_init(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + int ret; + + drvdata->ahbix_clk = devm_clk_get(dev, "ahbix-clk"); + if (IS_ERR(drvdata->ahbix_clk)) { + dev_err(dev, "error getting ahbix-clk: %ld\n", + PTR_ERR(drvdata->ahbix_clk)); + ret = PTR_ERR(drvdata->ahbix_clk); + goto err_ahbix_clk; + } + + ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); + if (ret) { + dev_err(dev, "error setting rate on ahbix_clk: %d\n", ret); + goto err_ahbix_clk; + } + dev_dbg(dev, "set ahbix_clk rate to %lu\n", + clk_get_rate(drvdata->ahbix_clk)); + + ret = clk_prepare_enable(drvdata->ahbix_clk); + if (ret) { + dev_err(dev, "error enabling ahbix_clk: %d\n", ret); + goto err_ahbix_clk; + } + +err_ahbix_clk: + return ret; +} + +static int ipq806x_lpass_exit(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + + clk_disable_unprepare(drvdata->ahbix_clk); + + return 0; +} + static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir) { if (dir == SNDRV_PCM_STREAM_PLAYBACK) @@ -82,6 +123,30 @@ static struct lpass_variant ipq806x_data = { .wrdma_reg_stride = 0x1000, .wrdma_channel_start = 5, .wrdma_channels = 4, + .loopback = REG_FIELD_ID(0x0010, 15, 15, 5, 0x4), + .spken = REG_FIELD_ID(0x0010, 14, 14, 5, 0x4), + .spkmode = REG_FIELD_ID(0x0010, 10, 13, 5, 0x4), + .spkmono = REG_FIELD_ID(0x0010, 9, 9, 5, 0x4), + .micen = REG_FIELD_ID(0x0010, 8, 8, 5, 0x4), + .micmode = REG_FIELD_ID(0x0010, 4, 7, 5, 0x4), + .micmono = REG_FIELD_ID(0x0010, 3, 3, 5, 0x4), + .wssrc = REG_FIELD_ID(0x0010, 2, 2, 5, 0x4), + .bitwidth = REG_FIELD_ID(0x0010, 0, 0, 5, 0x4), + + .rdma_dyncclk = REG_FIELD_ID(0x6000, 12, 12, 4, 0x1000), + .rdma_bursten = REG_FIELD_ID(0x6000, 11, 11, 4, 0x1000), + .rdma_wpscnt = REG_FIELD_ID(0x6000, 8, 10, 4, 0x1000), + .rdma_intf = REG_FIELD_ID(0x6000, 4, 7, 4, 0x1000), + .rdma_fifowm = REG_FIELD_ID(0x6000, 1, 3, 4, 0x1000), + .rdma_enable = REG_FIELD_ID(0x6000, 0, 0, 4, 0x1000), + + .wrdma_dyncclk = REG_FIELD_ID(0xB000, 12, 12, 4, 0x1000), + .wrdma_bursten = REG_FIELD_ID(0xB000, 11, 11, 4, 0x1000), + .wrdma_wpscnt = REG_FIELD_ID(0xB000, 8, 10, 4, 0x1000), + .wrdma_intf = REG_FIELD_ID(0xB000, 4, 7, 4, 0x1000), + .wrdma_fifowm = REG_FIELD_ID(0xB000, 1, 3, 4, 0x1000), + .wrdma_enable = REG_FIELD_ID(0xB000, 0, 0, 4, 0x1000), + .dai_driver = &ipq806x_lpass_cpu_dai_driver, .num_dai = 1, .dai_osr_clk_names = (const char *[]) { @@ -90,6 +155,8 @@ static struct lpass_variant ipq806x_data = { .dai_bit_clk_names = (const char *[]) { "mi2s-bit-clk", }, + .init = ipq806x_lpass_init, + .exit = ipq806x_lpass_exit, .alloc_dma_channel = ipq806x_lpass_alloc_dma_channel, .free_dma_channel = ipq806x_lpass_free_dma_channel, }; diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index 72a3e2f69572..5258e60d3646 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -12,15 +12,12 @@ (v->i2sctrl_reg_base + (addr) + v->i2sctrl_reg_stride * (port)) #define LPAIF_I2SCTL_REG(v, port) LPAIF_I2SCTL_REG_ADDR(v, 0x0, (port)) -#define LPAIF_I2SCTL_LOOPBACK_MASK 0x8000 -#define LPAIF_I2SCTL_LOOPBACK_SHIFT 15 -#define LPAIF_I2SCTL_LOOPBACK_DISABLE (0 << LPAIF_I2SCTL_LOOPBACK_SHIFT) -#define LPAIF_I2SCTL_LOOPBACK_ENABLE (1 << LPAIF_I2SCTL_LOOPBACK_SHIFT) -#define LPAIF_I2SCTL_SPKEN_MASK 0x4000 -#define LPAIF_I2SCTL_SPKEN_SHIFT 14 -#define LPAIF_I2SCTL_SPKEN_DISABLE (0 << LPAIF_I2SCTL_SPKEN_SHIFT) -#define LPAIF_I2SCTL_SPKEN_ENABLE (1 << LPAIF_I2SCTL_SPKEN_SHIFT) +#define LPAIF_I2SCTL_LOOPBACK_DISABLE 0 +#define LPAIF_I2SCTL_LOOPBACK_ENABLE 1 + +#define LPAIF_I2SCTL_SPKEN_DISABLE 0 +#define LPAIF_I2SCTL_SPKEN_ENABLE 1 #define LPAIF_I2SCTL_MODE_NONE 0 #define LPAIF_I2SCTL_MODE_SD0 1 @@ -31,40 +28,37 @@ #define LPAIF_I2SCTL_MODE_QUAD23 6 #define LPAIF_I2SCTL_MODE_6CH 7 #define LPAIF_I2SCTL_MODE_8CH 8 +#define LPAIF_I2SCTL_MODE_10CH 9 +#define LPAIF_I2SCTL_MODE_12CH 10 +#define LPAIF_I2SCTL_MODE_14CH 11 +#define LPAIF_I2SCTL_MODE_16CH 12 +#define LPAIF_I2SCTL_MODE_SD4 13 +#define LPAIF_I2SCTL_MODE_SD5 14 +#define LPAIF_I2SCTL_MODE_SD6 15 +#define LPAIF_I2SCTL_MODE_SD7 16 +#define LPAIF_I2SCTL_MODE_QUAD45 17 +#define LPAIF_I2SCTL_MODE_QUAD47 18 +#define LPAIF_I2SCTL_MODE_8CH_2 19 -#define LPAIF_I2SCTL_SPKMODE_MASK 0x3C00 -#define LPAIF_I2SCTL_SPKMODE_SHIFT 10 -#define LPAIF_I2SCTL_SPKMODE(mode) ((mode) << LPAIF_I2SCTL_SPKMODE_SHIFT) +#define LPAIF_I2SCTL_SPKMODE(mode) mode -#define LPAIF_I2SCTL_SPKMONO_MASK 0x0200 -#define LPAIF_I2SCTL_SPKMONO_SHIFT 9 -#define LPAIF_I2SCTL_SPKMONO_STEREO (0 << LPAIF_I2SCTL_SPKMONO_SHIFT) -#define LPAIF_I2SCTL_SPKMONO_MONO (1 << LPAIF_I2SCTL_SPKMONO_SHIFT) +#define LPAIF_I2SCTL_SPKMONO_STEREO 0 +#define LPAIF_I2SCTL_SPKMONO_MONO 1 -#define LPAIF_I2SCTL_MICEN_MASK GENMASK(8, 8) -#define LPAIF_I2SCTL_MICEN_SHIFT 8 -#define LPAIF_I2SCTL_MICEN_DISABLE (0 << LPAIF_I2SCTL_MICEN_SHIFT) -#define LPAIF_I2SCTL_MICEN_ENABLE (1 << LPAIF_I2SCTL_MICEN_SHIFT) +#define LPAIF_I2SCTL_MICEN_DISABLE 0 +#define LPAIF_I2SCTL_MICEN_ENABLE 1 -#define LPAIF_I2SCTL_MICMODE_MASK GENMASK(7, 4) -#define LPAIF_I2SCTL_MICMODE_SHIFT 4 -#define LPAIF_I2SCTL_MICMODE(mode) ((mode) << LPAIF_I2SCTL_MICMODE_SHIFT) +#define LPAIF_I2SCTL_MICMODE(mode) mode -#define LPAIF_I2SCTL_MIMONO_MASK GENMASK(3, 3) -#define LPAIF_I2SCTL_MICMONO_SHIFT 3 -#define LPAIF_I2SCTL_MICMONO_STEREO (0 << LPAIF_I2SCTL_MICMONO_SHIFT) -#define LPAIF_I2SCTL_MICMONO_MONO (1 << LPAIF_I2SCTL_MICMONO_SHIFT) +#define LPAIF_I2SCTL_MICMONO_STEREO 0 +#define LPAIF_I2SCTL_MICMONO_MONO 1 -#define LPAIF_I2SCTL_WSSRC_MASK 0x0004 -#define LPAIF_I2SCTL_WSSRC_SHIFT 2 -#define LPAIF_I2SCTL_WSSRC_INTERNAL (0 << LPAIF_I2SCTL_WSSRC_SHIFT) -#define LPAIF_I2SCTL_WSSRC_EXTERNAL (1 << LPAIF_I2SCTL_WSSRC_SHIFT) +#define LPAIF_I2SCTL_WSSRC_INTERNAL 0 +#define LPAIF_I2SCTL_WSSRC_EXTERNAL 1 -#define LPAIF_I2SCTL_BITWIDTH_MASK 0x0003 -#define LPAIF_I2SCTL_BITWIDTH_SHIFT 0 -#define LPAIF_I2SCTL_BITWIDTH_16 (0 << LPAIF_I2SCTL_BITWIDTH_SHIFT) -#define LPAIF_I2SCTL_BITWIDTH_24 (1 << LPAIF_I2SCTL_BITWIDTH_SHIFT) -#define LPAIF_I2SCTL_BITWIDTH_32 (2 << LPAIF_I2SCTL_BITWIDTH_SHIFT) +#define LPAIF_I2SCTL_BITWIDTH_16 0 +#define LPAIF_I2SCTL_BITWIDTH_24 1 +#define LPAIF_I2SCTL_BITWIDTH_32 2 /* LPAIF IRQ */ #define LPAIF_IRQ_REG_ADDR(v, addr, port) \ @@ -121,42 +115,59 @@ #define LPAIF_DMAPER_REG(v, chan, dir) __LPAIF_DMA_REG(v, chan, dir, PER) #define LPAIF_DMAPERCNT_REG(v, chan, dir) __LPAIF_DMA_REG(v, chan, dir, PERCNT) -#define LPAIF_DMACTL_BURSTEN_MASK 0x800 -#define LPAIF_DMACTL_BURSTEN_SHIFT 11 -#define LPAIF_DMACTL_BURSTEN_SINGLE (0 << LPAIF_DMACTL_BURSTEN_SHIFT) -#define LPAIF_DMACTL_BURSTEN_INCR4 (1 << LPAIF_DMACTL_BURSTEN_SHIFT) - -#define LPAIF_DMACTL_WPSCNT_MASK 0x700 -#define LPAIF_DMACTL_WPSCNT_SHIFT 8 -#define LPAIF_DMACTL_WPSCNT_ONE (0 << LPAIF_DMACTL_WPSCNT_SHIFT) -#define LPAIF_DMACTL_WPSCNT_TWO (1 << LPAIF_DMACTL_WPSCNT_SHIFT) -#define LPAIF_DMACTL_WPSCNT_THREE (2 << LPAIF_DMACTL_WPSCNT_SHIFT) -#define LPAIF_DMACTL_WPSCNT_FOUR (3 << LPAIF_DMACTL_WPSCNT_SHIFT) -#define LPAIF_DMACTL_WPSCNT_SIX (5 << LPAIF_DMACTL_WPSCNT_SHIFT) -#define LPAIF_DMACTL_WPSCNT_EIGHT (7 << LPAIF_DMACTL_WPSCNT_SHIFT) - -#define LPAIF_DMACTL_AUDINTF_MASK 0x0F0 -#define LPAIF_DMACTL_AUDINTF_SHIFT 4 -#define LPAIF_DMACTL_AUDINTF(id) (id << LPAIF_DMACTL_AUDINTF_SHIFT) - -#define LPAIF_DMACTL_FIFOWM_MASK 0x00E -#define LPAIF_DMACTL_FIFOWM_SHIFT 1 -#define LPAIF_DMACTL_FIFOWM_1 (0 << LPAIF_DMACTL_FIFOWM_SHIFT) -#define LPAIF_DMACTL_FIFOWM_2 (1 << LPAIF_DMACTL_FIFOWM_SHIFT) -#define LPAIF_DMACTL_FIFOWM_3 (2 << LPAIF_DMACTL_FIFOWM_SHIFT) -#define LPAIF_DMACTL_FIFOWM_4 (3 << LPAIF_DMACTL_FIFOWM_SHIFT) -#define LPAIF_DMACTL_FIFOWM_5 (4 << LPAIF_DMACTL_FIFOWM_SHIFT) -#define LPAIF_DMACTL_FIFOWM_6 (5 << LPAIF_DMACTL_FIFOWM_SHIFT) -#define LPAIF_DMACTL_FIFOWM_7 (6 << LPAIF_DMACTL_FIFOWM_SHIFT) -#define LPAIF_DMACTL_FIFOWM_8 (7 << LPAIF_DMACTL_FIFOWM_SHIFT) - -#define LPAIF_DMACTL_ENABLE_MASK 0x1 -#define LPAIF_DMACTL_ENABLE_SHIFT 0 -#define LPAIF_DMACTL_ENABLE_OFF (0 << LPAIF_DMACTL_ENABLE_SHIFT) -#define LPAIF_DMACTL_ENABLE_ON (1 << LPAIF_DMACTL_ENABLE_SHIFT) - -#define LPAIF_DMACTL_DYNCLK_MASK BIT(12) -#define LPAIF_DMACTL_DYNCLK_SHIFT 12 -#define LPAIF_DMACTL_DYNCLK_OFF (0 << LPAIF_DMACTL_DYNCLK_SHIFT) -#define LPAIF_DMACTL_DYNCLK_ON (1 << LPAIF_DMACTL_DYNCLK_SHIFT) +#define LPAIF_DMACTL_BURSTEN_SINGLE 0 +#define LPAIF_DMACTL_BURSTEN_INCR4 1 + +#define LPAIF_DMACTL_WPSCNT_ONE 0 +#define LPAIF_DMACTL_WPSCNT_TWO 1 +#define LPAIF_DMACTL_WPSCNT_THREE 2 +#define LPAIF_DMACTL_WPSCNT_FOUR 3 +#define LPAIF_DMACTL_WPSCNT_SIX 5 +#define LPAIF_DMACTL_WPSCNT_EIGHT 7 +#define LPAIF_DMACTL_WPSCNT_TEN 9 +#define LPAIF_DMACTL_WPSCNT_TWELVE 11 +#define LPAIF_DMACTL_WPSCNT_FOURTEEN 13 +#define LPAIF_DMACTL_WPSCNT_SIXTEEN 15 + +#define LPAIF_DMACTL_AUDINTF(id) id + +#define LPAIF_DMACTL_FIFOWM_1 0 +#define LPAIF_DMACTL_FIFOWM_2 1 +#define LPAIF_DMACTL_FIFOWM_3 2 +#define LPAIF_DMACTL_FIFOWM_4 3 +#define LPAIF_DMACTL_FIFOWM_5 4 +#define LPAIF_DMACTL_FIFOWM_6 5 +#define LPAIF_DMACTL_FIFOWM_7 6 +#define LPAIF_DMACTL_FIFOWM_8 7 +#define LPAIF_DMACTL_FIFOWM_9 8 +#define LPAIF_DMACTL_FIFOWM_10 9 +#define LPAIF_DMACTL_FIFOWM_11 10 +#define LPAIF_DMACTL_FIFOWM_12 11 +#define LPAIF_DMACTL_FIFOWM_13 12 +#define LPAIF_DMACTL_FIFOWM_14 13 +#define LPAIF_DMACTL_FIFOWM_15 14 +#define LPAIF_DMACTL_FIFOWM_16 15 +#define LPAIF_DMACTL_FIFOWM_17 16 +#define LPAIF_DMACTL_FIFOWM_18 17 +#define LPAIF_DMACTL_FIFOWM_19 18 +#define LPAIF_DMACTL_FIFOWM_20 19 +#define LPAIF_DMACTL_FIFOWM_21 20 +#define LPAIF_DMACTL_FIFOWM_22 21 +#define LPAIF_DMACTL_FIFOWM_23 22 +#define LPAIF_DMACTL_FIFOWM_24 23 +#define LPAIF_DMACTL_FIFOWM_25 24 +#define LPAIF_DMACTL_FIFOWM_26 25 +#define LPAIF_DMACTL_FIFOWM_27 26 +#define LPAIF_DMACTL_FIFOWM_28 27 +#define LPAIF_DMACTL_FIFOWM_29 28 +#define LPAIF_DMACTL_FIFOWM_30 29 +#define LPAIF_DMACTL_FIFOWM_31 30 +#define LPAIF_DMACTL_FIFOWM_32 31 + +#define LPAIF_DMACTL_ENABLE_OFF 0 +#define LPAIF_DMACTL_ENABLE_ON 1 + +#define LPAIF_DMACTL_DYNCLK_OFF 0 +#define LPAIF_DMACTL_DYNCLK_ON 1 + #endif /* __LPASS_LPAIF_REG_H__ */ diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 01179bc0e5e5..df692ed95503 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -50,6 +50,53 @@ static const struct snd_pcm_hardware lpass_platform_pcm_hardware = { .fifo_size = 0, }; +static int lpass_platform_alloc_dmactl_fields(struct device *dev, + struct regmap *map) +{ + struct lpass_data *drvdata = dev_get_drvdata(dev); + struct lpass_variant *v = drvdata->variant; + struct lpaif_dmactl *rd_dmactl, *wr_dmactl; + + drvdata->rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), + GFP_KERNEL); + if (drvdata->rd_dmactl == NULL) + return -ENOMEM; + + drvdata->wr_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), + GFP_KERNEL); + if (drvdata->wr_dmactl == NULL) + return -ENOMEM; + + rd_dmactl = drvdata->rd_dmactl; + wr_dmactl = drvdata->wr_dmactl; + + rd_dmactl->bursten = devm_regmap_field_alloc(dev, map, v->rdma_bursten); + rd_dmactl->wpscnt = devm_regmap_field_alloc(dev, map, v->rdma_wpscnt); + rd_dmactl->fifowm = devm_regmap_field_alloc(dev, map, v->rdma_fifowm); + rd_dmactl->intf = devm_regmap_field_alloc(dev, map, v->rdma_intf); + rd_dmactl->enable = devm_regmap_field_alloc(dev, map, v->rdma_enable); + rd_dmactl->dyncclk = devm_regmap_field_alloc(dev, map, v->rdma_dyncclk); + + if (IS_ERR(rd_dmactl->bursten) || IS_ERR(rd_dmactl->wpscnt) || + IS_ERR(rd_dmactl->fifowm) || IS_ERR(rd_dmactl->intf) || + IS_ERR(rd_dmactl->enable) || IS_ERR(rd_dmactl->dyncclk)) + return -EINVAL; + + wr_dmactl->bursten = devm_regmap_field_alloc(dev, map, v->wrdma_bursten); + wr_dmactl->wpscnt = devm_regmap_field_alloc(dev, map, v->wrdma_wpscnt); + wr_dmactl->fifowm = devm_regmap_field_alloc(dev, map, v->wrdma_fifowm); + wr_dmactl->intf = devm_regmap_field_alloc(dev, map, v->wrdma_intf); + wr_dmactl->enable = devm_regmap_field_alloc(dev, map, v->wrdma_enable); + wr_dmactl->dyncclk = devm_regmap_field_alloc(dev, map, v->wrdma_dyncclk); + + if (IS_ERR(wr_dmactl->bursten) || IS_ERR(wr_dmactl->wpscnt) || + IS_ERR(wr_dmactl->fifowm) || IS_ERR(wr_dmactl->intf) || + IS_ERR(wr_dmactl->enable) || IS_ERR(wr_dmactl->dyncclk)) + return -EINVAL; + + return 0; +} + static int lpass_platform_pcmops_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -61,7 +108,7 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component, int ret, dma_ch, dir = substream->stream; struct lpass_pcm_data *data; - data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -118,6 +165,7 @@ static int lpass_platform_pcmops_close(struct snd_soc_component *component, if (v->free_dma_channel) v->free_dma_channel(drvdata, data->dma_ch); + kfree(data); return 0; } @@ -133,11 +181,18 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, snd_pcm_format_t format = params_format(params); unsigned int channels = params_channels(params); unsigned int regval; - int ch, dir = substream->stream; + struct lpaif_dmactl *dmactl; + int id, dir = substream->stream; int bitwidth; int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start; - ch = pcm_data->dma_ch; + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + dmactl = drvdata->rd_dmactl; + id = pcm_data->dma_ch; + } else { + dmactl = drvdata->wr_dmactl; + id = pcm_data->dma_ch - v->wrdma_channel_start; + } bitwidth = snd_pcm_format_width(format); if (bitwidth < 0) { @@ -146,25 +201,39 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, return bitwidth; } - regval = LPAIF_DMACTL_BURSTEN_INCR4 | - LPAIF_DMACTL_AUDINTF(dma_port) | - LPAIF_DMACTL_FIFOWM_8; + ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4); + if (ret) { + dev_err(soc_runtime->dev, "error updating bursten field: %d\n", ret); + return ret; + } + + regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8); + if (ret) { + dev_err(soc_runtime->dev, "error updating fifowm field: %d\n", ret); + return ret; + } + + regmap_fields_write(dmactl->intf, id, LPAIF_DMACTL_AUDINTF(dma_port)); + if (ret) { + dev_err(soc_runtime->dev, "error updating audintf field: %d\n", ret); + return ret; + } switch (bitwidth) { case 16: switch (channels) { case 1: case 2: - regval |= LPAIF_DMACTL_WPSCNT_ONE; + regval = LPAIF_DMACTL_WPSCNT_ONE; break; case 4: - regval |= LPAIF_DMACTL_WPSCNT_TWO; + regval = LPAIF_DMACTL_WPSCNT_TWO; break; case 6: - regval |= LPAIF_DMACTL_WPSCNT_THREE; + regval = LPAIF_DMACTL_WPSCNT_THREE; break; case 8: - regval |= LPAIF_DMACTL_WPSCNT_FOUR; + regval = LPAIF_DMACTL_WPSCNT_FOUR; break; default: dev_err(soc_runtime->dev, @@ -177,19 +246,19 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, case 32: switch (channels) { case 1: - regval |= LPAIF_DMACTL_WPSCNT_ONE; + regval = LPAIF_DMACTL_WPSCNT_ONE; break; case 2: - regval |= LPAIF_DMACTL_WPSCNT_TWO; + regval = LPAIF_DMACTL_WPSCNT_TWO; break; case 4: - regval |= LPAIF_DMACTL_WPSCNT_FOUR; + regval = LPAIF_DMACTL_WPSCNT_FOUR; break; case 6: - regval |= LPAIF_DMACTL_WPSCNT_SIX; + regval = LPAIF_DMACTL_WPSCNT_SIX; break; case 8: - regval |= LPAIF_DMACTL_WPSCNT_EIGHT; + regval = LPAIF_DMACTL_WPSCNT_EIGHT; break; default: dev_err(soc_runtime->dev, @@ -204,10 +273,9 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, return -EINVAL; } - ret = regmap_write(drvdata->lpaif_map, - LPAIF_DMACTL_REG(v, ch, dir), regval); + ret = regmap_fields_write(dmactl->wpscnt, id, regval); if (ret) { - dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", + dev_err(soc_runtime->dev, "error writing to dmactl reg: %d\n", ret); return ret; } @@ -244,9 +312,17 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component, struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; - int ret, ch, dir = substream->stream; + struct lpaif_dmactl *dmactl; + int ret, id, ch, dir = substream->stream; ch = pcm_data->dma_ch; + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + dmactl = drvdata->rd_dmactl; + id = pcm_data->dma_ch; + } else { + dmactl = drvdata->wr_dmactl; + id = pcm_data->dma_ch - v->wrdma_channel_start; + } ret = regmap_write(drvdata->lpaif_map, LPAIF_DMABASE_REG(v, ch, dir), @@ -275,9 +351,7 @@ static int lpass_platform_pcmops_prepare(struct snd_soc_component *component, return ret; } - ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_DMACTL_REG(v, ch, dir), - LPAIF_DMACTL_ENABLE_MASK, LPAIF_DMACTL_ENABLE_ON); + ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON); if (ret) { dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); @@ -296,9 +370,18 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, struct snd_pcm_runtime *rt = substream->runtime; struct lpass_pcm_data *pcm_data = rt->private_data; struct lpass_variant *v = drvdata->variant; - int ret, ch, dir = substream->stream; + struct lpaif_dmactl *dmactl; + int ret, ch, id; + int dir = substream->stream; ch = pcm_data->dma_ch; + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + dmactl = drvdata->rd_dmactl; + id = pcm_data->dma_ch; + } else { + dmactl = drvdata->wr_dmactl; + id = pcm_data->dma_ch - v->wrdma_channel_start; + } switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -324,10 +407,8 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, return ret; } - ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_DMACTL_REG(v, ch, dir), - LPAIF_DMACTL_ENABLE_MASK, - LPAIF_DMACTL_ENABLE_ON); + ret = regmap_fields_write(dmactl->enable, id, + LPAIF_DMACTL_ENABLE_ON); if (ret) { dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); @@ -337,10 +418,8 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = regmap_update_bits(drvdata->lpaif_map, - LPAIF_DMACTL_REG(v, ch, dir), - LPAIF_DMACTL_ENABLE_MASK, - LPAIF_DMACTL_ENABLE_OFF); + ret = regmap_fields_write(dmactl->enable, id, + LPAIF_DMACTL_ENABLE_OFF); if (ret) { dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret); @@ -400,9 +479,8 @@ static int lpass_platform_pcmops_mmap(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = substream->runtime; - return dma_mmap_coherent(substream->pcm->card->dev, vma, - runtime->dma_area, runtime->dma_addr, - runtime->dma_bytes); + return dma_mmap_coherent(component->dev, vma, runtime->dma_area, + runtime->dma_addr, runtime->dma_bytes); } static irqreturn_t lpass_dma_interrupt_handler( @@ -560,7 +638,7 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) struct lpass_variant *v = drvdata->variant; int ret; - drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); + drvdata->lpaif_irq = platform_get_irq(pdev, 0); if (drvdata->lpaif_irq < 0) return -ENODEV; @@ -580,6 +658,13 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev) return ret; } + ret = lpass_platform_alloc_dmactl_fields(&pdev->dev, + drvdata->lpaif_map); + if (ret) { + dev_err(&pdev->dev, + "error initializing dmactl fields: %d\n", ret); + return ret; + } return devm_snd_soc_register_component(&pdev->dev, &lpass_component_driver, NULL, 0); diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c new file mode 100644 index 000000000000..167bf2cbc556 --- /dev/null +++ b/sound/soc/qcom/lpass-sc7180.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * lpass-sc7180.c -- ALSA SoC platform-machine driver for QTi LPASS + */ + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <dt-bindings/sound/sc7180-lpass.h> +#include <sound/pcm.h> +#include <sound/soc.h> + +#include "lpass-lpaif-reg.h" +#include "lpass.h" + +static struct snd_soc_dai_driver sc7180_lpass_cpu_dai_driver[] = { + [MI2S_PRIMARY] = { + .id = MI2S_PRIMARY, + .name = "Primary MI2S", + .playback = { + .stream_name = "Primary Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .capture = { + .stream_name = "Primary Capture", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, + + [MI2S_SECONDARY] = { + .id = MI2S_SECONDARY, + .name = "Secondary MI2S", + .playback = { + .stream_name = "Secondary Playback", + .formats = SNDRV_PCM_FMTBIT_S16, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, + }, + .probe = &asoc_qcom_lpass_cpu_dai_probe, + .ops = &asoc_qcom_lpass_cpu_dai_ops, + }, +}; + +static int sc7180_lpass_alloc_dma_channel(struct lpass_data *drvdata, + int direction) +{ + struct lpass_variant *v = drvdata->variant; + int chan = 0; + + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { + chan = find_first_zero_bit(&drvdata->dma_ch_bit_map, + v->rdma_channels); + + if (chan >= v->rdma_channels) + return -EBUSY; + } else { + chan = find_next_zero_bit(&drvdata->dma_ch_bit_map, + v->wrdma_channel_start + + v->wrdma_channels, + v->wrdma_channel_start); + + if (chan >= v->wrdma_channel_start + v->wrdma_channels) + return -EBUSY; + } + + set_bit(chan, &drvdata->dma_ch_bit_map); + + return chan; +} + +static int sc7180_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) +{ + clear_bit(chan, &drvdata->dma_ch_bit_map); + + return 0; +} + +static int sc7180_lpass_init(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + struct lpass_variant *variant = drvdata->variant; + struct device *dev = &pdev->dev; + int ret, i; + + drvdata->clks = devm_kcalloc(dev, variant->num_clks, + sizeof(*drvdata->clks), GFP_KERNEL); + drvdata->num_clks = variant->num_clks; + + for (i = 0; i < drvdata->num_clks; i++) + drvdata->clks[i].id = variant->clk_name[i]; + + ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "Failed to get clocks %d\n", ret); + return ret; + } + + ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); + if (ret) { + dev_err(dev, "sc7180 clk_enable failed\n"); + return ret; + } + + return 0; +} + +static int sc7180_lpass_exit(struct platform_device *pdev) +{ + struct lpass_data *drvdata = platform_get_drvdata(pdev); + + clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); + + return 0; +} + +static struct lpass_variant sc7180_data = { + .i2sctrl_reg_base = 0x1000, + .i2sctrl_reg_stride = 0x1000, + .i2s_ports = 3, + .irq_reg_base = 0x9000, + .irq_reg_stride = 0x1000, + .irq_ports = 3, + .rdma_reg_base = 0xC000, + .rdma_reg_stride = 0x1000, + .rdma_channels = 5, + .dmactl_audif_start = 1, + .wrdma_reg_base = 0x18000, + .wrdma_reg_stride = 0x1000, + .wrdma_channel_start = 5, + .wrdma_channels = 4, + + .loopback = REG_FIELD_ID(0x1000, 17, 17, 3, 0x1000), + .spken = REG_FIELD_ID(0x1000, 16, 16, 3, 0x1000), + .spkmode = REG_FIELD_ID(0x1000, 11, 15, 3, 0x1000), + .spkmono = REG_FIELD_ID(0x1000, 10, 10, 3, 0x1000), + .micen = REG_FIELD_ID(0x1000, 9, 9, 3, 0x1000), + .micmode = REG_FIELD_ID(0x1000, 4, 8, 3, 0x1000), + .micmono = REG_FIELD_ID(0x1000, 3, 3, 3, 0x1000), + .wssrc = REG_FIELD_ID(0x1000, 2, 2, 3, 0x1000), + .bitwidth = REG_FIELD_ID(0x1000, 0, 0, 3, 0x1000), + + .rdma_dyncclk = REG_FIELD_ID(0xC000, 21, 21, 5, 0x1000), + .rdma_bursten = REG_FIELD_ID(0xC000, 20, 20, 5, 0x1000), + .rdma_wpscnt = REG_FIELD_ID(0xC000, 16, 19, 5, 0x1000), + .rdma_intf = REG_FIELD_ID(0xC000, 12, 15, 5, 0x1000), + .rdma_fifowm = REG_FIELD_ID(0xC000, 1, 5, 5, 0x1000), + .rdma_enable = REG_FIELD_ID(0xC000, 0, 0, 5, 0x1000), + + .wrdma_dyncclk = REG_FIELD_ID(0x18000, 22, 22, 4, 0x1000), + .wrdma_bursten = REG_FIELD_ID(0x18000, 21, 21, 4, 0x1000), + .wrdma_wpscnt = REG_FIELD_ID(0x18000, 17, 20, 4, 0x1000), + .wrdma_intf = REG_FIELD_ID(0x18000, 12, 16, 4, 0x1000), + .wrdma_fifowm = REG_FIELD_ID(0x18000, 1, 5, 4, 0x1000), + .wrdma_enable = REG_FIELD_ID(0x18000, 0, 0, 4, 0x1000), + + .clk_name = (const char*[]) { + "pcnoc-sway-clk", + "audio-core", + "pcnoc-mport-clk", + }, + .num_clks = 3, + .dai_driver = sc7180_lpass_cpu_dai_driver, + .num_dai = ARRAY_SIZE(sc7180_lpass_cpu_dai_driver), + .dai_osr_clk_names = (const char *[]) { + "mclk0", + "null", + }, + .dai_bit_clk_names = (const char *[]) { + "mi2s-bit-clk0", + "mi2s-bit-clk1", + }, + .init = sc7180_lpass_init, + .exit = sc7180_lpass_exit, + .alloc_dma_channel = sc7180_lpass_alloc_dma_channel, + .free_dma_channel = sc7180_lpass_free_dma_channel, +}; + +static const struct of_device_id sc7180_lpass_cpu_device_id[] = { + {.compatible = "qcom,sc7180-lpass-cpu", .data = &sc7180_data}, + {} +}; + +static struct platform_driver sc7180_lpass_cpu_platform_driver = { + .driver = { + .name = "sc7180-lpass-cpu", + .of_match_table = of_match_ptr(sc7180_lpass_cpu_device_id), + }, + .probe = asoc_qcom_lpass_cpu_platform_probe, + .remove = asoc_qcom_lpass_cpu_platform_remove, +}; + +module_platform_driver(sc7180_lpass_cpu_platform_driver); + +MODULE_DESCRIPTION("SC7180 LPASS CPU DRIVER"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index bd19ec57c73d..51c9991a0edf 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -17,6 +17,28 @@ #define LPASS_MAX_MI2S_PORTS (8) #define LPASS_MAX_DMA_CHANNELS (8) +struct lpaif_i2sctl { + struct regmap_field *loopback; + struct regmap_field *spken; + struct regmap_field *spkmode; + struct regmap_field *spkmono; + struct regmap_field *micen; + struct regmap_field *micmode; + struct regmap_field *micmono; + struct regmap_field *wssrc; + struct regmap_field *bitwidth; +}; + + +struct lpaif_dmactl { + struct regmap_field *bursten; + struct regmap_field *wpscnt; + struct regmap_field *intf; + struct regmap_field *fifowm; + struct regmap_field *enable; + struct regmap_field *dyncclk; +}; + /* Both the CPU DAI and platform drivers will access this data */ struct lpass_data { @@ -51,10 +73,14 @@ struct lpass_data { /* used it for handling interrupt per dma channel */ struct snd_pcm_substream *substream[LPASS_MAX_DMA_CHANNELS]; - /* 8016 specific */ - struct clk *pcnoc_mport_clk; - struct clk *pcnoc_sway_clk; + /* SOC specific clock list */ + struct clk_bulk_data *clks; + int num_clks; + /* Regmap fields of I2SCTL & DMACTL registers bitfields */ + struct lpaif_i2sctl *i2sctl; + struct lpaif_dmactl *rd_dmactl; + struct lpaif_dmactl *wr_dmactl; }; /* Vairant data per each SOC */ @@ -72,6 +98,33 @@ struct lpass_variant { u32 wrdma_reg_stride; u32 wrdma_channels; + /* I2SCTL Register fields */ + struct reg_field loopback; + struct reg_field spken; + struct reg_field spkmode; + struct reg_field spkmono; + struct reg_field micen; + struct reg_field micmode; + struct reg_field micmono; + struct reg_field wssrc; + struct reg_field bitwidth; + + /* RD_DMA Register fields */ + struct reg_field rdma_bursten; + struct reg_field rdma_wpscnt; + struct reg_field rdma_intf; + struct reg_field rdma_fifowm; + struct reg_field rdma_enable; + struct reg_field rdma_dyncclk; + + /* WR_DMA Register fields */ + struct reg_field wrdma_bursten; + struct reg_field wrdma_wpscnt; + struct reg_field wrdma_intf; + struct reg_field wrdma_fifowm; + struct reg_field wrdma_enable; + struct reg_field wrdma_dyncclk; + /** * on SOCs like APQ8016 the channel control bits start * at different offset to ipq806x @@ -89,6 +142,10 @@ struct lpass_variant { int num_dai; const char * const *dai_osr_clk_names; const char * const *dai_bit_clk_names; + + /* SOC specific clocks configuration */ + const char **clk_name; + int num_clks; }; /* register the platform driver from the CPU DAI driver */ diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 9b7b218f2a20..a1dd31f306ce 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -50,7 +50,7 @@ enum stream_state { struct q6asm_dai_rtd { struct snd_pcm_substream *substream; struct snd_compr_stream *cstream; - struct snd_compr_params codec_param; + struct snd_codec codec; struct snd_dma_buffer dma_buffer; spinlock_t lock; phys_addr_t phys; @@ -64,8 +64,14 @@ struct q6asm_dai_rtd { uint16_t bits_per_sample; uint16_t source; /* Encoding source bit mask */ struct audio_client *audio_client; + uint32_t next_track_stream_id; + bool next_track; + uint32_t stream_id; uint16_t session_id; enum stream_state state; + uint32_t initial_samples_drop; + uint32_t trailing_samples_drop; + bool notify_on_drain; }; struct q6asm_dai_data { @@ -181,8 +187,8 @@ static void event_handler(uint32_t opcode, uint32_t token, switch (opcode) { case ASM_CLIENT_EVENT_CMD_RUN_DONE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - q6asm_write_async(prtd->audio_client, - prtd->pcm_count, 0, 0, NO_TIMESTAMP); + q6asm_write_async(prtd->audio_client, prtd->stream_id, + prtd->pcm_count, 0, 0, 0); break; case ASM_CLIENT_EVENT_CMD_EOS_DONE: prtd->state = Q6ASM_STREAM_STOPPED; @@ -191,8 +197,8 @@ static void event_handler(uint32_t opcode, uint32_t token, prtd->pcm_irq_pos += prtd->pcm_count; snd_pcm_period_elapsed(substream); if (prtd->state == Q6ASM_STREAM_RUNNING) - q6asm_write_async(prtd->audio_client, - prtd->pcm_count, 0, 0, NO_TIMESTAMP); + q6asm_write_async(prtd->audio_client, prtd->stream_id, + prtd->pcm_count, 0, 0, 0); break; } @@ -200,7 +206,7 @@ static void event_handler(uint32_t opcode, uint32_t token, prtd->pcm_irq_pos += prtd->pcm_count; snd_pcm_period_elapsed(substream); if (prtd->state == Q6ASM_STREAM_RUNNING) - q6asm_read(prtd->audio_client); + q6asm_read(prtd->audio_client, prtd->stream_id); break; default: @@ -233,7 +239,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, /* rate and channels are sent to audio driver */ if (prtd->state) { /* clear the previous setup if any */ - q6asm_cmd(prtd->audio_client, CMD_CLOSE); + q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); q6asm_unmap_memory_regions(substream->stream, prtd->audio_client); q6routing_stream_close(soc_prtd->dai_link->id, @@ -252,11 +258,13 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM, - 0, prtd->bits_per_sample); + ret = q6asm_open_write(prtd->audio_client, prtd->stream_id, + FORMAT_LINEAR_PCM, + 0, prtd->bits_per_sample, false); } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM, - prtd->bits_per_sample); + ret = q6asm_open_read(prtd->audio_client, prtd->stream_id, + FORMAT_LINEAR_PCM, + prtd->bits_per_sample); } if (ret < 0) { @@ -276,17 +284,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ret = q6asm_media_format_block_multi_ch_pcm( - prtd->audio_client, runtime->rate, - runtime->channels, NULL, + prtd->audio_client, prtd->stream_id, + runtime->rate, runtime->channels, NULL, prtd->bits_per_sample); } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client, - runtime->rate, runtime->channels, - prtd->bits_per_sample); + prtd->stream_id, + runtime->rate, + runtime->channels, + prtd->bits_per_sample); /* Queue the buffers */ for (i = 0; i < runtime->periods; i++) - q6asm_read(prtd->audio_client); + q6asm_read(prtd->audio_client, prtd->stream_id); } if (ret < 0) @@ -308,15 +318,18 @@ static int q6asm_dai_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id, + 0, 0, 0); break; case SNDRV_PCM_TRIGGER_STOP: prtd->state = Q6ASM_STREAM_STOPPED; - ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); + ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, + CMD_EOS); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); + ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, + CMD_PAUSE); break; default: ret = -EINVAL; @@ -361,6 +374,9 @@ static int q6asm_dai_open(struct snd_soc_component *component, return ret; } + /* DSP expects stream id from 1 */ + prtd->stream_id = 1; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) runtime->hw = q6asm_dai_hardware_playback; else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) @@ -427,7 +443,8 @@ static int q6asm_dai_close(struct snd_soc_component *component, if (prtd->audio_client) { if (prtd->state) - q6asm_cmd(prtd->audio_client, CMD_CLOSE); + q6asm_cmd(prtd->audio_client, prtd->stream_id, + CMD_CLOSE); q6asm_unmap_memory_regions(substream->stream, prtd->audio_client); @@ -493,14 +510,21 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, struct q6asm_dai_rtd *prtd = priv; struct snd_compr_stream *substream = prtd->cstream; unsigned long flags; + u32 wflags = 0; uint64_t avail; + uint32_t bytes_written, bytes_to_write; + bool is_last_buffer = false; switch (opcode) { case ASM_CLIENT_EVENT_CMD_RUN_DONE: spin_lock_irqsave(&prtd->lock, flags); if (!prtd->bytes_sent) { - q6asm_write_async(prtd->audio_client, prtd->pcm_count, - 0, 0, NO_TIMESTAMP); + q6asm_stream_remove_initial_silence(prtd->audio_client, + prtd->stream_id, + prtd->initial_samples_drop); + + q6asm_write_async(prtd->audio_client, prtd->stream_id, + prtd->pcm_count, 0, 0, 0); prtd->bytes_sent += prtd->pcm_count; } @@ -508,13 +532,37 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, break; case ASM_CLIENT_EVENT_CMD_EOS_DONE: - prtd->state = Q6ASM_STREAM_STOPPED; + spin_lock_irqsave(&prtd->lock, flags); + if (prtd->notify_on_drain) { + if (substream->partial_drain) { + /* + * Close old stream and make it stale, switch + * the active stream now! + */ + q6asm_cmd_nowait(prtd->audio_client, + prtd->stream_id, + CMD_CLOSE); + /* + * vaild stream ids start from 1, So we are + * toggling this between 1 and 2. + */ + prtd->stream_id = (prtd->stream_id == 1 ? 2 : 1); + } + + snd_compr_drain_notify(prtd->cstream); + prtd->notify_on_drain = false; + + } else { + prtd->state = Q6ASM_STREAM_STOPPED; + } + spin_unlock_irqrestore(&prtd->lock, flags); break; case ASM_CLIENT_EVENT_DATA_WRITE_DONE: spin_lock_irqsave(&prtd->lock, flags); - prtd->copied_total += prtd->pcm_count; + bytes_written = token >> ASM_WRITE_TOKEN_LEN_SHIFT; + prtd->copied_total += bytes_written; snd_compr_fragment_elapsed(substream); if (prtd->state != Q6ASM_STREAM_RUNNING) { @@ -523,13 +571,32 @@ static void compress_event_handler(uint32_t opcode, uint32_t token, } avail = prtd->bytes_received - prtd->bytes_sent; + if (avail > prtd->pcm_count) { + bytes_to_write = prtd->pcm_count; + } else { + if (substream->partial_drain || prtd->notify_on_drain) + is_last_buffer = true; + bytes_to_write = avail; + } - if (avail >= prtd->pcm_count) { - q6asm_write_async(prtd->audio_client, - prtd->pcm_count, 0, 0, NO_TIMESTAMP); - prtd->bytes_sent += prtd->pcm_count; + if (bytes_to_write) { + if (substream->partial_drain && is_last_buffer) { + wflags |= ASM_LAST_BUFFER_FLAG; + q6asm_stream_remove_trailing_silence(prtd->audio_client, + prtd->stream_id, + prtd->trailing_samples_drop); + } + + q6asm_write_async(prtd->audio_client, prtd->stream_id, + bytes_to_write, 0, 0, wflags); + + prtd->bytes_sent += bytes_to_write; } + if (prtd->notify_on_drain && is_last_buffer) + q6asm_cmd_nowait(prtd->audio_client, + prtd->stream_id, CMD_EOS); + spin_unlock_irqrestore(&prtd->lock, flags); break; @@ -560,6 +627,9 @@ static int q6asm_dai_compr_open(struct snd_soc_component *component, if (!prtd) return -ENOMEM; + /* DSP expects stream id from 1 */ + prtd->stream_id = 1; + prtd->cstream = stream; prtd->audio_client = q6asm_audio_client_alloc(dev, (q6asm_cb)compress_event_handler, @@ -606,8 +676,15 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd = stream->private_data; if (prtd->audio_client) { - if (prtd->state) - q6asm_cmd(prtd->audio_client, CMD_CLOSE); + if (prtd->state) { + q6asm_cmd(prtd->audio_client, prtd->stream_id, + CMD_CLOSE); + if (prtd->next_track_stream_id) { + q6asm_cmd(prtd->audio_client, + prtd->next_track_stream_id, + CMD_CLOSE); + } + } snd_dma_free_pages(&prtd->dma_buffer); q6asm_unmap_memory_regions(stream->direction, @@ -621,15 +698,13 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component, return 0; } -static int q6asm_dai_compr_set_params(struct snd_soc_component *component, - struct snd_compr_stream *stream, - struct snd_compr_params *params) +static int __q6asm_dai_compr_set_codec_params(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_codec *codec, + int stream_id) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; - struct snd_soc_pcm_runtime *rtd = stream->private_data; - int dir = stream->direction; - struct q6asm_dai_data *pdata; struct q6asm_flac_cfg flac_cfg; struct q6asm_wma_cfg wma_cfg; struct q6asm_alac_cfg alac_cfg; @@ -643,52 +718,18 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, struct snd_dec_alac *alac; struct snd_dec_ape *ape; - codec_options = &(prtd->codec_param.codec.options); - - - memcpy(&prtd->codec_param, params, sizeof(*params)); - - pdata = snd_soc_component_get_drvdata(component); - if (!pdata) - return -EINVAL; - - if (!prtd || !prtd->audio_client) { - dev_err(dev, "private data null or audio client freed\n"); - return -EINVAL; - } - - prtd->periods = runtime->fragments; - prtd->pcm_count = runtime->fragment_size; - prtd->pcm_size = runtime->fragments * runtime->fragment_size; - prtd->bits_per_sample = 16; - if (dir == SND_COMPRESS_PLAYBACK) { - ret = q6asm_open_write(prtd->audio_client, params->codec.id, - params->codec.profile, prtd->bits_per_sample); - - if (ret < 0) { - dev_err(dev, "q6asm_open_write failed\n"); - q6asm_audio_client_free(prtd->audio_client); - prtd->audio_client = NULL; - return ret; - } - } + codec_options = &(prtd->codec.options); - prtd->session_id = q6asm_get_session_id(prtd->audio_client); - ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE, - prtd->session_id, dir); - if (ret) { - dev_err(dev, "Stream reg failed ret:%d\n", ret); - return ret; - } + memcpy(&prtd->codec, codec, sizeof(*codec)); - switch (params->codec.id) { + switch (codec->id) { case SND_AUDIOCODEC_FLAC: memset(&flac_cfg, 0x0, sizeof(struct q6asm_flac_cfg)); flac = &codec_options->flac_d; - flac_cfg.ch_cfg = params->codec.ch_in; - flac_cfg.sample_rate = params->codec.sample_rate; + flac_cfg.ch_cfg = codec->ch_in; + flac_cfg.sample_rate = codec->sample_rate; flac_cfg.stream_info_present = 1; flac_cfg.sample_size = flac->sample_size; flac_cfg.min_blk_size = flac->min_blk_size; @@ -697,6 +738,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, flac_cfg.min_frame_size = flac->min_frame_size; ret = q6asm_stream_media_format_block_flac(prtd->audio_client, + stream_id, &flac_cfg); if (ret < 0) { dev_err(dev, "FLAC CMD Format block failed:%d\n", ret); @@ -709,10 +751,10 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg)); - wma_cfg.sample_rate = params->codec.sample_rate; - wma_cfg.num_channels = params->codec.ch_in; - wma_cfg.bytes_per_sec = params->codec.bit_rate / 8; - wma_cfg.block_align = params->codec.align; + wma_cfg.sample_rate = codec->sample_rate; + wma_cfg.num_channels = codec->ch_in; + wma_cfg.bytes_per_sec = codec->bit_rate / 8; + wma_cfg.block_align = codec->align; wma_cfg.bits_per_sample = prtd->bits_per_sample; wma_cfg.enc_options = wma->encoder_option; wma_cfg.adv_enc_options = wma->adv_encoder_option; @@ -726,7 +768,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, return -EINVAL; /* check the codec profile */ - switch (params->codec.profile) { + switch (codec->profile) { case SND_AUDIOPROFILE_WMA9: wma_cfg.fmtag = 0x161; wma_v9 = 1; @@ -750,16 +792,18 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, default: dev_err(dev, "Unknown WMA profile:%x\n", - params->codec.profile); + codec->profile); return -EIO; } if (wma_v9) ret = q6asm_stream_media_format_block_wma_v9( - prtd->audio_client, &wma_cfg); + prtd->audio_client, stream_id, + &wma_cfg); else ret = q6asm_stream_media_format_block_wma_v10( - prtd->audio_client, &wma_cfg); + prtd->audio_client, stream_id, + &wma_cfg); if (ret < 0) { dev_err(dev, "WMA9 CMD failed:%d\n", ret); return -EIO; @@ -770,10 +814,10 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, memset(&alac_cfg, 0x0, sizeof(alac_cfg)); alac = &codec_options->alac_d; - alac_cfg.sample_rate = params->codec.sample_rate; - alac_cfg.avg_bit_rate = params->codec.bit_rate; + alac_cfg.sample_rate = codec->sample_rate; + alac_cfg.avg_bit_rate = codec->bit_rate; alac_cfg.bit_depth = prtd->bits_per_sample; - alac_cfg.num_channels = params->codec.ch_in; + alac_cfg.num_channels = codec->ch_in; alac_cfg.frame_length = alac->frame_length; alac_cfg.pb = alac->pb; @@ -783,7 +827,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, alac_cfg.compatible_version = alac->compatible_version; alac_cfg.max_frame_bytes = alac->max_frame_bytes; - switch (params->codec.ch_in) { + switch (codec->ch_in) { case 1: alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO; break; @@ -792,6 +836,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, break; } ret = q6asm_stream_media_format_block_alac(prtd->audio_client, + stream_id, &alac_cfg); if (ret < 0) { dev_err(dev, "ALAC CMD Format block failed:%d\n", ret); @@ -803,8 +848,8 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, memset(&ape_cfg, 0x0, sizeof(ape_cfg)); ape = &codec_options->ape_d; - ape_cfg.sample_rate = params->codec.sample_rate; - ape_cfg.num_channels = params->codec.ch_in; + ape_cfg.sample_rate = codec->sample_rate; + ape_cfg.num_channels = codec->ch_in; ape_cfg.bits_per_sample = prtd->bits_per_sample; ape_cfg.compatible_version = ape->compatible_version; @@ -816,6 +861,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, ape_cfg.seek_table_present = ape->seek_table_present; ret = q6asm_stream_media_format_block_ape(prtd->audio_client, + stream_id, &ape_cfg); if (ret < 0) { dev_err(dev, "APE CMD Format block failed:%d\n", ret); @@ -827,6 +873,64 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, break; } + return 0; +} + +static int q6asm_dai_compr_set_params(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_params *params) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = stream->private_data; + int dir = stream->direction; + struct q6asm_dai_data *pdata; + struct device *dev = component->dev; + int ret; + + pdata = snd_soc_component_get_drvdata(component); + if (!pdata) + return -EINVAL; + + if (!prtd || !prtd->audio_client) { + dev_err(dev, "private data null or audio client freed\n"); + return -EINVAL; + } + + prtd->periods = runtime->fragments; + prtd->pcm_count = runtime->fragment_size; + prtd->pcm_size = runtime->fragments * runtime->fragment_size; + prtd->bits_per_sample = 16; + + if (dir == SND_COMPRESS_PLAYBACK) { + ret = q6asm_open_write(prtd->audio_client, prtd->stream_id, params->codec.id, + params->codec.profile, prtd->bits_per_sample, + true); + + if (ret < 0) { + dev_err(dev, "q6asm_open_write failed\n"); + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return ret; + } + } + + prtd->session_id = q6asm_get_session_id(prtd->audio_client); + ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE, + prtd->session_id, dir); + if (ret) { + dev_err(dev, "Stream reg failed ret:%d\n", ret); + return ret; + } + + ret = __q6asm_dai_compr_set_codec_params(component, stream, + ¶ms->codec, + prtd->stream_id); + if (ret) { + dev_err(dev, "codec param setup failed ret:%d\n", ret); + return ret; + } + ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, (prtd->pcm_size / prtd->periods), prtd->periods); @@ -841,6 +945,55 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, return 0; } +static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_metadata *metadata) +{ + struct snd_compr_runtime *runtime = stream->runtime; + struct q6asm_dai_rtd *prtd = runtime->private_data; + int ret = 0; + + switch (metadata->key) { + case SNDRV_COMPRESS_ENCODER_PADDING: + prtd->trailing_samples_drop = metadata->value[0]; + break; + case SNDRV_COMPRESS_ENCODER_DELAY: + prtd->initial_samples_drop = metadata->value[0]; + if (prtd->next_track_stream_id) { + ret = q6asm_open_write(prtd->audio_client, + prtd->next_track_stream_id, + prtd->codec.id, + prtd->codec.profile, + prtd->bits_per_sample, + true); + if (ret < 0) { + dev_err(component->dev, "q6asm_open_write failed\n"); + return ret; + } + ret = __q6asm_dai_compr_set_codec_params(component, stream, + &prtd->codec, + prtd->next_track_stream_id); + if (ret < 0) { + dev_err(component->dev, "q6asm_open_write failed\n"); + return ret; + } + + ret = q6asm_stream_remove_initial_silence(prtd->audio_client, + prtd->next_track_stream_id, + prtd->initial_samples_drop); + prtd->next_track_stream_id = 0; + + } + + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + static int q6asm_dai_compr_trigger(struct snd_soc_component *component, struct snd_compr_stream *stream, int cmd) { @@ -852,15 +1005,26 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id, + 0, 0, 0); break; case SNDRV_PCM_TRIGGER_STOP: prtd->state = Q6ASM_STREAM_STOPPED; - ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS); + ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, + CMD_EOS); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE); + ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id, + CMD_PAUSE); + break; + case SND_COMPR_TRIGGER_NEXT_TRACK: + prtd->next_track = true; + prtd->next_track_stream_id = (prtd->stream_id == 1 ? 2 : 1); + break; + case SND_COMPR_TRIGGER_DRAIN: + case SND_COMPR_TRIGGER_PARTIAL_DRAIN: + prtd->notify_on_drain = true; break; default: ret = -EINVAL; @@ -888,16 +1052,71 @@ static int q6asm_dai_compr_pointer(struct snd_soc_component *component, return 0; } -static int q6asm_dai_compr_ack(struct snd_soc_component *component, - struct snd_compr_stream *stream, - size_t count) +static int q6asm_compr_copy(struct snd_soc_component *component, + struct snd_compr_stream *stream, char __user *buf, + size_t count) { struct snd_compr_runtime *runtime = stream->runtime; struct q6asm_dai_rtd *prtd = runtime->private_data; unsigned long flags; + u32 wflags = 0; + int avail, bytes_in_flight = 0; + void *dstn; + size_t copy; + u32 app_pointer; + u32 bytes_received; + + bytes_received = prtd->bytes_received; + + /** + * Make sure that next track data pointer is aligned at 32 bit boundary + * This is a Mandatory requirement from DSP data buffers alignment + */ + if (prtd->next_track) + bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count); + + app_pointer = bytes_received/prtd->pcm_size; + app_pointer = bytes_received - (app_pointer * prtd->pcm_size); + dstn = prtd->dma_buffer.area + app_pointer; + + if (count < prtd->pcm_size - app_pointer) { + if (copy_from_user(dstn, buf, count)) + return -EFAULT; + } else { + copy = prtd->pcm_size - app_pointer; + if (copy_from_user(dstn, buf, copy)) + return -EFAULT; + if (copy_from_user(prtd->dma_buffer.area, buf + copy, + count - copy)) + return -EFAULT; + } spin_lock_irqsave(&prtd->lock, flags); - prtd->bytes_received += count; + + bytes_in_flight = prtd->bytes_received - prtd->copied_total; + + if (prtd->next_track) { + prtd->next_track = false; + prtd->copied_total = ALIGN(prtd->copied_total, prtd->pcm_count); + prtd->bytes_sent = ALIGN(prtd->bytes_sent, prtd->pcm_count); + } + + prtd->bytes_received = bytes_received + count; + + /* Kick off the data to dsp if its starving!! */ + if (prtd->state == Q6ASM_STREAM_RUNNING && (bytes_in_flight == 0)) { + uint32_t bytes_to_write = prtd->pcm_count; + + avail = prtd->bytes_received - prtd->bytes_sent; + + if (avail < prtd->pcm_count) + bytes_to_write = avail; + + q6asm_write_async(prtd->audio_client, prtd->stream_id, + bytes_to_write, 0, 0, wflags); + prtd->bytes_sent += bytes_to_write; + } + spin_unlock_irqrestore(&prtd->lock, flags); return count; @@ -954,12 +1173,13 @@ static struct snd_compress_ops q6asm_dai_compress_ops = { .open = q6asm_dai_compr_open, .free = q6asm_dai_compr_free, .set_params = q6asm_dai_compr_set_params, + .set_metadata = q6asm_dai_compr_set_metadata, .pointer = q6asm_dai_compr_pointer, .trigger = q6asm_dai_compr_trigger, .get_caps = q6asm_dai_compr_get_caps, .get_codec_caps = q6asm_dai_compr_get_codec_caps, .mmap = q6asm_dai_compr_mmap, - .ack = q6asm_dai_compr_ack, + .copy = q6asm_compr_copy, }; static int q6asm_dai_pcm_new(struct snd_soc_component *component, diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 755062eadcc8..d745a02fcd5f 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -51,6 +51,8 @@ #define ASM_STREAM_CMD_OPEN_READWRITE_V2 0x00010D8D #define ASM_MEDIA_FMT_ALAC 0x00012f31 #define ASM_MEDIA_FMT_APE 0x00012f32 +#define ASM_DATA_CMD_REMOVE_INITIAL_SILENCE 0x00010D67 +#define ASM_DATA_CMD_REMOVE_TRAILING_SILENCE 0x00010D68 #define ASM_LEGACY_STREAM_SESSION 0 @@ -270,7 +272,6 @@ struct audio_client { wait_queue_head_t cmd_wait; struct aprv2_ibasic_rsp_result_t result; int perf_mode; - int stream_id; struct q6asm *q6asm; struct device *dev; }; @@ -640,6 +641,8 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, case ASM_STREAM_CMD_OPEN_READWRITE_V2: case ASM_STREAM_CMD_SET_ENCDEC_PARAM: case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2: + case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE: + case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE: if (result->status != 0) { dev_err(ac->dev, "cmd = 0x%x returned error = 0x%x\n", @@ -671,6 +674,7 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, if (ac->io_mode & ASM_SYNC_IO_MODE) { phys_addr_t phys; unsigned long flags; + int token = hdr->token & ASM_WRITE_TOKEN_MASK; spin_lock_irqsave(&ac->lock, flags); @@ -682,12 +686,12 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, goto done; } - phys = port->buf[hdr->token].phys; + phys = port->buf[token].phys; if (lower_32_bits(phys) != result->opcode || upper_32_bits(phys) != result->status) { dev_err(ac->dev, "Expected addr %pa\n", - &port->buf[hdr->token].phys); + &port->buf[token].phys); spin_unlock_irqrestore(&ac->lock, flags); ret = -EINVAL; goto done; @@ -828,21 +832,21 @@ EXPORT_SYMBOL_GPL(q6asm_get_session_id); * @dev: Pointer to asm child device. * @cb: event callback. * @priv: private data associated with this client. - * @stream_id: stream id + * @session_id: session id * @perf_mode: performace mode for this client * * Return: Will be an error pointer on error or a valid audio client * on success. */ struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, - void *priv, int stream_id, + void *priv, int session_id, int perf_mode) { struct q6asm *a = dev_get_drvdata(dev->parent); struct audio_client *ac; unsigned long flags; - ac = q6asm_get_audio_client(a, stream_id + 1); + ac = q6asm_get_audio_client(a, session_id + 1); if (ac) { dev_err(dev, "Audio Client already active\n"); return ac; @@ -853,17 +857,15 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, return ERR_PTR(-ENOMEM); spin_lock_irqsave(&a->slock, flags); - a->session[stream_id + 1] = ac; + a->session[session_id + 1] = ac; spin_unlock_irqrestore(&a->slock, flags); - ac->session = stream_id + 1; + ac->session = session_id + 1; ac->cb = cb; ac->dev = dev; ac->q6asm = a; ac->priv = priv; ac->io_mode = ASM_SYNC_IO_MODE; ac->perf_mode = perf_mode; - /* DSP expects stream id from 1 */ - ac->stream_id = 1; ac->adev = a->adev; kref_init(&ac->refcount); @@ -919,8 +921,9 @@ err: * * Return: Will be an negative value on error or zero on success */ -int q6asm_open_write(struct audio_client *ac, uint32_t format, - u32 codec_profile, uint16_t bits_per_sample) +int q6asm_open_write(struct audio_client *ac, uint32_t stream_id, + uint32_t format, u32 codec_profile, + uint16_t bits_per_sample, bool is_gapless) { struct asm_stream_cmd_open_write_v3 *open; struct apr_pkt *pkt; @@ -935,11 +938,13 @@ int q6asm_open_write(struct audio_client *ac, uint32_t format, pkt = p; open = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3; open->mode_flags = 0x00; open->mode_flags |= ASM_LEGACY_STREAM_SESSION; + if (is_gapless) + open->mode_flags |= BIT(ASM_SHIFT_GAPLESS_MODE_FLAG); /* source endpoint : matrix */ open->sink_endpointype = ASM_END_POINT_DEVICE_MATRIX; @@ -998,8 +1003,9 @@ err: } EXPORT_SYMBOL_GPL(q6asm_open_write); -static int __q6asm_run(struct audio_client *ac, uint32_t flags, - uint32_t msw_ts, uint32_t lsw_ts, bool wait) +static int __q6asm_run(struct audio_client *ac, uint32_t stream_id, + uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts, + bool wait) { struct asm_session_cmd_run_v2 *run; struct apr_pkt *pkt; @@ -1014,7 +1020,7 @@ static int __q6asm_run(struct audio_client *ac, uint32_t flags, pkt = p; run = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_SESSION_CMD_RUN_V2; run->flags = flags; @@ -1042,10 +1048,10 @@ static int __q6asm_run(struct audio_client *ac, uint32_t flags, * * Return: Will be an negative value on error or zero on success */ -int q6asm_run(struct audio_client *ac, uint32_t flags, +int q6asm_run(struct audio_client *ac, uint32_t stream_id, uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts) { - return __q6asm_run(ac, flags, msw_ts, lsw_ts, true); + return __q6asm_run(ac, stream_id, flags, msw_ts, lsw_ts, true); } EXPORT_SYMBOL_GPL(q6asm_run); @@ -1053,16 +1059,17 @@ EXPORT_SYMBOL_GPL(q6asm_run); * q6asm_run_nowait() - start the audio client withou blocking * * @ac: audio client pointer + * @stream_id: stream id * @flags: flags associated with write * @msw_ts: timestamp msw * @lsw_ts: timestamp lsw * * Return: Will be an negative value on error or zero on success */ -int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, - uint32_t msw_ts, uint32_t lsw_ts) +int q6asm_run_nowait(struct audio_client *ac, uint32_t stream_id, + uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts) { - return __q6asm_run(ac, flags, msw_ts, lsw_ts, false); + return __q6asm_run(ac, stream_id, flags, msw_ts, lsw_ts, false); } EXPORT_SYMBOL_GPL(q6asm_run_nowait); @@ -1070,6 +1077,7 @@ EXPORT_SYMBOL_GPL(q6asm_run_nowait); * q6asm_media_format_block_multi_ch_pcm() - setup pcm configuration * * @ac: audio client pointer + * @stream_id: stream id * @rate: audio sample rate * @channels: number of audio channels. * @channel_map: channel map pointer @@ -1078,6 +1086,7 @@ EXPORT_SYMBOL_GPL(q6asm_run_nowait); * Return: Will be an negative value on error or zero on success */ int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, + uint32_t stream_id, uint32_t rate, uint32_t channels, u8 channel_map[PCM_MAX_NUM_CHANNEL], uint16_t bits_per_sample) @@ -1096,7 +1105,7 @@ int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, pkt = p; fmt = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); @@ -1125,8 +1134,8 @@ err: } EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm); - int q6asm_stream_media_format_block_flac(struct audio_client *ac, + uint32_t stream_id, struct q6asm_flac_cfg *cfg) { struct asm_flac_fmt_blk_v2 *fmt; @@ -1142,7 +1151,7 @@ int q6asm_stream_media_format_block_flac(struct audio_client *ac, pkt = p; fmt = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); @@ -1163,6 +1172,7 @@ int q6asm_stream_media_format_block_flac(struct audio_client *ac, EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_flac); int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac, + uint32_t stream_id, struct q6asm_wma_cfg *cfg) { struct asm_wmastdv9_fmt_blk_v2 *fmt; @@ -1178,7 +1188,7 @@ int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac, pkt = p; fmt = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); @@ -1200,6 +1210,7 @@ int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac, EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v9); int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac, + uint32_t stream_id, struct q6asm_wma_cfg *cfg) { struct asm_wmaprov10_fmt_blk_v2 *fmt; @@ -1215,7 +1226,7 @@ int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac, pkt = p; fmt = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); @@ -1238,6 +1249,7 @@ int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac, EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_wma_v10); int q6asm_stream_media_format_block_alac(struct audio_client *ac, + uint32_t stream_id, struct q6asm_alac_cfg *cfg) { struct asm_alac_fmt_blk_v2 *fmt; @@ -1253,7 +1265,7 @@ int q6asm_stream_media_format_block_alac(struct audio_client *ac, pkt = p; fmt = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); @@ -1279,6 +1291,7 @@ int q6asm_stream_media_format_block_alac(struct audio_client *ac, EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_alac); int q6asm_stream_media_format_block_ape(struct audio_client *ac, + uint32_t stream_id, struct q6asm_ape_cfg *cfg) { struct asm_ape_fmt_blk_v2 *fmt; @@ -1294,7 +1307,7 @@ int q6asm_stream_media_format_block_ape(struct audio_client *ac, pkt = p; fmt = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk); @@ -1317,10 +1330,60 @@ int q6asm_stream_media_format_block_ape(struct audio_client *ac, } EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_ape); +static int q6asm_stream_remove_silence(struct audio_client *ac, uint32_t stream_id, + uint32_t cmd, + uint32_t num_samples) +{ + uint32_t *samples; + struct apr_pkt *pkt; + void *p; + int rc, pkt_size; + + pkt_size = APR_HDR_SIZE + sizeof(uint32_t); + p = kzalloc(pkt_size, GFP_ATOMIC); + if (!p) + return -ENOMEM; + + pkt = p; + samples = p + APR_HDR_SIZE; + + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); + + pkt->hdr.opcode = cmd; + *samples = num_samples; + rc = apr_send_pkt(ac->adev, pkt); + if (rc == pkt_size) + rc = 0; + + kfree(pkt); + + return rc; +} + +int q6asm_stream_remove_initial_silence(struct audio_client *ac, + uint32_t stream_id, + uint32_t initial_samples) +{ + return q6asm_stream_remove_silence(ac, stream_id, + ASM_DATA_CMD_REMOVE_INITIAL_SILENCE, + initial_samples); +} +EXPORT_SYMBOL_GPL(q6asm_stream_remove_initial_silence); + +int q6asm_stream_remove_trailing_silence(struct audio_client *ac, uint32_t stream_id, + uint32_t trailing_samples) +{ + return q6asm_stream_remove_silence(ac, stream_id, + ASM_DATA_CMD_REMOVE_TRAILING_SILENCE, + trailing_samples); +} +EXPORT_SYMBOL_GPL(q6asm_stream_remove_trailing_silence); + /** * q6asm_enc_cfg_blk_pcm_format_support() - setup pcm configuration for capture * * @ac: audio client pointer + * @stream_id: stream id * @rate: audio sample rate * @channels: number of audio channels. * @bits_per_sample: bits per sample @@ -1328,7 +1391,9 @@ EXPORT_SYMBOL_GPL(q6asm_stream_media_format_block_ape); * Return: Will be an negative value on error or zero on success */ int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, - uint32_t rate, uint32_t channels, uint16_t bits_per_sample) + uint32_t stream_id, uint32_t rate, + uint32_t channels, + uint16_t bits_per_sample) { struct asm_multi_channel_pcm_enc_cfg_v2 *enc_cfg; struct apr_pkt *pkt; @@ -1344,7 +1409,7 @@ int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, pkt = p; enc_cfg = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM; enc_cfg->encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2; @@ -1376,10 +1441,11 @@ EXPORT_SYMBOL_GPL(q6asm_enc_cfg_blk_pcm_format_support); * q6asm_read() - read data of period size from audio client * * @ac: audio client pointer + * @stream_id: stream id * * Return: Will be an negative value on error or zero on success */ -int q6asm_read(struct audio_client *ac) +int q6asm_read(struct audio_client *ac, uint32_t stream_id) { struct asm_data_cmd_read_v2 *read; struct audio_port_data *port; @@ -1400,7 +1466,7 @@ int q6asm_read(struct audio_client *ac) spin_lock_irqsave(&ac->lock, flags); port = &ac->port[SNDRV_PCM_STREAM_CAPTURE]; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, stream_id); ab = &port->buf[port->dsp_buf]; pkt->hdr.opcode = ASM_DATA_CMD_READ_V2; read->buf_addr_lsw = lower_32_bits(ab->phys); @@ -1428,7 +1494,7 @@ int q6asm_read(struct audio_client *ac) } EXPORT_SYMBOL_GPL(q6asm_read); -static int __q6asm_open_read(struct audio_client *ac, +static int __q6asm_open_read(struct audio_client *ac, uint32_t stream_id, uint32_t format, uint16_t bits_per_sample) { struct asm_stream_cmd_open_read_v3 *open; @@ -1444,7 +1510,7 @@ static int __q6asm_open_read(struct audio_client *ac, pkt = p; open = p + APR_HDR_SIZE; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, stream_id); pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V3; /* Stream prio : High, provide meta info with encoded frames */ open->src_endpointype = ASM_END_POINT_DEVICE_MATRIX; @@ -1475,15 +1541,16 @@ static int __q6asm_open_read(struct audio_client *ac, * q6asm_open_read() - Open audio client for reading * * @ac: audio client pointer + * @stream_id: stream id * @format: audio sample format * @bits_per_sample: bits per sample * * Return: Will be an negative value on error or zero on success */ -int q6asm_open_read(struct audio_client *ac, uint32_t format, - uint16_t bits_per_sample) +int q6asm_open_read(struct audio_client *ac, uint32_t stream_id, + uint32_t format, uint16_t bits_per_sample) { - return __q6asm_open_read(ac, format, bits_per_sample); + return __q6asm_open_read(ac, stream_id, format, bits_per_sample); } EXPORT_SYMBOL_GPL(q6asm_open_read); @@ -1491,6 +1558,7 @@ EXPORT_SYMBOL_GPL(q6asm_open_read); * q6asm_write_async() - non blocking write * * @ac: audio client pointer + * @stream_id: stream id * @len: length in bytes * @msw_ts: timestamp msw * @lsw_ts: timestamp lsw @@ -1498,8 +1566,8 @@ EXPORT_SYMBOL_GPL(q6asm_open_read); * * Return: Will be an negative value on error or zero on success */ -int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, - uint32_t lsw_ts, uint32_t wflags) +int q6asm_write_async(struct audio_client *ac, uint32_t stream_id, uint32_t len, + uint32_t msw_ts, uint32_t lsw_ts, uint32_t wflags) { struct asm_data_cmd_write_v2 *write; struct audio_port_data *port; @@ -1520,10 +1588,10 @@ int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, spin_lock_irqsave(&ac->lock, flags); port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK]; - q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id); + q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, stream_id); ab = &port->buf[port->dsp_buf]; - pkt->hdr.token = port->dsp_buf; + pkt->hdr.token = port->dsp_buf | (len << ASM_WRITE_TOKEN_LEN_SHIFT); pkt->hdr.opcode = ASM_DATA_CMD_WRITE_V2; write->buf_addr_lsw = lower_32_bits(ab->phys); write->buf_addr_msw = upper_32_bits(ab->phys); @@ -1534,10 +1602,7 @@ int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, write->mem_map_handle = ac->port[SNDRV_PCM_STREAM_PLAYBACK].mem_map_handle; - if (wflags == NO_TIMESTAMP) - write->flags = (wflags & 0x800000FF); - else - write->flags = (0x80000000 | wflags); + write->flags = wflags; port->dsp_buf++; @@ -1567,9 +1632,9 @@ static void q6asm_reset_buf_state(struct audio_client *ac) spin_unlock_irqrestore(&ac->lock, flags); } -static int __q6asm_cmd(struct audio_client *ac, int cmd, bool wait) +static int __q6asm_cmd(struct audio_client *ac, uint32_t stream_id, int cmd, + bool wait) { - int stream_id = ac->stream_id; struct apr_pkt pkt; int rc; @@ -1616,13 +1681,14 @@ static int __q6asm_cmd(struct audio_client *ac, int cmd, bool wait) * q6asm_cmd() - run cmd on audio client * * @ac: audio client pointer + * @stream_id: stream id * @cmd: command to run on audio client. * * Return: Will be an negative value on error or zero on success */ -int q6asm_cmd(struct audio_client *ac, int cmd) +int q6asm_cmd(struct audio_client *ac, uint32_t stream_id, int cmd) { - return __q6asm_cmd(ac, cmd, true); + return __q6asm_cmd(ac, stream_id, cmd, true); } EXPORT_SYMBOL_GPL(q6asm_cmd); @@ -1630,13 +1696,14 @@ EXPORT_SYMBOL_GPL(q6asm_cmd); * q6asm_cmd_nowait() - non blocking, run cmd on audio client * * @ac: audio client pointer + * @stream_id: stream id * @cmd: command to run on audio client. * * Return: Will be an negative value on error or zero on success */ -int q6asm_cmd_nowait(struct audio_client *ac, int cmd) +int q6asm_cmd_nowait(struct audio_client *ac, uint32_t stream_id, int cmd) { - return __q6asm_cmd(ac, cmd, false); + return __q6asm_cmd(ac, stream_id, cmd, false); } EXPORT_SYMBOL_GPL(q6asm_cmd_nowait); diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h index 38a207d6cd95..82e584aa534f 100644 --- a/sound/soc/qcom/qdsp6/q6asm.h +++ b/sound/soc/qcom/qdsp6/q6asm.h @@ -20,6 +20,9 @@ #define ASM_CLIENT_EVENT_CMD_RUN_DONE 0x1008 #define ASM_CLIENT_EVENT_DATA_WRITE_DONE 0x1009 #define ASM_CLIENT_EVENT_DATA_READ_DONE 0x100a +#define ASM_WRITE_TOKEN_MASK GENMASK(15, 0) +#define ASM_WRITE_TOKEN_LEN_MASK GENMASK(31, 16) +#define ASM_WRITE_TOKEN_LEN_SHIFT 16 enum { LEGACY_PCM_MODE = 0, @@ -29,8 +32,8 @@ enum { }; #define MAX_SESSIONS 8 -#define NO_TIMESTAMP 0xFF00 #define FORMAT_LINEAR_PCM 0x0000 +#define ASM_LAST_BUFFER_FLAG BIT(30) struct q6asm_flac_cfg { u32 sample_rate; @@ -93,37 +96,53 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb, void *priv, int session_id, int perf_mode); void q6asm_audio_client_free(struct audio_client *ac); -int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts, - uint32_t lsw_ts, uint32_t flags); -int q6asm_open_write(struct audio_client *ac, uint32_t format, - u32 codec_profile, uint16_t bits_per_sample); +int q6asm_write_async(struct audio_client *ac, uint32_t stream_id, uint32_t len, + uint32_t msw_ts, uint32_t lsw_ts, uint32_t flags); +int q6asm_open_write(struct audio_client *ac, uint32_t stream_id, + uint32_t format, u32 codec_profile, + uint16_t bits_per_sample, bool is_gapless); -int q6asm_open_read(struct audio_client *ac, uint32_t format, - uint16_t bits_per_sample); +int q6asm_open_read(struct audio_client *ac, uint32_t stream_id, + uint32_t format, uint16_t bits_per_sample); int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, - uint32_t rate, uint32_t channels, uint16_t bits_per_sample); -int q6asm_read(struct audio_client *ac); + uint32_t stream_id, uint32_t rate, + uint32_t channels, + uint16_t bits_per_sample); + +int q6asm_read(struct audio_client *ac, uint32_t stream_id); int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, + uint32_t stream_id, uint32_t rate, uint32_t channels, u8 channel_map[PCM_MAX_NUM_CHANNEL], uint16_t bits_per_sample); int q6asm_stream_media_format_block_flac(struct audio_client *ac, + uint32_t stream_id, struct q6asm_flac_cfg *cfg); int q6asm_stream_media_format_block_wma_v9(struct audio_client *ac, + uint32_t stream_id, struct q6asm_wma_cfg *cfg); int q6asm_stream_media_format_block_wma_v10(struct audio_client *ac, + uint32_t stream_id, struct q6asm_wma_cfg *cfg); int q6asm_stream_media_format_block_alac(struct audio_client *ac, + uint32_t stream_id, struct q6asm_alac_cfg *cfg); int q6asm_stream_media_format_block_ape(struct audio_client *ac, + uint32_t stream_id, struct q6asm_ape_cfg *cfg); -int q6asm_run(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, - uint32_t lsw_ts); -int q6asm_run_nowait(struct audio_client *ac, uint32_t flags, uint32_t msw_ts, - uint32_t lsw_ts); -int q6asm_cmd(struct audio_client *ac, int cmd); -int q6asm_cmd_nowait(struct audio_client *ac, int cmd); +int q6asm_run(struct audio_client *ac, uint32_t stream_id, uint32_t flags, + uint32_t msw_ts, uint32_t lsw_ts); +int q6asm_run_nowait(struct audio_client *ac, uint32_t stream_id, + uint32_t flags, uint32_t msw_ts, uint32_t lsw_ts); +int q6asm_stream_remove_initial_silence(struct audio_client *ac, + uint32_t stream_id, + uint32_t initial_samples); +int q6asm_stream_remove_trailing_silence(struct audio_client *ac, + uint32_t stream_id, + uint32_t trailing_samples); +int q6asm_cmd(struct audio_client *ac, uint32_t stream_id, int cmd); +int q6asm_cmd_nowait(struct audio_client *ac, uint32_t stream_id, int cmd); int q6asm_get_session_id(struct audio_client *ac); int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac, diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index b8f0057a0510..8aa78ff640f5 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c @@ -15,9 +15,6 @@ #include <sound/jack.h> #include "regs-iis.h" -#include <asm/mach-types.h> - -#include <mach/gpio-samsung.h> #include "s3c24xx-i2s.h" static const unsigned int rates[] = { @@ -31,6 +28,8 @@ static const struct snd_pcm_hw_constraint_list hw_rates = { .list = rates, }; +static struct gpio_desc *gpiod_speaker_power; + static struct snd_soc_jack hp_jack; static struct snd_soc_jack_pin hp_jack_pins[] = { @@ -47,7 +46,6 @@ static struct snd_soc_jack_pin hp_jack_pins[] = { static struct snd_soc_jack_gpio hp_jack_gpios[] = { { - .gpio = S3C2410_GPG(4), .name = "hp-gpio", .report = SND_JACK_HEADPHONE, .invert = 1, @@ -123,9 +121,9 @@ static int h1940_spk_power(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value(S3C_GPIO_END + 9, 1); + gpiod_set_value(gpiod_speaker_power, 1); else - gpio_set_value(S3C_GPIO_END + 9, 0); + gpiod_set_value(gpiod_speaker_power, 0); return 0; } @@ -151,8 +149,6 @@ static const struct snd_soc_dapm_route audio_map[] = { {"VINM", NULL, "Mic Jack"}, }; -static struct platform_device *s3c24xx_snd_device; - static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd) { snd_soc_card_jack_new(rtd->card, "Headphone Jack", SND_JACK_HEADPHONE, @@ -194,55 +190,34 @@ static struct snd_soc_card h1940_asoc = { .num_dapm_routes = ARRAY_SIZE(audio_map), }; -static int __init h1940_init(void) +static int h1940_probe(struct platform_device *pdev) { - int ret; + struct device *dev = &pdev->dev; - if (!machine_is_h1940()) - return -ENODEV; + h1940_asoc.dev = dev; + hp_jack_gpios[0].gpiod_dev = dev; + gpiod_speaker_power = devm_gpiod_get(&pdev->dev, "speaker-power", + GPIOD_OUT_LOW); - /* configure some gpios */ - ret = gpio_request(S3C_GPIO_END + 9, "speaker-power"); - if (ret) - goto err_out; - - ret = gpio_direction_output(S3C_GPIO_END + 9, 0); - if (ret) - goto err_gpio; - - s3c24xx_snd_device = platform_device_alloc("soc-audio", -1); - if (!s3c24xx_snd_device) { - ret = -ENOMEM; - goto err_gpio; + if (IS_ERR(gpiod_speaker_power)) { + dev_err(dev, "Could not get gpio\n"); + return PTR_ERR(gpiod_speaker_power); } - platform_set_drvdata(s3c24xx_snd_device, &h1940_asoc); - ret = platform_device_add(s3c24xx_snd_device); - - if (ret) - goto err_plat; - - return 0; - -err_plat: - platform_device_put(s3c24xx_snd_device); -err_gpio: - gpio_free(S3C_GPIO_END + 9); - -err_out: - return ret; -} - -static void __exit h1940_exit(void) -{ - platform_device_unregister(s3c24xx_snd_device); - gpio_free(S3C_GPIO_END + 9); + return devm_snd_soc_register_card(dev, &h1940_asoc); } -module_init(h1940_init); -module_exit(h1940_exit); +static struct platform_driver h1940_audio_driver = { + .driver = { + .name = "h1940-audio", + .pm = &snd_soc_pm_ops, + }, + .probe = h1940_probe, +}; +module_platform_driver(h1940_audio_driver); /* Module information */ MODULE_AUTHOR("Arnaud Patard, Vasily Khoruzhick"); MODULE_DESCRIPTION("ALSA SoC H1940"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:h1940-audio"); diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 54317e0f68f8..9266070e0181 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -11,14 +11,11 @@ #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <sound/soc.h> -#include <mach/gpio-samsung.h> -#include <asm/mach-types.h> #include "regs-iis.h" - #include "../codecs/wm8753.h" #include "s3c24xx-i2s.h" @@ -166,6 +163,7 @@ static struct snd_soc_ops neo1973_voice_ops = { .hw_free = neo1973_voice_hw_free, }; +static struct gpio_desc *gpiod_hp_in, *gpiod_amp_shut; static int gta02_speaker_enabled; static int lm4853_set_spk(struct snd_kcontrol *kcontrol, @@ -173,7 +171,7 @@ static int lm4853_set_spk(struct snd_kcontrol *kcontrol, { gta02_speaker_enabled = ucontrol->value.integer.value[0]; - gpio_set_value(S3C2410_GPJ(2), !gta02_speaker_enabled); + gpiod_set_value(gpiod_hp_in, !gta02_speaker_enabled); return 0; } @@ -188,7 +186,7 @@ static int lm4853_get_spk(struct snd_kcontrol *kcontrol, static int lm4853_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - gpio_set_value(S3C2410_GPJ(1), SND_SOC_DAPM_EVENT_OFF(event)); + gpiod_set_value(gpiod_amp_shut, SND_SOC_DAPM_EVENT_OFF(event)); return 0; } @@ -308,13 +306,8 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = { }, }; -static const struct gpio neo1973_gta02_gpios[] = { - { S3C2410_GPJ(2), GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, - { S3C2410_GPJ(1), GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, -}; - static struct snd_soc_card neo1973 = { - .name = "neo1973", + .name = "neo1973gta02", .owner = THIS_MODULE, .dai_link = neo1973_dai, .num_links = ARRAY_SIZE(neo1973_dai), @@ -332,62 +325,36 @@ static struct snd_soc_card neo1973 = { .fully_routed = true, }; -static struct platform_device *neo1973_snd_device; - -static int __init neo1973_init(void) +static int neo1973_probe(struct platform_device *pdev) { - int ret; - - if (!machine_is_neo1973_gta02()) - return -ENODEV; + struct device *dev = &pdev->dev; - if (machine_is_neo1973_gta02()) { - neo1973.name = "neo1973gta02"; - neo1973.num_aux_devs = 1; - - ret = gpio_request_array(neo1973_gta02_gpios, - ARRAY_SIZE(neo1973_gta02_gpios)); - if (ret) - return ret; + gpiod_hp_in = devm_gpiod_get(dev, "hp", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_hp_in)) { + dev_err(dev, "missing gpio %s\n", "hp"); + return PTR_ERR(gpiod_hp_in); } - - neo1973_snd_device = platform_device_alloc("soc-audio", -1); - if (!neo1973_snd_device) { - ret = -ENOMEM; - goto err_gpio_free; + gpiod_amp_shut = devm_gpiod_get(dev, "amp-shut", GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_amp_shut)) { + dev_err(dev, "missing gpio %s\n", "amp-shut"); + return PTR_ERR(gpiod_amp_shut); } - platform_set_drvdata(neo1973_snd_device, &neo1973); - ret = platform_device_add(neo1973_snd_device); - - if (ret) - goto err_put_device; - - return 0; - -err_put_device: - platform_device_put(neo1973_snd_device); -err_gpio_free: - if (machine_is_neo1973_gta02()) { - gpio_free_array(neo1973_gta02_gpios, - ARRAY_SIZE(neo1973_gta02_gpios)); - } - return ret; + neo1973.dev = dev; + return devm_snd_soc_register_card(dev, &neo1973); } -module_init(neo1973_init); - -static void __exit neo1973_exit(void) -{ - platform_device_unregister(neo1973_snd_device); - if (machine_is_neo1973_gta02()) { - gpio_free_array(neo1973_gta02_gpios, - ARRAY_SIZE(neo1973_gta02_gpios)); - } -} -module_exit(neo1973_exit); +struct platform_driver neo1973_audio = { + .driver = { + .name = "neo1973-audio", + .pm = &snd_soc_pm_ops, + }, + .probe = neo1973_probe, +}; +module_platform_driver(neo1973_audio); /* Module information */ MODULE_AUTHOR("Graeme Gregory, [email protected], www.openmoko.org"); MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:neo1973-audio"); diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index 08f7c82aedb6..400a7f77c711 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c @@ -12,16 +12,13 @@ // Vasily Khoruzhick <[email protected]> #include <linux/types.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <sound/soc.h> #include <sound/jack.h> -#include <mach/gpio-samsung.h> #include "regs-iis.h" -#include <asm/mach-types.h> - #include "s3c24xx-i2s.h" static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); @@ -58,7 +55,6 @@ static struct snd_soc_jack_pin hp_jack_pins[] = { static struct snd_soc_jack_gpio hp_jack_gpios[] = { [0] = { - .gpio = S3C2410_GPG(12), .name = "hp-gpio", .report = SND_JACK_HEADPHONE, .invert = 1, @@ -123,8 +119,6 @@ static struct snd_soc_card rx1950_asoc = { .num_dapm_routes = ARRAY_SIZE(audio_map), }; -static struct platform_device *s3c24xx_snd_device; - static int rx1950_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -134,13 +128,15 @@ static int rx1950_startup(struct snd_pcm_substream *substream) &hw_rates); } +struct gpio_desc *gpiod_speaker_power; + static int rx1950_spk_power(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { if (SND_SOC_DAPM_EVENT_ON(event)) - gpio_set_value(S3C2410_GPA(1), 1); + gpiod_set_value(gpiod_speaker_power, 1); else - gpio_set_value(S3C2410_GPA(1), 0); + gpiod_set_value(gpiod_speaker_power, 0); return 0; } @@ -214,57 +210,35 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static int __init rx1950_init(void) +static int rx1950_probe(struct platform_device *pdev) { - int ret; - - if (!machine_is_rx1950()) - return -ENODEV; + struct device *dev = &pdev->dev; /* configure some gpios */ - ret = gpio_request(S3C2410_GPA(1), "speaker-power"); - if (ret) - goto err_gpio; - - ret = gpio_direction_output(S3C2410_GPA(1), 0); - if (ret) - goto err_gpio_conf; - - s3c24xx_snd_device = platform_device_alloc("soc-audio", -1); - if (!s3c24xx_snd_device) { - ret = -ENOMEM; - goto err_plat_alloc; - } - - platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc); - ret = platform_device_add(s3c24xx_snd_device); - - if (ret) { - platform_device_put(s3c24xx_snd_device); - goto err_plat_add; + gpiod_speaker_power = devm_gpiod_get(dev, "speaker-power", GPIOD_OUT_LOW); + if (IS_ERR(gpiod_speaker_power)) { + dev_err(dev, "cannot get gpio\n"); + return PTR_ERR(gpiod_speaker_power); } - return 0; - -err_plat_add: -err_plat_alloc: -err_gpio_conf: - gpio_free(S3C2410_GPA(1)); + hp_jack_gpios[0].gpiod_dev = dev; + rx1950_asoc.dev = dev; -err_gpio: - return ret; + return devm_snd_soc_register_card(dev, &rx1950_asoc); } -static void __exit rx1950_exit(void) -{ - platform_device_unregister(s3c24xx_snd_device); - gpio_free(S3C2410_GPA(1)); -} +struct platform_driver rx1950_audio = { + .driver = { + .name = "rx1950-audio", + .pm = &snd_soc_pm_ops, + }, + .probe = rx1950_probe, +}; -module_init(rx1950_init); -module_exit(rx1950_exit); +module_platform_driver(rx1950_audio); /* Module information */ MODULE_AUTHOR("Vasily Khoruzhick"); MODULE_DESCRIPTION("ALSA SoC RX1950"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rx1950-audio"); diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index ed21786104a1..e9481187a08c 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -616,8 +616,7 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); int s3c_i2sv2_probe(struct snd_soc_dai *dai, - struct s3c_i2sv2_info *i2s, - unsigned long base) + struct s3c_i2sv2_info *i2s) { struct device *dev = dai->dev; unsigned int iismod; diff --git a/sound/soc/samsung/s3c-i2s-v2.h b/sound/soc/samsung/s3c-i2s-v2.h index fe42b77999fd..8c6fc0d3d77e 100644 --- a/sound/soc/samsung/s3c-i2s-v2.h +++ b/sound/soc/samsung/s3c-i2s-v2.h @@ -83,8 +83,7 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, * @base: The base address for the registers. */ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai, - struct s3c_i2sv2_info *i2s, - unsigned long base); + struct s3c_i2sv2_info *i2s); /** * s3c_i2sv2_cleanup - cleanup resources allocated in s3c_i2sv2_probe diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index b35d828c1cfe..edfa9d11d2e5 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c @@ -49,7 +49,7 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai) snd_soc_dai_init_dma_data(dai, &s3c2412_i2s_pcm_stereo_out, &s3c2412_i2s_pcm_stereo_in); - ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS); + ret = s3c_i2sv2_probe(dai, &s3c2412_i2s); if (ret) return ret; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2fe1b2ec7c8f..bf46f410c8c6 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2827,6 +2827,37 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing); +int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname) +{ + struct device_node *node = card->dev->of_node; + struct snd_soc_aux_dev *aux; + int num, i; + + num = of_count_phandle_with_args(node, propname, NULL); + if (num == -ENOENT) { + return 0; + } else if (num < 0) { + dev_err(card->dev, "ASOC: Property '%s' could not be read: %d\n", + propname, num); + return num; + } + + aux = devm_kcalloc(card->dev, num, sizeof(*aux), GFP_KERNEL); + if (!aux) + return -ENOMEM; + card->aux_dev = aux; + card->num_aux_devs = num; + + for_each_card_pre_auxs(card, i, aux) { + aux->dlc.of_node = of_parse_phandle(node, propname, i); + if (!aux->dlc.of_node) + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_aux_devs); + unsigned int snd_soc_of_parse_daifmt(struct device_node *np, const char *prefix, struct device_node **bitclkmaster, diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 3aaf25e4f766..f644010cc568 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -166,6 +166,7 @@ config SND_SOC_SOF_CANNONLAKE_SUPPORT config SND_SOC_SOF_CANNONLAKE tristate select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -181,6 +182,7 @@ config SND_SOC_SOF_COFFEELAKE_SUPPORT config SND_SOC_SOF_COFFEELAKE tristate select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -196,6 +198,7 @@ config SND_SOC_SOF_ICELAKE_SUPPORT config SND_SOC_SOF_ICELAKE tristate select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -203,6 +206,7 @@ config SND_SOC_SOF_ICELAKE config SND_SOC_SOF_COMETLAKE tristate select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -229,6 +233,7 @@ config SND_SOC_SOF_TIGERLAKE_SUPPORT config SND_SOC_SOF_TIGERLAKE tristate select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -244,6 +249,7 @@ config SND_SOC_SOF_ELKHARTLAKE_SUPPORT config SND_SOC_SOF_ELKHARTLAKE tristate select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -329,6 +335,29 @@ config SND_SOC_SOF_HDA This option is not user-selectable but automagically handled by 'select' statements at a higher level +config SND_SOC_SOF_INTEL_SOUNDWIRE_LINK + bool "SOF support for SoundWire" + depends on SOUNDWIRE && ACPI + help + This adds support for SoundWire with Sound Open Firmware + for Intel(R) platforms. + Say Y if you want to enable SoundWire links with SOF. + If unsure select "N". + +config SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE + tristate + select SND_SOC_SOF_INTEL_SOUNDWIRE if SND_SOC_SOF_INTEL_SOUNDWIRE_LINK + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level + +config SND_SOC_SOF_INTEL_SOUNDWIRE + tristate + select SOUNDWIRE_INTEL + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level + endif ## SND_SOC_SOF_INTEL_PCI endif ## SND_SOC_SOF_INTEL_TOPLEVEL diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 16db0f50d139..95234ae59e42 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -202,7 +202,7 @@ static int cnl_ipc_send_msg(struct snd_sof_dev *sdev, * IPCs are sent at a high-rate. mod_delayed_work() * modifies the timer if the work is pending. * Also, a new delayed work should not be queued after the - * the CTX_SAVE IPC, which is sent before the DSP enters D3. + * CTX_SAVE IPC, which is sent before the DSP enters D3. */ if (hdr->cmd != (SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_CTX_SAVE)) mod_delayed_work(system_wq, &hdev->d0i3_work, diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 2c5c451fa19d..55811b99e47a 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -116,10 +116,10 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) struct hdac_hda_priv *hda_priv; + struct hda_codec *codec; #endif struct hda_bus *hbus = sof_to_hbus(sdev); struct hdac_device *hdev; - struct hda_codec *codec; u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; u32 resp = -1; @@ -178,6 +178,11 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, } return ret; + +error: + snd_hdac_ext_bus_device_exit(hdev); + return -ENOENT; + #else hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL); if (!hdev) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 63ca920c8e6e..b8157c1f37f3 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1179,7 +1179,13 @@ void hda_machine_select(struct snd_sof_dev *sdev) mach = snd_soc_acpi_find_machine(desc->machines); if (mach) { - sof_pdata->tplg_filename = mach->sof_tplg_filename; + /* + * If tplg file name is overridden, use it instead of + * the one set in mach table + */ + if (!sof_pdata->tplg_filename) + sof_pdata->tplg_filename = mach->sof_tplg_filename; + sof_pdata->machine = mach; if (mach->link_mask) { @@ -1207,3 +1213,4 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC); MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC_I915); MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); +MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 1c7698f8edd6..33d84405cf9c 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -29,7 +29,7 @@ bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev) continue; /* - * substream->runtime being not NULL indicates that + * substream->runtime being not NULL indicates * that the stream is open. No need to check the * stream state. */ diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index aa3532ba1434..f3a8140773db 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -35,8 +35,28 @@ static int sof_pci_debug; module_param_named(sof_pci_debug, sof_pci_debug, int, 0444); MODULE_PARM_DESC(sof_pci_debug, "SOF PCI debug options (0x0 all off)"); +static const char *sof_override_tplg_name; + #define SOF_PCI_DISABLE_PM_RUNTIME BIT(0) +static int sof_tplg_cb(const struct dmi_system_id *id) +{ + sof_override_tplg_name = id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_tplg_table[] = { + { + .callback = sof_tplg_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Terrador"), + }, + .driver_data = "sof-tgl-rt5682-ssp0-max98373-ssp2.tplg", + }, + {} +}; + static const struct dmi_system_id community_key_platforms[] = { { .ident = "Up Squared", @@ -347,6 +367,10 @@ static int sof_pci_probe(struct pci_dev *pci, sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path; + dmi_check_system(sof_tplg_table); + if (sof_override_tplg_name) + sof_pdata->tplg_filename = sof_override_tplg_name; + #if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) /* set callback to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_pci_probe_complete; diff --git a/sound/soc/sprd/sprd-pcm-compress.c b/sound/soc/sprd/sprd-pcm-compress.c index 749dcb7b993b..6507c03cc80e 100644 --- a/sound/soc/sprd/sprd-pcm-compress.c +++ b/sound/soc/sprd/sprd-pcm-compress.c @@ -559,7 +559,7 @@ static int sprd_platform_compr_copy(struct snd_soc_component *component, } else { /* * If the data count is larger than the available spaces - * of the the stage 0 IRAM buffer, we should copy one + * of the stage 0 IRAM buffer, we should copy one * partial data to the stage 0 IRAM buffer, and copy * the left to the stage 1 DDR buffer. */ diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 2af6404dbd62..6c13cc84b3fb 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -335,7 +335,7 @@ static int sun4i_codec_prepare_capture(struct snd_pcm_substream *substream, /* * FIXME: Undocumented in the datasheet, but - * Allwinner's code mentions that it is related + * Allwinner's code mentions that it is * related to microphone gain */ if (of_device_is_compatible(scodec->dev->of_node, diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index f5b7069bcca2..a41e25ad0aaf 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -121,50 +121,50 @@ /* mixer controls */ static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = { - SOC_DAPM_DOUBLE_R("DAC Playback Switch", + SOC_DAPM_DOUBLE_R("Mic1 Playback Switch", SUN50I_ADDA_OL_MIX_CTRL, SUN50I_ADDA_OR_MIX_CTRL, - SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0), - SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch", + SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0), + SOC_DAPM_DOUBLE_R("Mic2 Playback Switch", SUN50I_ADDA_OL_MIX_CTRL, SUN50I_ADDA_OR_MIX_CTRL, - SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0), + SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0), SOC_DAPM_DOUBLE_R("Line In Playback Switch", SUN50I_ADDA_OL_MIX_CTRL, SUN50I_ADDA_OR_MIX_CTRL, SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0), - SOC_DAPM_DOUBLE_R("Mic1 Playback Switch", + SOC_DAPM_DOUBLE_R("DAC Playback Switch", SUN50I_ADDA_OL_MIX_CTRL, SUN50I_ADDA_OR_MIX_CTRL, - SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0), - SOC_DAPM_DOUBLE_R("Mic2 Playback Switch", + SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0), + SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch", SUN50I_ADDA_OL_MIX_CTRL, SUN50I_ADDA_OR_MIX_CTRL, - SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0), + SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0), }; /* ADC mixer controls */ static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = { - SOC_DAPM_DOUBLE_R("Mixer Capture Switch", + SOC_DAPM_DOUBLE_R("Mic1 Capture Switch", SUN50I_ADDA_L_ADCMIX_SRC, SUN50I_ADDA_R_ADCMIX_SRC, - SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0), - SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch", + SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0), + SOC_DAPM_DOUBLE_R("Mic2 Capture Switch", SUN50I_ADDA_L_ADCMIX_SRC, SUN50I_ADDA_R_ADCMIX_SRC, - SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0), + SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0), SOC_DAPM_DOUBLE_R("Line In Capture Switch", SUN50I_ADDA_L_ADCMIX_SRC, SUN50I_ADDA_R_ADCMIX_SRC, SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0), - SOC_DAPM_DOUBLE_R("Mic1 Capture Switch", + SOC_DAPM_DOUBLE_R("Mixer Capture Switch", SUN50I_ADDA_L_ADCMIX_SRC, SUN50I_ADDA_R_ADCMIX_SRC, - SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0), - SOC_DAPM_DOUBLE_R("Mic2 Capture Switch", + SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0), + SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch", SUN50I_ADDA_L_ADCMIX_SRC, SUN50I_ADDA_R_ADCMIX_SRC, - SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0), + SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0), }; static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale, @@ -193,11 +193,6 @@ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0, sun50i_codec_hp_vol_scale), - SOC_DOUBLE("Headphone Playback Switch", - SUN50I_ADDA_MIX_DAC_CTRL, - SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE, - SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0), - /* Mixer pre-gain */ SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL, SUN50I_ADDA_MIC1_CTRL_MIC1G, @@ -233,20 +228,10 @@ static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = { SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0, sun50i_codec_lineout_vol_scale), - SOC_DOUBLE("Line Out Playback Switch", - SUN50I_ADDA_LINEOUT_CTRL0, - SUN50I_ADDA_LINEOUT_CTRL0_LEN, - SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0), - SOC_SINGLE_TLV("Earpiece Playback Volume", SUN50I_ADDA_EARPIECE_CTRL1, SUN50I_ADDA_EARPIECE_CTRL1_ESP_VOL, 0x1f, 0, sun50i_codec_earpiece_vol_scale), - - SOC_SINGLE("Earpiece Playback Switch", - SUN50I_ADDA_EARPIECE_CTRL1, - SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0), - }; static const char * const sun50i_codec_hp_src_enum_text[] = { @@ -264,6 +249,12 @@ static const struct snd_kcontrol_new sun50i_codec_hp_src[] = { sun50i_codec_hp_src_enum), }; +static const struct snd_kcontrol_new sun50i_codec_hp_switch = + SOC_DAPM_DOUBLE("Headphone Playback Switch", + SUN50I_ADDA_MIX_DAC_CTRL, + SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE, + SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0); + static const char * const sun50i_codec_lineout_src_enum_text[] = { "Stereo", "Mono Differential", }; @@ -279,6 +270,12 @@ static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = { sun50i_codec_lineout_src_enum), }; +static const struct snd_kcontrol_new sun50i_codec_lineout_switch = + SOC_DAPM_DOUBLE("Line Out Playback Switch", + SUN50I_ADDA_LINEOUT_CTRL0, + SUN50I_ADDA_LINEOUT_CTRL0_LEN, + SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0); + static const char * const sun50i_codec_earpiece_src_enum_text[] = { "DACR", "DACL", "Right Mixer", "Left Mixer", }; @@ -293,6 +290,12 @@ static const struct snd_kcontrol_new sun50i_codec_earpiece_src[] = { sun50i_codec_earpiece_src_enum), }; +static const struct snd_kcontrol_new sun50i_codec_earpiece_switch[] = { + SOC_DAPM_SINGLE("Earpiece Playback Switch", + SUN50I_ADDA_EARPIECE_CTRL1, + SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0), +}; + static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { /* DAC */ SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, @@ -311,18 +314,37 @@ static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { */ SND_SOC_DAPM_REGULATOR_SUPPLY("cpvdd", 0, 0), - SND_SOC_DAPM_MUX("Headphone Source Playback Route", + SND_SOC_DAPM_MUX("Left Headphone Source", + SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src), + SND_SOC_DAPM_MUX("Right Headphone Source", SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src), - SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN50I_ADDA_HP_CTRL, + SND_SOC_DAPM_SWITCH("Left Headphone Switch", + SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch), + SND_SOC_DAPM_SWITCH("Right Headphone Switch", + SND_SOC_NOPM, 0, 0, &sun50i_codec_hp_switch), + SND_SOC_DAPM_OUT_DRV("Left Headphone Amp", + SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("Right Headphone Amp", + SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("Headphone Amp", SUN50I_ADDA_HP_CTRL, SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0), SND_SOC_DAPM_OUTPUT("HP"), - SND_SOC_DAPM_MUX("Line Out Source Playback Route", + SND_SOC_DAPM_MUX("Left Line Out Source", SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src), + SND_SOC_DAPM_MUX("Right Line Out Source", + SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src), + SND_SOC_DAPM_SWITCH("Left Line Out Switch", + SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch), + SND_SOC_DAPM_SWITCH("Right Line Out Switch", + SND_SOC_NOPM, 0, 0, &sun50i_codec_lineout_switch), SND_SOC_DAPM_OUTPUT("LINEOUT"), SND_SOC_DAPM_MUX("Earpiece Source Playback Route", SND_SOC_NOPM, 0, 0, sun50i_codec_earpiece_src), + SOC_MIXER_NAMED_CTL_ARRAY("Earpiece Switch", + SND_SOC_NOPM, 0, 0, + sun50i_codec_earpiece_switch), SND_SOC_DAPM_OUT_DRV("Earpiece Amp", SUN50I_ADDA_EARPIECE_CTRL1, SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_EN, 0, NULL, 0), SND_SOC_DAPM_OUTPUT("EARPIECE"), @@ -363,83 +385,105 @@ static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0, sun50i_a64_codec_mixer_controls, ARRAY_SIZE(sun50i_a64_codec_mixer_controls)), - SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN50I_ADDA_ADC_CTRL, - SUN50I_ADDA_ADC_CTRL_ADCLEN, 0, + SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, sun50i_codec_adc_mixer_controls, ARRAY_SIZE(sun50i_codec_adc_mixer_controls)), - SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN50I_ADDA_ADC_CTRL, - SUN50I_ADDA_ADC_CTRL_ADCREN, 0, + SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0, sun50i_codec_adc_mixer_controls, ARRAY_SIZE(sun50i_codec_adc_mixer_controls)), }; static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { /* Left Mixer Routes */ + { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, + { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, + { "Left Mixer", "Line In Playback Switch", "LINEIN" }, { "Left Mixer", "DAC Playback Switch", "Left DAC" }, { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, - { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, /* Right Mixer Routes */ + { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, + { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, + { "Right Mixer", "Line In Playback Switch", "LINEIN" }, { "Right Mixer", "DAC Playback Switch", "Right DAC" }, { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" }, - { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" }, /* Left ADC Mixer Routes */ + { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, + { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, + { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" }, { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" }, { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" }, - { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, /* Right ADC Mixer Routes */ + { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, + { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, + { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" }, { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" }, { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" }, - { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" }, /* ADC Routes */ { "Left ADC", NULL, "Left ADC Mixer" }, { "Right ADC", NULL, "Right ADC Mixer" }, /* Headphone Routes */ - { "Headphone Source Playback Route", "DAC", "Left DAC" }, - { "Headphone Source Playback Route", "DAC", "Right DAC" }, - { "Headphone Source Playback Route", "Mixer", "Left Mixer" }, - { "Headphone Source Playback Route", "Mixer", "Right Mixer" }, - { "Headphone Amp", NULL, "Headphone Source Playback Route" }, + { "Left Headphone Source", "DAC", "Left DAC" }, + { "Left Headphone Source", "Mixer", "Left Mixer" }, + { "Left Headphone Switch", "Headphone Playback Switch", "Left Headphone Source" }, + { "Left Headphone Amp", NULL, "Left Headphone Switch" }, + { "Left Headphone Amp", NULL, "Headphone Amp" }, + { "HP", NULL, "Left Headphone Amp" }, + + { "Right Headphone Source", "DAC", "Right DAC" }, + { "Right Headphone Source", "Mixer", "Right Mixer" }, + { "Right Headphone Switch", "Headphone Playback Switch", "Right Headphone Source" }, + { "Right Headphone Amp", NULL, "Right Headphone Switch" }, + { "Right Headphone Amp", NULL, "Headphone Amp" }, + { "HP", NULL, "Right Headphone Amp" }, + { "Headphone Amp", NULL, "cpvdd" }, - { "HP", NULL, "Headphone Amp" }, /* Microphone Routes */ { "Mic1 Amplifier", NULL, "MIC1"}, /* Microphone Routes */ { "Mic2 Amplifier", NULL, "MIC2"}, - { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, - { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" }, - { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, - { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" }, - - /* Line-in Routes */ - { "Left Mixer", "Line In Playback Switch", "LINEIN" }, - { "Right Mixer", "Line In Playback Switch", "LINEIN" }, - { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" }, - { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" }, /* Line-out Routes */ - { "Line Out Source Playback Route", "Stereo", "Left Mixer" }, - { "Line Out Source Playback Route", "Stereo", "Right Mixer" }, - { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" }, - { "Line Out Source Playback Route", "Mono Differential", - "Right Mixer" }, - { "LINEOUT", NULL, "Line Out Source Playback Route" }, + { "Left Line Out Source", "Stereo", "Left Mixer" }, + { "Left Line Out Source", "Mono Differential", "Left Mixer" }, + { "Left Line Out Source", "Mono Differential", "Right Mixer" }, + { "Left Line Out Switch", "Line Out Playback Switch", "Left Line Out Source" }, + { "LINEOUT", NULL, "Left Line Out Switch" }, + + { "Right Line Out Switch", "Line Out Playback Switch", "Right Mixer" }, + { "Right Line Out Source", "Stereo", "Right Line Out Switch" }, + { "Right Line Out Source", "Mono Differential", "Left Line Out Switch" }, + { "LINEOUT", NULL, "Right Line Out Source" }, /* Earpiece Routes */ { "Earpiece Source Playback Route", "DACL", "Left DAC" }, { "Earpiece Source Playback Route", "DACR", "Right DAC" }, { "Earpiece Source Playback Route", "Left Mixer", "Left Mixer" }, { "Earpiece Source Playback Route", "Right Mixer", "Right Mixer" }, - { "Earpiece Amp", NULL, "Earpiece Source Playback Route" }, + { "Earpiece Switch", "Earpiece Playback Switch", "Earpiece Source Playback Route" }, + { "Earpiece Amp", NULL, "Earpiece Switch" }, { "EARPIECE", NULL, "Earpiece Amp" }, }; +static int sun50i_a64_codec_suspend(struct snd_soc_component *component) +{ + return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL, + BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE), + BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE)); +} + +static int sun50i_a64_codec_resume(struct snd_soc_component *component) +{ + return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL, + BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE), 0); +} + static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { .controls = sun50i_a64_codec_controls, .num_controls = ARRAY_SIZE(sun50i_a64_codec_controls), @@ -447,6 +491,8 @@ static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { .num_dapm_widgets = ARRAY_SIZE(sun50i_a64_codec_widgets), .dapm_routes = sun50i_a64_codec_routes, .num_dapm_routes = ARRAY_SIZE(sun50i_a64_codec_routes), + .suspend = sun50i_a64_codec_suspend, + .resume = sun50i_a64_codec_resume, }; static const struct of_device_id sun50i_codec_analog_of_match[] = { diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index ca51af114419..e3a1347d7ecd 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -13,6 +13,7 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/of_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/log2.h> @@ -85,10 +86,16 @@ #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) +struct sun8i_codec_quirks { + bool legacy_widgets : 1; + bool lrck_inversion : 1; +}; + struct sun8i_codec { - struct regmap *regmap; - struct clk *clk_module; - struct clk *clk_bus; + struct regmap *regmap; + struct clk *clk_module; + struct clk *clk_bus; + const struct sun8i_codec_quirks *quirks; }; static int sun8i_codec_runtime_resume(struct device *dev) @@ -209,18 +216,19 @@ static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV); /* - * It appears that the DAI and the codec don't share the same - * polarity for the LRCK signal when they mean 'normal' and - * 'inverted' in the datasheet. + * It appears that the DAI and the codec in the A33 SoC don't + * share the same polarity for the LRCK signal when they mean + * 'normal' and 'inverted' in the datasheet. * * Since the DAI here is our regular i2s driver that have been * tested with way more codecs than just this one, it means * that the codec probably gets it backward, and we have to * invert the value here. */ + value ^= scodec->quirks->lrck_inversion; regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV), - !value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV); + value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV); /* DAI format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -388,22 +396,30 @@ static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("ADC", SUN8I_ADC_DIG_CTRL, SUN8I_ADC_DIG_CTRL_ENDA, 0, NULL, 0), - /* Analog DAC AIF */ - SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Left", "Playback", 0, + /* AIF "DAC" Inputs */ + SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "Playback", 0, SUN8I_AIF1_DACDAT_CTRL, SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0), - SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Right", "Playback", 0, + SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "Playback", 0, SUN8I_AIF1_DACDAT_CTRL, SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0), - /* Analog ADC AIF */ - SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Left ADC", "Capture", 0, + /* AIF "ADC" Outputs */ + SND_SOC_DAPM_AIF_IN("AIF1 AD0L", "Capture", 0, SUN8I_AIF1_ADCDAT_CTRL, SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0L_ENA, 0), - SND_SOC_DAPM_AIF_IN("AIF1 Slot 0 Right ADC", "Capture", 0, + SND_SOC_DAPM_AIF_IN("AIF1 AD0R", "Capture", 0, SUN8I_AIF1_ADCDAT_CTRL, SUN8I_AIF1_ADCDAT_CTRL_AIF1_DA0R_ENA, 0), + /* ADC Inputs (connected to analog codec DAPM context) */ + SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), + + /* DAC Outputs (connected to analog codec DAPM context) */ + SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), + /* DAC and ADC Mixers */ SOC_MIXER_ARRAY("Left Digital DAC Mixer", SND_SOC_NOPM, 0, 0, sun8i_dac_mixer_controls), @@ -449,40 +465,92 @@ static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = { /* Clock Routes */ { "AIF1", NULL, "SYSCLK AIF1" }, { "AIF1 PLL", NULL, "AIF1" }, - { "RST AIF1", NULL, "AIF1 PLL" }, + { "SYSCLK", NULL, "AIF1 PLL" }, + + { "RST AIF1", NULL, "SYSCLK" }, { "MODCLK AFI1", NULL, "RST AIF1" }, - { "DAC", NULL, "MODCLK AFI1" }, - { "ADC", NULL, "MODCLK AFI1" }, + { "AIF1 AD0L", NULL, "MODCLK AFI1" }, + { "AIF1 AD0R", NULL, "MODCLK AFI1" }, + { "AIF1 DA0L", NULL, "MODCLK AFI1" }, + { "AIF1 DA0R", NULL, "MODCLK AFI1" }, { "RST DAC", NULL, "SYSCLK" }, { "MODCLK DAC", NULL, "RST DAC" }, { "DAC", NULL, "MODCLK DAC" }, + { "DACL", NULL, "DAC" }, + { "DACR", NULL, "DAC" }, { "RST ADC", NULL, "SYSCLK" }, { "MODCLK ADC", NULL, "RST ADC" }, { "ADC", NULL, "MODCLK ADC" }, + { "ADCL", NULL, "ADC" }, + { "ADCR", NULL, "ADC" }, /* DAC Routes */ - { "AIF1 Slot 0 Right", NULL, "DAC" }, - { "AIF1 Slot 0 Left", NULL, "DAC" }, + { "DACL", NULL, "Left Digital DAC Mixer" }, + { "DACR", NULL, "Right Digital DAC Mixer" }, /* DAC Mixer Routes */ - { "Left Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", - "AIF1 Slot 0 Left"}, - { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", - "AIF1 Slot 0 Right"}, + { "Left Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L" }, + { "Left Digital DAC Mixer", "ADC Digital DAC Playback Switch", "ADCL" }, + + { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R" }, + { "Right Digital DAC Mixer", "ADC Digital DAC Playback Switch", "ADCR" }, /* ADC Routes */ - { "AIF1 Slot 0 Right ADC", NULL, "ADC" }, - { "AIF1 Slot 0 Left ADC", NULL, "ADC" }, + { "AIF1 AD0L", NULL, "Left Digital ADC Mixer" }, + { "AIF1 AD0R", NULL, "Right Digital ADC Mixer" }, /* ADC Mixer Routes */ - { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", - "AIF1 Slot 0 Left ADC" }, - { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", - "AIF1 Slot 0 Right ADC" }, + { "Left Digital ADC Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L" }, + { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" }, + + { "Right Digital ADC Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R" }, + { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" }, }; +static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = { + /* Legacy ADC Inputs (connected to analog codec DAPM context) */ + SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0), + + /* Legacy DAC Outputs (connected to analog codec DAPM context) */ + SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = { + /* Legacy ADC Routes */ + { "ADCL", NULL, "AIF1 Slot 0 Left ADC" }, + { "ADCR", NULL, "AIF1 Slot 0 Right ADC" }, + + /* Legacy DAC Routes */ + { "AIF1 Slot 0 Left", NULL, "DACL" }, + { "AIF1 Slot 0 Right", NULL, "DACR" }, +}; + +static int sun8i_codec_component_probe(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); + int ret; + + /* Add widgets for backward compatibility with old device trees. */ + if (scodec->quirks->legacy_widgets) { + ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_legacy_widgets, + ARRAY_SIZE(sun8i_codec_legacy_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_legacy_routes, + ARRAY_SIZE(sun8i_codec_legacy_routes)); + if (ret) + return ret; + } + + return 0; +} + static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { .hw_params = sun8i_codec_hw_params, .set_fmt = sun8i_set_fmt, @@ -516,6 +584,7 @@ static const struct snd_soc_component_driver sun8i_soc_component = { .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), .dapm_routes = sun8i_codec_dapm_routes, .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes), + .probe = sun8i_codec_component_probe, .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, @@ -566,6 +635,8 @@ static int sun8i_codec_probe(struct platform_device *pdev) return PTR_ERR(scodec->regmap); } + scodec->quirks = of_device_get_match_data(&pdev->dev); + platform_set_drvdata(pdev, scodec); pm_runtime_enable(&pdev->dev); @@ -603,8 +674,17 @@ static int sun8i_codec_remove(struct platform_device *pdev) return 0; } +static const struct sun8i_codec_quirks sun8i_a33_quirks = { + .legacy_widgets = true, + .lrck_inversion = true, +}; + +static const struct sun8i_codec_quirks sun50i_a64_quirks = { +}; + static const struct of_device_id sun8i_codec_of_match[] = { - { .compatible = "allwinner,sun8i-a33-codec" }, + { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks }, + { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks }, {} }; MODULE_DEVICE_TABLE(of, sun8i_codec_of_match); diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 617440767c45..3ffdd0f6292a 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -633,7 +633,7 @@ static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id, * right channels), so it has to be divided by number * of tdm-slots (for I2S - divided by 2). * Instead of storing this ratio, we calculate a new - * tdm_slot width by dividing the the ratio by the + * tdm_slot width by dividing the ratio by the * number of configured tdm slots. */ mcasp->slot_width = div / mcasp->tdm_slots; diff --git a/sound/soc/xilinx/Kconfig b/sound/soc/xilinx/Kconfig index 1d3586b68db7..5bd2730aab76 100644 --- a/sound/soc/xilinx/Kconfig +++ b/sound/soc/xilinx/Kconfig @@ -9,14 +9,14 @@ config SND_SOC_XILINX_I2S encapsulates PCM in AES format and sends AES data. config SND_SOC_XILINX_AUDIO_FORMATTER - tristate "Audio support for the the Xilinx audio formatter" + tristate "Audio support for the Xilinx audio formatter" help Select this option to enable Xilinx audio formatter support. This provides DMA platform device support for audio functionality. config SND_SOC_XILINX_SPDIF - tristate "Audio support for the the Xilinx SPDIF" + tristate "Audio support for the Xilinx SPDIF" help Select this option to enable Xilinx SPDIF Audio. This provides playback and capture of SPDIF audio in |