diff --git a/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.txt b/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.txt deleted file mode 100644 index 860fc0da39c0..000000000000 --- a/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.txt +++ /dev/null @@ -1,18 +0,0 @@ -Bindings for I2S controller built into xtfpga Xtensa bitstreams. - -Required properties: -- compatible: shall be "cdns,xtfpga-i2s". -- reg: memory region (address and length) with device registers. -- interrupts: interrupt for the device. -- clocks: phandle to the clk used as master clock. I2S bus clock - is derived from it. - -Examples: - - i2s0: xtfpga-i2s@d080000 { - #sound-dai-cells = <0>; - compatible = "cdns,xtfpga-i2s"; - reg = <0x0d080000 0x40>; - interrupts = <2 1>; - clocks = <&cdce706 4>; - }; diff --git a/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.yaml b/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.yaml new file mode 100644 index 000000000000..9617acef3f0c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/cdns,xtfpga-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: I2S controller built into xtfpga Xtensa bitstreams + +maintainers: + - Max Filippov + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: cdns,xtfpga-i2s + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + description: phandle to the clk used as master clock. I2S bus clock is derived from it. + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + i2s@d080000 { + compatible = "cdns,xtfpga-i2s"; + reg = <0x0d080000 0x40>; + interrupts = <2 1>; + clocks = <&cdce706 4>; + #sound-dai-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42xx8.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42xx8.yaml index 7ae72bd901f4..a1ae548c4b7b 100644 --- a/Documentation/devicetree/bindings/sound/cirrus,cs42xx8.yaml +++ b/Documentation/devicetree/bindings/sound/cirrus,cs42xx8.yaml @@ -11,6 +11,7 @@ maintainers: allOf: - $ref: dai-common.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# properties: compatible: @@ -21,6 +22,9 @@ properties: reg: maxItems: 1 + spi-max-frequency: + maximum: 6000000 + clocks: minItems: 1 maxItems: 2 @@ -86,3 +90,22 @@ examples: reset-gpios = <&gpio 1>; }; }; + + spi { + #address-cells = <1>; + #size-cells = <0>; + cs-gpios = <&gpio 8 0>; + + codec@0 { + compatible = "cirrus,cs42888"; + reg = <0>; + spi-max-frequency = <6000000>; + clocks = <&codec_mclk 0>; + clock-names = "mclk"; + VA-supply = <®_audio>; + VD-supply = <®_audio>; + VLS-supply = <®_audio>; + VLC-supply = <®_audio>; + reset-gpios = <&gpio 1>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/everest,es8389.yaml b/Documentation/devicetree/bindings/sound/everest,es8389.yaml index 75ce0bc48904..7db84cf11386 100644 --- a/Documentation/devicetree/bindings/sound/everest,es8389.yaml +++ b/Documentation/devicetree/bindings/sound/everest,es8389.yaml @@ -27,6 +27,10 @@ properties: items: - const: mclk + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + "#sound-dai-cells": const: 0 diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml index 3a32f7517d0c..e3cadb93c183 100644 --- a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml @@ -98,6 +98,10 @@ properties: - rpmsg-audio-channel - rpmsg-micfil-channel + hp-det-gpios: + maxItems: 1 + description: The GPIO that detect headphones are plugged in + required: - compatible diff --git a/Documentation/devicetree/bindings/sound/fsl,sai.yaml b/Documentation/devicetree/bindings/sound/fsl,sai.yaml index 83b5ea5f3d70..ba65b3f3d066 100644 --- a/Documentation/devicetree/bindings/sound/fsl,sai.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,sai.yaml @@ -162,6 +162,13 @@ properties: of transmitter. type: boolean + fsl,sai-bit-clock-swap: + description: + Enable Bit Clock Swap, which swaps the bit clock used by the transmitter + or receiver in asynchronous mode, i.e. makes transmitter use RX_BCLK and + TX_SYNC, and vice versa, makes receiver use TX_BCLK and RX_SYNC. + type: boolean + fsl,shared-interrupt: description: Interrupt is shared with other modules. type: boolean diff --git a/Documentation/devicetree/bindings/sound/gpio-audio-amp.yaml b/Documentation/devicetree/bindings/sound/gpio-audio-amp.yaml new file mode 100644 index 000000000000..3690f3d1628c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/gpio-audio-amp.yaml @@ -0,0 +1,270 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/gpio-audio-amp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Audio amplifier driven by GPIOs + +maintainers: + - Herve Codina + +description: | + Audio GPIO amplifiers are driven by GPIO in order to control the gain value + of the amplifier, its mute function and/or its bypass function. + + Those amplifiers are based on discrete components (analog switches, op-amps + and more) where some of them, mostly analog switches, are controlled by GPIOs + to adjust the gain value of the whole amplifier and/or to control + the mute and/or bypass function. + + For instance, the following piece of hardware is a GPIO amplifier + + +5VA + ^ + |\ | + | \ + Vin >---------------------------|+ \ + | +-------+-----> Vout + .--\/\/\/--+------------|- / | + | | | / | + v | |/ | | + GND o v | + \ GND | + gpio >-----------> \ | + o o | + | | | + | '--\/\/\/--. | + | +--\/\/\/--' + '---------------' + +properties: + compatible: + oneOf: + - const: gpio-audio-amp-mono + description: + A single channel amplifier. All features apply to this sole channel. + + - const: gpio-audio-amp-stereo + description: + A dual channel amplifier (left and right). All features apply to both + channels producing the same effect on both channels at the same time. + + vdd-supply: + description: Main power supply of the amplifier + + vddio-supply: + description: Power supply related to the control path + + vdda1-supply: + description: Analog power supply + + vdda2-supply: + description: Additional analog power supply + + mute-gpios: + description: GPIO to control the mute function + maxItems: 1 + + bypass-gpios: + description: GPIO to control the bypass function + maxItems: 1 + + gain-gpios: + description: | + GPIOs to control the amplifier gain + + The gain value is computed from GPIOs value from 0 to 2^N-1 with N the + number of GPIO described. The first GPIO described is the lsb of the gain + value. + + For instance assuming 2 gpios + gain-gpios = <&gpio1 GPIO_ACTIVE_HIGH> <&gpio2 GPIO_ACTIVE_HIGH>; + The gain value will be the following: + + gpio1 | gpio2 | gain + ------+-------+----- + 0 | 0 | 0b00 -> 0 + 1 | 0 | 0b01 -> 1 + 0 | 1 | 0b10 -> 2 + 1 | 1 | 0b11 -> 3 + ------+-------+----- + + Note: The gain value, bits set to 1 or 0, indicate the state active (bit + set) or the state inactive (bit unset) of the related GPIO. The + physical voltage corresponding to this active/inactive state is + given by the GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags. + + minItems: 1 + maxItems: 16 + + gain-ranges: + $ref: /schemas/types.yaml#/definitions/int32-matrix + description: | + A list of one or more ranges of possible values. Each range is defined by + the first and last point in the range. Each point is defined by the pair + (GPIOs value, Gain in 0.01 dB unit). + + Ranges can be contiguous or holes can be present between ranges if some + gpios value should not be used. Also in a range the first point and the + last point can be identical. In that case, the range contains only one + item, the given point. + + items: + items: + - description: GPIOs value of the first point in the range + - description: Gain in 0.01 dB unit of the first point in the range + - description: GPIOs value of the last point in the range + - description: Gain in 0.01 dB unit of the last point in the range + description: | + A range defines a linear function (linear in dB) from the first point + to the last point, both included. The number of items in the range is + N = abs(first_point.gpio_value - last_point.gpio_value) + 1 + + It allows to define the gain range from the first_point.gain to + the last_point.gain, both points included. + + Gain (0.01 dB unit) + ^ + | last + +- - - - - - - - - - + point + | + . + | + . + | + . + +- - - - + . + | first . . + | point . . + | . . + +--------+-----------+---> gpios + value + + Note: Even if first_point.gpio_value is lower than last_point.gpio_value + and first_point.gain is lower than last_point.gain in the above + graphic, all combination of values are supported leading to an + increasing or a decreasing linear segment. + + minItems: 1 + maxItems: 65536 + + gain-labels: + $ref: /schemas/types.yaml#/definitions/string-array + minItems: 2 + maxItems: 65536 + description: | + List of the gain labels attached to the combination of GPIOs controlling + the gain. The first label is related to the gain value 0, the second label + is related to the gain value 1 and so on. + + With 2 GPIOs controlling the gain, GPIOs value can be 0, 1, 2 and 3. + Assuming that gain value set the hardware according to the following + table: + + GPIOs | Hardware + value | amplification + ------+-------------- + 0 | Low + 1 | Middle + 2 | High + 3 | Max + ------+-------------- + + The description using gain labels can be: + gain-labels = "Low", "Middle", "High", "Max"; + +dependencies: + gain-ranges: [ gain-gpios ] + gain-labels: [ gain-gpios ] + +required: + - compatible + - vdd-supply + +anyOf: + - required: + - gain-gpios + - required: + - mute-gpios + - required: + - bypass-gpios + +allOf: + - $ref: component-common.yaml# + - if: + required: + - gain-ranges + then: + properties: + gain-labels: false + - if: + required: + - gain-labels + then: + properties: + gain-ranges: false + +unevaluatedProperties: false + +examples: + - | + #include + + /* Gain controlled by gpios */ + amplifier-0 { + compatible = "gpio-audio-amp-mono"; + vdd-supply = <®ulator>; + gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>; + }; + + /* Gain controlled by gpio using a simple range on a stereo amplifier */ + amplifier-1 { + compatible = "gpio-audio-amp-stereo"; + vdd-supply = <®ulator>; + gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>; + gain-ranges = <0 (-300) 3 600>; + }; + + /* Gain controlled by gpio with labels */ + amplifier-3 { + compatible = "gpio-audio-amp-mono"; + vdd-supply = <®ulator>; + gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; + gain-labels = "Low", "High"; + }; + + /* A mutable stereo amplifier without any gain control */ + amplifier-4 { + compatible = "gpio-audio-amp-stereo"; + vdd-supply = <®ulator>; + mute-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; + }; + + /* + * Several supplies, gain controlled using more complex ranges, mute and + * bypass. + * + * Assuming 3 gpios for controlling the gain with the following table + * gpios value Gain + * 0b000 Do not use (gpios value not allowed) + * 0b001 - 3dB + * 0b010 + 3dB + * 0b011 + 10dB + * 0b100 Do not use (gpios value not allowed) + * 0b101 + 6dB + * 0b110 + 7dB + * 0b111 + 8dB + */ + amplifier-5 { + compatible = "gpio-audio-amp-mono"; + vdd-supply = <®ulator>; + vddio-supply = <®ulator1>; + vdda1-supply = <®ulator2>; + gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, + <&gpio 1 GPIO_ACTIVE_HIGH>, + <&gpio 2 GPIO_ACTIVE_HIGH>; + gain-ranges = <1 (-300) 2 300>, + <3 1000 3 1000>, + <5 600 7 800>; + mute-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; + bypass-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>; + }; +... diff --git a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml index 5424d4f16f52..950e3eab2942 100644 --- a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml +++ b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml @@ -37,7 +37,13 @@ patternProperties: items: enum: - i2s + - left_j + - right_j + - dsp_a - dsp_b + - pdm + - msb + - lsb dai-tdm-slot-num: true diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml index 45382c4d86aa..30f331366566 100644 --- a/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml +++ b/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml @@ -32,6 +32,7 @@ properties: maxItems: 1 clocks: + minItems: 34 items: - description: audio infra sys clock - description: top audio mux 1 @@ -67,8 +68,13 @@ properties: - description: top audio a1 sys pd - description: top audio a2 sys pd - description: audio merge interface pd + - description: HADDS2 PLL 294 MHz (HDMI audio path root) + - description: HDMI audio interface pd + - description: S/PDIF interface pd + - description: audio APLL root pd clock-names: + minItems: 34 items: - const: infra_sys_audio_clk - const: top_audio_mux1_sel @@ -104,6 +110,10 @@ properties: - const: audio_a1sys_pd - const: audio_a2sys_pd - const: audio_mrgif_pd + - const: hadds2pll_294m + - const: audio_hdmi_pd + - const: audio_spdf_pd + - const: audio_apll_pd required: - compatible @@ -113,4 +123,17 @@ required: - clocks - clock-names +allOf: + - if: + properties: + compatible: + contains: + const: mediatek,mt7622-audio + then: + properties: + clocks: + maxItems: 34 + clock-names: + maxItems: 34 + additionalProperties: false diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml new file mode 100644 index 000000000000..9d5a8166e51f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt2701-hdmi-audio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT2701/MT7623N HDMI audio output + +maintainers: + - Daniel Golle + +description: + Sound card routing the MT2701/MT7623N Audio Front End HDMI + playback path to the on-chip HDMI transmitter. The AFE + provides the DMA memif and internal I2S engine; the HDMI + transmitter acts as the audio codec on the serialised link. + +properties: + compatible: + oneOf: + - const: mediatek,mt2701-hdmi-audio + - items: + - const: mediatek,mt7623n-hdmi-audio + - const: mediatek,mt2701-hdmi-audio + + mediatek,platform: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle of the MT2701/MT7623N AFE platform node. + + mediatek,audio-codec: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle of the HDMI transmitter acting as audio codec. + +required: + - compatible + - mediatek,platform + - mediatek,audio-codec + +additionalProperties: false + +examples: + - | + sound-hdmi { + compatible = "mediatek,mt7623n-hdmi-audio", + "mediatek,mt2701-hdmi-audio"; + mediatek,platform = <&afe>; + mediatek,audio-codec = <&hdmi0>; + }; diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt6351-sound.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt6351-sound.yaml new file mode 100644 index 000000000000..b422e238b512 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt6351-sound.yaml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt6351-sound.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT6351 Audio CODEC + +maintainers: + - KaiChieh Chuang + +description: + MT6351 Audio CODEC is a part of the MediaTek MT6351 PMIC. + It communicates with the SoC through the MediaTek PMIC wrapper(pwrap). + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: mediatek,mt6351-sound + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - "#sound-dai-cells" + +unevaluatedProperties: false + +examples: + - | + sound { + compatible = "mediatek,mt6351-sound"; + #sound-dai-cells = <0>; + }; diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml new file mode 100644 index 000000000000..949f8622baf9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt8196-afe.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek Audio Front End PCM controller for MT8196 + +maintainers: + - Darren Ye + +properties: + compatible: + const: mediatek,mt8196-afe + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + memory-region: + maxItems: 1 + + power-domains: + maxItems: 1 + + clocks: + items: + - description: mux for audio intbus + - description: mux for audio engen1 + - description: mux for audio engen2 + - description: mux for audio h + - description: audio apll1 clock + - description: audio apll2 clock + - description: audio apll12 divide for i2sin0 + - description: audio apll12 divide for i2sin1 + - description: audio apll12 divide for fmi2s + - description: audio apll12 divide for tdmout mck + - description: audio apll12 divide for tdmout bck + - description: mux for adsp clock + + clock-names: + items: + - const: top_aud_intbus + - const: top_aud_eng1 + - const: top_aud_eng2 + - const: top_aud_h + - const: apll1 + - const: apll2 + - const: apll12_div_i2sin0 + - const: apll12_div_i2sin1 + - const: apll12_div_fmi2s + - const: apll12_div_tdmout_m + - const: apll12_div_tdmout_b + - const: top_adsp + +required: + - compatible + - reg + - interrupts + - memory-region + - power-domains + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + afe@1a110000 { + compatible = "mediatek,mt8196-afe"; + reg = <0 0x1a110000 0 0x9000>; + interrupts = ; + memory-region = <&afe_dma_mem_reserved>; + power-domains = <&scpsys 14>; //MT8196_POWER_DOMAIN_AUDIO + pinctrl-names = "default"; + pinctrl-0 = <&aud_pins_default>; + clocks = <&vlp_cksys_clk 40>, //CLK_VLP_CK_AUD_INTBUS_SEL + <&vlp_cksys_clk 38>, //CLK_VLP_CK_AUD_ENGEN1_SEL + <&vlp_cksys_clk 39>, //CLK_VLP_CK_AUD_ENGEN2_SEL + <&vlp_cksys_clk 37>, //CLK_VLP_CK_AUDIO_H_SEL + <&vlp_cksys_clk 0>, //CLK_VLP_CK_VLP_APLL1 + <&vlp_cksys_clk 1>, //CLK_VLP_CK_VLP_APLL2 + <&cksys_clk 80>, //CLK_CK_APLL12_CK_DIV_I2SIN0 + <&cksys_clk 81>, //CLK_CK_APLL12_CK_DIV_I2SIN1 + <&cksys_clk 92>, //CLK_CK_APLL12_CK_DIV_FMI2S + <&cksys_clk 93>, //CLK_CK_APLL12_CK_DIV_TDMOUT_M + <&cksys_clk 94>, //CLK_CK_APLL12_CK_DIV_TDMOUT_B + <&cksys_clk 45>; //CLK_CK_ADSP_SEL + clock-names = "top_aud_intbus", + "top_aud_eng1", + "top_aud_eng2", + "top_aud_h", + "apll1", + "apll2", + "apll12_div_i2sin0", + "apll12_div_i2sin1", + "apll12_div_fmi2s", + "apll12_div_tdmout_m", + "apll12_div_tdmout_b", + "top_adsp"; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8196-nau8825.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8196-nau8825.yaml new file mode 100644 index 000000000000..83350faa1e29 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8196-nau8825.yaml @@ -0,0 +1,100 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt8196-nau8825.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT8196 ASoC sound card + +maintainers: + - Darren Ye + +allOf: + - $ref: sound-card-common.yaml# + +properties: + compatible: + enum: + - mediatek,mt8196-nau8825-sound + - mediatek,mt8196-rt5682s-sound + - mediatek,mt8196-rt5650-sound + + mediatek,platform: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of MT8188 ASoC platform. + +patternProperties: + "^dai-link-[0-9]+$": + type: object + description: + Container for dai-link level properties and CODEC sub-nodes. + + properties: + link-name: + description: + This property corresponds to the name of the BE dai-link to which + we are going to update parameters in this node. + items: + enum: + - TDM_DPTX_BE + - I2SOUT6_BE + - I2SIN6_BE + - I2SOUT4_BE + - I2SOUT3_BE + + codec: + description: Holds subnode which indicates codec dai. + type: object + additionalProperties: false + properties: + sound-dai: + minItems: 1 + maxItems: 2 + required: + - sound-dai + + dai-format: + description: audio format. + items: + enum: + - i2s + - right_j + - left_j + - dsp_a + - dsp_b + + mediatek,clk-provider: + $ref: /schemas/types.yaml#/definitions/string + description: Indicates dai-link clock master. + enum: + - cpu + - codec + + additionalProperties: false + + required: + - link-name + +required: + - compatible + - mediatek,platform + +unevaluatedProperties: false + +examples: + - | + sound { + compatible = "mediatek,mt8196-nau8825-sound"; + model = "mt8196-nau8825"; + mediatek,platform = <&afe>; + dai-link-0 { + link-name = "I2SOUT6_BE"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&nau8825>; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/sound/mt6351.txt b/Documentation/devicetree/bindings/sound/mt6351.txt deleted file mode 100644 index 7fb2cb99245e..000000000000 --- a/Documentation/devicetree/bindings/sound/mt6351.txt +++ /dev/null @@ -1,16 +0,0 @@ -Mediatek MT6351 Audio Codec - -The communication between MT6351 and SoC is through Mediatek PMIC wrapper. -For more detail, please visit Mediatek PMIC wrapper documentation. - -Must be a child node of PMIC wrapper. - -Required properties: - -- compatible : "mediatek,mt6351-sound". - -Example: - -mt6351_snd { - compatible = "mediatek,mt6351-sound"; -}; diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8822.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8822.yaml index cb8182bbc491..cf4c13038241 100644 --- a/Documentation/devicetree/bindings/sound/nuvoton,nau8822.yaml +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8822.yaml @@ -30,6 +30,20 @@ properties: clock-names: const: mclk + vdda-supply: + description: Analog power supply + + vddb-supply: + description: Digital buffer (input/output) supply + + vddc-supply: + description: Digital core supply + + vddspk-supply: + description: + Speaker supply (power supply pin for RSPKOUT, LSPKOUT, AUXOUT2 and + AUXTOUT1 output drivers) + nuvoton,spk-btl: description: If set, configure the two loudspeaker outputs as a Bridge Tied Load output @@ -54,5 +68,9 @@ examples: codec@1a { compatible = "nuvoton,nau8822"; reg = <0x1a>; + vdda-supply = <&vcca_3v3_s0>; + vddb-supply = <&vcca_3v3_s0>; + vddc-supply = <&vcca_3v3_s0>; + vddspk-supply = <&vcca_3v3_s0>; }; }; diff --git a/Documentation/devicetree/bindings/sound/realtek,rt5677.yaml b/Documentation/devicetree/bindings/sound/realtek,rt5677.yaml index 9ce23e58e5ea..ae27ae78b1b2 100644 --- a/Documentation/devicetree/bindings/sound/realtek,rt5677.yaml +++ b/Documentation/devicetree/bindings/sound/realtek,rt5677.yaml @@ -58,7 +58,7 @@ properties: 0 - floating (reset value) 1 - pull down 2 - pull up - $ref: /schemas/types.yaml#/definitions/uint32-array + $ref: /schemas/types.yaml#/definitions/uint8-array minItems: 6 maxItems: 6 items: @@ -130,6 +130,6 @@ examples: realtek,pow-ldo2-gpio = <&gpio 3 GPIO_ACTIVE_HIGH>; realtek,reset-gpio = <&gpio 3 GPIO_ACTIVE_LOW>; realtek,in1-differential; - realtek,gpio-config = <0 0 0 0 0 2>; + realtek,gpio-config = /bits/ 8 <0 0 0 0 0 2>; }; }; diff --git a/Documentation/devicetree/bindings/sound/renesas,fsi.yaml b/Documentation/devicetree/bindings/sound/renesas,fsi.yaml index df91991699a7..803945b7f82f 100644 --- a/Documentation/devicetree/bindings/sound/renesas,fsi.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,fsi.yaml @@ -9,9 +9,6 @@ title: Renesas FIFO-buffered Serial Interface (FSI) maintainers: - Kuninori Morimoto -allOf: - - $ref: dai-common.yaml# - properties: $nodename: pattern: "^sound@.*" @@ -38,7 +35,32 @@ properties: maxItems: 1 clocks: - maxItems: 1 + minItems: 1 + items: + - description: Main FSI module clock + - description: | + SPU bus/bridge clock. On R8A7740, this clock must be enabled to allow + register access as the FSI block is connected behind the SPU bus. + - description: CPG DIV6 functional clocks for FSI port A + - description: CPG DIV6 functional clocks for FSI port B + - description: FSI dividers for port A used for audio clock generation + - description: FSI dividers for port B used for audio clock generation + - description: External clock inputs for FSI port A provided by the board + - description: External clock inputs for FSI port B provided by the board + + clock-names: + minItems: 1 + maxItems: 8 + items: + enum: + - fck # Main FSI module clock + - spu # optional SPU bus/bridge clock + - icka # optional CPG DIV6 functional clocks for FSI port A + - ickb # optional CPG DIV6 functional clocks for FSI port B + - diva # optional FSI dividers for port A used for audio clock generation + - divb # optional FSI dividers for port B used for audio clock generation + - xcka # optional External clock inputs for FSI port A provided by the board + - xckb # optional External clock inputs for FSI port B provided by the board power-domains: maxItems: 1 @@ -69,6 +91,30 @@ required: unevaluatedProperties: false +allOf: + - $ref: dai-common.yaml# + - if: + properties: + compatible: + contains: + const: renesas,fsi2-r8a7740 + then: + required: + - clock-names + + properties: + clock-names: + minItems: 2 + items: + - const: fck + - const: spu + - enum: [icka, ickb, diva, divb, xcka, xckb] + - enum: [icka, ickb, diva, divb, xcka, xckb] + - enum: [icka, ickb, diva, divb, xcka, xckb] + - enum: [icka, ickb, diva, divb, xcka, xckb] + - enum: [icka, ickb, diva, divb, xcka, xckb] + - enum: [icka, ickb, diva, divb, xcka, xckb] + examples: - | #include @@ -77,7 +123,11 @@ examples: compatible = "renesas,fsi2-r8a7740", "renesas,sh_fsi2"; reg = <0xfe1f0000 0x400>; interrupts = ; - clocks = <&mstp3_clks R8A7740_CLK_FSI>; + clocks = <&mstp3_clks R8A7740_CLK_FSI>, <&spu_clk>, + <&fsia_clk>, <&fsiack_clk>, <&fsidiva_clk>, + <&fsib_clk>, <&fsibck_clk>, <&fsidivb_clk>; + clock-names = "fck", "spu", "icka", "xcka", "diva", + "ickb", "xckb", "divb"; power-domains = <&pd_a4mp>; #sound-dai-cells = <1>; diff --git a/Documentation/devicetree/bindings/sound/renesas,r9a09g047-sound.yaml b/Documentation/devicetree/bindings/sound/renesas,r9a09g047-sound.yaml new file mode 100644 index 000000000000..d7fa16554698 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/renesas,r9a09g047-sound.yaml @@ -0,0 +1,800 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/renesas,r9a09g047-sound.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/G3E Sound Controller + +maintainers: + - Kuninori Morimoto + - John Madieu + +description: + The RZ/G3E (R9A09G047) sound controller is based on R-Car Sound IP + with extended DMA channel support (up to 5 DMACs per direction), + additional clock domains (47 clocks including per-SSI ADG clocks), + and additional reset lines (14 including SCU, ADG and Audio DMAC + peri-peri resets). SSI operates exclusively in BUSIF mode with + 2-4 BUSIF channels per SSI. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: renesas,r9a09g047-sound + + reg: + maxItems: 5 + + reg-names: + items: + - const: scu + - const: adg + - const: ssiu + - const: ssi + - const: audmapp + + "#sound-dai-cells": + const: 1 + + "#clock-cells": + const: 0 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + clocks: + maxItems: 47 + + clock-names: + items: + - const: ssi-all + - const: ssi-0 + - const: ssi-1 + - const: ssi-2 + - const: ssi-3 + - const: ssi-4 + - const: ssi-5 + - const: ssi-6 + - const: ssi-7 + - const: ssi-8 + - const: ssi-9 + - const: src-0 + - const: src-1 + - const: src-2 + - const: src-3 + - const: src-4 + - const: src-5 + - const: src-6 + - const: src-7 + - const: src-8 + - const: src-9 + - const: mix-0 + - const: mix-1 + - const: ctu-0 + - const: ctu-1 + - const: dvc-0 + - const: dvc-1 + - const: audio-clka + - const: audio-clkb + - const: audio-clkc + - const: audio-clki + - const: ssif_supply + - const: scu + - const: scu_x2 + - const: scu_supply + - const: adg-ssi-0 + - const: adg-ssi-1 + - const: adg-ssi-2 + - const: adg-ssi-3 + - const: adg-ssi-4 + - const: adg-ssi-5 + - const: adg-ssi-6 + - const: adg-ssi-7 + - const: adg-ssi-8 + - const: adg-ssi-9 + - const: audmapp + - const: adg + + power-domains: + maxItems: 1 + + resets: + maxItems: 14 + + reset-names: + items: + - const: ssi-all + - const: ssi-0 + - const: ssi-1 + - const: ssi-2 + - const: ssi-3 + - const: ssi-4 + - const: ssi-5 + - const: ssi-6 + - const: ssi-7 + - const: ssi-8 + - const: ssi-9 + - const: scu + - const: adg + - const: audmapp + + dvc: + type: object + additionalProperties: false + + patternProperties: + "^dvc-[0-1]$": + type: object + additionalProperties: false + + properties: + dmas: + maxItems: 5 + description: + List of references to DMA specifiers, one per DMA + controller, all for the transmission direction + (DVC is playback-only). The dma-engine core falls + through the list to find a free channel. + + dma-names: + maxItems: 5 + allOf: + - items: + enum: + - tx + + required: + - dmas + - dma-names + + mix: + type: object + additionalProperties: false + description: + Per-channel Mixer (MIX) sub-nodes. Each mix-N node has no + properties of its own. It exists so the driver can enumerate + the MIX instances and so that DT labels can be attached to it + for the dai/playback/capture phandle routing arrays. + + patternProperties: + "^mix-[0-1]$": + type: object + additionalProperties: false + + ctu: + type: object + additionalProperties: false + description: + Per-channel Channel Transfer Unit (CTU) sub-nodes. Each ctu-N + node has no properties of its own. It exists so the driver + can enumerate the CTU instances and so that DT labels can be + attached to it for the dai/playback/capture phandle routing arrays. + + patternProperties: + "^ctu-[0-7]$": + type: object + additionalProperties: false + + src: + type: object + additionalProperties: false + + patternProperties: + "^src-[0-9]$": + type: object + additionalProperties: false + + properties: + interrupts: + maxItems: 1 + + dmas: + maxItems: 10 + description: + Must contain a list of pairs of references to DMA + specifiers, one for transmission and one for reception, + repeated for each DMA controller. The dma-engine core + falls through the list to find a free channel. + + dma-names: + maxItems: 10 + allOf: + - items: + enum: + - tx + - rx + + ssiu: + type: object + additionalProperties: false + + patternProperties: + "^ssiu-[0-9]+$": + type: object + additionalProperties: false + + properties: + dmas: + maxItems: 10 + description: + Must contain a list of pairs of references to DMA + specifiers, one for transmission and one for reception, + repeated for each DMA controller. The dma-engine core + falls through the list to find a free channel. + + dma-names: + maxItems: 10 + allOf: + - items: + enum: + - tx + - rx + + required: + - dmas + - dma-names + + ssi: + type: object + additionalProperties: false + + patternProperties: + "^ssi-[0-9]$": + type: object + additionalProperties: false + + properties: + interrupts: + maxItems: 1 + + shared-pin: + description: Shared clock pin. + $ref: /schemas/types.yaml#/definitions/flag + + required: + - interrupts + + ports: + $ref: audio-graph-port.yaml#/definitions/port-base + unevaluatedProperties: false + patternProperties: + '^port@[0-9a-f]+$': + $ref: audio-graph-port.yaml#/definitions/port-base + unevaluatedProperties: false + properties: + reg: + maxItems: 1 + endpoint: + $ref: audio-graph-port.yaml#/definitions/endpoint-base + unevaluatedProperties: false + properties: + playback: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Ordered list of phandles to the in-SoC modules used + by this DAI in the playback direction. Each phandle + must reference one of the ssi-N, src-N, ctu-N, + mix-N or dvc-N sub-nodes of the parent sound + controller. The list order is the pipeline order + from CPU to off-SoC endpoint. + capture: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Ordered list of phandles to the in-SoC modules used + by this DAI in the capture direction. Each phandle + must reference one of the ssi-N, src-N, ctu-N, + mix-N or dvc-N sub-nodes of the parent sound + controller. The list order is the pipeline order + from off-SoC endpoint to CPU. + +required: + - compatible + - reg + - reg-names + - "#sound-dai-cells" + - "#clock-cells" + - clocks + - clock-names + - resets + - reset-names + +unevaluatedProperties: false + +examples: + - | + #include + + sound@13c00000 { + #sound-dai-cells = <1>; + #clock-cells = <0>; + compatible = "renesas,r9a09g047-sound"; + reg = <0x13c00000 0x10000>, + <0x13c20000 0x10000>, + <0x13c30000 0x1000>, + <0x13c31000 0x1f000>, + <0x13c50000 0x10000>; + reg-names = "scu", "adg", "ssiu", "ssi", "audmapp"; + clocks = <&cpg 245>, + <&cpg 385>, <&cpg 386>, + <&cpg 387>, <&cpg 388>, + <&cpg 389>, <&cpg 390>, + <&cpg 391>, <&cpg 392>, + <&cpg 393>, <&cpg 394>, + <&cpg 372>, <&cpg 373>, + <&cpg 374>, <&cpg 375>, + <&cpg 376>, <&cpg 377>, + <&cpg 378>, <&cpg 379>, + <&cpg 380>, <&cpg 381>, + <&cpg 370>, <&cpg 371>, + <&cpg 370>, <&cpg 371>, + <&cpg 368>, <&cpg 369>, + <&cpg 251>, <&cpg 252>, + <&cpg 253>, <&cpg 250>, + <&cpg 384>, + <&cpg 246>, <&cpg 247>, + <&cpg 382>, + <&cpg 352>, <&cpg 353>, + <&cpg 354>, <&cpg 355>, + <&cpg 356>, <&cpg 357>, + <&cpg 358>, <&cpg 359>, + <&cpg 360>, <&cpg 361>, + <&cpg 248>, <&cpg 249>; + clock-names = "ssi-all", + "ssi-0", "ssi-1", + "ssi-2", "ssi-3", + "ssi-4", "ssi-5", + "ssi-6", "ssi-7", + "ssi-8", "ssi-9", + "src-0", "src-1", + "src-2", "src-3", + "src-4", "src-5", + "src-6", "src-7", + "src-8", "src-9", + "mix-0", "mix-1", + "ctu-0", "ctu-1", + "dvc-0", "dvc-1", + "audio-clka", "audio-clkb", + "audio-clkc", "audio-clki", + "ssif_supply", + "scu", "scu_x2", + "scu_supply", + "adg-ssi-0", "adg-ssi-1", + "adg-ssi-2", "adg-ssi-3", + "adg-ssi-4", "adg-ssi-5", + "adg-ssi-6", "adg-ssi-7", + "adg-ssi-8", "adg-ssi-9", + "audmapp", "adg"; + power-domains = <&cpg>; + resets = <&cpg 225>, + <&cpg 226>, <&cpg 227>, + <&cpg 228>, <&cpg 229>, + <&cpg 230>, <&cpg 231>, + <&cpg 232>, <&cpg 233>, + <&cpg 234>, <&cpg 235>, + <&cpg 236>, <&cpg 238>, <&cpg 237>; + reset-names = "ssi-all", + "ssi-0", "ssi-1", + "ssi-2", "ssi-3", + "ssi-4", "ssi-5", + "ssi-6", "ssi-7", + "ssi-8", "ssi-9", + "scu", "adg", + "audmapp"; + + ctu { + ctu-0 { }; + ctu-1 { }; + ctu-2 { }; + ctu-3 { }; + ctu-4 { }; + ctu-5 { }; + ctu-6 { }; + ctu-7 { }; + }; + + dvc { + dvc0: dvc-0 { + dmas = <&dmac0 0x1db3>, <&dmac1 0x1db3>, + <&dmac2 0x1db3>, <&dmac3 0x1db3>, + <&dmac4 0x1db3>; + dma-names = "tx", "tx", "tx", "tx", "tx"; + }; + dvc1: dvc-1 { + dmas = <&dmac0 0x1db4>, <&dmac1 0x1db4>, + <&dmac2 0x1db4>, <&dmac3 0x1db4>, + <&dmac4 0x1db4>; + dma-names = "tx", "tx", "tx", "tx", "tx"; + }; + }; + + mix { + mix-0 { }; + mix-1 { }; + }; + + src { + src0: src-0 { + interrupts = ; + dmas = <&dmac0 0x1d9f>, <&dmac0 0x1da9>, + <&dmac1 0x1d9f>, <&dmac1 0x1da9>, + <&dmac2 0x1d9f>, <&dmac2 0x1da9>, + <&dmac3 0x1d9f>, <&dmac3 0x1da9>, + <&dmac4 0x1d9f>, <&dmac4 0x1da9>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src1: src-1 { + interrupts = ; + dmas = <&dmac0 0x1da0>, <&dmac0 0x1daa>, + <&dmac1 0x1da0>, <&dmac1 0x1daa>, + <&dmac2 0x1da0>, <&dmac2 0x1daa>, + <&dmac3 0x1da0>, <&dmac3 0x1daa>, + <&dmac4 0x1da0>, <&dmac4 0x1daa>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-2 { + interrupts = ; + dmas = <&dmac0 0x1da1>, <&dmac0 0x1dab>, + <&dmac1 0x1da1>, <&dmac1 0x1dab>, + <&dmac2 0x1da1>, <&dmac2 0x1dab>, + <&dmac3 0x1da1>, <&dmac3 0x1dab>, + <&dmac4 0x1da1>, <&dmac4 0x1dab>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-3 { + interrupts = ; + dmas = <&dmac0 0x1da2>, <&dmac0 0x1dac>, + <&dmac1 0x1da2>, <&dmac1 0x1dac>, + <&dmac2 0x1da2>, <&dmac2 0x1dac>, + <&dmac3 0x1da2>, <&dmac3 0x1dac>, + <&dmac4 0x1da2>, <&dmac4 0x1dac>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-4 { + interrupts = ; + dmas = <&dmac0 0x1da3>, <&dmac0 0x1dad>, + <&dmac1 0x1da3>, <&dmac1 0x1dad>, + <&dmac2 0x1da3>, <&dmac2 0x1dad>, + <&dmac3 0x1da3>, <&dmac3 0x1dad>, + <&dmac4 0x1da3>, <&dmac4 0x1dad>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-5 { + interrupts = ; + dmas = <&dmac0 0x1da4>, <&dmac0 0x1dae>, + <&dmac1 0x1da4>, <&dmac1 0x1dae>, + <&dmac2 0x1da4>, <&dmac2 0x1dae>, + <&dmac3 0x1da4>, <&dmac3 0x1dae>, + <&dmac4 0x1da4>, <&dmac4 0x1dae>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-6 { + interrupts = ; + dmas = <&dmac0 0x1da5>, <&dmac0 0x1daf>, + <&dmac1 0x1da5>, <&dmac1 0x1daf>, + <&dmac2 0x1da5>, <&dmac2 0x1daf>, + <&dmac3 0x1da5>, <&dmac3 0x1daf>, + <&dmac4 0x1da5>, <&dmac4 0x1daf>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-7 { + interrupts = ; + dmas = <&dmac0 0x1da6>, <&dmac0 0x1db0>, + <&dmac1 0x1da6>, <&dmac1 0x1db0>, + <&dmac2 0x1da6>, <&dmac2 0x1db0>, + <&dmac3 0x1da6>, <&dmac3 0x1db0>, + <&dmac4 0x1da6>, <&dmac4 0x1db0>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-8 { + interrupts = ; + dmas = <&dmac0 0x1da7>, <&dmac0 0x1db1>, + <&dmac1 0x1da7>, <&dmac1 0x1db1>, + <&dmac2 0x1da7>, <&dmac2 0x1db1>, + <&dmac3 0x1da7>, <&dmac3 0x1db1>, + <&dmac4 0x1da7>, <&dmac4 0x1db1>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + src-9 { + interrupts = ; + dmas = <&dmac0 0x1da8>, <&dmac0 0x1db2>, + <&dmac1 0x1da8>, <&dmac1 0x1db2>, + <&dmac2 0x1da8>, <&dmac2 0x1db2>, + <&dmac3 0x1da8>, <&dmac3 0x1db2>, + <&dmac4 0x1da8>, <&dmac4 0x1db2>; + dma-names = "rx", "tx", "rx", "tx", "rx", "tx", + "rx", "tx", "rx", "tx"; + }; + }; + + ssi { + ssi-0 { + interrupts = ; + }; + ssi-1 { + interrupts = ; + }; + ssi-2 { + interrupts = ; + }; + ssi3: ssi-3 { + interrupts = ; + }; + ssi4: ssi-4 { + interrupts = ; + shared-pin; + }; + ssi-5 { + interrupts = ; + }; + ssi-6 { + interrupts = ; + }; + ssi-7 { + interrupts = ; + }; + ssi-8 { + interrupts = ; + }; + ssi-9 { + interrupts = ; + }; + }; + + ssiu { + ssiu-0 { + dmas = <&dmac0 0x1d61>, <&dmac0 0x1d62>, + <&dmac1 0x1d61>, <&dmac1 0x1d62>, + <&dmac2 0x1d61>, <&dmac2 0x1d62>, + <&dmac3 0x1d61>, <&dmac3 0x1d62>, + <&dmac4 0x1d61>, <&dmac4 0x1d62>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-1 { + dmas = <&dmac0 0x1d63>, <&dmac0 0x1d64>, + <&dmac1 0x1d63>, <&dmac1 0x1d64>, + <&dmac2 0x1d63>, <&dmac2 0x1d64>, + <&dmac3 0x1d63>, <&dmac3 0x1d64>, + <&dmac4 0x1d63>, <&dmac4 0x1d64>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-2 { + dmas = <&dmac0 0x1d65>, <&dmac0 0x1d66>, + <&dmac1 0x1d65>, <&dmac1 0x1d66>, + <&dmac2 0x1d65>, <&dmac2 0x1d66>, + <&dmac3 0x1d65>, <&dmac3 0x1d66>, + <&dmac4 0x1d65>, <&dmac4 0x1d66>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-3 { + dmas = <&dmac0 0x1d67>, <&dmac0 0x1d68>, + <&dmac1 0x1d67>, <&dmac1 0x1d68>, + <&dmac2 0x1d67>, <&dmac2 0x1d68>, + <&dmac3 0x1d67>, <&dmac3 0x1d68>, + <&dmac4 0x1d67>, <&dmac4 0x1d68>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-4 { + dmas = <&dmac0 0x1d69>, <&dmac0 0x1d6a>, + <&dmac1 0x1d69>, <&dmac1 0x1d6a>, + <&dmac2 0x1d69>, <&dmac2 0x1d6a>, + <&dmac3 0x1d69>, <&dmac3 0x1d6a>, + <&dmac4 0x1d69>, <&dmac4 0x1d6a>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-5 { + dmas = <&dmac0 0x1d6b>, <&dmac0 0x1d6c>, + <&dmac1 0x1d6b>, <&dmac1 0x1d6c>, + <&dmac2 0x1d6b>, <&dmac2 0x1d6c>, + <&dmac3 0x1d6b>, <&dmac3 0x1d6c>, + <&dmac4 0x1d6b>, <&dmac4 0x1d6c>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-6 { + dmas = <&dmac0 0x1d6d>, <&dmac0 0x1d6e>, + <&dmac1 0x1d6d>, <&dmac1 0x1d6e>, + <&dmac2 0x1d6d>, <&dmac2 0x1d6e>, + <&dmac3 0x1d6d>, <&dmac3 0x1d6e>, + <&dmac4 0x1d6d>, <&dmac4 0x1d6e>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-7 { + dmas = <&dmac0 0x1d6f>, <&dmac0 0x1d70>, + <&dmac1 0x1d6f>, <&dmac1 0x1d70>, + <&dmac2 0x1d6f>, <&dmac2 0x1d70>, + <&dmac3 0x1d6f>, <&dmac3 0x1d70>, + <&dmac4 0x1d6f>, <&dmac4 0x1d70>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-8 { + dmas = <&dmac0 0x1d71>, <&dmac0 0x1d72>, + <&dmac1 0x1d71>, <&dmac1 0x1d72>, + <&dmac2 0x1d71>, <&dmac2 0x1d72>, + <&dmac3 0x1d71>, <&dmac3 0x1d72>, + <&dmac4 0x1d71>, <&dmac4 0x1d72>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-9 { + dmas = <&dmac0 0x1d73>, <&dmac0 0x1d74>, + <&dmac1 0x1d73>, <&dmac1 0x1d74>, + <&dmac2 0x1d73>, <&dmac2 0x1d74>, + <&dmac3 0x1d73>, <&dmac3 0x1d74>, + <&dmac4 0x1d73>, <&dmac4 0x1d74>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-10 { + dmas = <&dmac0 0x1d75>, <&dmac0 0x1d76>, + <&dmac1 0x1d75>, <&dmac1 0x1d76>, + <&dmac2 0x1d75>, <&dmac2 0x1d76>, + <&dmac3 0x1d75>, <&dmac3 0x1d76>, + <&dmac4 0x1d75>, <&dmac4 0x1d76>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-11 { + dmas = <&dmac0 0x1d77>, <&dmac0 0x1d78>, + <&dmac1 0x1d77>, <&dmac1 0x1d78>, + <&dmac2 0x1d77>, <&dmac2 0x1d78>, + <&dmac3 0x1d77>, <&dmac3 0x1d78>, + <&dmac4 0x1d77>, <&dmac4 0x1d78>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-12 { + dmas = <&dmac0 0x1d79>, <&dmac0 0x1d7a>, + <&dmac1 0x1d79>, <&dmac1 0x1d7a>, + <&dmac2 0x1d79>, <&dmac2 0x1d7a>, + <&dmac3 0x1d79>, <&dmac3 0x1d7a>, + <&dmac4 0x1d79>, <&dmac4 0x1d7a>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-13 { + dmas = <&dmac0 0x1d7b>, <&dmac0 0x1d7c>, + <&dmac1 0x1d7b>, <&dmac1 0x1d7c>, + <&dmac2 0x1d7b>, <&dmac2 0x1d7c>, + <&dmac3 0x1d7b>, <&dmac3 0x1d7c>, + <&dmac4 0x1d7b>, <&dmac4 0x1d7c>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-14 { + dmas = <&dmac0 0x1d7d>, <&dmac0 0x1d7e>, + <&dmac1 0x1d7d>, <&dmac1 0x1d7e>, + <&dmac2 0x1d7d>, <&dmac2 0x1d7e>, + <&dmac3 0x1d7d>, <&dmac3 0x1d7e>, + <&dmac4 0x1d7d>, <&dmac4 0x1d7e>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-15 { + dmas = <&dmac0 0x1d7f>, <&dmac0 0x1d80>, + <&dmac1 0x1d7f>, <&dmac1 0x1d80>, + <&dmac2 0x1d7f>, <&dmac2 0x1d80>, + <&dmac3 0x1d7f>, <&dmac3 0x1d80>, + <&dmac4 0x1d7f>, <&dmac4 0x1d80>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-16 { + dmas = <&dmac0 0x1d81>, <&dmac0 0x1d82>, + <&dmac1 0x1d81>, <&dmac1 0x1d82>, + <&dmac2 0x1d81>, <&dmac2 0x1d82>, + <&dmac3 0x1d81>, <&dmac3 0x1d82>, + <&dmac4 0x1d81>, <&dmac4 0x1d82>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-17 { + dmas = <&dmac0 0x1d83>, <&dmac0 0x1d84>, + <&dmac1 0x1d83>, <&dmac1 0x1d84>, + <&dmac2 0x1d83>, <&dmac2 0x1d84>, + <&dmac3 0x1d83>, <&dmac3 0x1d84>, + <&dmac4 0x1d83>, <&dmac4 0x1d84>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-18 { + dmas = <&dmac0 0x1d85>, <&dmac0 0x1d86>, + <&dmac1 0x1d85>, <&dmac1 0x1d86>, + <&dmac2 0x1d85>, <&dmac2 0x1d86>, + <&dmac3 0x1d85>, <&dmac3 0x1d86>, + <&dmac4 0x1d85>, <&dmac4 0x1d86>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-19 { + dmas = <&dmac0 0x1d87>, <&dmac0 0x1d88>, + <&dmac1 0x1d87>, <&dmac1 0x1d88>, + <&dmac2 0x1d87>, <&dmac2 0x1d88>, + <&dmac3 0x1d87>, <&dmac3 0x1d88>, + <&dmac4 0x1d87>, <&dmac4 0x1d88>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-20 { + dmas = <&dmac0 0x1d89>, <&dmac0 0x1d8a>, + <&dmac1 0x1d89>, <&dmac1 0x1d8a>, + <&dmac2 0x1d89>, <&dmac2 0x1d8a>, + <&dmac3 0x1d89>, <&dmac3 0x1d8a>, + <&dmac4 0x1d89>, <&dmac4 0x1d8a>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-21 { + dmas = <&dmac0 0x1d8b>, <&dmac0 0x1d8c>, + <&dmac1 0x1d8b>, <&dmac1 0x1d8c>, + <&dmac2 0x1d8b>, <&dmac2 0x1d8c>, + <&dmac3 0x1d8b>, <&dmac3 0x1d8c>, + <&dmac4 0x1d8b>, <&dmac4 0x1d8c>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-22 { + dmas = <&dmac0 0x1d8d>, <&dmac0 0x1d8e>, + <&dmac1 0x1d8d>, <&dmac1 0x1d8e>, + <&dmac2 0x1d8d>, <&dmac2 0x1d8e>, + <&dmac3 0x1d8d>, <&dmac3 0x1d8e>, + <&dmac4 0x1d8d>, <&dmac4 0x1d8e>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-23 { + dmas = <&dmac0 0x1d8f>, <&dmac0 0x1d90>, + <&dmac1 0x1d8f>, <&dmac1 0x1d90>, + <&dmac2 0x1d8f>, <&dmac2 0x1d90>, + <&dmac3 0x1d8f>, <&dmac3 0x1d90>, + <&dmac4 0x1d8f>, <&dmac4 0x1d90>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-24 { + dmas = <&dmac0 0x1d91>, <&dmac0 0x1d92>, + <&dmac1 0x1d91>, <&dmac1 0x1d92>, + <&dmac2 0x1d91>, <&dmac2 0x1d92>, + <&dmac3 0x1d91>, <&dmac3 0x1d92>, + <&dmac4 0x1d91>, <&dmac4 0x1d92>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-25 { + dmas = <&dmac0 0x1d93>, <&dmac0 0x1d94>, + <&dmac1 0x1d93>, <&dmac1 0x1d94>, + <&dmac2 0x1d93>, <&dmac2 0x1d94>, + <&dmac3 0x1d93>, <&dmac3 0x1d94>, + <&dmac4 0x1d93>, <&dmac4 0x1d94>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-26 { + dmas = <&dmac0 0x1d95>, <&dmac0 0x1d96>, + <&dmac1 0x1d95>, <&dmac1 0x1d96>, + <&dmac2 0x1d95>, <&dmac2 0x1d96>, + <&dmac3 0x1d95>, <&dmac3 0x1d96>, + <&dmac4 0x1d95>, <&dmac4 0x1d96>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + ssiu-27 { + dmas = <&dmac0 0x1d97>, <&dmac0 0x1d98>, + <&dmac1 0x1d97>, <&dmac1 0x1d98>, + <&dmac2 0x1d97>, <&dmac2 0x1d98>, + <&dmac3 0x1d97>, <&dmac3 0x1d98>, + <&dmac4 0x1d97>, <&dmac4 0x1d98>; + dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx"; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + rsnd_endpoint0: endpoint { + remote-endpoint = <&codec_endpoint>; + dai-format = "i2s"; + bitclock-master = <&rsnd_endpoint0>; + frame-master = <&rsnd_endpoint0>; + playback = <&ssi3>, <&src1>, <&dvc1>; + capture = <&ssi4>, <&src0>, <&dvc0>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml index 502907dd28b3..b174d7498029 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml +++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml @@ -45,8 +45,8 @@ properties: clocks: items: - - description: clock for SPDIF bus - description: clock for SPDIF controller + - description: clock for SPDIF bus clock-names: items: diff --git a/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml index 55bd0b307d22..240d90402e4f 100644 --- a/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/spacemit,k1-i2s.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/sound/spacemit,k1-i2s.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: K1 I2S controller +title: SpacemiT K1/K3 I2S controller description: The I2S bus (Inter-IC sound bus) is a serial link for digital @@ -15,27 +15,54 @@ maintainers: allOf: - $ref: dai-common.yaml# + - if: + properties: + compatible: + contains: + const: spacemit,k3-i2s + then: + properties: + clocks: + minItems: 7 + clock-names: + minItems: 7 + else: + properties: + clocks: + maxItems: 4 + clock-names: + maxItems: 4 properties: compatible: - const: spacemit,k1-i2s + enum: + - spacemit,k1-i2s + - spacemit,k3-i2s reg: maxItems: 1 clocks: + minItems: 4 items: - description: clock for I2S sysclk - description: clock for I2S bclk - description: clock for I2S bus - description: clock for I2S controller + - description: clock for I2S sysclk divider + - description: clock for I2S common sysclk + - description: clock for I2S common bclk clock-names: + minItems: 4 items: - const: sysclk - const: bclk - const: bus - const: func + - const: sysclk_div + - const: c_sysclk + - const: c_bclk dmas: minItems: 1 diff --git a/Documentation/devicetree/bindings/sound/ti,tas2781.yaml b/Documentation/devicetree/bindings/sound/ti,tas2781.yaml index b21466bb0730..aa5a317b5a36 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas2781.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tas2781.yaml @@ -71,6 +71,9 @@ properties: ti,tas2572: 6.6-W Digital Input smart amp with I/V sense and integrated 13-V Class-H Boost + ti,tas2573: Boosted Class-D Audio Amplifier with Integrated DSP and IV + Sense + ti,tas2574: 8.5-W Digital Input smart amp with I/V sense and integrated 15-V Class-H Boost @@ -121,6 +124,7 @@ properties: - ti,tas2568 - ti,tas2570 - ti,tas2572 + - ti,tas2573 - ti,tas2574 - ti,tas5802 - ti,tas5806m @@ -183,6 +187,7 @@ allOf: contains: enum: - ti,tas2563 + - ti,tas2573 - ti,tas5825 then: properties: diff --git a/Documentation/devicetree/bindings/sound/ti,tas67524.yaml b/Documentation/devicetree/bindings/sound/ti,tas67524.yaml new file mode 100644 index 000000000000..812a4d39e2a5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,tas67524.yaml @@ -0,0 +1,280 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,tas67524.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TAS67524 Audio Amplifier + +maintainers: + - Sen Wang + +description: + The TAS67524 is a four-channel, digital-input, automotive + Class-D audio amplifier with load diagnostics and an integrated + DSP for audio processing. + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + oneOf: + - items: + - enum: + - ti,tas6754 + - const: ti,tas67524 + - const: ti,tas67524 + + reg: + maxItems: 1 + + '#sound-dai-cells': + const: 1 + description: | + The device exposes three DAIs, selected by index. + 0 - Standard Audio Path (Playback) + 1 - Low-Latency Playback Path (Playback) + 2 - Sensory Feedback (Capture - Vpredict and Isense) + By default, all four channels of each DAI are active. + + interrupts: + maxItems: 1 + description: + Active-low falling-edge interrupt from the FAULT pin. When provided, + the driver uses IRQ-driven fault reporting instead of polling. + + powerdown-gpios: + maxItems: 1 + description: + GPIO connected to the PD pin, active low. Controls the internal + digital circuitry power state. When asserted the device enters + full power-down mode and all register state is lost. Can be omitted if + PD pin is hardwired or externally controlled. + + standby-gpios: + maxItems: 1 + description: + GPIO connected to the STBY pin, active low. Controls the analog + power stage. When asserted the device enters Deep Sleep mode but + remains I2C-accessible with registers retained. Can be omitted if + STBY pin is tied to PD or hardwired. + + dvdd-supply: + description: + Digital logic supply (1.62 V to 3.6 V). All three supply rails must + be within their recommended operating ranges before the PD pin is + released. + + pvdd-supply: + description: + Output FET power supply (4.5 V to 19 V). All three supply rails must + be within their recommended operating ranges before the PD pin is + released. + + vbat-supply: + description: + Battery supply for the Class-D output stage (4.5 V to 19 V). Optional + when PVDD and VBAT are connected to the same supply rail. When absent, + VBAT is assumed hardwired to PVDD. + + ti,fast-boot: + type: boolean + description: + Skip DC load diagnostic sweep at power-on to reduce boot latency. + Automatic diagnostics after fault conditions remain enabled. Hardware + overcurrent protection is always active. + + ti,audio-slot-no: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + TDM slot offset for the standard audio playback path via SDIN1. A value + of 4 maps to slot 4. If omitted, slot assignment is derived from the + tx_mask provided via set_tdm_slot(). Without either property, no slot + mapping is configured. + + ti,llp-slot-no: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + TDM slot offset for the low-latency playback path via SDIN1. If omitted, + slot assignment is derived from the tx_mask provided via set_tdm_slot(). + Without either property, no slot mapping is configured. Disabled outside + of LLP mode, and only relevant for TDM formats. + + ti,vpredict-slot-no: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + In TDM mode, enables Vpredict output and assigns its starting slot; + four consecutive slots carry Vpredict Ch1-4 on SDOUT1. May coexist + with ti,isense-slot-no using separate non-overlapping slots. + + In I2S mode, enables Vpredict output on SDOUT1 (Ch1/Ch2) and SDOUT2 + (Ch3/Ch4). The slot value is unused. Requires a GPIO configured as + sdout2 for Ch3/Ch4; without it only Ch1/Ch2 are output. Mutually + exclusive with ti,isense-slot-no; if both are set, Vpredict takes + priority. + + Irrelevant in Left-J and Right-J modes. + + ti,isense-slot-no: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + In TDM mode, enables Isense output and assigns its starting slot; + four consecutive slots carry Isense Ch1-4 on SDOUT1. May coexist + with ti,vpredict-slot-no using separate non-overlapping slots. + + In I2S mode, enables Isense output on SDOUT1 (Ch1/Ch2) and SDOUT2 + (Ch3/Ch4). The slot value is unused. Requires a GPIO configured as + SDOUT2 for Ch3/Ch4; without it only Ch1/Ch2 are output. Mutually + exclusive with ti,vpredict-slot-no; Vpredict takes priority if both + are set. + + Irrelevant in Left-J and Right-J modes. + + ti,gpio1-function: + $ref: /schemas/types.yaml#/definitions/string + description: + Function for the GPIO_1 pin. When omitted, GPIO_1 remains in its + power-on default state. + enum: + - low # Output: driven low + - auto-mute # Output: high when all channels are auto-muted + - auto-mute-ch4 # Output: high when channel 4 is auto-muted + - auto-mute-ch3 # Output: high when channel 3 is auto-muted + - auto-mute-ch2 # Output: high when channel 2 is auto-muted + - auto-mute-ch1 # Output: high when channel 1 is auto-muted + - sdout2 # Output: Routes secondary serial data output 2 + - sdout1 # Output: Re-routes secondary serial data output 1 + - warn # Output: warning signal (OTW, CBC) + - fault # Output: fault signal (OTSD, OC, DC) + - clock-sync # Output: clock synchronisation + - invalid-clock # Output: high when clock is invalid + - high # Output: driven high + - mute # Input: external mute control + - phase-sync # Input: phase synchronisation + - sdin2 # Input: secondary SDIN2 for I2S/LJ/RJ ch3/ch4 + - deep-sleep # Input: asserted transitions device to Deep Sleep + - hiz # Input: asserted transitions device to Hi-Z + - play # Input: asserted transitions device to Play + - sleep # Input: asserted transitions device to Sleep + + ti,gpio2-function: + $ref: /schemas/types.yaml#/definitions/string + description: + Function for the GPIO_2 pin. When omitted, GPIO_2 remains in its + power-on default state. + enum: + - low # Output: driven low + - auto-mute # Output: high when all channels are auto-muted + - auto-mute-ch4 # Output: high when channel 4 is auto-muted + - auto-mute-ch3 # Output: high when channel 3 is auto-muted + - auto-mute-ch2 # Output: high when channel 2 is auto-muted + - auto-mute-ch1 # Output: high when channel 1 is auto-muted + - sdout2 # Output: Routes secondary serial data output 2 + - sdout1 # Output: Re-routes secondary serial data output 1 + - warn # Output: warning signal (OTW, CBC) + - fault # Output: fault signal (OTSD, OC, DC) + - clock-sync # Output: clock synchronisation + - invalid-clock # Output: high when clock is invalid + - high # Output: driven high + - mute # Input: external mute control + - phase-sync # Input: phase synchronisation + - sdin2 # Input: secondary SDIN2 for I2S/LJ/RJ ch3/ch4 + - deep-sleep # Input: asserted transitions device to Deep Sleep + - hiz # Input: asserted transitions device to Hi-Z + - play # Input: asserted transitions device to Play + - sleep # Input: asserted transitions device to Sleep + + ports: + $ref: /schemas/graph.yaml#/properties/ports + properties: + port@0: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: Standard audio playback port (DAI 0). + + port@1: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: Low-latency playback port (LLP) (DAI 1). + + port@2: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + description: Sensory feedback capture port (DAI 2). + + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + - '#sound-dai-cells' + - dvdd-supply + - pvdd-supply + +anyOf: + - required: [powerdown-gpios] + - required: [standby-gpios] + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + amplifier@70 { + compatible = "ti,tas67524"; + reg = <0x70>; + #sound-dai-cells = <1>; + sound-name-prefix = "TAS0"; + + standby-gpios = <&main_gpio0 33 GPIO_ACTIVE_LOW>; + + dvdd-supply = <&dvdd_1v8>; + pvdd-supply = <&pvdd_12v>; + vbat-supply = <&vbat_12v>; + + ti,audio-slot-no = <0>; + ti,llp-slot-no = <4>; + ti,vpredict-slot-no = <0>; + ti,isense-slot-no = <4>; + + ti,gpio2-function = "warn"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tas0_audio_ep: endpoint { + dai-format = "dsp_b"; + remote-endpoint = <&be_tas0_audio_ep>; + }; + }; + + port@1 { + reg = <1>; + + tas0_anc_ep: endpoint { + remote-endpoint = <&be_tas0_anc_ep>; + }; + }; + + port@2 { + reg = <2>; + + tas0_fb_ep: endpoint { + remote-endpoint = <&be_tas0_fb_ep>; + }; + }; + }; + }; + }; diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst index f75f08763941..c4aef14a3147 100644 --- a/Documentation/sound/alsa-configuration.rst +++ b/Documentation/sound/alsa-configuration.rst @@ -1097,7 +1097,7 @@ output (with ``--no-upload`` option) to kernel bugzilla or alsa-devel ML (see the section `Links and Addresses`_). ``power_save`` and ``power_save_controller`` options are for power-saving -mode. See powersave.rst for details. +mode. See Documentation/sound/designs/powersave.rst for details. Note 2: If you get click noises on output, try the module option ``position_fix=1`` or ``2``. ``position_fix=1`` will use the SD_LPIB @@ -1168,7 +1168,7 @@ line_outs_monitor enable_monitor Enable Analog Out on Channel 63/64 by default. -See hdspm.rst for details. +See Documentation/sound/cards/hdspm.rst for details. Module snd-ice1712 ------------------ @@ -2383,6 +2383,24 @@ quirk_flags ``V(x) = k * x``; ``dB(x) = 20 * log10(x)``. Overrides bit 24 * bit 28: ``mixer_capture_linear_vol`` Similar to bit 27 but for capture streams. Overrides bit 25 + * bit 29: ``ifb_silence_on_empty`` + In implicit feedback mode, when an entire capture URB returns with + all iso_frame_desc[i].status != 0 (bytes==0), do not silently return + from snd_usb_handle_sync_urb. Instead fall through and enqueue a + packet_info containing only size-0 packets, so the OUT ring keeps + moving (emits silence). Needed by Behringer Flow 8 (1397:050c). + * bit 30: ``mixer_get_cur_broken`` + Some mixers are sticky, which means that setting their current volume + is a no-op, and reading the current volume returns a constant value. + The sticky check disables these mixers to prevent confusing userspace. + However, some devices do have a tunable volume despite the reported + current volume being constant. As the sticky check can't distinguish + between the two categories, setting this flag tells that the device + should fall into the second category when GET_CUR returns a constant + value, resulting in the sticky check being non-fatal and only + disabling GET_CUR instead of the whole mixer. The current volume will + then be provided by the internal cache that stores the last set + volume This module supports multiple devices, autoprobe and hotplugging. diff --git a/Documentation/sound/codecs/index.rst b/Documentation/sound/codecs/index.rst index 2cb95d87bbef..7594d0a38d6b 100644 --- a/Documentation/sound/codecs/index.rst +++ b/Documentation/sound/codecs/index.rst @@ -7,3 +7,4 @@ Codec-Specific Information :maxdepth: 2 cs35l56 + tas675x diff --git a/Documentation/sound/codecs/tas675x.rst b/Documentation/sound/codecs/tas675x.rst new file mode 100644 index 000000000000..c08b0e392306 --- /dev/null +++ b/Documentation/sound/codecs/tas675x.rst @@ -0,0 +1,820 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================================== +TAS675x Codec Mixer Controls +====================================== + +This document describes the ALSA mixer controls for the TAS675x +4-channel amplifier driver. + +For device tree bindings, see: +Documentation/devicetree/bindings/sound/ti,tas67524.yaml + +DSP Signal Path Mode +==================== + +DSP Signal Path Mode +-------------------- + +:Description: Signal processing mode selection. +:Type: Enumerated +:Default: Normal +:Options: Normal, LLP, FFLP +:Register: 0x32 bits [1:0] + +Normal + Full DSP with all features available. + +LLP (Low Latency Path) + Bypasses DSP processing. DSP protection features (Thermal Foldback, + PVDD Foldback, Clip Detect) and Real-Time Load Diagnostics unavailable. + +FFLP (Full Feature Low Latency Path) + Reduced latency. Real-Time Load Diagnostics unavailable. + +The following controls are unavailable in LLP mode: +``Thermal Foldback Switch``, ``PVDD Foldback Switch``, +``DC Blocker Bypass Switch``, ``Clip Detect Switch``, ``Audio SDOUT Switch``. + +The following controls require Normal mode (unavailable in FFLP and LLP): +``CHx RTLDG Switch``, ``RTLDG Clip Mask Switch``, ``ISENSE Calibration Switch``, +``RTLDG Open Load Threshold``, ``RTLDG Short Load Threshold``, +``CHx RTLDG Impedance``. + +Volume Controls +=============== + +Analog Playback Volume +---------------------- + +:Description: Analog output gain for all channels (CH1/CH2 and CH3/CH4 pairs). +:Type: Volume (TLV) +:Default: 0 dB +:Range: -15.5 dB to 0 dB (0.5 dB steps) +:Register: 0x4A (CH1/CH2), 0x4B (CH3/CH4) + +Analog Gain Ramp Step +--------------------- + +:Description: Anti-pop ramp step duration for analog gain transitions. +:Type: Enumerated +:Default: 15us +:Options: 15us, 60us, 200us, 400us +:Register: 0x4E bits [3:2] + +CHx Digital Playback Volume +--------------------------- + +:Description: Per-channel digital volume control (x = 1, 2, 3, 4). +:Type: Volume (TLV) +:Default: 0 dB +:Range: -103 dB to 0 dB (0.5 dB steps) +:Bounds: 0x30 (min/mute) to 0xFF (max) +:Register: 0x40 (CH1), 0x41 (CH2), 0x42 (CH3), 0x43 (CH4) + +Volume Ramp Down Rate +--------------------- + +:Description: Update frequency during mute transition. +:Type: Enumerated +:Default: 16 FS +:Options: 4 FS, 16 FS, 32 FS, Instant +:Register: 0x44 bits [7:6] + +Volume Ramp Down Step +--------------------- + +:Description: dB change per update during mute. +:Type: Enumerated +:Default: 0.5dB +:Options: 4dB, 2dB, 1dB, 0.5dB +:Register: 0x44 bits [5:4] + +Volume Ramp Up Rate +------------------- + +:Description: Update frequency during unmute transition. +:Type: Enumerated +:Default: 16 FS +:Options: 4 FS, 16 FS, 32 FS, Instant +:Register: 0x44 bits [3:2] + +Volume Ramp Up Step +------------------- + +:Description: dB change per update during unmute. +:Type: Enumerated +:Default: 0.5dB +:Options: 4dB, 2dB, 1dB, 0.5dB +:Register: 0x44 bits [1:0] + +CH1/2 Volume Combine +-------------------- + +:Description: Links digital volume controls for CH1 and CH2. +:Type: Enumerated +:Default: Independent +:Options: Independent, CH2 follows CH1, CH1 follows CH2 +:Register: 0x46 bits [1:0] + +CH3/4 Volume Combine +-------------------- + +:Description: Links digital volume controls for CH3 and CH4. +:Type: Enumerated +:Default: Independent +:Options: Independent, CH4 follows CH3, CH3 follows CH4 +:Register: 0x46 bits [3:2] + +Auto Mute & Silence Detection +============================== + +CHx Auto Mute Switch +-------------------- + +:Description: Enables automatic muting on zero-signal detection (x = 1, 2, 3, 4). +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x47 bit [0] (CH1), bit [1] (CH2), bit [2] (CH3), bit [3] (CH4) + +Auto Mute Combine Switch +------------------------ + +:Description: Coordinated muting behaviour across all channels. +:Type: Boolean Switch +:Default: Disabled (0) +:Behavior: Disabled: channels mute independently when their signal is zero. + Enabled: all channels mute together only when all detect zero + signal; unmute when any channel has non-zero signal. +:Register: 0x47 bit [4] + +CHx Auto Mute Time +------------------ + +:Description: Duration of zero signal before muting triggers (x = 1, 2, 3, 4). +:Type: Enumerated +:Default: 11.5ms +:Options: 11.5ms, 53ms, 106.5ms, 266.5ms, 535ms, 1065ms, 2665ms, 5330ms +:Register: 0x48 bits [7:4] (CH1), bits [3:0] (CH2), + 0x49 bits [7:4] (CH3), bits [3:0] (CH4) +:Note: Values are at 96 kHz. At 48 kHz, times are doubled. + +Clock & EMI Management +====================== + +Spread Spectrum Mode +-------------------- + +:Description: Frequency dithering mode to reduce peak EMI. +:Type: Enumerated +:Default: Disabled +:Options: Disabled, Triangle, Random, Triangle and Random +:Register: 0x61 bits [1:0] + +SS Triangle Range +----------------- + +:Description: Frequency deviation range for Triangle spread spectrum. +:Type: Enumerated +:Default: 6.5% +:Options: 6.5%, 13.5%, 5%, 10% +:Register: 0x62 bits [1:0] +:Note: Applies only when Spread Spectrum Mode includes Triangle. + +SS Random Range +--------------- + +:Description: Frequency deviation range for Random spread spectrum. +:Type: Enumerated +:Default: 0.83% +:Options: 0.83%, 2.50%, 5.83%, 12.50%, 25.83% +:Register: 0x62 bits [6:4] +:Note: Applies only when Spread Spectrum Mode includes Random. + +SS Random Dwell Range +--------------------- + +:Description: Dwell time range for Random spread spectrum (FSS = spread + spectrum modulation frequency). +:Type: Enumerated +:Default: 1/FSS to 2/FSS +:Options: 1/FSS to 2/FSS, 1/FSS to 4/FSS, 1/FSS to 8/FSS, 1/FSS to 15/FSS +:Register: 0x62 bits [3:2] +:Note: Applies only when Spread Spectrum Mode includes Random. + +SS Triangle Dwell Min +--------------------- + +:Description: Minimum dwell time at Triangle spread spectrum frequency extremes. +:Type: Integer +:Default: 0 +:Range: 0 to 15 (0 = feature disabled) +:Register: 0x66 bits [7:4] +:Note: Counts in FSS clock cycles. The modulator holds the extreme + frequency for at least this many FSS cycles before reversing. + When Dwell Min equals Dwell Max, the dwell feature is inactive. + For FSS values at each PWM frequency refer to the "Spread + Spectrum" section of the TRM. + +SS Triangle Dwell Max +--------------------- + +:Description: Maximum dwell time at Triangle spread spectrum frequency extremes. +:Type: Integer +:Default: 0 +:Range: 0 to 15 (0 = feature disabled) +:Register: 0x66 bits [3:0] +:Note: Counts in FSS clock cycles. Must be >= Dwell Min. When Dwell Max + equals Dwell Min, the dwell feature is inactive. + +Hardware Protection +=================== + +OTSD Auto Recovery Switch +-------------------------- + +:Description: Enables automatic recovery from over-temperature shutdown. +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x8F bit [1] +:Note: When disabled, manual fault clearing is required after OTSD events. + +Overcurrent Limit Level +----------------------- + +:Description: Current-limit trip point sensitivity. +:Type: Enumerated +:Default: Level 4 +:Options: Level 4, Level 3, Level 2, Level 1 +:Register: 0x55 bits [1:0] +:Note: Level 4 is the least sensitive (highest trip current); Level 1 is + the most sensitive. The exact ILIM values depend on operating + conditions (PVDD voltage, switching frequency, and temperature). + Refer to the Electrical Characteristics table and the + "Overcurrent Limit (Cycle-By-Cycle)" section of the TRM. + +CHx OTW Threshold +----------------- + +:Description: Over-temperature warning threshold per channel (x = 1, 2, 3, 4). +:Type: Enumerated +:Default: >95C +:Options: Disabled, >95C, >110C, >125C, >135C, >145C, >155C, >165C +:Register: 0xE2 bits [6:4] (CH1), bits [2:0] (CH2), + 0xE3 bits [6:4] (CH3), bits [2:0] (CH4) + +Temperature and Voltage Monitoring +=================================== + +PVDD Sense +---------- + +:Description: Supply voltage sense register. +:Type: Integer (read-only) +:Range: 0 to 255 +:Conversion: value × 0.19 V +:Register: 0x74 + +Global Temperature +------------------ + +:Description: Global die temperature sense register. +:Type: Integer (read-only) +:Range: 0 to 255 +:Conversion: (value × 0.5 °C) − 50 °C +:Register: 0x75 + +CHx Temperature Range +--------------------- + +:Description: Per-channel coarse temperature range indicator (x = 1, 2, 3, 4). +:Type: Integer (read-only) +:Range: 0 to 3 +:Mapping: 0 = <80 °C, 1 = 80–100 °C, 2 = 100–120 °C, 3 = >120 °C +:Register: 0xBB bits [7:6] (CH1), bits [5:4] (CH2), + 0xBC bits [3:2] (CH3), bits [1:0] (CH4) + +Load Diagnostics +================ + +The TAS675x provides three load diagnostic modes: + +DC Load Diagnostics (DC LDG) + Measures DC resistance to detect S2G (short-to-ground), S2P + (short-to-power), OL (open load), and SL (shorted load) faults. + +AC Load Diagnostics (AC LDG) + Measures complex AC impedance at a configurable frequency. Detects + capacitive loads and tweeter configurations. + +Real-Time Load Diagnostics (RTLDG) + Monitors impedance continuously during playback using a pilot tone. + Normal DSP mode only, at 48 kHz or 96 kHz. + +Fast Boot Mode +-------------- + +By default the device runs DC load diagnostics at initialization before +accepting audio. Setting ``ti,fast-boot`` in the device tree bypasses this +initial diagnostic run for faster startup. Automatic diagnostics after +fault recovery remain enabled. + +DC Load Diagnostics +------------------- + +The ``CHx DC LDG Report`` 4-bit fault field uses the following encoding: + + ====== =========== =================================================== + Bit Fault Description + ====== =========== =================================================== + [3] S2G Short-to-Ground + [2] S2P Short-to-Power + [1] OL Open Load + [0] SL Shorted Load + ====== =========== =================================================== + +DC LDG Trigger +~~~~~~~~~~~~~~ + +:Description: Triggers manual DC load diagnostics on all channels. +:Type: Boolean (write-only) +:Note: Returns -EBUSY if any DAI stream (playback or capture) is active. + The driver manages all channel state transitions. Blocks until + diagnostics complete or time out (300 ms). + +DC LDG Auto Diagnostics Switch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Enables automatic DC diagnostics after fault recovery. +:Type: Boolean Switch +:Default: Enabled (1) +:Register: 0xB0 bit [0] +:Note: Active-low, when enabled, affected channels re-run diagnostics after + fault recovery and retry approximately every 750 ms until resolved. + +CHx LO LDG Switch +~~~~~~~~~~~~~~~~~ + +:Description: Enables line output load detection per channel (x = 1, 2, 3, 4). +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0xB1 bit [3] (CH1), bit [2] (CH2), bit [1] (CH3), bit [0] (CH4) +:Note: When enabled and DC diagnostics report OL, the device tests for + a high-impedance line output load. + +DC LDG SLOL Ramp Time +~~~~~~~~~~~~~~~~~~~~~ + +:Description: Voltage ramp time for shorted-load and open-load detection. +:Type: Enumerated +:Default: 15 ms +:Options: 15 ms, 30 ms, 10 ms, 20 ms +:Register: 0xB2 bits [7:6] + +DC LDG SLOL Settling Time +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Settling time for shorted-load and open-load detection. +:Type: Enumerated +:Default: 10 ms +:Options: 10 ms, 5 ms, 20 ms, 15 ms +:Register: 0xB2 bits [5:4] + +DC LDG S2PG Ramp Time +~~~~~~~~~~~~~~~~~~~~~ + +:Description: Voltage ramp time for short-to-power and short-to-ground detection. +:Type: Enumerated +:Default: 5 ms +:Options: 5 ms, 2.5 ms, 10 ms, 15 ms +:Register: 0xB2 bits [3:2] + +DC LDG S2PG Settling Time +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Settling time for short-to-power and short-to-ground detection. +:Type: Enumerated +:Default: 10 ms +:Options: 10 ms, 5 ms, 20 ms, 30 ms +:Register: 0xB2 bits [1:0] + +CHx DC LDG SL Threshold +~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Shorted-load detection threshold per channel (x = 1, 2, 3, 4). +:Type: Enumerated +:Default: 1 Ohm +:Options: 0.5 Ohm, 1 Ohm, 1.5 Ohm, 2 Ohm, 2.5 Ohm, + 3 Ohm, 3.5 Ohm, 4 Ohm, 4.5 Ohm, 5 Ohm +:Register: 0xB3 bits [7:4] (CH1), bits [3:0] (CH2), + 0xB4 bits [7:4] (CH3), bits [3:0] (CH4) + +DC LDG Result +~~~~~~~~~~~~~ + +:Description: Overall DC diagnostic result register. +:Type: Integer (read-only) +:Range: 0x00 to 0xFF +:Register: 0xC2 +:Bit Encoding: + + ======== ===================================================== + Bits Description + ======== ===================================================== + [7:4] Line output detection result, one bit per channel + [3:0] DC diagnostic pass/fail per channel (1=pass, 0=fail) + ======== ===================================================== + +CHx DC LDG Report +~~~~~~~~~~~~~~~~~ + +:Description: DC diagnostic fault status per channel (x = 1, 2, 3, 4). +:Type: Integer (read-only) +:Range: 0x0 to 0xF +:Register: 0xC0 bits [7:4] (CH1), bits [3:0] (CH2), + 0xC1 bits [7:4] (CH3), bits [3:0] (CH4) +:Note: See fault bit encoding table at the start of this section. + +CHx LO LDG Report +~~~~~~~~~~~~~~~~~ + +:Description: Line output load detection result per channel (x = 1, 2, 3, 4). +:Type: Boolean (read-only) +:Values: 0 = not detected, 1 = line output load detected +:Register: 0xC2 bit [7] (CH1), bit [6] (CH2), bit [5] (CH3), bit [4] (CH4) + +CHx DC Resistance +~~~~~~~~~~~~~~~~~ + +:Description: Measured DC load resistance per channel (x = 1, 2, 3, 4). +:Type: Float (read-only, displayed in ohms) +:Resolution: 0.1 ohm per code (10-bit value) +:Range: 0.0 to 102.3 ohms +:Register: 0xD9 bits [7:6]/[5:4]/[3:2]/[1:0] (MSB for CH1–CH4), + 0xDA (CH1 LSB), 0xDB (CH2 LSB), 0xDC (CH3 LSB), 0xDD (CH4 LSB) + +AC Load Diagnostics +------------------- + +AC LDG Trigger +~~~~~~~~~~~~~~ + +:Description: Triggers AC impedance measurement on all channels. +:Type: Boolean (write-only) +:Note: Returns -EBUSY if any DAI stream (playback or capture) is active. + The driver transitions all channels to SLEEP state before starting + the measurement. Blocks until diagnostics complete or time out. + +AC LDG Gain +~~~~~~~~~~~ + +:Description: Measurement resolution for AC diagnostics. +:Type: Boolean Switch +:Default: 1 (Gain 8) +:Values: 0 = 0.8 ohm/code (Gain 1), 1 = 0.1 ohm/code (Gain 8) +:Register: 0xB5 bit [4] +:Note: Gain 8 recommended for load impedances below 8 ohms. + +AC LDG Test Frequency +~~~~~~~~~~~~~~~~~~~~~ + +:Description: Test signal frequency for AC impedance measurement. +:Type: Integer +:Default: 200 (0xC8 = 18.75 kHz) +:Range: 0x01 to 0xFF (0x00 reserved) +:Formula: Frequency = 93.75 Hz × register value +:Register: 0xB8 + +CHx AC LDG Real / CHx AC LDG Imag +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Real and imaginary AC impedance components per channel + (x = 1, 2, 3, 4). +:Type: Integer (read-only) +:Range: 0x00 to 0xFF (8-bit signed) +:Register: 0xC3 (CH1 Real), 0xC4 (CH1 Imag), 0xC5 (CH2 Real), 0xC6 (CH2 Imag), + 0xC7 (CH3 Real), 0xC8 (CH3 Imag), 0xC9 (CH4 Real), 0xCA (CH4 Imag) +:Note: Scale set by AC LDG Gain. + +Speaker Protection & Detection +------------------------------- + +Tweeter Detection Switch +~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Enables tweeter detection using the AC impedance magnitude comparator. +:Type: Boolean Switch +:Default: Enabled (1) +:Register: 0xB6 bit [0] +:Note: The underlying register bit is TWEETER DETECT DISABLE (active-low). + Control value 1 = detection enabled (register bit 0), 0 = disabled + (register bit 1). + +Tweeter Detect Threshold +~~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Magnitude threshold for tweeter detection. +:Type: Integer +:Default: 0 +:Range: 0x00 to 0xFF +:Resolution: 0.8 ohm/code (AC LDG Gain=0) or 0.1 ohm/code (AC LDG Gain=1) +:Register: 0xB7 + +CHx Tweeter Detect Report +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:Description: Tweeter detection result per channel (x = 1, 2, 3, 4). +:Type: Boolean (read-only) +:Values: 0 = no tweeter detected, 1 = tweeter detected +:Register: 0xCB bit [3] (CH1), bit [2] (CH2), bit [1] (CH3), bit [0] (CH4) + +DSP Protection Features +======================= + +These controls are unavailable in LLP mode. + +Thermal Foldback Switch +----------------------- + +:Description: Enables dynamic gain reduction based on die temperature. +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x3A bit [0] + +PVDD Foldback Switch +-------------------- + +:Description: Enables automatic gain limiting when supply voltage drops + (Automatic Gain Limiter). +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x3A bit [4] + +DC Blocker Bypass Switch +------------------------ + +:Description: Bypasses the DC-blocking high-pass filter. +:Type: Boolean Switch +:Default: Not bypassed (0) +:Register: 0x39 bit [0] + +Clip Detect Switch +------------------ + +:Description: Enables DSP-based clip detection (Pseudo-Analog Clip Detect). +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x93 bit [6] + +Audio SDOUT Switch +------------------ + +:Description: Routes post-processed audio to the SDOUT pin instead of + Vpredict data. +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x3A bit [5] +:Note: When enabled, replaces Vpredict data on SDOUT with post-processed + SDIN. All SDOUT configurations that apply to Vpredict also apply + to SDIN-to-SDOUT transmission. + +Real-Time Load Diagnostics +=========================== + +These controls require Normal DSP mode at 48 kHz or 96 kHz. They are +unavailable at 192 kHz and in FFLP and LLP modes. + + +CHx RTLDG Switch +---------------- + +:Description: Enables real-time impedance monitoring during playback + (x = 1, 2, 3, 4). +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x37 bit [3] (CH1), bit [2] (CH2), bit [1] (CH3), bit [0] (CH4) + +RTLDG Clip Mask Switch +---------------------- + +:Description: Suppresses impedance updates during clipping events. +:Type: Boolean Switch +:Default: Enabled (1) +:Register: 0x37 bit [4] + +ISENSE Calibration Switch +-------------------------- + +:Description: Enables current sense calibration for accurate impedance + measurements. +:Type: Boolean Switch +:Default: Disabled (0) +:Register: 0x5B bit [3] + +RTLDG Open Load Threshold +-------------------------- + +:Description: DSP coefficient for open load fault detection threshold. +:Type: DSP coefficient (extended control) +:Register: DSP Book 0x8C, page 0x22, 0x98 + +RTLDG Short Load Threshold +--------------------------- + +:Description: DSP coefficient for shorted load fault detection threshold. +:Type: DSP coefficient (extended control) +:Register: DSP Book 0x8C, page 0x22, 0x9C + +CHx RTLDG Impedance +------------------- + +:Description: Real-time load impedance per channel (x = 1, 2, 3, 4). +:Type: Float (read-only, displayed in ohms) +:Register: 0xD1–0xD2 (CH1), 0xD3–0xD4 (CH2), 0xD5–0xD6 (CH3), 0xD7–0xD8 (CH4) +:Note: Valid only during PLAY state with RTLDG enabled at 48 or + 96 kHz. Holds stale data in SLEEP, MUTE, or Hi-Z states. + +Fault Monitoring +================ + +The driver monitors faults via IRQ or periodic polling (fallback when +no ``interrupts`` DT property is present). Detected faults are logged +and cleared so affected channels can recover. + +Kernel log messages use the format:: + + tas675x : Latched: 0x + +Critical faults are logged at ``CRIT`` level; warnings at ``WARN``. + +The following fault registers are monitored: + +Critical Faults +--------------- + +These faults place affected channels into the FAULT state. The driver +issues fault clear (register 0x01 bit 3) to allow recovery. + +Overtemperature Shutdown (0x87) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [4] Global OTSD + [3:0] CH1-CH4 OTSD respectively + ======== ========================================== + +Fires when die temperature exceeds the OTSD threshold. If auto-recovery +is enabled (``OTSD Auto Recovery Switch``), channels return to their +previous state after cooling. Otherwise fault clear is required. + +Overcurrent / DC Fault (0x8E) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [7:4] Overcurrent Shutdown, CH1-CH4 respectively + [3:0] DC Fault, CH1-CH4 respectively + ======== ========================================== + +Overcurrent shutdown occurs when output current reaches the shutdown +threshold (e.g. output short to GND). DC fault fires when DC offset +exceeds the DCFAULT threshold. + +Real-Time Load Diagnostic Fault (0x8B) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [7:4] Shorted Load faults, CH1-CH4 respectively + [3:0] Open Load faults, CH1-CH4 respectively + ======== ========================================== + +Reported during playback when RTLDG detects impedance outside the +configured open/short thresholds. Requires RTLDG and current sense to +be enabled, and a sampling rate of 48 kHz or 96 kHz. + +CBC Fault/Warning (0x8D) +~~~~~~~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [7:4] Load current warning, CH1-CH4 respectively + [3:0] Load current fault, CH1-CH4 respectively + ======== ========================================== + +Cycle-by-cycle current limiting events. A warning fires when the +current limit is active for at least 25% of a 21.3 ms window. A fault +fires if the warning persists for 170.4 ms continuously. + +Warnings +-------- + +These conditions are logged but do not place channels into FAULT state. +Corresponding register bits are cleared when read. Nonetheless, the driver +still clears all events as warnings also latch the (mapped) FAULT pin. + +Power Fault (0x86) +~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [7] DVDD Power-On-Reset + [4] DVDD Undervoltage + [3] PVDD Overvoltage + [2] VBAT Overvoltage + [1] PVDD Undervoltage + [0] VBAT Undervoltage + ======== ========================================== + +Supply-related events. DVDD POR at bit 7 is expected after every +power-up and can be ignored. + +CP / OUTM Soft Short Fault (0x7D) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [5:2] OUTM soft short, CH4-CH1 respectively + [1] Charge Pump UVLO (latched) + [0] Charge Pump UVLO (unlatched/live status) + ======== ========================================== + +Per-channel out_minus soft short faults and charge pump undervoltage lockout. + +Clock Fault (0x8A) +~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [0] Clock error + ======== ========================================== + +Fires on clock halt or unsupported SCLK/FSYNC ratio. Only logged when +a stream is active (suppressed during idle to avoid noise from normal +stream stop/start transitions). See `Clock Fault Behaviour`_ below. + +Overtemperature Warning (0x88) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [4] Global OTW + [3:0] CH1-CH4 OTW respectively + ======== ========================================== + +Fires when temperature crosses the OTW threshold. The device continues +to operate. Only logged on change to avoid log spam. + +Clip Warning (0x89) +~~~~~~~~~~~~~~~~~~~ + + ======== ========================================== + Bits Description + ======== ========================================== + [3:0] CH1-CH4 clip detected respectively + ======== ========================================== + +Fires when the audio signal magnitude exceeds the clip detection +threshold. Requires Clip Detect to be enabled. Only logged when a +stream is active. + +Driver Known Limitations +======================== + +Clock Fault Behaviour +--------------------- + +On Stream Stop +~~~~~~~~~~~~~~ + +Every time a playback stream stops the FAULT pin briefly asserts. The +ASoC PCM trigger stop sequence calls DAIs in reverse order, so the CPU +DAI stops SCLK before the codec can transition to sleep. The device +detects the clock halt and latches ``CLK_FAULT_LATCHED``, which asserts +the FAULT pin. The driver clears the latch in the ``mute_stream`` +callback that follows, so the FAULT pin flicker lasts only a few +milliseconds. Audio output is not affected and no kernel log message +is produced. + +On Rapid Rate Switching +~~~~~~~~~~~~~~~~~~~~~~~ + +When streams are started in rapid succession, an intermittent +``Clock Fault Latched: 0x01`` message may appear in the kernel log. +A (conservative) ~0.5 second gap between sessions eliminates this. + +References +========== + +- TAS675x Technical Reference Manual: SLOU589A +- Device Tree Bindings: Documentation/devicetree/bindings/sound/ti,tas67524.yaml +- ALSA Control Name Conventions: Documentation/sound/designs/control-names.rst diff --git a/Documentation/sound/soc/index.rst b/Documentation/sound/soc/index.rst index 8bed8f8f48da..22878d73f7a5 100644 --- a/Documentation/sound/soc/index.rst +++ b/Documentation/sound/soc/index.rst @@ -2,7 +2,7 @@ ALSA SoC Layer ============== -The documentation is spilt into the following sections:- +The documentation is split into the following sections:- .. toctree:: :maxdepth: 2 diff --git a/Documentation/sound/soc/platform.rst b/Documentation/sound/soc/platform.rst index bd21d0a4dd9b..53caba6ce4ce 100644 --- a/Documentation/sound/soc/platform.rst +++ b/Documentation/sound/soc/platform.rst @@ -75,4 +75,4 @@ Each SoC DSP driver usually supplies the following features :- 3. DMA IO to/from DSP buffers (if applicable) 4. Definition of DSP front end (FE) PCM devices. -Please see DPCM.txt for a description of item 4. +Please see dpcm.rst for a description of item 4. diff --git a/Documentation/sound/soc/usb.rst b/Documentation/sound/soc/usb.rst index 94c12f9d9dd1..9cb860547f22 100644 --- a/Documentation/sound/soc/usb.rst +++ b/Documentation/sound/soc/usb.rst @@ -103,7 +103,7 @@ Returns 0 on success, and -EOPNOTSUPP on failure. - ``usbdev``: the usb device that was discovered - ``sdev``: capabilities of the device -**snd_soc_usb_connect()** notifies the ASoC USB DCPM BE DAI link of a USB +**snd_soc_usb_connect()** notifies the ASoC USB DPCM BE DAI link of a USB audio device detection. This can be utilized in the BE DAI driver to keep track of available USB audio devices. This is intended to be called by the USB offload driver residing in USB SND. @@ -118,7 +118,7 @@ Returns 0 on success, negative error code on failure. - ``usbdev``: the usb device that was removed - ``sdev``: capabilities to free -**snd_soc_usb_disconnect()** notifies the ASoC USB DCPM BE DAI link of a USB +**snd_soc_usb_disconnect()** notifies the ASoC USB DPCM BE DAI link of a USB audio device removal. This is intended to be called by the USB offload driver that resides in USB SND. diff --git a/MAINTAINERS b/MAINTAINERS index 6958488d43c8..4017b5f721e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15060,6 +15060,15 @@ F: arch/loongarch/ F: drivers/*/*loongarch* F: drivers/cpufreq/loongson3_cpufreq.c +LOONGSON AUDIO (ASoC) DRIVERS +M: Binbin Zhou +L: linux-sound@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/sound/loongson,ls-audio-card.yaml +F: Documentation/devicetree/bindings/sound/loongson,ls2k1000-i2s.yaml +F: sound/soc/loongson/loongson_*.c +F: sound/soc/loongson/loongson_*.h + LOONGSON GPIO DRIVER M: Yinbo Zhu L: linux-gpio@vger.kernel.org @@ -25131,6 +25140,13 @@ F: include/sound/dmaengine_pcm.h F: sound/core/pcm_dmaengine.c F: sound/soc/soc-generic-dmaengine-pcm.c +SOUND - SOC LAYER / GPIO AUDIO AMPLIFIER +M: Herve Codina +L: linux-sound@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/sound/gpio-audio-amp.yaml +F: sound/soc/codecs/simple-amplifier.c + SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) M: Liam Girdwood M: Mark Brown @@ -26465,17 +26481,20 @@ TEXAS INSTRUMENTS AUDIO (ASoC/HDA) DRIVERS M: Shenghao Ding M: Kevin Lu M: Baojun Xu +M: Sen Wang L: linux-sound@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/sound/ti,tas2552.yaml F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml F: Documentation/devicetree/bindings/sound/ti,tas2770.yaml F: Documentation/devicetree/bindings/sound/ti,tas27xx.yaml +F: Documentation/devicetree/bindings/sound/ti,tas67524.yaml F: Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml F: Documentation/devicetree/bindings/sound/ti,pcm1681.yaml F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml F: Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml +F: Documentation/sound/codecs/tas675x* F: include/sound/tas2*.h F: include/sound/tlv320*.h F: sound/hda/codecs/side-codecs/tas2781_hda_i2c.c @@ -26489,6 +26508,7 @@ F: sound/soc/codecs/pcm3168a*.* F: sound/soc/codecs/pcm5102a.c F: sound/soc/codecs/pcm512x*.* F: sound/soc/codecs/tas2*.* +F: sound/soc/codecs/tas675x*.* F: sound/soc/codecs/tlv320*.* F: sound/soc/codecs/tpa6130a2.* diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index ff6361979038..c588eeea1485 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -58,8 +58,15 @@ static unsigned long ac97_reset_config[] = { GPIO95_AC97_nRESET, }; -void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio) +void pxa27x_configure_ac97reset(struct gpio_desc *gpiod, bool to_gpio) { + int reset_gpio; + + if (!gpiod) + return; + + reset_gpio = desc_to_gpio(gpiod); + /* * This helper function is used to work around a bug in the pxa27x's * ac97 controller during a warm reset. The configuration of the diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index c96312ac2be7..24213a0ea831 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -1132,6 +1132,7 @@ EXPORT_SYMBOL(release_firmware); /* Async support */ struct firmware_work { struct work_struct work; + struct list_head list; struct module *module; const char *name; struct device *device; @@ -1140,6 +1141,17 @@ struct firmware_work { u32 opt_flags; }; +static LIST_HEAD(firmware_work_list); +static DEFINE_SPINLOCK(firmware_work_lock); + +static void firmware_work_free(struct firmware_work *fw_work) +{ + put_device(fw_work->device); /* taken in request_firmware_nowait() */ + module_put(fw_work->module); + kfree_const(fw_work->name); + kfree(fw_work); +} + static void request_firmware_work_func(struct work_struct *work) { struct firmware_work *fw_work; @@ -1150,11 +1162,15 @@ static void request_firmware_work_func(struct work_struct *work) _request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0, 0, fw_work->opt_flags); fw_work->cont(fw, fw_work->context); - put_device(fw_work->device); /* taken in request_firmware_nowait() */ - module_put(fw_work->module); - kfree_const(fw_work->name); - kfree(fw_work); + spin_lock_irq(&firmware_work_lock); + if (!list_empty(&fw_work->list)) { + list_del_init(&fw_work->list); + spin_unlock_irq(&firmware_work_lock); + firmware_work_free(fw_work); + return; + } + spin_unlock_irq(&firmware_work_lock); } @@ -1164,6 +1180,7 @@ static int _request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context), bool nowarn) { struct firmware_work *fw_work; + unsigned long flags; fw_work = kzalloc_obj(struct firmware_work, gfp); if (!fw_work) @@ -1196,7 +1213,12 @@ static int _request_firmware_nowait( get_device(fw_work->device); INIT_WORK(&fw_work->work, request_firmware_work_func); + + spin_lock_irqsave(&firmware_work_lock, flags); + list_add_tail(&fw_work->list, &firmware_work_list); schedule_work(&fw_work->work); + spin_unlock_irqrestore(&firmware_work_lock, flags); + return 0; } @@ -1259,6 +1281,44 @@ int firmware_request_nowait_nowarn( } EXPORT_SYMBOL_GPL(firmware_request_nowait_nowarn); +/** + * request_firmware_nowait_cancel() - cancel an async firmware request + * @device: device for which the firmware is being loaded + * @context: context passed to request_firmware_nowait() + * @cont: callback passed to request_firmware_nowait() + * + * Cancel a pending request_firmware_nowait() request for @device, @context + * and @cont. If the associated work has already started, this function waits + * until the callback has returned. If the callback has already completed, this + * function does nothing. + * + * This function may sleep. + */ +void request_firmware_nowait_cancel(struct device *device, void *context, + void (*cont)(const struct firmware *fw, + void *context)) +{ + struct firmware_work *fw_work = NULL; + struct firmware_work *tmp; + + spin_lock_irq(&firmware_work_lock); + list_for_each_entry_reverse(tmp, &firmware_work_list, list) { + if (tmp->device == device && tmp->context == context && + tmp->cont == cont) { + fw_work = tmp; + list_del_init(&fw_work->list); + break; + } + } + spin_unlock_irq(&firmware_work_lock); + + if (!fw_work) + return; + cancel_work_sync(&fw_work->work); + firmware_work_free(fw_work); +} +EXPORT_SYMBOL_GPL(request_firmware_nowait_cancel); + #ifdef CONFIG_FW_CACHE static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index fe5316d93fef..b7bdf19ebb42 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -1372,6 +1372,34 @@ int sdw_slave_get_current_bank(struct sdw_slave *slave) } EXPORT_SYMBOL_GPL(sdw_slave_get_current_bank); +/** + * sdw_slave_wait_for_init - Wait for device initialisation + * @slave: Pointer to the SoundWire peripheral. + * @timeout_ms: Timeout in milliseconds. + * + * Wait for a peripheral device to enumerate and be initialised by the + * SoundWire core. + * + * Return: Zero on success, and a negative error code on failure. + */ +int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms) +{ + unsigned long time; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(timeout_ms)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete\n"); + sdw_show_ping_status(slave->bus, true); + return -ETIMEDOUT; + } + + slave->unattach_request = 0; + + return 0; +} +EXPORT_SYMBOL_GPL(sdw_slave_wait_for_init); + static int sdw_slave_set_frequency(struct sdw_slave *slave) { int scale_index; diff --git a/include/linux/firmware.h b/include/linux/firmware.h index aae1b85ffc10..0fa3b027f02f 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -110,6 +110,9 @@ int request_firmware_nowait( struct module *module, bool uevent, const char *name, struct device *device, gfp_t gfp, void *context, void (*cont)(const struct firmware *fw, void *context)); +void request_firmware_nowait_cancel(struct device *device, void *context, + void (*cont)(const struct firmware *fw, + void *context)); int request_firmware_direct(const struct firmware **fw, const char *name, struct device *device); int request_firmware_into_buf(const struct firmware **firmware_p, @@ -157,6 +160,13 @@ static inline int request_firmware_nowait( return -EINVAL; } +static inline void request_firmware_nowait_cancel(struct device *device, + void *context, + void (*cont)(const struct firmware *fw, + void *context)) +{ +} + static inline void release_firmware(const struct firmware *fw) { } diff --git a/include/linux/of.h b/include/linux/of.h index 959786f8f196..28153616e616 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1476,6 +1476,13 @@ static inline int of_property_read_s32(const struct device_node *np, return of_property_read_u32(np, propname, (u32*) out_value); } +static inline int of_property_read_s32_index(const struct device_node *np, + const char *propname, u32 index, + s32 *out_value) +{ + return of_property_read_u32_index(np, propname, index, (u32 *)out_value); +} + #define of_for_each_phandle(it, err, np, ln, cn, cc) \ for (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)), \ err = of_phandle_iterator_next(it); \ diff --git a/include/linux/platform_data/asoc-pxa.h b/include/linux/platform_data/asoc-pxa.h index 7b5b9e20fbf5..0d5eaf4b100c 100644 --- a/include/linux/platform_data/asoc-pxa.h +++ b/include/linux/platform_data/asoc-pxa.h @@ -6,27 +6,6 @@ #include #include -/* - * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95) - * a -1 value means no gpio will be used for reset - * @codec_pdata: AC97 codec platform_data - - * reset_gpio should only be specified for pxa27x CPUs where a silicon - * bug prevents correct operation of the reset line. If not specified, - * the default behaviour on these CPUs is to consider gpio 113 as the - * AC97 reset line, which is the default on most boards. - */ -typedef struct { - int (*startup)(struct snd_pcm_substream *, void *); - void (*shutdown)(struct snd_pcm_substream *, void *); - void (*suspend)(void *); - void (*resume)(void *); - void *priv; - int reset_gpio; - void *codec_pdata[AC97_BUS_MAX_DEVICES]; -} pxa2xx_audio_ops_t; - -extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops); -extern void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio); +extern void pxa27x_configure_ac97reset(struct gpio_desc *reset_gpio, bool to_gpio); #endif diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 6147eb1fb210..a46cbaec5949 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -1093,6 +1093,8 @@ int sdw_slave_get_current_bank(struct sdw_slave *sdev); int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base); +int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms); + /* messaging and data APIs */ int sdw_read(struct sdw_slave *slave, u32 addr); int sdw_write(struct sdw_slave *slave, u32 addr, u8 value); @@ -1136,6 +1138,12 @@ static inline int sdw_slave_get_current_bank(struct sdw_slave *sdev) return -EINVAL; } +static inline int sdw_slave_wait_for_init(struct sdw_slave *slave, int timeout_ms) +{ + WARN_ONCE(1, "SoundWire API is disabled"); + return -EINVAL; +} + /* messaging and data APIs */ static inline int sdw_read(struct sdw_slave *slave, u32 addr) { diff --git a/include/sound/ac97/codec.h b/include/sound/ac97/codec.h index 882b849b9255..69b404c354f5 100644 --- a/include/sound/ac97/codec.h +++ b/include/sound/ac97/codec.h @@ -108,6 +108,9 @@ static inline void ac97_set_drvdata(struct ac97_codec_device *adev, dev_set_drvdata(ac97_codec_dev2dev(adev), data); } -void *snd_ac97_codec_get_platdata(const struct ac97_codec_device *adev); +static inline void *snd_ac97_codec_get_platdata(const struct ac97_codec_device *adev) +{ + return NULL; +} #endif diff --git a/include/sound/ac97/controller.h b/include/sound/ac97/controller.h index 06b5afb7fa6b..d5895ea3922b 100644 --- a/include/sound/ac97/controller.h +++ b/include/sound/ac97/controller.h @@ -62,14 +62,13 @@ struct ac97_controller_ops { #if IS_ENABLED(CONFIG_AC97_BUS_NEW) struct ac97_controller *snd_ac97_controller_register( const struct ac97_controller_ops *ops, struct device *dev, - unsigned short slots_available, void **codecs_pdata); + unsigned short slots_available); void snd_ac97_controller_unregister(struct ac97_controller *ac97_ctrl); #else static inline struct ac97_controller * snd_ac97_controller_register(const struct ac97_controller_ops *ops, struct device *dev, - unsigned short slots_available, - void **codecs_pdata) + unsigned short slots_available) { return ERR_PTR(-ENODEV); } diff --git a/include/sound/acp7x_chip_offset_byte.h b/include/sound/acp7x_chip_offset_byte.h new file mode 100644 index 000000000000..772c3d38cb8d --- /dev/null +++ b/include/sound/acp7x_chip_offset_byte.h @@ -0,0 +1,2519 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 7.x Register Documentation + * + * Copyright 2026 Advanced Micro Devices, Inc. + */ + +#ifndef _acp_ip_7x_chip_OFFSET_BYTE_H +#define _acp_ip_7x_chip_OFFSET_BYTE_H + +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x000C00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x000C04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x000C08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x000C0C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x000C10 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x000C14 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x000C18 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x000C1C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x000C20 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x000C24 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x000C28 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x000C2C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x000C30 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x000C34 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x000C38 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x000C3C +#define ACPAXI2AXI_ATU_CTRL 0x000C40 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_9 0x000C44 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_9 0x000C48 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_10 0x000C4C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_10 0x000C50 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_11 0x000C54 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_11 0x000C58 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_12 0x000C5C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_12 0x000C60 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_13 0x000C64 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_13 0x000C68 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_14 0x000C6C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_14 0x000C70 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_15 0x000C74 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_15 0x000C78 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_16 0x000C7C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_16 0x000C80 + +#define ACP_SOFT_RESET 0x001000 +#define ACP_CONTROL 0x001004 +#define ACP_STATUS 0x001008 +#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x001010 +#define ACP_ZSC_DSP_CTRL 0x001014 +#define ACP_ZSC_STS 0x001018 +#define ACP_PGFSM_CONTROL 0x001024 +#define ACP_PGFSM_STATUS 0x001028 +#define ACP_CLKMUX_SEL 0x00102C +#define ACP_SW_48MHz_CLK_SEL 0x001030 +#define ACP_AUDIO_CLK_SEL 0x001038 +#define ACP_PDM_CORE_CLK_SEL 0x00103C + +#define ACP_PME_EN 0x001400 +#define ACP_DEVICE_STATE 0x001404 +#define SW_DEVICE_STATE 0x001430 +#define ACP_PIN_CONFIG 0x001440 +#define ACP_PAD_PULLUP_CTRL 0x001444 +#define ACP_PAD_PULLDOWN_CTRL 0x001448 +#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x00144C +#define ACP_PAD_SCHMEN_CTRL 0x001450 +#define ACP_SW_PAD_KEEPER_EN 0x001454 +#define ACP_SW_WAKE_EN 0x001458 +#define ACP_I2S_WAKE_EN 0x00145C +#define ACP_ACLK_AUDIOCLK_CTRL 0x001464 +#define ACP_PAD_DISABLE_OE_CTRL 0x001468 +#define ACP_SW0_PME_STS 0x001474 +#define ACP_SW1_PME_STS 0x001478 +#define ACP_SW2_PME_STS 0x00147C +#define ACP_SW3_PME_STS 0x001480 +#define ACP_I2S_PME_STS 0x001484 +#define ACP_TDM_LOOPBACK_EN 0x001488 + +#define ACP_FUTURE_REG_ACLK_0 0x0018E0 +#define ACP_FUTURE_REG_ACLK_1 0x0018E4 +#define ACP_FUTURE_REG_ACLK_2 0x0018E8 +#define ACP_FUTURE_REG_ACLK_3 0x0018EC +#define ACP_FUTURE_REG_ACLK_4 0x0018F0 +#define ACP_AXI2DAGB_SEM_0 0x0018F4 + +#define ACP_EXTERNAL_INTR_ENB 0x001A00 +#define ACP_EXTERNAL_INTR_CNTL 0x001A04 +#define ACP_EXTERNAL_INTR_CNTL1 0x001A08 +#define ACP_EXTERNAL_SW0_INTR_CNTL 0x001A0C +#define ACP_EXTERNAL_SW1_INTR_CNTL 0x001A10 +#define ACP_EXTERNAL_SW2_INTR_CNTL 0x001A14 +#define ACP_EXTERNAL_SW3_INTR_CNTL 0x001A18 +#define ACP_EXTERNAL_INTR_STAT 0x001A1C +#define ACP_EXTERNAL_INTR_STAT1 0x001A20 +#define ACP_EXTERNAL_SW0_INTR_STAT 0x001A24 +#define ACP_EXTERNAL_SW1_INTR_STAT 0x001A28 +#define ACP_EXTERNAL_SW2_INTR_STAT 0x001A2C +#define ACP_EXTERNAL_SW3_INTR_STAT 0x001A30 +#define ACP_ERROR_STATUS 0x001A88 +#define ACP_ERROR_INTR_CTRL1 0x001AA4 +#define ACP_P1_FUTURE_REG_ACLK_0 0x001AB4 +#define ACP_P1_FUTURE_REG_ACLK_1 0x001AB8 + +#define ACP_I2S_TDM0_RX_RINGBUFADDR 0x002000 +#define ACP_I2S_TDM0_RX_RINGBUFSIZE 0x002004 +#define ACP_I2S_TDM0_RX_LINKPOSITIONCNTR 0x002008 +#define ACP_I2S_TDM0_RX_FIFOADDR 0x00200C +#define ACP_I2S_TDM0_RX_FIFOSIZE 0x002010 +#define ACP_I2S_TDM0_RX_DMA_SIZE 0x002014 +#define ACP_I2S_TDM0_RX_LINEARPOSITIONCNTR_HIGH 0x002018 +#define ACP_I2S_TDM0_RX_LINEARPOSITIONCNTR_LOW 0x00201C +#define ACP_I2S_TDM0_RX_INTR_WATERMARK_SIZE 0x002020 +#define ACP_I2S_TDM0_TX_RINGBUFADDR 0x002024 +#define ACP_I2S_TDM0_TX_RINGBUFSIZE 0x002028 +#define ACP_I2S_TDM0_TX_LINKPOSITIONCNTR 0x00202C +#define ACP_I2S_TDM0_TX_FIFOADDR 0x002030 +#define ACP_I2S_TDM0_TX_FIFOSIZE 0x002034 +#define ACP_I2S_TDM0_TX_DMA_SIZE 0x002038 +#define ACP_I2S_TDM0_TX_LINEARPOSITIONCNTR_HIGH 0x00203C +#define ACP_I2S_TDM0_TX_LINEARPOSITIONCNTR_LOW 0x002040 +#define ACP_I2S_TDM0_TX_INTR_WATERMARK_SIZE 0x002044 +#define ACP_I2S_TDM0_POS_TRACK_TX_CTRL 0x002048 +#define ACP_I2S_TDM0_TX_DMA_POS 0x00204C +#define ACP_I2S_TDM0_POS_TRACK_I2S_RX_CTRL 0x002050 +#define ACP_I2S_TDM0_RX_DMA_POS 0x002054 +#define ACP_I2S_TDM0_ERROR_STATUS 0x002058 +#define ACP_I2S_TDM0_ERROR_MASK 0x00205C +#define ACP_I2S_TDM0_IER 0x002100 +#define ACP_I2S_TDM0_IRER 0x002104 +#define ACP_I2S_TDM0_RXFRMT 0x002108 +#define ACP_I2S_TDM0_ITER 0x00210C +#define ACP_I2S_TDM0_TXFRMT 0x002110 +#define ACP_I2S_TDM0_MSTRCLKGEN 0x002114 +#define ACP_I2S_TDM0_OUTPUT_SPLIT_EN 0x002118 +#define ACP_I2S_TDM0_WALLCLK_MISC 0x00211C +#define ACP_I2S_TDM0_WALL_CLK_COUNTER 0x002120 +#define ACP_I2S_TDM_REFCLKGEN 0x002124 +#define ACP_TDM_SYNCEN 0x002128 +#define ACP_TDM_LRCLK_START 0x00212C +#define ACP_I2S_TDM0_WALLCLK_INTR_CNTL 0x002130 + +#define ACP_I2S_TDM1_RX_RINGBUFADDR 0x002200 +#define ACP_I2S_TDM1_RX_RINGBUFSIZE 0x002204 +#define ACP_I2S_TDM1_RX_LINKPOSITIONCNTR 0x002208 +#define ACP_I2S_TDM1_RX_FIFOADDR 0x00220C +#define ACP_I2S_TDM1_RX_FIFOSIZE 0x002210 +#define ACP_I2S_TDM1_RX_DMA_SIZE 0x002214 +#define ACP_I2S_TDM1_RX_LINEARPOSITIONCNTR_HIGH 0x002218 +#define ACP_I2S_TDM1_RX_LINEARPOSITIONCNTR_LOW 0x00221C +#define ACP_I2S_TDM1_RX_INTR_WATERMARK_SIZE 0x002220 +#define ACP_I2S_TDM1_TX_RINGBUFADDR 0x002224 +#define ACP_I2S_TDM1_TX_RINGBUFSIZE 0x002228 +#define ACP_I2S_TDM1_TX_LINKPOSITIONCNTR 0x00222C +#define ACP_I2S_TDM1_TX_FIFOADDR 0x002230 +#define ACP_I2S_TDM1_TX_FIFOSIZE 0x002234 +#define ACP_I2S_TDM1_TX_DMA_SIZE 0x002238 +#define ACP_I2S_TDM1_TX_LINEARPOSITIONCNTR_HIGH 0x00223C +#define ACP_I2S_TDM1_TX_LINEARPOSITIONCNTR_LOW 0x002240 +#define ACP_I2S_TDM1_TX_INTR_WATERMARK_SIZE 0x002244 +#define ACP_I2S_TDM1_POS_TRACK_TX_CTRL 0x002248 +#define ACP_I2S_TDM1_TX_DMA_POS 0x00224C +#define ACP_I2S_TDM1_POS_TRACK_I2S_RX_CTRL 0x002250 +#define ACP_I2S_TDM1_RX_DMA_POS 0x002254 +#define ACP_I2S_TDM1_ERROR_STATUS 0x002258 +#define ACP_I2S_TDM1_ERROR_MASK 0x00225C +#define ACP_I2S_TDM1_IER 0x002300 +#define ACP_I2S_TDM1_IRER 0x002304 +#define ACP_I2S_TDM1_RXFRMT 0x002308 +#define ACP_I2S_TDM1_ITER 0x00230C +#define ACP_I2S_TDM1_TXFRMT 0x002310 +#define ACP_I2S_TDM1_MSTRCLKGEN 0x002314 +#define ACP_I2S_TDM1_OUTPUT_SPLIT_EN 0x002318 +#define ACP_I2S_TDM1_WALLCLK_MISC 0x00231C +#define ACP_I2S_TDM1_WALL_CLK_COUNTER 0x002320 +#define ACP_I2S_TDM1_WALLCLK_INTR_CNTL 0x002330 + +#define ACP_I2S_TDM2_RX_RINGBUFADDR 0x002400 +#define ACP_I2S_TDM2_RX_RINGBUFSIZE 0x002404 +#define ACP_I2S_TDM2_RX_LINKPOSITIONCNTR 0x002408 +#define ACP_I2S_TDM2_RX_FIFOADDR 0x00240C +#define ACP_I2S_TDM2_RX_FIFOSIZE 0x002410 +#define ACP_I2S_TDM2_RX_DMA_SIZE 0x002414 +#define ACP_I2S_TDM2_RX_LINEARPOSITIONCNTR_HIGH 0x002418 +#define ACP_I2S_TDM2_RX_LINEARPOSITIONCNTR_LOW 0x00241C +#define ACP_I2S_TDM2_RX_INTR_WATERMARK_SIZE 0x002420 +#define ACP_I2S_TDM2_TX_RINGBUFADDR 0x002424 +#define ACP_I2S_TDM2_TX_RINGBUFSIZE 0x002428 +#define ACP_I2S_TDM2_TX_LINKPOSITIONCNTR 0x00242C +#define ACP_I2S_TDM2_TX_FIFOADDR 0x002430 +#define ACP_I2S_TDM2_TX_FIFOSIZE 0x002434 +#define ACP_I2S_TDM2_TX_DMA_SIZE 0x002438 +#define ACP_I2S_TDM2_TX_LINEARPOSITIONCNTR_HIGH 0x00243C +#define ACP_I2S_TDM2_TX_LINEARPOSITIONCNTR_LOW 0x002440 +#define ACP_I2S_TDM2_TX_INTR_WATERMARK_SIZE 0x002444 +#define ACP_I2S_TDM2_POS_TRACK_TX_CTRL 0x002448 +#define ACP_I2S_TDM2_TX_DMA_POS 0x00244C +#define ACP_I2S_TDM2_POS_TRACK_I2S_RX_CTRL 0x002450 +#define ACP_I2S_TDM2_RX_DMA_POS 0x002454 +#define ACP_I2S_TDM2_ERROR_STATUS 0x002458 +#define ACP_I2S_TDM2_ERROR_MASK 0x00245C +#define ACP_I2S_TDM2_IER 0x002500 +#define ACP_I2S_TDM2_IRER 0x002504 +#define ACP_I2S_TDM2_RXFRMT 0x002508 +#define ACP_I2S_TDM2_ITER 0x00250C +#define ACP_I2S_TDM2_TXFRMT 0x002510 +#define ACP_I2S_TDM2_MSTRCLKGEN 0x002514 +#define ACP_I2S_TDM2_OUTPUT_SPLIT_EN 0x002518 +#define ACP_I2S_TDM2_WALLCLK_MISC 0x00251C +#define ACP_I2S_TDM2_WALL_CLK_COUNTER 0x002520 +#define ACP_I2S_TDM2_WALLCLK_INTR_CNTL 0x002530 + +#define ACP_SW_CTRL_COUNT 0x004D00 +#define ACP_SW_GSYNC_EN 0x004D04 +#define ACP_SW_GSYNC_EN_PRE_SELECT 0x004D08 +#define ACP_SW_GSYNC_DP_EN 0x004D0C + +#define ACP_SW0_GLOBAL_CAPABILITIES 0x004E00 +#define ACP_SW0_RX_DMA0_RINGBUFADDR 0x004E04 +#define ACP_SW0_RX_DMA0_RINGBUFSIZE 0x004E08 +#define ACP_SW0_RX_DMA0_FIFOADDR 0x004E0C +#define ACP_SW0_RX_DMA0_FIFOSIZE 0x004E10 +#define ACP_SW0_RX_DMA0_BURST_SIZE 0x004E14 +#define ACP_SW0_RX_DMA0_LINKPOSITIONCNTR 0x004E18 +#define ACP_SW0_RX_DMA0_LINEARPOSITIONCNTR_HIGH 0x004E1C +#define ACP_SW0_RX_DMA0_LINEARPOSITIONCNTR_LOW 0x004E20 +#define ACP_SW0_RX_DMA0_INTR_WATERMARK_SIZE 0x004E24 +#define ACP_SW0_RX_DMA1_RINGBUFADDR 0x004E28 +#define ACP_SW0_RX_DMA1_RINGBUFSIZE 0x004E2C +#define ACP_SW0_RX_DMA1_FIFOADDR 0x004E30 +#define ACP_SW0_RX_DMA1_FIFOSIZE 0x004E34 +#define ACP_SW0_RX_DMA1_BURST_SIZE 0x004E38 +#define ACP_SW0_RX_DMA1_LINKPOSITIONCNTR 0x004E3C +#define ACP_SW0_RX_DMA1_LINEARPOSITIONCNTR_HIGH 0x004E40 +#define ACP_SW0_RX_DMA1_LINEARPOSITIONCNTR_LOW 0x004E44 +#define ACP_SW0_RX_DMA1_INTR_WATERMARK_SIZE 0x004E48 +#define ACP_SW0_RX_DMA2_RINGBUFADDR 0x004E4C +#define ACP_SW0_RX_DMA2_RINGBUFSIZE 0x004E50 +#define ACP_SW0_RX_DMA2_FIFOADDR 0x004E54 +#define ACP_SW0_RX_DMA2_FIFOSIZE 0x004E58 +#define ACP_SW0_RX_DMA2_BURST_SIZE 0x004E5C +#define ACP_SW0_RX_DMA2_LINKPOSITIONCNTR 0x004E60 +#define ACP_SW0_RX_DMA2_LINEARPOSITIONCNTR_HIGH 0x004E64 +#define ACP_SW0_RX_DMA2_LINEARPOSITIONCNTR_LOW 0x004E68 +#define ACP_SW0_RX_DMA2_INTR_WATERMARK_SIZE 0x004E6C +#define ACP_SW0_RX_DMA3_RINGBUFADDR 0x004E70 +#define ACP_SW0_RX_DMA3_RINGBUFSIZE 0x004E74 +#define ACP_SW0_RX_DMA3_FIFOADDR 0x004E78 +#define ACP_SW0_RX_DMA3_FIFOSIZE 0x004E7C +#define ACP_SW0_RX_DMA3_BURST_SIZE 0x004E80 +#define ACP_SW0_RX_DMA3_LINKPOSITIONCNTR 0x004E84 +#define ACP_SW0_RX_DMA3_LINEARPOSITIONCNTR_HIGH 0x004E88 +#define ACP_SW0_RX_DMA3_LINEARPOSITIONCNTR_LOW 0x004E8C +#define ACP_SW0_RX_DMA3_INTR_WATERMARK_SIZE 0x004E90 +#define ACP_SW0_RX_DMA4_RINGBUFADDR 0x004E94 +#define ACP_SW0_RX_DMA4_RINGBUFSIZE 0x004E98 +#define ACP_SW0_RX_DMA4_FIFOADDR 0x004E9C +#define ACP_SW0_RX_DMA4_FIFOSIZE 0x004EA0 +#define ACP_SW0_RX_DMA4_BURST_SIZE 0x004EA4 +#define ACP_SW0_RX_DMA4_LINKPOSITIONCNTR 0x004EA8 +#define ACP_SW0_RX_DMA4_LINEARPOSITIONCNTR_HIGH 0x004EAC +#define ACP_SW0_RX_DMA4_LINEARPOSITIONCNTR_LOW 0x004EB0 +#define ACP_SW0_RX_DMA4_INTR_WATERMARK_SIZE 0x004EB4 +#define ACP_SW0_RX_DMA5_RINGBUFADDR 0x004EB8 +#define ACP_SW0_RX_DMA5_RINGBUFSIZE 0x004EBC +#define ACP_SW0_RX_DMA5_FIFOADDR 0x004EC0 +#define ACP_SW0_RX_DMA5_FIFOSIZE 0x004EC4 +#define ACP_SW0_RX_DMA5_BURST_SIZE 0x004EC8 +#define ACP_SW0_RX_DMA5_LINKPOSITIONCNTR 0x004ECC +#define ACP_SW0_RX_DMA5_LINEARPOSITIONCNTR_HIGH 0x004ED0 +#define ACP_SW0_RX_DMA5_LINEARPOSITIONCNTR_LOW 0x004ED4 +#define ACP_SW0_RX_DMA5_INTR_WATERMARK_SIZE 0x004ED8 +#define ACP_SW0_RX_DMA6_RINGBUFADDR 0x004EDC +#define ACP_SW0_RX_DMA6_RINGBUFSIZE 0x004EE0 +#define ACP_SW0_RX_DMA6_FIFOADDR 0x004EE4 +#define ACP_SW0_RX_DMA6_FIFOSIZE 0x004EE8 +#define ACP_SW0_RX_DMA6_BURST_SIZE 0x004EEC +#define ACP_SW0_RX_DMA6_LINKPOSITIONCNTR 0x004EF0 +#define ACP_SW0_RX_DMA6_LINEARPOSITIONCNTR_HIGH 0x004EF4 +#define ACP_SW0_RX_DMA6_LINEARPOSITIONCNTR_LOW 0x004EF8 +#define ACP_SW0_RX_DMA6_INTR_WATERMARK_SIZE 0x004EFC +#define ACP_SW0_RX_DMA7_RINGBUFADDR 0x004F00 +#define ACP_SW0_RX_DMA7_RINGBUFSIZE 0x004F04 +#define ACP_SW0_RX_DMA7_FIFOADDR 0x004F08 +#define ACP_SW0_RX_DMA7_FIFOSIZE 0x004F0C +#define ACP_SW0_RX_DMA7_BURST_SIZE 0x004F10 +#define ACP_SW0_RX_DMA7_LINKPOSITIONCNTR 0x004F14 +#define ACP_SW0_RX_DMA7_LINEARPOSITIONCNTR_HIGH 0x004F18 +#define ACP_SW0_RX_DMA7_LINEARPOSITIONCNTR_LOW 0x004F1C +#define ACP_SW0_RX_DMA7_INTR_WATERMARK_SIZE 0x004F20 +#define ACP_SW0_TX_DMA0_RINGBUFADDR 0x004F24 +#define ACP_SW0_TX_DMA0_RINGBUFSIZE 0x004F28 +#define ACP_SW0_TX_DMA0_FIFOADDR 0x004F2C +#define ACP_SW0_TX_DMA0_FIFOSIZE 0x004F30 +#define ACP_SW0_TX_DMA0_BURST_SIZE 0x004F34 +#define ACP_SW0_TX_DMA0_LINKPOSITIONCNTR 0x004F38 +#define ACP_SW0_TX_DMA0_LINEARPOSITIONCNTR_HIGH 0x004F3C +#define ACP_SW0_TX_DMA0_LINEARPOSITIONCNTR_LOW 0x004F40 +#define ACP_SW0_TX_DMA0_INTR_WATERMARK_SIZE 0x004F44 +#define ACP_SW0_TX_DMA1_RINGBUFADDR 0x004F48 +#define ACP_SW0_TX_DMA1_RINGBUFSIZE 0x004F4C +#define ACP_SW0_TX_DMA1_FIFOADDR 0x004F50 +#define ACP_SW0_TX_DMA1_FIFOSIZE 0x004F54 +#define ACP_SW0_TX_DMA1_BURST_SIZE 0x004F58 +#define ACP_SW0_TX_DMA1_LINKPOSITIONCNTR 0x004F5C +#define ACP_SW0_TX_DMA1_LINEARPOSITIONCNTR_HIGH 0x004F60 +#define ACP_SW0_TX_DMA1_LINEARPOSITIONCNTR_LOW 0x004F64 +#define ACP_SW0_TX_DMA1_INTR_WATERMARK_SIZE 0x004F68 +#define ACP_SW0_TX_DMA2_RINGBUFADDR 0x004F6C +#define ACP_SW0_TX_DMA2_RINGBUFSIZE 0x004F70 +#define ACP_SW0_TX_DMA2_FIFOADDR 0x004F74 +#define ACP_SW0_TX_DMA2_FIFOSIZE 0x004F78 +#define ACP_SW0_TX_DMA2_BURST_SIZE 0x004F7C +#define ACP_SW0_TX_DMA2_LINKPOSITIONCNTR 0x004F80 +#define ACP_SW0_TX_DMA2_LINEARPOSITIONCNTR_HIGH 0x004F84 +#define ACP_SW0_TX_DMA2_LINEARPOSITIONCNTR_LOW 0x004F88 +#define ACP_SW0_TX_DMA2_INTR_WATERMARK_SIZE 0x004F8C +#define ACP_SW0_TX_DMA3_RINGBUFADDR 0x004F90 +#define ACP_SW0_TX_DMA3_RINGBUFSIZE 0x004F94 +#define ACP_SW0_TX_DMA3_FIFOADDR 0x004F98 +#define ACP_SW0_TX_DMA3_FIFOSIZE 0x004F9C +#define ACP_SW0_TX_DMA3_BURST_SIZE 0x004FA0 +#define ACP_SW0_TX_DMA3_LINKPOSITIONCNTR 0x004FA4 +#define ACP_SW0_TX_DMA3_LINEARPOSITIONCNTR_HIGH 0x004FA8 +#define ACP_SW0_TX_DMA3_LINEARPOSITIONCNTR_LOW 0x004FAC +#define ACP_SW0_TX_DMA3_INTR_WATERMARK_SIZE 0x004FB0 +#define ACP_SW0_TX_DMA4_RINGBUFADDR 0x004FB4 +#define ACP_SW0_TX_DMA4_RINGBUFSIZE 0x004FB8 +#define ACP_SW0_TX_DMA4_FIFOADDR 0x004FBC +#define ACP_SW0_TX_DMA4_FIFOSIZE 0x004FC0 +#define ACP_SW0_TX_DMA4_BURST_SIZE 0x004FC4 +#define ACP_SW0_TX_DMA4_LINKPOSITIONCNTR 0x004FC8 +#define ACP_SW0_TX_DMA4_LINEARPOSITIONCNTR_HIGH 0x004FCC +#define ACP_SW0_TX_DMA4_LINEARPOSITIONCNTR_LOW 0x004FD0 +#define ACP_SW0_TX_DMA4_INTR_WATERMARK_SIZE 0x004FD4 +#define ACP_SW0_TX_DMA5_RINGBUFADDR 0x004FD8 +#define ACP_SW0_TX_DMA5_RINGBUFSIZE 0x004FDC +#define ACP_SW0_TX_DMA5_FIFOADDR 0x004FE0 +#define ACP_SW0_TX_DMA5_FIFOSIZE 0x004FE4 +#define ACP_SW0_TX_DMA5_BURST_SIZE 0x004FE8 +#define ACP_SW0_TX_DMA5_LINKPOSITIONCNTR 0x004FEC +#define ACP_SW0_TX_DMA5_LINEARPOSITIONCNTR_HIGH 0x004FF0 +#define ACP_SW0_TX_DMA5_LINEARPOSITIONCNTR_LOW 0x004FF4 +#define ACP_SW0_TX_DMA5_INTR_WATERMARK_SIZE 0x004FF8 +#define ACP_SW0_TX_DMA6_RINGBUFADDR 0x004FFC +#define ACP_SW0_TX_DMA6_RINGBUFSIZE 0x005000 +#define ACP_SW0_TX_DMA6_FIFOADDR 0x005004 +#define ACP_SW0_TX_DMA6_FIFOSIZE 0x005008 +#define ACP_SW0_TX_DMA6_BURST_SIZE 0x00500C +#define ACP_SW0_TX_DMA6_LINKPOSITIONCNTR 0x005010 +#define ACP_SW0_TX_DMA6_LINEARPOSITIONCNTR_HIGH 0x005014 +#define ACP_SW0_TX_DMA6_LINEARPOSITIONCNTR_LOW 0x005018 +#define ACP_SW0_TX_DMA6_INTR_WATERMARK_SIZE 0x00501C +#define ACP_SW0_TX_DMA7_RINGBUFADDR 0x005020 +#define ACP_SW0_TX_DMA7_RINGBUFSIZE 0x005024 +#define ACP_SW0_TX_DMA7_FIFOADDR 0x005028 +#define ACP_SW0_TX_DMA7_FIFOSIZE 0x00502C +#define ACP_SW0_TX_DMA7_BURST_SIZE 0x005030 +#define ACP_SW0_TX_DMA7_LINKPOSITIONCNTR 0x005034 +#define ACP_SW0_TX_DMA7_LINEARPOSITIONCNTR_HIGH 0x005038 +#define ACP_SW0_TX_DMA7_LINEARPOSITIONCNTR_LOW 0x00503C +#define ACP_SW0_TX_DMA7_INTR_WATERMARK_SIZE 0x005040 +#define ACP_SW0_RX_DMA0_POS_TRACK 0x005044 +#define ACP_SW0_RX_DMA0_POS 0x005048 +#define ACP_SW0_RX_DMA1_POS_TRACK 0x00504C +#define ACP_SW0_RX_DMA1_POS 0x005050 +#define ACP_SW0_RX_DMA2_POS_TRACK 0x005054 +#define ACP_SW0_RX_DMA2_POS 0x005058 +#define ACP_SW0_RX_DMA3_POS_TRACK 0x00505C +#define ACP_SW0_RX_DMA3_POS 0x005060 +#define ACP_SW0_RX_DMA4_POS_TRACK 0x005064 +#define ACP_SW0_RX_DMA4_POS 0x005068 +#define ACP_SW0_RX_DMA5_POS_TRACK 0x00506C +#define ACP_SW0_RX_DMA5_POS 0x005070 +#define ACP_SW0_RX_DMA6_POS_TRACK 0x005074 +#define ACP_SW0_RX_DMA6_POS 0x005078 +#define ACP_SW0_RX_DMA7_POS_TRACK 0x00507C +#define ACP_SW0_RX_DMA7_POS 0x005080 +#define ACP_SW0_TX_DMA0_POS_TRACK 0x005084 +#define ACP_SW0_TX_DMA0_POS 0x005088 +#define ACP_SW0_TX_DMA1_POS_TRACK 0x00508C +#define ACP_SW0_TX_DMA1_POS 0x005090 +#define ACP_SW0_TX_DMA2_POS_TRACK 0x005094 +#define ACP_SW0_TX_DMA2_POS 0x005098 +#define ACP_SW0_TX_DMA3_POS_TRACK 0x00509C +#define ACP_SW0_TX_DMA3_POS 0x0050A0 +#define ACP_SW0_TX_DMA4_POS_TRACK 0x0050A4 +#define ACP_SW0_TX_DMA4_POS 0x0050A8 +#define ACP_SW0_TX_DMA5_POS_TRACK 0x0050AC +#define ACP_SW0_TX_DMA5_POS 0x0050B0 +#define ACP_SW0_TX_DMA6_POS_TRACK 0x0050B4 +#define ACP_SW0_TX_DMA6_POS 0x0050B8 +#define ACP_SW0_TX_DMA7_POS_TRACK 0x0050BC +#define ACP_SW0_TX_DMA7_POS 0x0050C0 +#define ACP_SW0_FIFO_ERROR_REASON 0x0050C4 +#define ACP_SW0_FIFO_ERROR_INTR_MASK 0x0050C8 +#define ACP_SW0_ERROR_REASON1 0x0050CC +#define ACP_SW0_ERROR_INTR_MASK1 0x0050D0 +#define ACP_SW0_ERROR_REASON2 0x0050D4 +#define ACP_SW0_ERROR_INTR_MASK2 0x0050D8 + +#define ACP_SW0_CORB_BASE_ADDRESS 0x005100 +#define ACP_SW0_CORB_WRITE_POINTER 0x005104 +#define ACP_SW0_CORB_READ_POINTER 0x005108 +#define ACP_SW0_CORB_CONTROL 0x00510C +#define ACP_SW0_CORB_SIZE 0x005114 +#define ACP_SW0_RIRB_BASE_ADDRESS 0x005118 +#define ACP_SW0_RIRB_WRITE_POINTER 0x00511C +#define ACP_SW0_RIRB_RESPONSE_INTERRUPT_COUNT 0x005120 +#define ACP_SW0_RIRB_CONTROL 0x005124 +#define ACP_SW0_RIRB_SIZE 0x005128 +#define ACP_SW0_RIRB_FIFO_MIN_THDL 0x00512C +#define ACP_SW0_IMM_CMD_UPPER_WORD 0x005130 +#define ACP_SW0_IMM_CMD_LOWER_QWORD 0x005134 +#define ACP_SW0_IMM_RESP_UPPER_WORD 0x005138 +#define ACP_SW0_IMM_RESP_LOWER_QWORD 0x00513C +#define ACP_SW0_IMM_CMD_STS 0x005140 +#define ACP_SW0_BRA_BASE_ADDRESS 0x005144 +#define ACP_SW0_BRA_TRANSFER_SIZE 0x005148 +#define ACP_SW0_BRA_DMA_BUSY 0x00514C +#define ACP_SW0_BRA_RESP 0x005150 +#define ACP_SW0_BRA_RESP_FRAME_ADDR 0x005154 +#define ACP_SW0_BRA_CURRENT_TRANSFER_SIZE 0x005158 +#define ACP_SW0_STATE_CHANGE_STATUS_0TO7 0x00515C +#define ACP_SW0_STATE_CHANGE_STATUS_8TO11 0x005160 +#define ACP_SW0_STATE_CHANGE_STATUS_MASK_0TO7 0x005164 +#define ACP_SW0_STATE_CHANGE_STATUS_MASK_8TO11 0x005168 +#define ACP_SW0_CLK_FREQUENCY_CTRL_BANK0 0x00516C +#define ACP_SW0_CLK_FREQUENCY_CTRL_BANK1 0x005170 +#define ACP_SW0_ERROR_INTR_MASK 0x005174 +#define ACP_SW0_PHY_TEST_MODE_DATA_OFF 0x005178 +#define ACP_SW0_DATA_TO_PDM_EN 0x00517C + +#define ACP_SW0_EN 0x005200 +#define ACP_SW0_EN_STATUS 0x005204 +#define ACP_SW0_FRAMESIZE_BANK0 0x005208 +#define ACP_SW0_FRAMESIZE_BANK1 0x00520C +#define ACP_SW0_SSP_COUNTER 0x005210 +#define ACP_SW0_TX_STREAM0_EN 0x005214 +#define ACP_SW0_TX_STREAM1_EN 0x005218 +#define ACP_SW0_TX_STREAM2_EN 0x00521C +#define ACP_SW0_TX_STREAM3_EN 0x005220 +#define ACP_SW0_TX_STREAM4_EN 0x005224 +#define ACP_SW0_TX_STREAM5_EN 0x005228 +#define ACP_SW0_TX_STREAM6_EN 0x00522C +#define ACP_SW0_TX_STREAM7_EN 0x005230 +#define ACP_SW0_TX_STREAM0_EN_STATUS 0x005234 +#define ACP_SW0_TX_STREAM1_EN_STATUS 0x005238 +#define ACP_SW0_TX_STREAM2_EN_STATUS 0x00523C +#define ACP_SW0_TX_STREAM3_EN_STATUS 0x005240 +#define ACP_SW0_TX_STREAM4_EN_STATUS 0x005244 +#define ACP_SW0_TX_STREAM5_EN_STATUS 0x005248 +#define ACP_SW0_TX_STREAM6_EN_STATUS 0x00524C +#define ACP_SW0_TX_STREAM7_EN_STATUS 0x005250 +#define ACP_SW0_TX_DP0_FRAME_FORMAT 0x005254 +#define ACP_SW0_TX_DP1_FRAME_FORMAT 0x005258 +#define ACP_SW0_TX_DP2_FRAME_FORMAT 0x00525C +#define ACP_SW0_TX_DP3_FRAME_FORMAT 0x005260 +#define ACP_SW0_TX_DP4_FRAME_FORMAT 0x005264 +#define ACP_SW0_TX_DP5_FRAME_FORMAT 0x005268 +#define ACP_SW0_TX_DP6_FRAME_FORMAT 0x00526C +#define ACP_SW0_TX_DP7_FRAME_FORMAT 0x005270 +#define ACP_SW0_TX_DP0_0_SAMPLEINTERVAL_BANK0 0x005280 +#define ACP_SW0_TX_DP0_0_HCTRL_BANK0 0x005284 +#define ACP_SW0_TX_DP0_0_HCTRL_OFFSET_BANK0 0x005288 +#define ACP_SW0_TX_DP0_0_LANE_CTRL_BANK0 0x00528C +#define ACP_SW0_TX_DP0_0_CHANNEL_ENABLE_BANK0 0x005290 +#define ACP_SW0_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005294 +#define ACP_SW0_TX_DP0_0_SAMPLEINTERVAL_BANK1 0x005298 +#define ACP_SW0_TX_DP0_0_HCTRL_BANK1 0x00529C +#define ACP_SW0_TX_DP0_0_HCTRL_OFFSET_BANK1 0x0052A0 +#define ACP_SW0_TX_DP0_0_LANE_CTRL_BANK1 0x0052A4 +#define ACP_SW0_TX_DP0_0_CHANNEL_ENABLE_BANK1 0x0052A8 +#define ACP_SW0_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0052AC +#define ACP_SW0_TX_DP0_1_SAMPLEINTERVAL_BANK0 0x0052B0 +#define ACP_SW0_TX_DP0_1_HCTRL_BANK0 0x0052B4 +#define ACP_SW0_TX_DP0_1_HCTRL_OFFSET_BANK0 0x0052B8 +#define ACP_SW0_TX_DP0_1_LANE_CTRL_BANK0 0x0052BC +#define ACP_SW0_TX_DP0_1_CHANNEL_ENABLE_BANK0 0x0052C0 +#define ACP_SW0_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0052C4 +#define ACP_SW0_TX_DP0_1_SAMPLEINTERVAL_BANK1 0x0052C8 +#define ACP_SW0_TX_DP0_1_HCTRL_BANK1 0x0052CC +#define ACP_SW0_TX_DP0_1_HCTRL_OFFSET_BANK1 0x0052D0 +#define ACP_SW0_TX_DP0_1_LANE_CTRL_BANK1 0x0052D4 +#define ACP_SW0_TX_DP0_1_CHANNEL_ENABLE_BANK1 0x0052D8 +#define ACP_SW0_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0052DC +#define ACP_SW0_TX_DP0_2_SAMPLEINTERVAL_BANK0 0x0052E0 +#define ACP_SW0_TX_DP0_2_HCTRL_BANK0 0x0052E4 +#define ACP_SW0_TX_DP0_2_HCTRL_OFFSET_BANK0 0x0052E8 +#define ACP_SW0_TX_DP0_2_LANE_CTRL_BANK0 0x0052EC +#define ACP_SW0_TX_DP0_2_CHANNEL_ENABLE_BANK0 0x0052F0 +#define ACP_SW0_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0052F4 +#define ACP_SW0_TX_DP0_2_SAMPLEINTERVAL_BANK1 0x0052F8 +#define ACP_SW0_TX_DP0_2_HCTRL_BANK1 0x0052FC +#define ACP_SW0_TX_DP0_2_HCTRL_OFFSET_BANK1 0x005300 +#define ACP_SW0_TX_DP0_2_LANE_CTRL_BANK1 0x005304 +#define ACP_SW0_TX_DP0_2_CHANNEL_ENABLE_BANK1 0x005308 +#define ACP_SW0_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00530C +#define ACP_SW0_TX_DP0_3_SAMPLEINTERVAL_BANK0 0x005310 +#define ACP_SW0_TX_DP0_3_HCTRL_BANK0 0x005314 +#define ACP_SW0_TX_DP0_3_HCTRL_OFFSET_BANK0 0x005318 +#define ACP_SW0_TX_DP0_3_LANE_CTRL_BANK0 0x00531C +#define ACP_SW0_TX_DP0_3_CHANNEL_ENABLE_BANK0 0x005320 +#define ACP_SW0_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005324 +#define ACP_SW0_TX_DP0_3_SAMPLEINTERVAL_BANK1 0x005328 +#define ACP_SW0_TX_DP0_3_HCTRL_BANK1 0x00532C +#define ACP_SW0_TX_DP0_3_HCTRL_OFFSET_BANK1 0x005330 +#define ACP_SW0_TX_DP0_3_LANE_CTRL_BANK1 0x005334 +#define ACP_SW0_TX_DP0_3_CHANNEL_ENABLE_BANK1 0x005338 +#define ACP_SW0_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00533C +#define ACP_SW0_TX_DP1_SAMPLEINTERVAL_BANK0 0x005370 +#define ACP_SW0_TX_DP1_HCTRL_BANK0 0x005374 +#define ACP_SW0_TX_DP1_HCTRL_OFFSET_BANK0 0x005378 +#define ACP_SW0_TX_DP1_LANE_CTRL_BANK0 0x00537C +#define ACP_SW0_TX_DP1_CHANNEL_ENABLE_BANK0 0x005380 +#define ACP_SW0_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005384 +#define ACP_SW0_TX_DP1_SAMPLEINTERVAL_BANK1 0x005388 +#define ACP_SW0_TX_DP1_HCTRL_BANK1 0x00538C +#define ACP_SW0_TX_DP1_HCTRL_OFFSET_BANK1 0x005390 +#define ACP_SW0_TX_DP1_LANE_CTRL_BANK1 0x005394 +#define ACP_SW0_TX_DP1_CHANNEL_ENABLE_BANK1 0x005398 +#define ACP_SW0_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00539C +#define ACP_SW0_TX_DP2_SAMPLEINTERVAL_BANK0 0x0053A0 +#define ACP_SW0_TX_DP2_HCTRL_BANK0 0x0053A4 +#define ACP_SW0_TX_DP2_HCTRL_OFFSET_BANK0 0x0053A8 +#define ACP_SW0_TX_DP2_LANE_CTRL_BANK0 0x0053AC +#define ACP_SW0_TX_DP2_CHANNEL_ENABLE_BANK0 0x0053B0 +#define ACP_SW0_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0053B4 +#define ACP_SW0_TX_DP2_SAMPLEINTERVAL_BANK1 0x0053B8 +#define ACP_SW0_TX_DP2_HCTRL_BANK1 0x0053BC +#define ACP_SW0_TX_DP2_HCTRL_OFFSET_BANK1 0x0053C0 +#define ACP_SW0_TX_DP2_LANE_CTRL_BANK1 0x0053C4 +#define ACP_SW0_TX_DP2_CHANNEL_ENABLE_BANK1 0x0053C8 +#define ACP_SW0_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0053CC +#define ACP_SW0_TX_DP3_SAMPLEINTERVAL_BANK0 0x0053D0 +#define ACP_SW0_TX_DP3_HCTRL_BANK0 0x0053D4 +#define ACP_SW0_TX_DP3_HCTRL_OFFSET_BANK0 0x0053D8 +#define ACP_SW0_TX_DP3_LANE_CTRL_BANK0 0x0053DC +#define ACP_SW0_TX_DP3_CHANNEL_ENABLE_BANK0 0x0053E0 +#define ACP_SW0_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0053E4 +#define ACP_SW0_TX_DP3_SAMPLEINTERVAL_BANK1 0x0053E8 +#define ACP_SW0_TX_DP3_HCTRL_BANK1 0x0053EC +#define ACP_SW0_TX_DP3_HCTRL_OFFSET_BANK1 0x0053F0 +#define ACP_SW0_TX_DP3_LANE_CTRL_BANK1 0x0053F4 +#define ACP_SW0_TX_DP3_CHANNEL_ENABLE_BANK1 0x0053F8 +#define ACP_SW0_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0053FC +#define ACP_SW0_TX_DP4_SAMPLEINTERVAL_BANK0 0x005400 +#define ACP_SW0_TX_DP4_HCTRL_BANK0 0x005404 +#define ACP_SW0_TX_DP4_HCTRL_OFFSET_BANK0 0x005408 +#define ACP_SW0_TX_DP4_LANE_CTRL_BANK0 0x00540C +#define ACP_SW0_TX_DP4_CHANNEL_ENABLE_BANK0 0x005410 +#define ACP_SW0_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005414 +#define ACP_SW0_TX_DP4_SAMPLEINTERVAL_BANK1 0x005418 +#define ACP_SW0_TX_DP4_HCTRL_BANK1 0x00541C +#define ACP_SW0_TX_DP4_HCTRL_OFFSET_BANK1 0x005420 +#define ACP_SW0_TX_DP4_LANE_CTRL_BANK1 0x005424 +#define ACP_SW0_TX_DP4_CHANNEL_ENABLE_BANK1 0x005428 +#define ACP_SW0_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00542C +#define ACP_SW0_TX_DP5_SAMPLEINTERVAL_BANK0 0x005430 +#define ACP_SW0_TX_DP5_HCTRL_BANK0 0x005434 +#define ACP_SW0_TX_DP5_HCTRL_OFFSET_BANK0 0x005438 +#define ACP_SW0_TX_DP5_LANE_CTRL_BANK0 0x00543C +#define ACP_SW0_TX_DP5_CHANNEL_ENABLE_BANK0 0x005440 +#define ACP_SW0_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005444 +#define ACP_SW0_TX_DP5_SAMPLEINTERVAL_BANK1 0x005448 +#define ACP_SW0_TX_DP5_HCTRL_BANK1 0x00544C +#define ACP_SW0_TX_DP5_HCTRL_OFFSET_BANK1 0x005450 +#define ACP_SW0_TX_DP5_LANE_CTRL_BANK1 0x005454 +#define ACP_SW0_TX_DP5_CHANNEL_ENABLE_BANK1 0x005458 +#define ACP_SW0_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00545C +#define ACP_SW0_TX_DP6_SAMPLEINTERVAL_BANK0 0x005460 +#define ACP_SW0_TX_DP6_HCTRL_BANK0 0x005464 +#define ACP_SW0_TX_DP6_HCTRL_OFFSET_BANK0 0x005468 +#define ACP_SW0_TX_DP6_LANE_CTRL_BANK0 0x00546C +#define ACP_SW0_TX_DP6_CHANNEL_ENABLE_BANK0 0x005470 +#define ACP_SW0_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005474 +#define ACP_SW0_TX_DP6_SAMPLEINTERVAL_BANK1 0x005478 +#define ACP_SW0_TX_DP6_HCTRL_BANK1 0x00547C +#define ACP_SW0_TX_DP6_HCTRL_OFFSET_BANK1 0x005480 +#define ACP_SW0_TX_DP6_LANE_CTRL_BANK1 0x005484 +#define ACP_SW0_TX_DP6_CHANNEL_ENABLE_BANK1 0x005488 +#define ACP_SW0_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00548C +#define ACP_SW0_TX_DP7_SAMPLEINTERVAL_BANK0 0x005490 +#define ACP_SW0_TX_DP7_HCTRL_BANK0 0x005494 +#define ACP_SW0_TX_DP7_HCTRL_OFFSET_BANK0 0x005498 +#define ACP_SW0_TX_DP7_LANE_CTRL_BANK0 0x00549C +#define ACP_SW0_TX_DP7_CHANNEL_ENABLE_BANK0 0x0054A0 +#define ACP_SW0_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0054A4 +#define ACP_SW0_TX_DP7_SAMPLEINTERVAL_BANK1 0x0054A8 +#define ACP_SW0_TX_DP7_HCTRL_BANK1 0x0054AC +#define ACP_SW0_TX_DP7_HCTRL_OFFSET_BANK1 0x0054B0 +#define ACP_SW0_TX_DP7_LANE_CTRL_BANK1 0x0054B4 +#define ACP_SW0_TX_DP7_CHANNEL_ENABLE_BANK1 0x0054B8 +#define ACP_SW0_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0054BC +#define ACP_SW0_RX_STREAM0_EN 0x005514 +#define ACP_SW0_RX_STREAM1_EN 0x005518 +#define ACP_SW0_RX_STREAM2_EN 0x00551C +#define ACP_SW0_RX_STREAM3_EN 0x005520 +#define ACP_SW0_RX_STREAM4_EN 0x005524 +#define ACP_SW0_RX_STREAM5_EN 0x005528 +#define ACP_SW0_RX_STREAM6_EN 0x00552C +#define ACP_SW0_RX_STREAM7_EN 0x005530 +#define ACP_SW0_RX_STREAM0_EN_STATUS 0x005534 +#define ACP_SW0_RX_STREAM1_EN_STATUS 0x005538 +#define ACP_SW0_RX_STREAM2_EN_STATUS 0x00553C +#define ACP_SW0_RX_STREAM3_EN_STATUS 0x005540 +#define ACP_SW0_RX_STREAM4_EN_STATUS 0x005544 +#define ACP_SW0_RX_STREAM5_EN_STATUS 0x005548 +#define ACP_SW0_RX_STREAM6_EN_STATUS 0x00554C +#define ACP_SW0_RX_STREAM7_EN_STATUS 0x005550 +#define ACP_SW0_RX_DP0_FRAME_FORMAT 0x005554 +#define ACP_SW0_RX_DP1_FRAME_FORMAT 0x005558 +#define ACP_SW0_RX_DP2_FRAME_FORMAT 0x00555C +#define ACP_SW0_RX_DP3_FRAME_FORMAT 0x005560 +#define ACP_SW0_RX_DP4_FRAME_FORMAT 0x005564 +#define ACP_SW0_RX_DP5_FRAME_FORMAT 0x005568 +#define ACP_SW0_RX_DP6_FRAME_FORMAT 0x00556C +#define ACP_SW0_RX_DP7_FRAME_FORMAT 0x005570 +#define ACP_SW0_RX_DP0_0_SAMPLEINTERVAL_BANK0 0x005580 +#define ACP_SW0_RX_DP0_0_HCTRL_BANK0 0x005584 +#define ACP_SW0_RX_DP0_0_HCTRL_OFFSET_BANK0 0x005588 +#define ACP_SW0_RX_DP0_0_LANE_CTRL_BANK0 0x00558C +#define ACP_SW0_RX_DP0_0_CHANNEL_ENABLE_BANK0 0x005590 +#define ACP_SW0_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005594 +#define ACP_SW0_RX_DP0_0_SAMPLEINTERVAL_BANK1 0x005598 +#define ACP_SW0_RX_DP0_0_HCTRL_BANK1 0x00559C +#define ACP_SW0_RX_DP0_0_HCTRL_OFFSET_BANK1 0x0055A0 +#define ACP_SW0_RX_DP0_0_LANE_CTRL_BANK1 0x0055A4 +#define ACP_SW0_RX_DP0_0_CHANNEL_ENABLE_BANK1 0x0055A8 +#define ACP_SW0_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0055AC +#define ACP_SW0_RX_DP0_1_SAMPLEINTERVAL_BANK0 0x0055B0 +#define ACP_SW0_RX_DP0_1_HCTRL_BANK0 0x0055B4 +#define ACP_SW0_RX_DP0_1_HCTRL_OFFSET_BANK0 0x0055B8 +#define ACP_SW0_RX_DP0_1_LANE_CTRL_BANK0 0x0055BC +#define ACP_SW0_RX_DP0_1_CHANNEL_ENABLE_BANK0 0x0055C0 +#define ACP_SW0_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0055C4 +#define ACP_SW0_RX_DP0_1_SAMPLEINTERVAL_BANK1 0x0055C8 +#define ACP_SW0_RX_DP0_1_HCTRL_BANK1 0x0055CC +#define ACP_SW0_RX_DP0_1_HCTRL_OFFSET_BANK1 0x0055D0 +#define ACP_SW0_RX_DP0_1_LANE_CTRL_BANK1 0x0055D4 +#define ACP_SW0_RX_DP0_1_CHANNEL_ENABLE_BANK1 0x0055D8 +#define ACP_SW0_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0055DC +#define ACP_SW0_RX_DP0_2_SAMPLEINTERVAL_BANK0 0x0055E0 +#define ACP_SW0_RX_DP0_2_HCTRL_BANK0 0x0055E4 +#define ACP_SW0_RX_DP0_2_HCTRL_OFFSET_BANK0 0x0055E8 +#define ACP_SW0_RX_DP0_2_LANE_CTRL_BANK0 0x0055EC +#define ACP_SW0_RX_DP0_2_CHANNEL_ENABLE_BANK0 0x0055F0 +#define ACP_SW0_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0055F4 +#define ACP_SW0_RX_DP0_2_SAMPLEINTERVAL_BANK1 0x0055F8 +#define ACP_SW0_RX_DP0_2_HCTRL_BANK1 0x0055FC +#define ACP_SW0_RX_DP0_2_HCTRL_OFFSET_BANK1 0x005600 +#define ACP_SW0_RX_DP0_2_LANE_CTRL_BANK1 0x005604 +#define ACP_SW0_RX_DP0_2_CHANNEL_ENABLE_BANK1 0x005608 +#define ACP_SW0_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00560C +#define ACP_SW0_RX_DP0_3_SAMPLEINTERVAL_BANK0 0x005610 +#define ACP_SW0_RX_DP0_3_HCTRL_BANK0 0x005614 +#define ACP_SW0_RX_DP0_3_HCTRL_OFFSET_BANK0 0x005618 +#define ACP_SW0_RX_DP0_3_LANE_CTRL_BANK0 0x00561C +#define ACP_SW0_RX_DP0_3_CHANNEL_ENABLE_BANK0 0x005620 +#define ACP_SW0_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005624 +#define ACP_SW0_RX_DP0_3_SAMPLEINTERVAL_BANK1 0x005628 +#define ACP_SW0_RX_DP0_3_HCTRL_BANK1 0x00562C +#define ACP_SW0_RX_DP0_3_HCTRL_OFFSET_BANK1 0x005630 +#define ACP_SW0_RX_DP0_3_LANE_CTRL_BANK1 0x005634 +#define ACP_SW0_RX_DP0_3_CHANNEL_ENABLE_BANK1 0x005638 +#define ACP_SW0_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00563C +#define ACP_SW0_RX_DP1_SAMPLEINTERVAL_BANK0 0x005670 +#define ACP_SW0_RX_DP1_HCTRL_BANK0 0x005674 +#define ACP_SW0_RX_DP1_HCTRL_OFFSET_BANK0 0x005678 +#define ACP_SW0_RX_DP1_LANE_CTRL_BANK0 0x00567C +#define ACP_SW0_RX_DP1_CHANNEL_ENABLE_BANK0 0x005680 +#define ACP_SW0_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005684 +#define ACP_SW0_RX_DP1_SAMPLEINTERVAL_BANK1 0x005688 +#define ACP_SW0_RX_DP1_HCTRL_BANK1 0x00568C +#define ACP_SW0_RX_DP1_HCTRL_OFFSET_BANK1 0x005690 +#define ACP_SW0_RX_DP1_LANE_CTRL_BANK1 0x005694 +#define ACP_SW0_RX_DP1_CHANNEL_ENABLE_BANK1 0x005698 +#define ACP_SW0_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00569C +#define ACP_SW0_RX_DP2_SAMPLEINTERVAL_BANK0 0x0056A0 +#define ACP_SW0_RX_DP2_HCTRL_BANK0 0x0056A4 +#define ACP_SW0_RX_DP2_HCTRL_OFFSET_BANK0 0x0056A8 +#define ACP_SW0_RX_DP2_LANE_CTRL_BANK0 0x0056AC +#define ACP_SW0_RX_DP2_CHANNEL_ENABLE_BANK0 0x0056B0 +#define ACP_SW0_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0056B4 +#define ACP_SW0_RX_DP2_SAMPLEINTERVAL_BANK1 0x0056B8 +#define ACP_SW0_RX_DP2_HCTRL_BANK1 0x0056BC +#define ACP_SW0_RX_DP2_HCTRL_OFFSET_BANK1 0x0056C0 +#define ACP_SW0_RX_DP2_LANE_CTRL_BANK1 0x0056C4 +#define ACP_SW0_RX_DP2_CHANNEL_ENABLE_BANK1 0x0056C8 +#define ACP_SW0_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0056CC +#define ACP_SW0_RX_DP3_SAMPLEINTERVAL_BANK0 0x0056D0 +#define ACP_SW0_RX_DP3_HCTRL_BANK0 0x0056D4 +#define ACP_SW0_RX_DP3_HCTRL_OFFSET_BANK0 0x0056D8 +#define ACP_SW0_RX_DP3_LANE_CTRL_BANK0 0x0056DC +#define ACP_SW0_RX_DP3_CHANNEL_ENABLE_BANK0 0x0056E0 +#define ACP_SW0_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0056E4 +#define ACP_SW0_RX_DP3_SAMPLEINTERVAL_BANK1 0x0056E8 +#define ACP_SW0_RX_DP3_HCTRL_BANK1 0x0056EC +#define ACP_SW0_RX_DP3_HCTRL_OFFSET_BANK1 0x0056F0 +#define ACP_SW0_RX_DP3_LANE_CTRL_BANK1 0x0056F4 +#define ACP_SW0_RX_DP3_CHANNEL_ENABLE_BANK1 0x0056F8 +#define ACP_SW0_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0056FC +#define ACP_SW0_RX_DP4_SAMPLEINTERVAL_BANK0 0x005700 +#define ACP_SW0_RX_DP4_HCTRL_BANK0 0x005704 +#define ACP_SW0_RX_DP4_HCTRL_OFFSET_BANK0 0x005708 +#define ACP_SW0_RX_DP4_LANE_CTRL_BANK0 0x00570C +#define ACP_SW0_RX_DP4_CHANNEL_ENABLE_BANK0 0x005710 +#define ACP_SW0_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005714 +#define ACP_SW0_RX_DP4_SAMPLEINTERVAL_BANK1 0x005718 +#define ACP_SW0_RX_DP4_HCTRL_BANK1 0x00571C +#define ACP_SW0_RX_DP4_HCTRL_OFFSET_BANK1 0x005720 +#define ACP_SW0_RX_DP4_LANE_CTRL_BANK1 0x005724 +#define ACP_SW0_RX_DP4_CHANNEL_ENABLE_BANK1 0x005728 +#define ACP_SW0_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00572C +#define ACP_SW0_RX_DP5_SAMPLEINTERVAL_BANK0 0x005730 +#define ACP_SW0_RX_DP5_HCTRL_BANK0 0x005734 +#define ACP_SW0_RX_DP5_HCTRL_OFFSET_BANK0 0x005738 +#define ACP_SW0_RX_DP5_LANE_CTRL_BANK0 0x00573C +#define ACP_SW0_RX_DP5_CHANNEL_ENABLE_BANK0 0x005740 +#define ACP_SW0_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005744 +#define ACP_SW0_RX_DP5_SAMPLEINTERVAL_BANK1 0x005748 +#define ACP_SW0_RX_DP5_HCTRL_BANK1 0x00574C +#define ACP_SW0_RX_DP5_HCTRL_OFFSET_BANK1 0x005750 +#define ACP_SW0_RX_DP5_LANE_CTRL_BANK1 0x005754 +#define ACP_SW0_RX_DP5_CHANNEL_ENABLE_BANK1 0x005758 +#define ACP_SW0_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00575C +#define ACP_SW0_RX_DP6_SAMPLEINTERVAL_BANK0 0x005760 +#define ACP_SW0_RX_DP6_HCTRL_BANK0 0x005764 +#define ACP_SW0_RX_DP6_HCTRL_OFFSET_BANK0 0x005768 +#define ACP_SW0_RX_DP6_LANE_CTRL_BANK0 0x00576C +#define ACP_SW0_RX_DP6_CHANNEL_ENABLE_BANK0 0x005770 +#define ACP_SW0_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x005774 +#define ACP_SW0_RX_DP6_SAMPLEINTERVAL_BANK1 0x005778 +#define ACP_SW0_RX_DP6_HCTRL_BANK1 0x00577C +#define ACP_SW0_RX_DP6_HCTRL_OFFSET_BANK1 0x005780 +#define ACP_SW0_RX_DP6_LANE_CTRL_BANK1 0x005784 +#define ACP_SW0_RX_DP6_CHANNEL_ENABLE_BANK1 0x005788 +#define ACP_SW0_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00578C +#define ACP_SW0_RX_DP7_SAMPLEINTERVAL_BANK0 0x005790 +#define ACP_SW0_RX_DP7_HCTRL_BANK0 0x005794 +#define ACP_SW0_RX_DP7_HCTRL_OFFSET_BANK0 0x005798 +#define ACP_SW0_RX_DP7_LANE_CTRL_BANK0 0x00579C +#define ACP_SW0_RX_DP7_CHANNEL_ENABLE_BANK0 0x0057A0 +#define ACP_SW0_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0057A4 +#define ACP_SW0_RX_DP7_SAMPLEINTERVAL_BANK1 0x0057A8 +#define ACP_SW0_RX_DP7_HCTRL_BANK1 0x0057AC +#define ACP_SW0_RX_DP7_HCTRL_OFFSET_BANK1 0x0057B0 +#define ACP_SW0_RX_DP7_LANE_CTRL_BANK1 0x0057B4 +#define ACP_SW0_RX_DP7_CHANNEL_ENABLE_BANK1 0x0057B8 +#define ACP_SW0_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0057BC +#define ACP_SW0_BPT_PORT_EN 0x0057C0 +#define ACP_SW0_BPT_PORT_EN_STATUS 0x0057C4 +#define ACP_SW0_BPT_PORT_FRAME_FORMAT 0x0057C8 +#define ACP_SW0_BPT_PORT_SAMPLEINTERVAL_BANK0 0x0057CC +#define ACP_SW0_BPT_PORT_HCTRL_BANK0 0x0057D0 +#define ACP_SW0_BPT_PORT_OFFSET_BANK0 0x0057D4 +#define ACP_SW0_BPT_PORT_LANE_SELECT_BANK0 0x0057D8 +#define ACP_SW0_BPT_PORT_CHANNEL_ENABLE_BANK0 0x0057DC +#define ACP_SW0_BPT_PORT_SAMPLEINTERVAL_BANK1 0x0057E0 +#define ACP_SW0_BPT_PORT_HCTRL_BANK1 0x0057E4 +#define ACP_SW0_BPT_PORT_OFFSET_BANK1 0x0057E8 +#define ACP_SW0_BPT_PORT_LANE_SELECT_BANK1 0x0057EC +#define ACP_SW0_BPT_PORT_CHANNEL_ENABLE_BANK1 0x0057F0 +#define ACP_SW0_BPT_PORT_FIRST_BYTE_ADDR 0x0057F4 +#define ACP_SW0_CLK_RESUME_CTRL 0x0057F8 +#define ACP_SW0_CLK_RESUME_DELAY_CNTR 0x0057FC +#define ACP_SW0_BUS_RESET_CTRL 0x005800 +#define ACP_SW0_PRBS_ERR_STATUS 0x005804 +#define ACP_SW0_WALLCLK_MISC 0x005808 +#define ACP_SW0_WALL_CLK_COUNTER 0x00580C +#define ACP_SW0_PING_STATUS_REGISTER_LOW 0x005810 +#define ACP_SW0_PING_STATUS_REGISTER_HIGH 0x005814 +#define ACP_SW0_PING_STATUS_CURRENT_BANK_SEL 0x005818 +#define ACP_SW0_TZD_CHANGE 0x00581C +#define ACP_SW0_WALLCLK_INTR_CNTL 0x005820 + +#define ACP_SW1_GLOBAL_CAPABILITIES 0x006E00 +#define ACP_SW1_RX_DMA0_RINGBUFADDR 0x006E04 +#define ACP_SW1_RX_DMA0_RINGBUFSIZE 0x006E08 +#define ACP_SW1_RX_DMA0_FIFOADDR 0x006E0C +#define ACP_SW1_RX_DMA0_FIFOSIZE 0x006E10 +#define ACP_SW1_RX_DMA0_BURST_SIZE 0x006E14 +#define ACP_SW1_RX_DMA0_LINKPOSITIONCNTR 0x006E18 +#define ACP_SW1_RX_DMA0_LINEARPOSITIONCNTR_HIGH 0x006E1C +#define ACP_SW1_RX_DMA0_LINEARPOSITIONCNTR_LOW 0x006E20 +#define ACP_SW1_RX_DMA0_INTR_WATERMARK_SIZE 0x006E24 +#define ACP_SW1_RX_DMA1_RINGBUFADDR 0x006E28 +#define ACP_SW1_RX_DMA1_RINGBUFSIZE 0x006E2C +#define ACP_SW1_RX_DMA1_FIFOADDR 0x006E30 +#define ACP_SW1_RX_DMA1_FIFOSIZE 0x006E34 +#define ACP_SW1_RX_DMA1_BURST_SIZE 0x006E38 +#define ACP_SW1_RX_DMA1_LINKPOSITIONCNTR 0x006E3C +#define ACP_SW1_RX_DMA1_LINEARPOSITIONCNTR_HIGH 0x006E40 +#define ACP_SW1_RX_DMA1_LINEARPOSITIONCNTR_LOW 0x006E44 +#define ACP_SW1_RX_DMA1_INTR_WATERMARK_SIZE 0x006E48 +#define ACP_SW1_RX_DMA2_RINGBUFADDR 0x006E4C +#define ACP_SW1_RX_DMA2_RINGBUFSIZE 0x006E50 +#define ACP_SW1_RX_DMA2_FIFOADDR 0x006E54 +#define ACP_SW1_RX_DMA2_FIFOSIZE 0x006E58 +#define ACP_SW1_RX_DMA2_BURST_SIZE 0x006E5C +#define ACP_SW1_RX_DMA2_LINKPOSITIONCNTR 0x006E60 +#define ACP_SW1_RX_DMA2_LINEARPOSITIONCNTR_HIGH 0x006E64 +#define ACP_SW1_RX_DMA2_LINEARPOSITIONCNTR_LOW 0x006E68 +#define ACP_SW1_RX_DMA2_INTR_WATERMARK_SIZE 0x006E6C +#define ACP_SW1_RX_DMA3_RINGBUFADDR 0x006E70 +#define ACP_SW1_RX_DMA3_RINGBUFSIZE 0x006E74 +#define ACP_SW1_RX_DMA3_FIFOADDR 0x006E78 +#define ACP_SW1_RX_DMA3_FIFOSIZE 0x006E7C +#define ACP_SW1_RX_DMA3_BURST_SIZE 0x006E80 +#define ACP_SW1_RX_DMA3_LINKPOSITIONCNTR 0x006E84 +#define ACP_SW1_RX_DMA3_LINEARPOSITIONCNTR_HIGH 0x006E88 +#define ACP_SW1_RX_DMA3_LINEARPOSITIONCNTR_LOW 0x006E8C +#define ACP_SW1_RX_DMA3_INTR_WATERMARK_SIZE 0x006E90 +#define ACP_SW1_RX_DMA4_RINGBUFADDR 0x006E94 +#define ACP_SW1_RX_DMA4_RINGBUFSIZE 0x006E98 +#define ACP_SW1_RX_DMA4_FIFOADDR 0x006E9C +#define ACP_SW1_RX_DMA4_FIFOSIZE 0x006EA0 +#define ACP_SW1_RX_DMA4_BURST_SIZE 0x006EA4 +#define ACP_SW1_RX_DMA4_LINKPOSITIONCNTR 0x006EA8 +#define ACP_SW1_RX_DMA4_LINEARPOSITIONCNTR_HIGH 0x006EAC +#define ACP_SW1_RX_DMA4_LINEARPOSITIONCNTR_LOW 0x006EB0 +#define ACP_SW1_RX_DMA4_INTR_WATERMARK_SIZE 0x006EB4 +#define ACP_SW1_RX_DMA5_RINGBUFADDR 0x006EB8 +#define ACP_SW1_RX_DMA5_RINGBUFSIZE 0x006EBC +#define ACP_SW1_RX_DMA5_FIFOADDR 0x006EC0 +#define ACP_SW1_RX_DMA5_FIFOSIZE 0x006EC4 +#define ACP_SW1_RX_DMA5_BURST_SIZE 0x006EC8 +#define ACP_SW1_RX_DMA5_LINKPOSITIONCNTR 0x006ECC +#define ACP_SW1_RX_DMA5_LINEARPOSITIONCNTR_HIGH 0x006ED0 +#define ACP_SW1_RX_DMA5_LINEARPOSITIONCNTR_LOW 0x006ED4 +#define ACP_SW1_RX_DMA5_INTR_WATERMARK_SIZE 0x006ED8 +#define ACP_SW1_RX_DMA6_RINGBUFADDR 0x006EDC +#define ACP_SW1_RX_DMA6_RINGBUFSIZE 0x006EE0 +#define ACP_SW1_RX_DMA6_FIFOADDR 0x006EE4 +#define ACP_SW1_RX_DMA6_FIFOSIZE 0x006EE8 +#define ACP_SW1_RX_DMA6_BURST_SIZE 0x006EEC +#define ACP_SW1_RX_DMA6_LINKPOSITIONCNTR 0x006EF0 +#define ACP_SW1_RX_DMA6_LINEARPOSITIONCNTR_HIGH 0x006EF4 +#define ACP_SW1_RX_DMA6_LINEARPOSITIONCNTR_LOW 0x006EF8 +#define ACP_SW1_RX_DMA6_INTR_WATERMARK_SIZE 0x006EFC +#define ACP_SW1_RX_DMA7_RINGBUFADDR 0x006F00 +#define ACP_SW1_RX_DMA7_RINGBUFSIZE 0x006F04 +#define ACP_SW1_RX_DMA7_FIFOADDR 0x006F08 +#define ACP_SW1_RX_DMA7_FIFOSIZE 0x006F0C +#define ACP_SW1_RX_DMA7_BURST_SIZE 0x006F10 +#define ACP_SW1_RX_DMA7_LINKPOSITIONCNTR 0x006F14 +#define ACP_SW1_RX_DMA7_LINEARPOSITIONCNTR_HIGH 0x006F18 +#define ACP_SW1_RX_DMA7_LINEARPOSITIONCNTR_LOW 0x006F1C +#define ACP_SW1_RX_DMA7_INTR_WATERMARK_SIZE 0x006F20 +#define ACP_SW1_TX_DMA0_RINGBUFADDR 0x006F24 +#define ACP_SW1_TX_DMA0_RINGBUFSIZE 0x006F28 +#define ACP_SW1_TX_DMA0_FIFOADDR 0x006F2C +#define ACP_SW1_TX_DMA0_FIFOSIZE 0x006F30 +#define ACP_SW1_TX_DMA0_BURST_SIZE 0x006F34 +#define ACP_SW1_TX_DMA0_LINKPOSITIONCNTR 0x006F38 +#define ACP_SW1_TX_DMA0_LINEARPOSITIONCNTR_HIGH 0x006F3C +#define ACP_SW1_TX_DMA0_LINEARPOSITIONCNTR_LOW 0x006F40 +#define ACP_SW1_TX_DMA0_INTR_WATERMARK_SIZE 0x006F44 +#define ACP_SW1_TX_DMA1_RINGBUFADDR 0x006F48 +#define ACP_SW1_TX_DMA1_RINGBUFSIZE 0x006F4C +#define ACP_SW1_TX_DMA1_FIFOADDR 0x006F50 +#define ACP_SW1_TX_DMA1_FIFOSIZE 0x006F54 +#define ACP_SW1_TX_DMA1_BURST_SIZE 0x006F58 +#define ACP_SW1_TX_DMA1_LINKPOSITIONCNTR 0x006F5C +#define ACP_SW1_TX_DMA1_LINEARPOSITIONCNTR_HIGH 0x006F60 +#define ACP_SW1_TX_DMA1_LINEARPOSITIONCNTR_LOW 0x006F64 +#define ACP_SW1_TX_DMA1_INTR_WATERMARK_SIZE 0x006F68 +#define ACP_SW1_TX_DMA2_RINGBUFADDR 0x006F6C +#define ACP_SW1_TX_DMA2_RINGBUFSIZE 0x006F70 +#define ACP_SW1_TX_DMA2_FIFOADDR 0x006F74 +#define ACP_SW1_TX_DMA2_FIFOSIZE 0x006F78 +#define ACP_SW1_TX_DMA2_BURST_SIZE 0x006F7C +#define ACP_SW1_TX_DMA2_LINKPOSITIONCNTR 0x006F80 +#define ACP_SW1_TX_DMA2_LINEARPOSITIONCNTR_HIGH 0x006F84 +#define ACP_SW1_TX_DMA2_LINEARPOSITIONCNTR_LOW 0x006F88 +#define ACP_SW1_TX_DMA2_INTR_WATERMARK_SIZE 0x006F8C +#define ACP_SW1_TX_DMA3_RINGBUFADDR 0x006F90 +#define ACP_SW1_TX_DMA3_RINGBUFSIZE 0x006F94 +#define ACP_SW1_TX_DMA3_FIFOADDR 0x006F98 +#define ACP_SW1_TX_DMA3_FIFOSIZE 0x006F9C +#define ACP_SW1_TX_DMA3_BURST_SIZE 0x006FA0 +#define ACP_SW1_TX_DMA3_LINKPOSITIONCNTR 0x006FA4 +#define ACP_SW1_TX_DMA3_LINEARPOSITIONCNTR_HIGH 0x006FA8 +#define ACP_SW1_TX_DMA3_LINEARPOSITIONCNTR_LOW 0x006FAC +#define ACP_SW1_TX_DMA3_INTR_WATERMARK_SIZE 0x006FB0 +#define ACP_SW1_TX_DMA4_RINGBUFADDR 0x006FB4 +#define ACP_SW1_TX_DMA4_RINGBUFSIZE 0x006FB8 +#define ACP_SW1_TX_DMA4_FIFOADDR 0x006FBC +#define ACP_SW1_TX_DMA4_FIFOSIZE 0x006FC0 +#define ACP_SW1_TX_DMA4_BURST_SIZE 0x006FC4 +#define ACP_SW1_TX_DMA4_LINKPOSITIONCNTR 0x006FC8 +#define ACP_SW1_TX_DMA4_LINEARPOSITIONCNTR_HIGH 0x006FCC +#define ACP_SW1_TX_DMA4_LINEARPOSITIONCNTR_LOW 0x006FD0 +#define ACP_SW1_TX_DMA4_INTR_WATERMARK_SIZE 0x006FD4 +#define ACP_SW1_TX_DMA5_RINGBUFADDR 0x006FD8 +#define ACP_SW1_TX_DMA5_RINGBUFSIZE 0x006FDC +#define ACP_SW1_TX_DMA5_FIFOADDR 0x006FE0 +#define ACP_SW1_TX_DMA5_FIFOSIZE 0x006FE4 +#define ACP_SW1_TX_DMA5_BURST_SIZE 0x006FE8 +#define ACP_SW1_TX_DMA5_LINKPOSITIONCNTR 0x006FEC +#define ACP_SW1_TX_DMA5_LINEARPOSITIONCNTR_HIGH 0x006FF0 +#define ACP_SW1_TX_DMA5_LINEARPOSITIONCNTR_LOW 0x006FF4 +#define ACP_SW1_TX_DMA5_INTR_WATERMARK_SIZE 0x006FF8 +#define ACP_SW1_TX_DMA6_RINGBUFADDR 0x006FFC +#define ACP_SW1_TX_DMA6_RINGBUFSIZE 0x007000 +#define ACP_SW1_TX_DMA6_FIFOADDR 0x007004 +#define ACP_SW1_TX_DMA6_FIFOSIZE 0x007008 +#define ACP_SW1_TX_DMA6_BURST_SIZE 0x00700C +#define ACP_SW1_TX_DMA6_LINKPOSITIONCNTR 0x007010 +#define ACP_SW1_TX_DMA6_LINEARPOSITIONCNTR_HIGH 0x007014 +#define ACP_SW1_TX_DMA6_LINEARPOSITIONCNTR_LOW 0x007018 +#define ACP_SW1_TX_DMA6_INTR_WATERMARK_SIZE 0x00701C +#define ACP_SW1_TX_DMA7_RINGBUFADDR 0x007020 +#define ACP_SW1_TX_DMA7_RINGBUFSIZE 0x007024 +#define ACP_SW1_TX_DMA7_FIFOADDR 0x007028 +#define ACP_SW1_TX_DMA7_FIFOSIZE 0x00702C +#define ACP_SW1_TX_DMA7_BURST_SIZE 0x007030 +#define ACP_SW1_TX_DMA7_LINKPOSITIONCNTR 0x007034 +#define ACP_SW1_TX_DMA7_LINEARPOSITIONCNTR_HIGH 0x007038 +#define ACP_SW1_TX_DMA7_LINEARPOSITIONCNTR_LOW 0x00703C +#define ACP_SW1_TX_DMA7_INTR_WATERMARK_SIZE 0x007040 +#define ACP_SW1_RX_DMA0_POS_TRACK 0x007044 +#define ACP_SW1_RX_DMA0_POS 0x007048 +#define ACP_SW1_RX_DMA1_POS_TRACK 0x00704C +#define ACP_SW1_RX_DMA1_POS 0x007050 +#define ACP_SW1_RX_DMA2_POS_TRACK 0x007054 +#define ACP_SW1_RX_DMA2_POS 0x007058 +#define ACP_SW1_RX_DMA3_POS_TRACK 0x00705C +#define ACP_SW1_RX_DMA3_POS 0x007060 +#define ACP_SW1_RX_DMA4_POS_TRACK 0x007064 +#define ACP_SW1_RX_DMA4_POS 0x007068 +#define ACP_SW1_RX_DMA5_POS_TRACK 0x00706C +#define ACP_SW1_RX_DMA5_POS 0x007070 +#define ACP_SW1_RX_DMA6_POS_TRACK 0x007074 +#define ACP_SW1_RX_DMA6_POS 0x007078 +#define ACP_SW1_RX_DMA7_POS_TRACK 0x00707C +#define ACP_SW1_RX_DMA7_POS 0x007080 +#define ACP_SW1_TX_DMA0_POS_TRACK 0x007084 +#define ACP_SW1_TX_DMA0_POS 0x007088 +#define ACP_SW1_TX_DMA1_POS_TRACK 0x00708C +#define ACP_SW1_TX_DMA1_POS 0x007090 +#define ACP_SW1_TX_DMA2_POS_TRACK 0x007094 +#define ACP_SW1_TX_DMA2_POS 0x007098 +#define ACP_SW1_TX_DMA3_POS_TRACK 0x00709C +#define ACP_SW1_TX_DMA3_POS 0x0070A0 +#define ACP_SW1_TX_DMA4_POS_TRACK 0x0070A4 +#define ACP_SW1_TX_DMA4_POS 0x0070A8 +#define ACP_SW1_TX_DMA5_POS_TRACK 0x0070AC +#define ACP_SW1_TX_DMA5_POS 0x0070B0 +#define ACP_SW1_TX_DMA6_POS_TRACK 0x0070B4 +#define ACP_SW1_TX_DMA6_POS 0x0070B8 +#define ACP_SW1_TX_DMA7_POS_TRACK 0x0070BC +#define ACP_SW1_TX_DMA7_POS 0x0070C0 +#define ACP_SW1_FIFO_ERROR_REASON 0x0070C4 +#define ACP_SW1_FIFO_ERROR_INTR_MASK 0x0070C8 +#define ACP_SW1_ERROR_REASON1 0x0070CC +#define ACP_SW1_ERROR_INTR_MASK1 0x0070D0 +#define ACP_SW1_ERROR_REASON2 0x0070D4 +#define ACP_SW1_ERROR_INTR_MASK2 0x0070D8 + +#define ACP_SW1_CORB_BASE_ADDRESS 0x007100 +#define ACP_SW1_CORB_WRITE_POINTER 0x007104 +#define ACP_SW1_CORB_READ_POINTER 0x007108 +#define ACP_SW1_CORB_CONTROL 0x00710C +#define ACP_SW1_CORB_SIZE 0x007114 +#define ACP_SW1_RIRB_BASE_ADDRESS 0x007118 +#define ACP_SW1_RIRB_WRITE_POINTER 0x00711C +#define ACP_SW1_RIRB_RESPONSE_INTERRUPT_COUNT 0x007120 +#define ACP_SW1_RIRB_CONTROL 0x007124 +#define ACP_SW1_RIRB_SIZE 0x007128 +#define ACP_SW1_RIRB_FIFO_MIN_THDL 0x00712C +#define ACP_SW1_IMM_CMD_UPPER_WORD 0x007130 +#define ACP_SW1_IMM_CMD_LOWER_QWORD 0x007134 +#define ACP_SW1_IMM_RESP_UPPER_WORD 0x007138 +#define ACP_SW1_IMM_RESP_LOWER_QWORD 0x00713C +#define ACP_SW1_IMM_CMD_STS 0x007140 +#define ACP_SW1_BRA_BASE_ADDRESS 0x007144 +#define ACP_SW1_BRA_TRANSFER_SIZE 0x007148 +#define ACP_SW1_BRA_DMA_BUSY 0x00714C +#define ACP_SW1_BRA_RESP 0x007150 +#define ACP_SW1_BRA_RESP_FRAME_ADDR 0x007154 +#define ACP_SW1_BRA_CURRENT_TRANSFER_SIZE 0x007158 +#define ACP_SW1_STATE_CHANGE_STATUS_0TO7 0x00715C +#define ACP_SW1_STATE_CHANGE_STATUS_8TO11 0x007160 +#define ACP_SW1_STATE_CHANGE_STATUS_MASK_0TO7 0x007164 +#define ACP_SW1_STATE_CHANGE_STATUS_MASK_8TO11 0x007168 +#define ACP_SW1_CLK_FREQUENCY_CTRL_BANK0 0x00716C +#define ACP_SW1_CLK_FREQUENCY_CTRL_BANK1 0x007170 +#define ACP_SW1_ERROR_INTR_MASK 0x007174 +#define ACP_SW1_PHY_TEST_MODE_DATA_OFF 0x007178 +#define ACP_SW1_DATA_TO_PDM_EN 0x00717C + +#define ACP_SW1_EN 0x007200 +#define ACP_SW1_EN_STATUS 0x007204 +#define ACP_SW1_FRAMESIZE_BANK0 0x007208 +#define ACP_SW1_FRAMESIZE_BANK1 0x00720C +#define ACP_SW1_SSP_COUNTER 0x007210 +#define ACP_SW1_TX_STREAM0_EN 0x007214 +#define ACP_SW1_TX_STREAM1_EN 0x007218 +#define ACP_SW1_TX_STREAM2_EN 0x00721C +#define ACP_SW1_TX_STREAM3_EN 0x007220 +#define ACP_SW1_TX_STREAM4_EN 0x007224 +#define ACP_SW1_TX_STREAM5_EN 0x007228 +#define ACP_SW1_TX_STREAM6_EN 0x00722C +#define ACP_SW1_TX_STREAM7_EN 0x007230 +#define ACP_SW1_TX_STREAM0_EN_STATUS 0x007234 +#define ACP_SW1_TX_STREAM1_EN_STATUS 0x007238 +#define ACP_SW1_TX_STREAM2_EN_STATUS 0x00723C +#define ACP_SW1_TX_STREAM3_EN_STATUS 0x007240 +#define ACP_SW1_TX_STREAM4_EN_STATUS 0x007244 +#define ACP_SW1_TX_STREAM5_EN_STATUS 0x007248 +#define ACP_SW1_TX_STREAM6_EN_STATUS 0x00724C +#define ACP_SW1_TX_STREAM7_EN_STATUS 0x007250 +#define ACP_SW1_TX_DP0_FRAME_FORMAT 0x007254 +#define ACP_SW1_TX_DP1_FRAME_FORMAT 0x007258 +#define ACP_SW1_TX_DP2_FRAME_FORMAT 0x00725C +#define ACP_SW1_TX_DP3_FRAME_FORMAT 0x007260 +#define ACP_SW1_TX_DP4_FRAME_FORMAT 0x007264 +#define ACP_SW1_TX_DP5_FRAME_FORMAT 0x007268 +#define ACP_SW1_TX_DP6_FRAME_FORMAT 0x00726C +#define ACP_SW1_TX_DP7_FRAME_FORMAT 0x007270 +#define ACP_SW1_TX_DP0_0_SAMPLEINTERVAL_BANK0 0x007280 +#define ACP_SW1_TX_DP0_0_HCTRL_BANK0 0x007284 +#define ACP_SW1_TX_DP0_0_HCTRL_OFFSET_BANK0 0x007288 +#define ACP_SW1_TX_DP0_0_LANE_CTRL_BANK0 0x00728C +#define ACP_SW1_TX_DP0_0_CHANNEL_ENABLE_BANK0 0x007290 +#define ACP_SW1_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007294 +#define ACP_SW1_TX_DP0_0_SAMPLEINTERVAL_BANK1 0x007298 +#define ACP_SW1_TX_DP0_0_HCTRL_BANK1 0x00729C +#define ACP_SW1_TX_DP0_0_HCTRL_OFFSET_BANK1 0x0072A0 +#define ACP_SW1_TX_DP0_0_LANE_CTRL_BANK1 0x0072A4 +#define ACP_SW1_TX_DP0_0_CHANNEL_ENABLE_BANK1 0x0072A8 +#define ACP_SW1_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0072AC +#define ACP_SW1_TX_DP0_1_SAMPLEINTERVAL_BANK0 0x0072B0 +#define ACP_SW1_TX_DP0_1_HCTRL_BANK0 0x0072B4 +#define ACP_SW1_TX_DP0_1_HCTRL_OFFSET_BANK0 0x0072B8 +#define ACP_SW1_TX_DP0_1_LANE_CTRL_BANK0 0x0072BC +#define ACP_SW1_TX_DP0_1_CHANNEL_ENABLE_BANK0 0x0072C0 +#define ACP_SW1_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0072C4 +#define ACP_SW1_TX_DP0_1_SAMPLEINTERVAL_BANK1 0x0072C8 +#define ACP_SW1_TX_DP0_1_HCTRL_BANK1 0x0072CC +#define ACP_SW1_TX_DP0_1_HCTRL_OFFSET_BANK1 0x0072D0 +#define ACP_SW1_TX_DP0_1_LANE_CTRL_BANK1 0x0072D4 +#define ACP_SW1_TX_DP0_1_CHANNEL_ENABLE_BANK1 0x0072D8 +#define ACP_SW1_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0072DC +#define ACP_SW1_TX_DP0_2_SAMPLEINTERVAL_BANK0 0x0072E0 +#define ACP_SW1_TX_DP0_2_HCTRL_BANK0 0x0072E4 +#define ACP_SW1_TX_DP0_2_HCTRL_OFFSET_BANK0 0x0072E8 +#define ACP_SW1_TX_DP0_2_LANE_CTRL_BANK0 0x0072EC +#define ACP_SW1_TX_DP0_2_CHANNEL_ENABLE_BANK0 0x0072F0 +#define ACP_SW1_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0072F4 +#define ACP_SW1_TX_DP0_2_SAMPLEINTERVAL_BANK1 0x0072F8 +#define ACP_SW1_TX_DP0_2_HCTRL_BANK1 0x0072FC +#define ACP_SW1_TX_DP0_2_HCTRL_OFFSET_BANK1 0x007300 +#define ACP_SW1_TX_DP0_2_LANE_CTRL_BANK1 0x007304 +#define ACP_SW1_TX_DP0_2_CHANNEL_ENABLE_BANK1 0x007308 +#define ACP_SW1_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00730C +#define ACP_SW1_TX_DP0_3_SAMPLEINTERVAL_BANK0 0x007310 +#define ACP_SW1_TX_DP0_3_HCTRL_BANK0 0x007314 +#define ACP_SW1_TX_DP0_3_HCTRL_OFFSET_BANK0 0x007318 +#define ACP_SW1_TX_DP0_3_LANE_CTRL_BANK0 0x00731C +#define ACP_SW1_TX_DP0_3_CHANNEL_ENABLE_BANK0 0x007320 +#define ACP_SW1_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007324 +#define ACP_SW1_TX_DP0_3_SAMPLEINTERVAL_BANK1 0x007328 +#define ACP_SW1_TX_DP0_3_HCTRL_BANK1 0x00732C +#define ACP_SW1_TX_DP0_3_HCTRL_OFFSET_BANK1 0x007330 +#define ACP_SW1_TX_DP0_3_LANE_CTRL_BANK1 0x007334 +#define ACP_SW1_TX_DP0_3_CHANNEL_ENABLE_BANK1 0x007338 +#define ACP_SW1_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00733C +#define ACP_SW1_TX_DP1_SAMPLEINTERVAL_BANK0 0x007370 +#define ACP_SW1_TX_DP1_HCTRL_BANK0 0x007374 +#define ACP_SW1_TX_DP1_HCTRL_OFFSET_BANK0 0x007378 +#define ACP_SW1_TX_DP1_LANE_CTRL_BANK0 0x00737C +#define ACP_SW1_TX_DP1_CHANNEL_ENABLE_BANK0 0x007380 +#define ACP_SW1_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007384 +#define ACP_SW1_TX_DP1_SAMPLEINTERVAL_BANK1 0x007388 +#define ACP_SW1_TX_DP1_HCTRL_BANK1 0x00738C +#define ACP_SW1_TX_DP1_HCTRL_OFFSET_BANK1 0x007390 +#define ACP_SW1_TX_DP1_LANE_CTRL_BANK1 0x007394 +#define ACP_SW1_TX_DP1_CHANNEL_ENABLE_BANK1 0x007398 +#define ACP_SW1_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00739C +#define ACP_SW1_TX_DP2_SAMPLEINTERVAL_BANK0 0x0073A0 +#define ACP_SW1_TX_DP2_HCTRL_BANK0 0x0073A4 +#define ACP_SW1_TX_DP2_HCTRL_OFFSET_BANK0 0x0073A8 +#define ACP_SW1_TX_DP2_LANE_CTRL_BANK0 0x0073AC +#define ACP_SW1_TX_DP2_CHANNEL_ENABLE_BANK0 0x0073B0 +#define ACP_SW1_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0073B4 +#define ACP_SW1_TX_DP2_SAMPLEINTERVAL_BANK1 0x0073B8 +#define ACP_SW1_TX_DP2_HCTRL_BANK1 0x0073BC +#define ACP_SW1_TX_DP2_HCTRL_OFFSET_BANK1 0x0073C0 +#define ACP_SW1_TX_DP2_LANE_CTRL_BANK1 0x0073C4 +#define ACP_SW1_TX_DP2_CHANNEL_ENABLE_BANK1 0x0073C8 +#define ACP_SW1_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0073CC +#define ACP_SW1_TX_DP3_SAMPLEINTERVAL_BANK0 0x0073D0 +#define ACP_SW1_TX_DP3_HCTRL_BANK0 0x0073D4 +#define ACP_SW1_TX_DP3_HCTRL_OFFSET_BANK0 0x0073D8 +#define ACP_SW1_TX_DP3_LANE_CTRL_BANK0 0x0073DC +#define ACP_SW1_TX_DP3_CHANNEL_ENABLE_BANK0 0x0073E0 +#define ACP_SW1_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0073E4 +#define ACP_SW1_TX_DP3_SAMPLEINTERVAL_BANK1 0x0073E8 +#define ACP_SW1_TX_DP3_HCTRL_BANK1 0x0073EC +#define ACP_SW1_TX_DP3_HCTRL_OFFSET_BANK1 0x0073F0 +#define ACP_SW1_TX_DP3_LANE_CTRL_BANK1 0x0073F4 +#define ACP_SW1_TX_DP3_CHANNEL_ENABLE_BANK1 0x0073F8 +#define ACP_SW1_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0073FC +#define ACP_SW1_TX_DP4_SAMPLEINTERVAL_BANK0 0x007400 +#define ACP_SW1_TX_DP4_HCTRL_BANK0 0x007404 +#define ACP_SW1_TX_DP4_HCTRL_OFFSET_BANK0 0x007408 +#define ACP_SW1_TX_DP4_LANE_CTRL_BANK0 0x00740C +#define ACP_SW1_TX_DP4_CHANNEL_ENABLE_BANK0 0x007410 +#define ACP_SW1_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007414 +#define ACP_SW1_TX_DP4_SAMPLEINTERVAL_BANK1 0x007418 +#define ACP_SW1_TX_DP4_HCTRL_BANK1 0x00741C +#define ACP_SW1_TX_DP4_HCTRL_OFFSET_BANK1 0x007420 +#define ACP_SW1_TX_DP4_LANE_CTRL_BANK1 0x007424 +#define ACP_SW1_TX_DP4_CHANNEL_ENABLE_BANK1 0x007428 +#define ACP_SW1_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00742C +#define ACP_SW1_TX_DP5_SAMPLEINTERVAL_BANK0 0x007430 +#define ACP_SW1_TX_DP5_HCTRL_BANK0 0x007434 +#define ACP_SW1_TX_DP5_HCTRL_OFFSET_BANK0 0x007438 +#define ACP_SW1_TX_DP5_LANE_CTRL_BANK0 0x00743C +#define ACP_SW1_TX_DP5_CHANNEL_ENABLE_BANK0 0x007440 +#define ACP_SW1_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007444 +#define ACP_SW1_TX_DP5_SAMPLEINTERVAL_BANK1 0x007448 +#define ACP_SW1_TX_DP5_HCTRL_BANK1 0x00744C +#define ACP_SW1_TX_DP5_HCTRL_OFFSET_BANK1 0x007450 +#define ACP_SW1_TX_DP5_LANE_CTRL_BANK1 0x007454 +#define ACP_SW1_TX_DP5_CHANNEL_ENABLE_BANK1 0x007458 +#define ACP_SW1_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00745C +#define ACP_SW1_TX_DP6_SAMPLEINTERVAL_BANK0 0x007460 +#define ACP_SW1_TX_DP6_HCTRL_BANK0 0x007464 +#define ACP_SW1_TX_DP6_HCTRL_OFFSET_BANK0 0x007468 +#define ACP_SW1_TX_DP6_LANE_CTRL_BANK0 0x00746C +#define ACP_SW1_TX_DP6_CHANNEL_ENABLE_BANK0 0x007470 +#define ACP_SW1_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007474 +#define ACP_SW1_TX_DP6_SAMPLEINTERVAL_BANK1 0x007478 +#define ACP_SW1_TX_DP6_HCTRL_BANK1 0x00747C +#define ACP_SW1_TX_DP6_HCTRL_OFFSET_BANK1 0x007480 +#define ACP_SW1_TX_DP6_LANE_CTRL_BANK1 0x007484 +#define ACP_SW1_TX_DP6_CHANNEL_ENABLE_BANK1 0x007488 +#define ACP_SW1_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00748C +#define ACP_SW1_TX_DP7_SAMPLEINTERVAL_BANK0 0x007490 +#define ACP_SW1_TX_DP7_HCTRL_BANK0 0x007494 +#define ACP_SW1_TX_DP7_HCTRL_OFFSET_BANK0 0x007498 +#define ACP_SW1_TX_DP7_LANE_CTRL_BANK0 0x00749C +#define ACP_SW1_TX_DP7_CHANNEL_ENABLE_BANK0 0x0074A0 +#define ACP_SW1_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0074A4 +#define ACP_SW1_TX_DP7_SAMPLEINTERVAL_BANK1 0x0074A8 +#define ACP_SW1_TX_DP7_HCTRL_BANK1 0x0074AC +#define ACP_SW1_TX_DP7_HCTRL_OFFSET_BANK1 0x0074B0 +#define ACP_SW1_TX_DP7_LANE_CTRL_BANK1 0x0074B4 +#define ACP_SW1_TX_DP7_CHANNEL_ENABLE_BANK1 0x0074B8 +#define ACP_SW1_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0074BC +#define ACP_SW1_RX_STREAM0_EN 0x007514 +#define ACP_SW1_RX_STREAM1_EN 0x007518 +#define ACP_SW1_RX_STREAM2_EN 0x00751C +#define ACP_SW1_RX_STREAM3_EN 0x007520 +#define ACP_SW1_RX_STREAM4_EN 0x007524 +#define ACP_SW1_RX_STREAM5_EN 0x007528 +#define ACP_SW1_RX_STREAM6_EN 0x00752C +#define ACP_SW1_RX_STREAM7_EN 0x007530 +#define ACP_SW1_RX_STREAM0_EN_STATUS 0x007534 +#define ACP_SW1_RX_STREAM1_EN_STATUS 0x007538 +#define ACP_SW1_RX_STREAM2_EN_STATUS 0x00753C +#define ACP_SW1_RX_STREAM3_EN_STATUS 0x007540 +#define ACP_SW1_RX_STREAM4_EN_STATUS 0x007544 +#define ACP_SW1_RX_STREAM5_EN_STATUS 0x007548 +#define ACP_SW1_RX_STREAM6_EN_STATUS 0x00754C +#define ACP_SW1_RX_STREAM7_EN_STATUS 0x007550 +#define ACP_SW1_RX_DP0_FRAME_FORMAT 0x007554 +#define ACP_SW1_RX_DP1_FRAME_FORMAT 0x007558 +#define ACP_SW1_RX_DP2_FRAME_FORMAT 0x00755C +#define ACP_SW1_RX_DP3_FRAME_FORMAT 0x007560 +#define ACP_SW1_RX_DP4_FRAME_FORMAT 0x007564 +#define ACP_SW1_RX_DP5_FRAME_FORMAT 0x007568 +#define ACP_SW1_RX_DP6_FRAME_FORMAT 0x00756C +#define ACP_SW1_RX_DP7_FRAME_FORMAT 0x007570 +#define ACP_SW1_RX_DP0_0_SAMPLEINTERVAL_BANK0 0x007580 +#define ACP_SW1_RX_DP0_0_HCTRL_BANK0 0x007584 +#define ACP_SW1_RX_DP0_0_HCTRL_OFFSET_BANK0 0x007588 +#define ACP_SW1_RX_DP0_0_LANE_CTRL_BANK0 0x00758C +#define ACP_SW1_RX_DP0_0_CHANNEL_ENABLE_BANK0 0x007590 +#define ACP_SW1_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007594 +#define ACP_SW1_RX_DP0_0_SAMPLEINTERVAL_BANK1 0x007598 +#define ACP_SW1_RX_DP0_0_HCTRL_BANK1 0x00759C +#define ACP_SW1_RX_DP0_0_HCTRL_OFFSET_BANK1 0x0075A0 +#define ACP_SW1_RX_DP0_0_LANE_CTRL_BANK1 0x0075A4 +#define ACP_SW1_RX_DP0_0_CHANNEL_ENABLE_BANK1 0x0075A8 +#define ACP_SW1_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0075AC +#define ACP_SW1_RX_DP0_1_SAMPLEINTERVAL_BANK0 0x0075B0 +#define ACP_SW1_RX_DP0_1_HCTRL_BANK0 0x0075B4 +#define ACP_SW1_RX_DP0_1_HCTRL_OFFSET_BANK0 0x0075B8 +#define ACP_SW1_RX_DP0_1_LANE_CTRL_BANK0 0x0075BC +#define ACP_SW1_RX_DP0_1_CHANNEL_ENABLE_BANK0 0x0075C0 +#define ACP_SW1_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0075C4 +#define ACP_SW1_RX_DP0_1_SAMPLEINTERVAL_BANK1 0x0075C8 +#define ACP_SW1_RX_DP0_1_HCTRL_BANK1 0x0075CC +#define ACP_SW1_RX_DP0_1_HCTRL_OFFSET_BANK1 0x0075D0 +#define ACP_SW1_RX_DP0_1_LANE_CTRL_BANK1 0x0075D4 +#define ACP_SW1_RX_DP0_1_CHANNEL_ENABLE_BANK1 0x0075D8 +#define ACP_SW1_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0075DC +#define ACP_SW1_RX_DP0_2_SAMPLEINTERVAL_BANK0 0x0075E0 +#define ACP_SW1_RX_DP0_2_HCTRL_BANK0 0x0075E4 +#define ACP_SW1_RX_DP0_2_HCTRL_OFFSET_BANK0 0x0075E8 +#define ACP_SW1_RX_DP0_2_LANE_CTRL_BANK0 0x0075EC +#define ACP_SW1_RX_DP0_2_CHANNEL_ENABLE_BANK0 0x0075F0 +#define ACP_SW1_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0075F4 +#define ACP_SW1_RX_DP0_2_SAMPLEINTERVAL_BANK1 0x0075F8 +#define ACP_SW1_RX_DP0_2_HCTRL_BANK1 0x0075FC +#define ACP_SW1_RX_DP0_2_HCTRL_OFFSET_BANK1 0x007600 +#define ACP_SW1_RX_DP0_2_LANE_CTRL_BANK1 0x007604 +#define ACP_SW1_RX_DP0_2_CHANNEL_ENABLE_BANK1 0x007608 +#define ACP_SW1_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00760C +#define ACP_SW1_RX_DP0_3_SAMPLEINTERVAL_BANK0 0x007610 +#define ACP_SW1_RX_DP0_3_HCTRL_BANK0 0x007614 +#define ACP_SW1_RX_DP0_3_HCTRL_OFFSET_BANK0 0x007618 +#define ACP_SW1_RX_DP0_3_LANE_CTRL_BANK0 0x00761C +#define ACP_SW1_RX_DP0_3_CHANNEL_ENABLE_BANK0 0x007620 +#define ACP_SW1_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007624 +#define ACP_SW1_RX_DP0_3_SAMPLEINTERVAL_BANK1 0x007628 +#define ACP_SW1_RX_DP0_3_HCTRL_BANK1 0x00762C +#define ACP_SW1_RX_DP0_3_HCTRL_OFFSET_BANK1 0x007630 +#define ACP_SW1_RX_DP0_3_LANE_CTRL_BANK1 0x007634 +#define ACP_SW1_RX_DP0_3_CHANNEL_ENABLE_BANK1 0x007638 +#define ACP_SW1_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00763C +#define ACP_SW1_RX_DP1_SAMPLEINTERVAL_BANK0 0x007670 +#define ACP_SW1_RX_DP1_HCTRL_BANK0 0x007674 +#define ACP_SW1_RX_DP1_HCTRL_OFFSET_BANK0 0x007678 +#define ACP_SW1_RX_DP1_LANE_CTRL_BANK0 0x00767C +#define ACP_SW1_RX_DP1_CHANNEL_ENABLE_BANK0 0x007680 +#define ACP_SW1_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007684 +#define ACP_SW1_RX_DP1_SAMPLEINTERVAL_BANK1 0x007688 +#define ACP_SW1_RX_DP1_HCTRL_BANK1 0x00768C +#define ACP_SW1_RX_DP1_HCTRL_OFFSET_BANK1 0x007690 +#define ACP_SW1_RX_DP1_LANE_CTRL_BANK1 0x007694 +#define ACP_SW1_RX_DP1_CHANNEL_ENABLE_BANK1 0x007698 +#define ACP_SW1_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00769C +#define ACP_SW1_RX_DP2_SAMPLEINTERVAL_BANK0 0x0076A0 +#define ACP_SW1_RX_DP2_HCTRL_BANK0 0x0076A4 +#define ACP_SW1_RX_DP2_HCTRL_OFFSET_BANK0 0x0076A8 +#define ACP_SW1_RX_DP2_LANE_CTRL_BANK0 0x0076AC +#define ACP_SW1_RX_DP2_CHANNEL_ENABLE_BANK0 0x0076B0 +#define ACP_SW1_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0076B4 +#define ACP_SW1_RX_DP2_SAMPLEINTERVAL_BANK1 0x0076B8 +#define ACP_SW1_RX_DP2_HCTRL_BANK1 0x0076BC +#define ACP_SW1_RX_DP2_HCTRL_OFFSET_BANK1 0x0076C0 +#define ACP_SW1_RX_DP2_LANE_CTRL_BANK1 0x0076C4 +#define ACP_SW1_RX_DP2_CHANNEL_ENABLE_BANK1 0x0076C8 +#define ACP_SW1_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0076CC +#define ACP_SW1_RX_DP3_SAMPLEINTERVAL_BANK0 0x0076D0 +#define ACP_SW1_RX_DP3_HCTRL_BANK0 0x0076D4 +#define ACP_SW1_RX_DP3_HCTRL_OFFSET_BANK0 0x0076D8 +#define ACP_SW1_RX_DP3_LANE_CTRL_BANK0 0x0076DC +#define ACP_SW1_RX_DP3_CHANNEL_ENABLE_BANK0 0x0076E0 +#define ACP_SW1_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0076E4 +#define ACP_SW1_RX_DP3_SAMPLEINTERVAL_BANK1 0x0076E8 +#define ACP_SW1_RX_DP3_HCTRL_BANK1 0x0076EC +#define ACP_SW1_RX_DP3_HCTRL_OFFSET_BANK1 0x0076F0 +#define ACP_SW1_RX_DP3_LANE_CTRL_BANK1 0x0076F4 +#define ACP_SW1_RX_DP3_CHANNEL_ENABLE_BANK1 0x0076F8 +#define ACP_SW1_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0076FC +#define ACP_SW1_RX_DP4_SAMPLEINTERVAL_BANK0 0x007700 +#define ACP_SW1_RX_DP4_HCTRL_BANK0 0x007704 +#define ACP_SW1_RX_DP4_HCTRL_OFFSET_BANK0 0x007708 +#define ACP_SW1_RX_DP4_LANE_CTRL_BANK0 0x00770C +#define ACP_SW1_RX_DP4_CHANNEL_ENABLE_BANK0 0x007710 +#define ACP_SW1_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007714 +#define ACP_SW1_RX_DP4_SAMPLEINTERVAL_BANK1 0x007718 +#define ACP_SW1_RX_DP4_HCTRL_BANK1 0x00771C +#define ACP_SW1_RX_DP4_HCTRL_OFFSET_BANK1 0x007720 +#define ACP_SW1_RX_DP4_LANE_CTRL_BANK1 0x007724 +#define ACP_SW1_RX_DP4_CHANNEL_ENABLE_BANK1 0x007728 +#define ACP_SW1_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00772C +#define ACP_SW1_RX_DP5_SAMPLEINTERVAL_BANK0 0x007730 +#define ACP_SW1_RX_DP5_HCTRL_BANK0 0x007734 +#define ACP_SW1_RX_DP5_HCTRL_OFFSET_BANK0 0x007738 +#define ACP_SW1_RX_DP5_LANE_CTRL_BANK0 0x00773C +#define ACP_SW1_RX_DP5_CHANNEL_ENABLE_BANK0 0x007740 +#define ACP_SW1_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007744 +#define ACP_SW1_RX_DP5_SAMPLEINTERVAL_BANK1 0x007748 +#define ACP_SW1_RX_DP5_HCTRL_BANK1 0x00774C +#define ACP_SW1_RX_DP5_HCTRL_OFFSET_BANK1 0x007750 +#define ACP_SW1_RX_DP5_LANE_CTRL_BANK1 0x007754 +#define ACP_SW1_RX_DP5_CHANNEL_ENABLE_BANK1 0x007758 +#define ACP_SW1_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00775C +#define ACP_SW1_RX_DP6_SAMPLEINTERVAL_BANK0 0x007760 +#define ACP_SW1_RX_DP6_HCTRL_BANK0 0x007764 +#define ACP_SW1_RX_DP6_HCTRL_OFFSET_BANK0 0x007768 +#define ACP_SW1_RX_DP6_LANE_CTRL_BANK0 0x00776C +#define ACP_SW1_RX_DP6_CHANNEL_ENABLE_BANK0 0x007770 +#define ACP_SW1_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x007774 +#define ACP_SW1_RX_DP6_SAMPLEINTERVAL_BANK1 0x007778 +#define ACP_SW1_RX_DP6_HCTRL_BANK1 0x00777C +#define ACP_SW1_RX_DP6_HCTRL_OFFSET_BANK1 0x007780 +#define ACP_SW1_RX_DP6_LANE_CTRL_BANK1 0x007784 +#define ACP_SW1_RX_DP6_CHANNEL_ENABLE_BANK1 0x007788 +#define ACP_SW1_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00778C +#define ACP_SW1_RX_DP7_SAMPLEINTERVAL_BANK0 0x007790 +#define ACP_SW1_RX_DP7_HCTRL_BANK0 0x007794 +#define ACP_SW1_RX_DP7_HCTRL_OFFSET_BANK0 0x007798 +#define ACP_SW1_RX_DP7_LANE_CTRL_BANK0 0x00779C +#define ACP_SW1_RX_DP7_CHANNEL_ENABLE_BANK0 0x0077A0 +#define ACP_SW1_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0077A4 +#define ACP_SW1_RX_DP7_SAMPLEINTERVAL_BANK1 0x0077A8 +#define ACP_SW1_RX_DP7_HCTRL_BANK1 0x0077AC +#define ACP_SW1_RX_DP7_HCTRL_OFFSET_BANK1 0x0077B0 +#define ACP_SW1_RX_DP7_LANE_CTRL_BANK1 0x0077B4 +#define ACP_SW1_RX_DP7_CHANNEL_ENABLE_BANK1 0x0077B8 +#define ACP_SW1_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0077BC +#define ACP_SW1_BPT_PORT_EN 0x0077C0 +#define ACP_SW1_BPT_PORT_EN_STATUS 0x0077C4 +#define ACP_SW1_BPT_PORT_FRAME_FORMAT 0x0077C8 +#define ACP_SW1_BPT_PORT_SAMPLEINTERVAL_BANK0 0x0077CC +#define ACP_SW1_BPT_PORT_HCTRL_BANK0 0x0077D0 +#define ACP_SW1_BPT_PORT_OFFSET_BANK0 0x0077D4 +#define ACP_SW1_BPT_PORT_LANE_SELECT_BANK0 0x0077D8 +#define ACP_SW1_BPT_PORT_CHANNEL_ENABLE_BANK0 0x0077DC +#define ACP_SW1_BPT_PORT_SAMPLEINTERVAL_BANK1 0x0077E0 +#define ACP_SW1_BPT_PORT_HCTRL_BANK1 0x0077E4 +#define ACP_SW1_BPT_PORT_OFFSET_BANK1 0x0077E8 +#define ACP_SW1_BPT_PORT_LANE_SELECT_BANK1 0x0077EC +#define ACP_SW1_BPT_PORT_CHANNEL_ENABLE_BANK1 0x0077F0 +#define ACP_SW1_BPT_PORT_FIRST_BYTE_ADDR 0x0077F4 +#define ACP_SW1_CLK_RESUME_CTRL 0x0077F8 +#define ACP_SW1_CLK_RESUME_DELAY_CNTR 0x0077FC +#define ACP_SW1_BUS_RESET_CTRL 0x007800 +#define ACP_SW1_PRBS_ERR_STATUS 0x007804 +#define ACP_SW1_WALLCLK_MISC 0x007808 +#define ACP_SW1_WALL_CLK_COUNTER 0x00780C +#define ACP_SW1_PING_STATUS_REGISTER_LOW 0x007810 +#define ACP_SW1_PING_STATUS_REGISTER_HIGH 0x007814 +#define ACP_SW1_PING_STATUS_CURRENT_BANK_SEL 0x007818 +#define ACP_SW1_TZD_CHANGE 0x00781C +#define ACP_SW1_WALLCLK_INTR_CNTL 0x007820 + +#define ACP_SW2_GLOBAL_CAPABILITIES 0x008E00 +#define ACP_SW2_RX_DMA0_RINGBUFADDR 0x008E04 +#define ACP_SW2_RX_DMA0_RINGBUFSIZE 0x008E08 +#define ACP_SW2_RX_DMA0_FIFOADDR 0x008E0C +#define ACP_SW2_RX_DMA0_FIFOSIZE 0x008E10 +#define ACP_SW2_RX_DMA0_BURST_SIZE 0x008E14 +#define ACP_SW2_RX_DMA0_LINKPOSITIONCNTR 0x008E18 +#define ACP_SW2_RX_DMA0_LINEARPOSITIONCNTR_HIGH 0x008E1C +#define ACP_SW2_RX_DMA0_LINEARPOSITIONCNTR_LOW 0x008E20 +#define ACP_SW2_RX_DMA0_INTR_WATERMARK_SIZE 0x008E24 +#define ACP_SW2_RX_DMA1_RINGBUFADDR 0x008E28 +#define ACP_SW2_RX_DMA1_RINGBUFSIZE 0x008E2C +#define ACP_SW2_RX_DMA1_FIFOADDR 0x008E30 +#define ACP_SW2_RX_DMA1_FIFOSIZE 0x008E34 +#define ACP_SW2_RX_DMA1_BURST_SIZE 0x008E38 +#define ACP_SW2_RX_DMA1_LINKPOSITIONCNTR 0x008E3C +#define ACP_SW2_RX_DMA1_LINEARPOSITIONCNTR_HIGH 0x008E40 +#define ACP_SW2_RX_DMA1_LINEARPOSITIONCNTR_LOW 0x008E44 +#define ACP_SW2_RX_DMA1_INTR_WATERMARK_SIZE 0x008E48 +#define ACP_SW2_RX_DMA2_RINGBUFADDR 0x008E4C +#define ACP_SW2_RX_DMA2_RINGBUFSIZE 0x008E50 +#define ACP_SW2_RX_DMA2_FIFOADDR 0x008E54 +#define ACP_SW2_RX_DMA2_FIFOSIZE 0x008E58 +#define ACP_SW2_RX_DMA2_BURST_SIZE 0x008E5C +#define ACP_SW2_RX_DMA2_LINKPOSITIONCNTR 0x008E60 +#define ACP_SW2_RX_DMA2_LINEARPOSITIONCNTR_HIGH 0x008E64 +#define ACP_SW2_RX_DMA2_LINEARPOSITIONCNTR_LOW 0x008E68 +#define ACP_SW2_RX_DMA2_INTR_WATERMARK_SIZE 0x008E6C +#define ACP_SW2_RX_DMA3_RINGBUFADDR 0x008E70 +#define ACP_SW2_RX_DMA3_RINGBUFSIZE 0x008E74 +#define ACP_SW2_RX_DMA3_FIFOADDR 0x008E78 +#define ACP_SW2_RX_DMA3_FIFOSIZE 0x008E7C +#define ACP_SW2_RX_DMA3_BURST_SIZE 0x008E80 +#define ACP_SW2_RX_DMA3_LINKPOSITIONCNTR 0x008E84 +#define ACP_SW2_RX_DMA3_LINEARPOSITIONCNTR_HIGH 0x008E88 +#define ACP_SW2_RX_DMA3_LINEARPOSITIONCNTR_LOW 0x008E8C +#define ACP_SW2_RX_DMA3_INTR_WATERMARK_SIZE 0x008E90 +#define ACP_SW2_RX_DMA4_RINGBUFADDR 0x008E94 +#define ACP_SW2_RX_DMA4_RINGBUFSIZE 0x008E98 +#define ACP_SW2_RX_DMA4_FIFOADDR 0x008E9C +#define ACP_SW2_RX_DMA4_FIFOSIZE 0x008EA0 +#define ACP_SW2_RX_DMA4_BURST_SIZE 0x008EA4 +#define ACP_SW2_RX_DMA4_LINKPOSITIONCNTR 0x008EA8 +#define ACP_SW2_RX_DMA4_LINEARPOSITIONCNTR_HIGH 0x008EAC +#define ACP_SW2_RX_DMA4_LINEARPOSITIONCNTR_LOW 0x008EB0 +#define ACP_SW2_RX_DMA4_INTR_WATERMARK_SIZE 0x008EB4 +#define ACP_SW2_RX_DMA5_RINGBUFADDR 0x008EB8 +#define ACP_SW2_RX_DMA5_RINGBUFSIZE 0x008EBC +#define ACP_SW2_RX_DMA5_FIFOADDR 0x008EC0 +#define ACP_SW2_RX_DMA5_FIFOSIZE 0x008EC4 +#define ACP_SW2_RX_DMA5_BURST_SIZE 0x008EC8 +#define ACP_SW2_RX_DMA5_LINKPOSITIONCNTR 0x008ECC +#define ACP_SW2_RX_DMA5_LINEARPOSITIONCNTR_HIGH 0x008ED0 +#define ACP_SW2_RX_DMA5_LINEARPOSITIONCNTR_LOW 0x008ED4 +#define ACP_SW2_RX_DMA5_INTR_WATERMARK_SIZE 0x008ED8 +#define ACP_SW2_RX_DMA6_RINGBUFADDR 0x008EDC +#define ACP_SW2_RX_DMA6_RINGBUFSIZE 0x008EE0 +#define ACP_SW2_RX_DMA6_FIFOADDR 0x008EE4 +#define ACP_SW2_RX_DMA6_FIFOSIZE 0x008EE8 +#define ACP_SW2_RX_DMA6_BURST_SIZE 0x008EEC +#define ACP_SW2_RX_DMA6_LINKPOSITIONCNTR 0x008EF0 +#define ACP_SW2_RX_DMA6_LINEARPOSITIONCNTR_HIGH 0x008EF4 +#define ACP_SW2_RX_DMA6_LINEARPOSITIONCNTR_LOW 0x008EF8 +#define ACP_SW2_RX_DMA6_INTR_WATERMARK_SIZE 0x008EFC +#define ACP_SW2_RX_DMA7_RINGBUFADDR 0x008F00 +#define ACP_SW2_RX_DMA7_RINGBUFSIZE 0x008F04 +#define ACP_SW2_RX_DMA7_FIFOADDR 0x008F08 +#define ACP_SW2_RX_DMA7_FIFOSIZE 0x008F0C +#define ACP_SW2_RX_DMA7_BURST_SIZE 0x008F10 +#define ACP_SW2_RX_DMA7_LINKPOSITIONCNTR 0x008F14 +#define ACP_SW2_RX_DMA7_LINEARPOSITIONCNTR_HIGH 0x008F18 +#define ACP_SW2_RX_DMA7_LINEARPOSITIONCNTR_LOW 0x008F1C +#define ACP_SW2_RX_DMA7_INTR_WATERMARK_SIZE 0x008F20 +#define ACP_SW2_TX_DMA0_RINGBUFADDR 0x008F24 +#define ACP_SW2_TX_DMA0_RINGBUFSIZE 0x008F28 +#define ACP_SW2_TX_DMA0_FIFOADDR 0x008F2C +#define ACP_SW2_TX_DMA0_FIFOSIZE 0x008F30 +#define ACP_SW2_TX_DMA0_BURST_SIZE 0x008F34 +#define ACP_SW2_TX_DMA0_LINKPOSITIONCNTR 0x008F38 +#define ACP_SW2_TX_DMA0_LINEARPOSITIONCNTR_HIGH 0x008F3C +#define ACP_SW2_TX_DMA0_LINEARPOSITIONCNTR_LOW 0x008F40 +#define ACP_SW2_TX_DMA0_INTR_WATERMARK_SIZE 0x008F44 +#define ACP_SW2_TX_DMA1_RINGBUFADDR 0x008F48 +#define ACP_SW2_TX_DMA1_RINGBUFSIZE 0x008F4C +#define ACP_SW2_TX_DMA1_FIFOADDR 0x008F50 +#define ACP_SW2_TX_DMA1_FIFOSIZE 0x008F54 +#define ACP_SW2_TX_DMA1_BURST_SIZE 0x008F58 +#define ACP_SW2_TX_DMA1_LINKPOSITIONCNTR 0x008F5C +#define ACP_SW2_TX_DMA1_LINEARPOSITIONCNTR_HIGH 0x008F60 +#define ACP_SW2_TX_DMA1_LINEARPOSITIONCNTR_LOW 0x008F64 +#define ACP_SW2_TX_DMA1_INTR_WATERMARK_SIZE 0x008F68 +#define ACP_SW2_TX_DMA2_RINGBUFADDR 0x008F6C +#define ACP_SW2_TX_DMA2_RINGBUFSIZE 0x008F70 +#define ACP_SW2_TX_DMA2_FIFOADDR 0x008F74 +#define ACP_SW2_TX_DMA2_FIFOSIZE 0x008F78 +#define ACP_SW2_TX_DMA2_BURST_SIZE 0x008F7C +#define ACP_SW2_TX_DMA2_LINKPOSITIONCNTR 0x008F80 +#define ACP_SW2_TX_DMA2_LINEARPOSITIONCNTR_HIGH 0x008F84 +#define ACP_SW2_TX_DMA2_LINEARPOSITIONCNTR_LOW 0x008F88 +#define ACP_SW2_TX_DMA2_INTR_WATERMARK_SIZE 0x008F8C +#define ACP_SW2_TX_DMA3_RINGBUFADDR 0x008F90 +#define ACP_SW2_TX_DMA3_RINGBUFSIZE 0x008F94 +#define ACP_SW2_TX_DMA3_FIFOADDR 0x008F98 +#define ACP_SW2_TX_DMA3_FIFOSIZE 0x008F9C +#define ACP_SW2_TX_DMA3_BURST_SIZE 0x008FA0 +#define ACP_SW2_TX_DMA3_LINKPOSITIONCNTR 0x008FA4 +#define ACP_SW2_TX_DMA3_LINEARPOSITIONCNTR_HIGH 0x008FA8 +#define ACP_SW2_TX_DMA3_LINEARPOSITIONCNTR_LOW 0x008FAC +#define ACP_SW2_TX_DMA3_INTR_WATERMARK_SIZE 0x008FB0 +#define ACP_SW2_TX_DMA4_RINGBUFADDR 0x008FB4 +#define ACP_SW2_TX_DMA4_RINGBUFSIZE 0x008FB8 +#define ACP_SW2_TX_DMA4_FIFOADDR 0x008FBC +#define ACP_SW2_TX_DMA4_FIFOSIZE 0x008FC0 +#define ACP_SW2_TX_DMA4_BURST_SIZE 0x008FC4 +#define ACP_SW2_TX_DMA4_LINKPOSITIONCNTR 0x008FC8 +#define ACP_SW2_TX_DMA4_LINEARPOSITIONCNTR_HIGH 0x008FCC +#define ACP_SW2_TX_DMA4_LINEARPOSITIONCNTR_LOW 0x008FD0 +#define ACP_SW2_TX_DMA4_INTR_WATERMARK_SIZE 0x008FD4 +#define ACP_SW2_TX_DMA5_RINGBUFADDR 0x008FD8 +#define ACP_SW2_TX_DMA5_RINGBUFSIZE 0x008FDC +#define ACP_SW2_TX_DMA5_FIFOADDR 0x008FE0 +#define ACP_SW2_TX_DMA5_FIFOSIZE 0x008FE4 +#define ACP_SW2_TX_DMA5_BURST_SIZE 0x008FE8 +#define ACP_SW2_TX_DMA5_LINKPOSITIONCNTR 0x008FEC +#define ACP_SW2_TX_DMA5_LINEARPOSITIONCNTR_HIGH 0x008FF0 +#define ACP_SW2_TX_DMA5_LINEARPOSITIONCNTR_LOW 0x008FF4 +#define ACP_SW2_TX_DMA5_INTR_WATERMARK_SIZE 0x008FF8 +#define ACP_SW2_TX_DMA6_RINGBUFADDR 0x008FFC +#define ACP_SW2_TX_DMA6_RINGBUFSIZE 0x009000 +#define ACP_SW2_TX_DMA6_FIFOADDR 0x009004 +#define ACP_SW2_TX_DMA6_FIFOSIZE 0x009008 +#define ACP_SW2_TX_DMA6_BURST_SIZE 0x00900C +#define ACP_SW2_TX_DMA6_LINKPOSITIONCNTR 0x009010 +#define ACP_SW2_TX_DMA6_LINEARPOSITIONCNTR_HIGH 0x009014 +#define ACP_SW2_TX_DMA6_LINEARPOSITIONCNTR_LOW 0x009018 +#define ACP_SW2_TX_DMA6_INTR_WATERMARK_SIZE 0x00901C +#define ACP_SW2_TX_DMA7_RINGBUFADDR 0x009020 +#define ACP_SW2_TX_DMA7_RINGBUFSIZE 0x009024 +#define ACP_SW2_TX_DMA7_FIFOADDR 0x009028 +#define ACP_SW2_TX_DMA7_FIFOSIZE 0x00902C +#define ACP_SW2_TX_DMA7_BURST_SIZE 0x009030 +#define ACP_SW2_TX_DMA7_LINKPOSITIONCNTR 0x009034 +#define ACP_SW2_TX_DMA7_LINEARPOSITIONCNTR_HIGH 0x009038 +#define ACP_SW2_TX_DMA7_LINEARPOSITIONCNTR_LOW 0x00903C +#define ACP_SW2_TX_DMA7_INTR_WATERMARK_SIZE 0x009040 +#define ACP_SW2_RX_DMA0_POS_TRACK 0x009044 +#define ACP_SW2_RX_DMA0_POS 0x009048 +#define ACP_SW2_RX_DMA1_POS_TRACK 0x00904C +#define ACP_SW2_RX_DMA1_POS 0x009050 +#define ACP_SW2_RX_DMA2_POS_TRACK 0x009054 +#define ACP_SW2_RX_DMA2_POS 0x009058 +#define ACP_SW2_RX_DMA3_POS_TRACK 0x00905C +#define ACP_SW2_RX_DMA3_POS 0x009060 +#define ACP_SW2_RX_DMA4_POS_TRACK 0x009064 +#define ACP_SW2_RX_DMA4_POS 0x009068 +#define ACP_SW2_RX_DMA5_POS_TRACK 0x00906C +#define ACP_SW2_RX_DMA5_POS 0x009070 +#define ACP_SW2_RX_DMA6_POS_TRACK 0x009074 +#define ACP_SW2_RX_DMA6_POS 0x009078 +#define ACP_SW2_RX_DMA7_POS_TRACK 0x00907C +#define ACP_SW2_RX_DMA7_POS 0x009080 +#define ACP_SW2_TX_DMA0_POS_TRACK 0x009084 +#define ACP_SW2_TX_DMA0_POS 0x009088 +#define ACP_SW2_TX_DMA1_POS_TRACK 0x00908C +#define ACP_SW2_TX_DMA1_POS 0x009090 +#define ACP_SW2_TX_DMA2_POS_TRACK 0x009094 +#define ACP_SW2_TX_DMA2_POS 0x009098 +#define ACP_SW2_TX_DMA3_POS_TRACK 0x00909C +#define ACP_SW2_TX_DMA3_POS 0x0090A0 +#define ACP_SW2_TX_DMA4_POS_TRACK 0x0090A4 +#define ACP_SW2_TX_DMA4_POS 0x0090A8 +#define ACP_SW2_TX_DMA5_POS_TRACK 0x0090AC +#define ACP_SW2_TX_DMA5_POS 0x0090B0 +#define ACP_SW2_TX_DMA6_POS_TRACK 0x0090B4 +#define ACP_SW2_TX_DMA6_POS 0x0090B8 +#define ACP_SW2_TX_DMA7_POS_TRACK 0x0090BC +#define ACP_SW2_TX_DMA7_POS 0x0090C0 +#define ACP_SW2_FIFO_ERROR_REASON 0x0090C4 +#define ACP_SW2_FIFO_ERROR_INTR_MASK 0x0090C8 +#define ACP_SW2_ERROR_REASON1 0x0090CC +#define ACP_SW2_ERROR_INTR_MASK1 0x0090D0 +#define ACP_SW2_ERROR_REASON2 0x0090D4 +#define ACP_SW2_ERROR_INTR_MASK2 0x0090D8 + +#define ACP_SW2_CORB_BASE_ADDRESS 0x009100 +#define ACP_SW2_CORB_WRITE_POINTER 0x009104 +#define ACP_SW2_CORB_READ_POINTER 0x009108 +#define ACP_SW2_CORB_CONTROL 0x00910C +#define ACP_SW2_CORB_SIZE 0x009114 +#define ACP_SW2_RIRB_BASE_ADDRESS 0x009118 +#define ACP_SW2_RIRB_WRITE_POINTER 0x00911C +#define ACP_SW2_RIRB_RESPONSE_INTERRUPT_COUNT 0x009120 +#define ACP_SW2_RIRB_CONTROL 0x009124 +#define ACP_SW2_RIRB_SIZE 0x009128 +#define ACP_SW2_RIRB_FIFO_MIN_THDL 0x00912C +#define ACP_SW2_IMM_CMD_UPPER_WORD 0x009130 +#define ACP_SW2_IMM_CMD_LOWER_QWORD 0x009134 +#define ACP_SW2_IMM_RESP_UPPER_WORD 0x009138 +#define ACP_SW2_IMM_RESP_LOWER_QWORD 0x00913C +#define ACP_SW2_IMM_CMD_STS 0x009140 +#define ACP_SW2_BRA_BASE_ADDRESS 0x009144 +#define ACP_SW2_BRA_TRANSFER_SIZE 0x009148 +#define ACP_SW2_BRA_DMA_BUSY 0x00914C +#define ACP_SW2_BRA_RESP 0x009150 +#define ACP_SW2_BRA_RESP_FRAME_ADDR 0x009154 +#define ACP_SW2_BRA_CURRENT_TRANSFER_SIZE 0x009158 +#define ACP_SW2_STATE_CHANGE_STATUS_0TO7 0x00915C +#define ACP_SW2_STATE_CHANGE_STATUS_8TO11 0x009160 +#define ACP_SW2_STATE_CHANGE_STATUS_MASK_0TO7 0x009164 +#define ACP_SW2_STATE_CHANGE_STATUS_MASK_8TO11 0x009168 +#define ACP_SW2_CLK_FREQUENCY_CTRL_BANK0 0x00916C +#define ACP_SW2_CLK_FREQUENCY_CTRL_BANK1 0x009170 +#define ACP_SW2_ERROR_INTR_MASK 0x009174 +#define ACP_SW2_PHY_TEST_MODE_DATA_OFF 0x009178 +#define ACP_SW2_DATA_TO_PDM_EN 0x00917C + +#define ACP_SW2_EN 0x009200 +#define ACP_SW2_EN_STATUS 0x009204 +#define ACP_SW2_FRAMESIZE_BANK0 0x009208 +#define ACP_SW2_FRAMESIZE_BANK1 0x00920C +#define ACP_SW2_SSP_COUNTER 0x009210 +#define ACP_SW2_TX_STREAM0_EN 0x009214 +#define ACP_SW2_TX_STREAM1_EN 0x009218 +#define ACP_SW2_TX_STREAM2_EN 0x00921C +#define ACP_SW2_TX_STREAM3_EN 0x009220 +#define ACP_SW2_TX_STREAM4_EN 0x009224 +#define ACP_SW2_TX_STREAM5_EN 0x009228 +#define ACP_SW2_TX_STREAM6_EN 0x00922C +#define ACP_SW2_TX_STREAM7_EN 0x009230 +#define ACP_SW2_TX_STREAM0_EN_STATUS 0x009234 +#define ACP_SW2_TX_STREAM1_EN_STATUS 0x009238 +#define ACP_SW2_TX_STREAM2_EN_STATUS 0x00923C +#define ACP_SW2_TX_STREAM3_EN_STATUS 0x009240 +#define ACP_SW2_TX_STREAM4_EN_STATUS 0x009244 +#define ACP_SW2_TX_STREAM5_EN_STATUS 0x009248 +#define ACP_SW2_TX_STREAM6_EN_STATUS 0x00924C +#define ACP_SW2_TX_STREAM7_EN_STATUS 0x009250 +#define ACP_SW2_TX_DP0_FRAME_FORMAT 0x009254 +#define ACP_SW2_TX_DP1_FRAME_FORMAT 0x009258 +#define ACP_SW2_TX_DP2_FRAME_FORMAT 0x00925C +#define ACP_SW2_TX_DP3_FRAME_FORMAT 0x009260 +#define ACP_SW2_TX_DP4_FRAME_FORMAT 0x009264 +#define ACP_SW2_TX_DP5_FRAME_FORMAT 0x009268 +#define ACP_SW2_TX_DP6_FRAME_FORMAT 0x00926C +#define ACP_SW2_TX_DP7_FRAME_FORMAT 0x009270 +#define ACP_SW2_TX_DP0_0_SAMPLEINTERVAL_BANK0 0x009280 +#define ACP_SW2_TX_DP0_0_HCTRL_BANK0 0x009284 +#define ACP_SW2_TX_DP0_0_HCTRL_OFFSET_BANK0 0x009288 +#define ACP_SW2_TX_DP0_0_LANE_CTRL_BANK0 0x00928C +#define ACP_SW2_TX_DP0_0_CHANNEL_ENABLE_BANK0 0x009290 +#define ACP_SW2_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009294 +#define ACP_SW2_TX_DP0_0_SAMPLEINTERVAL_BANK1 0x009298 +#define ACP_SW2_TX_DP0_0_HCTRL_BANK1 0x00929C +#define ACP_SW2_TX_DP0_0_HCTRL_OFFSET_BANK1 0x0092A0 +#define ACP_SW2_TX_DP0_0_LANE_CTRL_BANK1 0x0092A4 +#define ACP_SW2_TX_DP0_0_CHANNEL_ENABLE_BANK1 0x0092A8 +#define ACP_SW2_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0092AC +#define ACP_SW2_TX_DP0_1_SAMPLEINTERVAL_BANK0 0x0092B0 +#define ACP_SW2_TX_DP0_1_HCTRL_BANK0 0x0092B4 +#define ACP_SW2_TX_DP0_1_HCTRL_OFFSET_BANK0 0x0092B8 +#define ACP_SW2_TX_DP0_1_LANE_CTRL_BANK0 0x0092BC +#define ACP_SW2_TX_DP0_1_CHANNEL_ENABLE_BANK0 0x0092C0 +#define ACP_SW2_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0092C4 +#define ACP_SW2_TX_DP0_1_SAMPLEINTERVAL_BANK1 0x0092C8 +#define ACP_SW2_TX_DP0_1_HCTRL_BANK1 0x0092CC +#define ACP_SW2_TX_DP0_1_HCTRL_OFFSET_BANK1 0x0092D0 +#define ACP_SW2_TX_DP0_1_LANE_CTRL_BANK1 0x0092D4 +#define ACP_SW2_TX_DP0_1_CHANNEL_ENABLE_BANK1 0x0092D8 +#define ACP_SW2_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0092DC +#define ACP_SW2_TX_DP0_2_SAMPLEINTERVAL_BANK0 0x0092E0 +#define ACP_SW2_TX_DP0_2_HCTRL_BANK0 0x0092E4 +#define ACP_SW2_TX_DP0_2_HCTRL_OFFSET_BANK0 0x0092E8 +#define ACP_SW2_TX_DP0_2_LANE_CTRL_BANK0 0x0092EC +#define ACP_SW2_TX_DP0_2_CHANNEL_ENABLE_BANK0 0x0092F0 +#define ACP_SW2_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0092F4 +#define ACP_SW2_TX_DP0_2_SAMPLEINTERVAL_BANK1 0x0092F8 +#define ACP_SW2_TX_DP0_2_HCTRL_BANK1 0x0092FC +#define ACP_SW2_TX_DP0_2_HCTRL_OFFSET_BANK1 0x009300 +#define ACP_SW2_TX_DP0_2_LANE_CTRL_BANK1 0x009304 +#define ACP_SW2_TX_DP0_2_CHANNEL_ENABLE_BANK1 0x009308 +#define ACP_SW2_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00930C +#define ACP_SW2_TX_DP0_3_SAMPLEINTERVAL_BANK0 0x009310 +#define ACP_SW2_TX_DP0_3_HCTRL_BANK0 0x009314 +#define ACP_SW2_TX_DP0_3_HCTRL_OFFSET_BANK0 0x009318 +#define ACP_SW2_TX_DP0_3_LANE_CTRL_BANK0 0x00931C +#define ACP_SW2_TX_DP0_3_CHANNEL_ENABLE_BANK0 0x009320 +#define ACP_SW2_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009324 +#define ACP_SW2_TX_DP0_3_SAMPLEINTERVAL_BANK1 0x009328 +#define ACP_SW2_TX_DP0_3_HCTRL_BANK1 0x00932C +#define ACP_SW2_TX_DP0_3_HCTRL_OFFSET_BANK1 0x009330 +#define ACP_SW2_TX_DP0_3_LANE_CTRL_BANK1 0x009334 +#define ACP_SW2_TX_DP0_3_CHANNEL_ENABLE_BANK1 0x009338 +#define ACP_SW2_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00933C +#define ACP_SW2_TX_DP1_SAMPLEINTERVAL_BANK0 0x009370 +#define ACP_SW2_TX_DP1_HCTRL_BANK0 0x009374 +#define ACP_SW2_TX_DP1_HCTRL_OFFSET_BANK0 0x009378 +#define ACP_SW2_TX_DP1_LANE_CTRL_BANK0 0x00937C +#define ACP_SW2_TX_DP1_CHANNEL_ENABLE_BANK0 0x009380 +#define ACP_SW2_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009384 +#define ACP_SW2_TX_DP1_SAMPLEINTERVAL_BANK1 0x009388 +#define ACP_SW2_TX_DP1_HCTRL_BANK1 0x00938C +#define ACP_SW2_TX_DP1_HCTRL_OFFSET_BANK1 0x009390 +#define ACP_SW2_TX_DP1_LANE_CTRL_BANK1 0x009394 +#define ACP_SW2_TX_DP1_CHANNEL_ENABLE_BANK1 0x009398 +#define ACP_SW2_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00939C +#define ACP_SW2_TX_DP2_SAMPLEINTERVAL_BANK0 0x0093A0 +#define ACP_SW2_TX_DP2_HCTRL_BANK0 0x0093A4 +#define ACP_SW2_TX_DP2_HCTRL_OFFSET_BANK0 0x0093A8 +#define ACP_SW2_TX_DP2_LANE_CTRL_BANK0 0x0093AC +#define ACP_SW2_TX_DP2_CHANNEL_ENABLE_BANK0 0x0093B0 +#define ACP_SW2_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0093B4 +#define ACP_SW2_TX_DP2_SAMPLEINTERVAL_BANK1 0x0093B8 +#define ACP_SW2_TX_DP2_HCTRL_BANK1 0x0093BC +#define ACP_SW2_TX_DP2_HCTRL_OFFSET_BANK1 0x0093C0 +#define ACP_SW2_TX_DP2_LANE_CTRL_BANK1 0x0093C4 +#define ACP_SW2_TX_DP2_CHANNEL_ENABLE_BANK1 0x0093C8 +#define ACP_SW2_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0093CC +#define ACP_SW2_TX_DP3_SAMPLEINTERVAL_BANK0 0x0093D0 +#define ACP_SW2_TX_DP3_HCTRL_BANK0 0x0093D4 +#define ACP_SW2_TX_DP3_HCTRL_OFFSET_BANK0 0x0093D8 +#define ACP_SW2_TX_DP3_LANE_CTRL_BANK0 0x0093DC +#define ACP_SW2_TX_DP3_CHANNEL_ENABLE_BANK0 0x0093E0 +#define ACP_SW2_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0093E4 +#define ACP_SW2_TX_DP3_SAMPLEINTERVAL_BANK1 0x0093E8 +#define ACP_SW2_TX_DP3_HCTRL_BANK1 0x0093EC +#define ACP_SW2_TX_DP3_HCTRL_OFFSET_BANK1 0x0093F0 +#define ACP_SW2_TX_DP3_LANE_CTRL_BANK1 0x0093F4 +#define ACP_SW2_TX_DP3_CHANNEL_ENABLE_BANK1 0x0093F8 +#define ACP_SW2_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0093FC +#define ACP_SW2_TX_DP4_SAMPLEINTERVAL_BANK0 0x009400 +#define ACP_SW2_TX_DP4_HCTRL_BANK0 0x009404 +#define ACP_SW2_TX_DP4_HCTRL_OFFSET_BANK0 0x009408 +#define ACP_SW2_TX_DP4_LANE_CTRL_BANK0 0x00940C +#define ACP_SW2_TX_DP4_CHANNEL_ENABLE_BANK0 0x009410 +#define ACP_SW2_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009414 +#define ACP_SW2_TX_DP4_SAMPLEINTERVAL_BANK1 0x009418 +#define ACP_SW2_TX_DP4_HCTRL_BANK1 0x00941C +#define ACP_SW2_TX_DP4_HCTRL_OFFSET_BANK1 0x009420 +#define ACP_SW2_TX_DP4_LANE_CTRL_BANK1 0x009424 +#define ACP_SW2_TX_DP4_CHANNEL_ENABLE_BANK1 0x009428 +#define ACP_SW2_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00942C +#define ACP_SW2_TX_DP5_SAMPLEINTERVAL_BANK0 0x009430 +#define ACP_SW2_TX_DP5_HCTRL_BANK0 0x009434 +#define ACP_SW2_TX_DP5_HCTRL_OFFSET_BANK0 0x009438 +#define ACP_SW2_TX_DP5_LANE_CTRL_BANK0 0x00943C +#define ACP_SW2_TX_DP5_CHANNEL_ENABLE_BANK0 0x009440 +#define ACP_SW2_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009444 +#define ACP_SW2_TX_DP5_SAMPLEINTERVAL_BANK1 0x009448 +#define ACP_SW2_TX_DP5_HCTRL_BANK1 0x00944C +#define ACP_SW2_TX_DP5_HCTRL_OFFSET_BANK1 0x009450 +#define ACP_SW2_TX_DP5_LANE_CTRL_BANK1 0x009454 +#define ACP_SW2_TX_DP5_CHANNEL_ENABLE_BANK1 0x009458 +#define ACP_SW2_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00945C +#define ACP_SW2_TX_DP6_SAMPLEINTERVAL_BANK0 0x009460 +#define ACP_SW2_TX_DP6_HCTRL_BANK0 0x009464 +#define ACP_SW2_TX_DP6_HCTRL_OFFSET_BANK0 0x009468 +#define ACP_SW2_TX_DP6_LANE_CTRL_BANK0 0x00946C +#define ACP_SW2_TX_DP6_CHANNEL_ENABLE_BANK0 0x009470 +#define ACP_SW2_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009474 +#define ACP_SW2_TX_DP6_SAMPLEINTERVAL_BANK1 0x009478 +#define ACP_SW2_TX_DP6_HCTRL_BANK1 0x00947C +#define ACP_SW2_TX_DP6_HCTRL_OFFSET_BANK1 0x009480 +#define ACP_SW2_TX_DP6_LANE_CTRL_BANK1 0x009484 +#define ACP_SW2_TX_DP6_CHANNEL_ENABLE_BANK1 0x009488 +#define ACP_SW2_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00948C +#define ACP_SW2_TX_DP7_SAMPLEINTERVAL_BANK0 0x009490 +#define ACP_SW2_TX_DP7_HCTRL_BANK0 0x009494 +#define ACP_SW2_TX_DP7_HCTRL_OFFSET_BANK0 0x009498 +#define ACP_SW2_TX_DP7_LANE_CTRL_BANK0 0x00949C +#define ACP_SW2_TX_DP7_CHANNEL_ENABLE_BANK0 0x0094A0 +#define ACP_SW2_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0094A4 +#define ACP_SW2_TX_DP7_SAMPLEINTERVAL_BANK1 0x0094A8 +#define ACP_SW2_TX_DP7_HCTRL_BANK1 0x0094AC +#define ACP_SW2_TX_DP7_HCTRL_OFFSET_BANK1 0x0094B0 +#define ACP_SW2_TX_DP7_LANE_CTRL_BANK1 0x0094B4 +#define ACP_SW2_TX_DP7_CHANNEL_ENABLE_BANK1 0x0094B8 +#define ACP_SW2_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0094BC +#define ACP_SW2_RX_STREAM0_EN 0x009514 +#define ACP_SW2_RX_STREAM1_EN 0x009518 +#define ACP_SW2_RX_STREAM2_EN 0x00951C +#define ACP_SW2_RX_STREAM3_EN 0x009520 +#define ACP_SW2_RX_STREAM4_EN 0x009524 +#define ACP_SW2_RX_STREAM5_EN 0x009528 +#define ACP_SW2_RX_STREAM6_EN 0x00952C +#define ACP_SW2_RX_STREAM7_EN 0x009530 +#define ACP_SW2_RX_STREAM0_EN_STATUS 0x009534 +#define ACP_SW2_RX_STREAM1_EN_STATUS 0x009538 +#define ACP_SW2_RX_STREAM2_EN_STATUS 0x00953C +#define ACP_SW2_RX_STREAM3_EN_STATUS 0x009540 +#define ACP_SW2_RX_STREAM4_EN_STATUS 0x009544 +#define ACP_SW2_RX_STREAM5_EN_STATUS 0x009548 +#define ACP_SW2_RX_STREAM6_EN_STATUS 0x00954C +#define ACP_SW2_RX_STREAM7_EN_STATUS 0x009550 +#define ACP_SW2_RX_DP0_FRAME_FORMAT 0x009554 +#define ACP_SW2_RX_DP1_FRAME_FORMAT 0x009558 +#define ACP_SW2_RX_DP2_FRAME_FORMAT 0x00955C +#define ACP_SW2_RX_DP3_FRAME_FORMAT 0x009560 +#define ACP_SW2_RX_DP4_FRAME_FORMAT 0x009564 +#define ACP_SW2_RX_DP5_FRAME_FORMAT 0x009568 +#define ACP_SW2_RX_DP6_FRAME_FORMAT 0x00956C +#define ACP_SW2_RX_DP7_FRAME_FORMAT 0x009570 +#define ACP_SW2_RX_DP0_0_SAMPLEINTERVAL_BANK0 0x009580 +#define ACP_SW2_RX_DP0_0_HCTRL_BANK0 0x009584 +#define ACP_SW2_RX_DP0_0_HCTRL_OFFSET_BANK0 0x009588 +#define ACP_SW2_RX_DP0_0_LANE_CTRL_BANK0 0x00958C +#define ACP_SW2_RX_DP0_0_CHANNEL_ENABLE_BANK0 0x009590 +#define ACP_SW2_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009594 +#define ACP_SW2_RX_DP0_0_SAMPLEINTERVAL_BANK1 0x009598 +#define ACP_SW2_RX_DP0_0_HCTRL_BANK1 0x00959C +#define ACP_SW2_RX_DP0_0_HCTRL_OFFSET_BANK1 0x0095A0 +#define ACP_SW2_RX_DP0_0_LANE_CTRL_BANK1 0x0095A4 +#define ACP_SW2_RX_DP0_0_CHANNEL_ENABLE_BANK1 0x0095A8 +#define ACP_SW2_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0095AC +#define ACP_SW2_RX_DP0_1_SAMPLEINTERVAL_BANK0 0x0095B0 +#define ACP_SW2_RX_DP0_1_HCTRL_BANK0 0x0095B4 +#define ACP_SW2_RX_DP0_1_HCTRL_OFFSET_BANK0 0x0095B8 +#define ACP_SW2_RX_DP0_1_LANE_CTRL_BANK0 0x0095BC +#define ACP_SW2_RX_DP0_1_CHANNEL_ENABLE_BANK0 0x0095C0 +#define ACP_SW2_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0095C4 +#define ACP_SW2_RX_DP0_1_SAMPLEINTERVAL_BANK1 0x0095C8 +#define ACP_SW2_RX_DP0_1_HCTRL_BANK1 0x0095CC +#define ACP_SW2_RX_DP0_1_HCTRL_OFFSET_BANK1 0x0095D0 +#define ACP_SW2_RX_DP0_1_LANE_CTRL_BANK1 0x0095D4 +#define ACP_SW2_RX_DP0_1_CHANNEL_ENABLE_BANK1 0x0095D8 +#define ACP_SW2_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0095DC +#define ACP_SW2_RX_DP0_2_SAMPLEINTERVAL_BANK0 0x0095E0 +#define ACP_SW2_RX_DP0_2_HCTRL_BANK0 0x0095E4 +#define ACP_SW2_RX_DP0_2_HCTRL_OFFSET_BANK0 0x0095E8 +#define ACP_SW2_RX_DP0_2_LANE_CTRL_BANK0 0x0095EC +#define ACP_SW2_RX_DP0_2_CHANNEL_ENABLE_BANK0 0x0095F0 +#define ACP_SW2_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0095F4 +#define ACP_SW2_RX_DP0_2_SAMPLEINTERVAL_BANK1 0x0095F8 +#define ACP_SW2_RX_DP0_2_HCTRL_BANK1 0x0095FC +#define ACP_SW2_RX_DP0_2_HCTRL_OFFSET_BANK1 0x009600 +#define ACP_SW2_RX_DP0_2_LANE_CTRL_BANK1 0x009604 +#define ACP_SW2_RX_DP0_2_CHANNEL_ENABLE_BANK1 0x009608 +#define ACP_SW2_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00960C +#define ACP_SW2_RX_DP0_3_SAMPLEINTERVAL_BANK0 0x009610 +#define ACP_SW2_RX_DP0_3_HCTRL_BANK0 0x009614 +#define ACP_SW2_RX_DP0_3_HCTRL_OFFSET_BANK0 0x009618 +#define ACP_SW2_RX_DP0_3_LANE_CTRL_BANK0 0x00961C +#define ACP_SW2_RX_DP0_3_CHANNEL_ENABLE_BANK0 0x009620 +#define ACP_SW2_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009624 +#define ACP_SW2_RX_DP0_3_SAMPLEINTERVAL_BANK1 0x009628 +#define ACP_SW2_RX_DP0_3_HCTRL_BANK1 0x00962C +#define ACP_SW2_RX_DP0_3_HCTRL_OFFSET_BANK1 0x009630 +#define ACP_SW2_RX_DP0_3_LANE_CTRL_BANK1 0x009634 +#define ACP_SW2_RX_DP0_3_CHANNEL_ENABLE_BANK1 0x009638 +#define ACP_SW2_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00963C +#define ACP_SW2_RX_DP1_SAMPLEINTERVAL_BANK0 0x009670 +#define ACP_SW2_RX_DP1_HCTRL_BANK0 0x009674 +#define ACP_SW2_RX_DP1_HCTRL_OFFSET_BANK0 0x009678 +#define ACP_SW2_RX_DP1_LANE_CTRL_BANK0 0x00967C +#define ACP_SW2_RX_DP1_CHANNEL_ENABLE_BANK0 0x009680 +#define ACP_SW2_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009684 +#define ACP_SW2_RX_DP1_SAMPLEINTERVAL_BANK1 0x009688 +#define ACP_SW2_RX_DP1_HCTRL_BANK1 0x00968C +#define ACP_SW2_RX_DP1_HCTRL_OFFSET_BANK1 0x009690 +#define ACP_SW2_RX_DP1_LANE_CTRL_BANK1 0x009694 +#define ACP_SW2_RX_DP1_CHANNEL_ENABLE_BANK1 0x009698 +#define ACP_SW2_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00969C +#define ACP_SW2_RX_DP2_SAMPLEINTERVAL_BANK0 0x0096A0 +#define ACP_SW2_RX_DP2_HCTRL_BANK0 0x0096A4 +#define ACP_SW2_RX_DP2_HCTRL_OFFSET_BANK0 0x0096A8 +#define ACP_SW2_RX_DP2_LANE_CTRL_BANK0 0x0096AC +#define ACP_SW2_RX_DP2_CHANNEL_ENABLE_BANK0 0x0096B0 +#define ACP_SW2_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0096B4 +#define ACP_SW2_RX_DP2_SAMPLEINTERVAL_BANK1 0x0096B8 +#define ACP_SW2_RX_DP2_HCTRL_BANK1 0x0096BC +#define ACP_SW2_RX_DP2_HCTRL_OFFSET_BANK1 0x0096C0 +#define ACP_SW2_RX_DP2_LANE_CTRL_BANK1 0x0096C4 +#define ACP_SW2_RX_DP2_CHANNEL_ENABLE_BANK1 0x0096C8 +#define ACP_SW2_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0096CC +#define ACP_SW2_RX_DP3_SAMPLEINTERVAL_BANK0 0x0096D0 +#define ACP_SW2_RX_DP3_HCTRL_BANK0 0x0096D4 +#define ACP_SW2_RX_DP3_HCTRL_OFFSET_BANK0 0x0096D8 +#define ACP_SW2_RX_DP3_LANE_CTRL_BANK0 0x0096DC +#define ACP_SW2_RX_DP3_CHANNEL_ENABLE_BANK0 0x0096E0 +#define ACP_SW2_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0096E4 +#define ACP_SW2_RX_DP3_SAMPLEINTERVAL_BANK1 0x0096E8 +#define ACP_SW2_RX_DP3_HCTRL_BANK1 0x0096EC +#define ACP_SW2_RX_DP3_HCTRL_OFFSET_BANK1 0x0096F0 +#define ACP_SW2_RX_DP3_LANE_CTRL_BANK1 0x0096F4 +#define ACP_SW2_RX_DP3_CHANNEL_ENABLE_BANK1 0x0096F8 +#define ACP_SW2_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0096FC +#define ACP_SW2_RX_DP4_SAMPLEINTERVAL_BANK0 0x009700 +#define ACP_SW2_RX_DP4_HCTRL_BANK0 0x009704 +#define ACP_SW2_RX_DP4_HCTRL_OFFSET_BANK0 0x009708 +#define ACP_SW2_RX_DP4_LANE_CTRL_BANK0 0x00970C +#define ACP_SW2_RX_DP4_CHANNEL_ENABLE_BANK0 0x009710 +#define ACP_SW2_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009714 +#define ACP_SW2_RX_DP4_SAMPLEINTERVAL_BANK1 0x009718 +#define ACP_SW2_RX_DP4_HCTRL_BANK1 0x00971C +#define ACP_SW2_RX_DP4_HCTRL_OFFSET_BANK1 0x009720 +#define ACP_SW2_RX_DP4_LANE_CTRL_BANK1 0x009724 +#define ACP_SW2_RX_DP4_CHANNEL_ENABLE_BANK1 0x009728 +#define ACP_SW2_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00972C +#define ACP_SW2_RX_DP5_SAMPLEINTERVAL_BANK0 0x009730 +#define ACP_SW2_RX_DP5_HCTRL_BANK0 0x009734 +#define ACP_SW2_RX_DP5_HCTRL_OFFSET_BANK0 0x009738 +#define ACP_SW2_RX_DP5_LANE_CTRL_BANK0 0x00973C +#define ACP_SW2_RX_DP5_CHANNEL_ENABLE_BANK0 0x009740 +#define ACP_SW2_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009744 +#define ACP_SW2_RX_DP5_SAMPLEINTERVAL_BANK1 0x009748 +#define ACP_SW2_RX_DP5_HCTRL_BANK1 0x00974C +#define ACP_SW2_RX_DP5_HCTRL_OFFSET_BANK1 0x009750 +#define ACP_SW2_RX_DP5_LANE_CTRL_BANK1 0x009754 +#define ACP_SW2_RX_DP5_CHANNEL_ENABLE_BANK1 0x009758 +#define ACP_SW2_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00975C +#define ACP_SW2_RX_DP6_SAMPLEINTERVAL_BANK0 0x009760 +#define ACP_SW2_RX_DP6_HCTRL_BANK0 0x009764 +#define ACP_SW2_RX_DP6_HCTRL_OFFSET_BANK0 0x009768 +#define ACP_SW2_RX_DP6_LANE_CTRL_BANK0 0x00976C +#define ACP_SW2_RX_DP6_CHANNEL_ENABLE_BANK0 0x009770 +#define ACP_SW2_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x009774 +#define ACP_SW2_RX_DP6_SAMPLEINTERVAL_BANK1 0x009778 +#define ACP_SW2_RX_DP6_HCTRL_BANK1 0x00977C +#define ACP_SW2_RX_DP6_HCTRL_OFFSET_BANK1 0x009780 +#define ACP_SW2_RX_DP6_LANE_CTRL_BANK1 0x009784 +#define ACP_SW2_RX_DP6_CHANNEL_ENABLE_BANK1 0x009788 +#define ACP_SW2_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00978C +#define ACP_SW2_RX_DP7_SAMPLEINTERVAL_BANK0 0x009790 +#define ACP_SW2_RX_DP7_HCTRL_BANK0 0x009794 +#define ACP_SW2_RX_DP7_HCTRL_OFFSET_BANK0 0x009798 +#define ACP_SW2_RX_DP7_LANE_CTRL_BANK0 0x00979C +#define ACP_SW2_RX_DP7_CHANNEL_ENABLE_BANK0 0x0097A0 +#define ACP_SW2_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x0097A4 +#define ACP_SW2_RX_DP7_SAMPLEINTERVAL_BANK1 0x0097A8 +#define ACP_SW2_RX_DP7_HCTRL_BANK1 0x0097AC +#define ACP_SW2_RX_DP7_HCTRL_OFFSET_BANK1 0x0097B0 +#define ACP_SW2_RX_DP7_LANE_CTRL_BANK1 0x0097B4 +#define ACP_SW2_RX_DP7_CHANNEL_ENABLE_BANK1 0x0097B8 +#define ACP_SW2_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x0097BC +#define ACP_SW2_BPT_PORT_EN 0x0097C0 +#define ACP_SW2_BPT_PORT_EN_STATUS 0x0097C4 +#define ACP_SW2_BPT_PORT_FRAME_FORMAT 0x0097C8 +#define ACP_SW2_BPT_PORT_SAMPLEINTERVAL_BANK0 0x0097CC +#define ACP_SW2_BPT_PORT_HCTRL_BANK0 0x0097D0 +#define ACP_SW2_BPT_PORT_OFFSET_BANK0 0x0097D4 +#define ACP_SW2_BPT_PORT_LANE_SELECT_BANK0 0x0097D8 +#define ACP_SW2_BPT_PORT_CHANNEL_ENABLE_BANK0 0x0097DC +#define ACP_SW2_BPT_PORT_SAMPLEINTERVAL_BANK1 0x0097E0 +#define ACP_SW2_BPT_PORT_HCTRL_BANK1 0x0097E4 +#define ACP_SW2_BPT_PORT_OFFSET_BANK1 0x0097E8 +#define ACP_SW2_BPT_PORT_LANE_SELECT_BANK1 0x0097EC +#define ACP_SW2_BPT_PORT_CHANNEL_ENABLE_BANK1 0x0097F0 +#define ACP_SW2_BPT_PORT_FIRST_BYTE_ADDR 0x0097F4 +#define ACP_SW2_CLK_RESUME_CTRL 0x0097F8 +#define ACP_SW2_CLK_RESUME_DELAY_CNTR 0x0097FC +#define ACP_SW2_BUS_RESET_CTRL 0x009800 +#define ACP_SW2_PRBS_ERR_STATUS 0x009804 +#define ACP_SW2_WALLCLK_MISC 0x009808 +#define ACP_SW2_WALL_CLK_COUNTER 0x00980C +#define ACP_SW2_PING_STATUS_REGISTER_LOW 0x009810 +#define ACP_SW2_PING_STATUS_REGISTER_HIGH 0x009814 +#define ACP_SW2_PING_STATUS_CURRENT_BANK_SEL 0x009818 +#define ACP_SW2_TZD_CHANGE 0x00981C +#define ACP_SW2_WALLCLK_INTR_CNTL 0x009820 + +#define ACP_SW3_GLOBAL_CAPABILITIES 0x00AE00 +#define ACP_SW3_RX_DMA0_RINGBUFADDR 0x00AE04 +#define ACP_SW3_RX_DMA0_RINGBUFSIZE 0x00AE08 +#define ACP_SW3_RX_DMA0_FIFOADDR 0x00AE0C +#define ACP_SW3_RX_DMA0_FIFOSIZE 0x00AE10 +#define ACP_SW3_RX_DMA0_BURST_SIZE 0x00AE14 +#define ACP_SW3_RX_DMA0_LINKPOSITIONCNTR 0x00AE18 +#define ACP_SW3_RX_DMA0_LINEARPOSITIONCNTR_HIGH 0x00AE1C +#define ACP_SW3_RX_DMA0_LINEARPOSITIONCNTR_LOW 0x00AE20 +#define ACP_SW3_RX_DMA0_INTR_WATERMARK_SIZE 0x00AE24 +#define ACP_SW3_RX_DMA1_RINGBUFADDR 0x00AE28 +#define ACP_SW3_RX_DMA1_RINGBUFSIZE 0x00AE2C +#define ACP_SW3_RX_DMA1_FIFOADDR 0x00AE30 +#define ACP_SW3_RX_DMA1_FIFOSIZE 0x00AE34 +#define ACP_SW3_RX_DMA1_BURST_SIZE 0x00AE38 +#define ACP_SW3_RX_DMA1_LINKPOSITIONCNTR 0x00AE3C +#define ACP_SW3_RX_DMA1_LINEARPOSITIONCNTR_HIGH 0x00AE40 +#define ACP_SW3_RX_DMA1_LINEARPOSITIONCNTR_LOW 0x00AE44 +#define ACP_SW3_RX_DMA1_INTR_WATERMARK_SIZE 0x00AE48 +#define ACP_SW3_RX_DMA2_RINGBUFADDR 0x00AE4C +#define ACP_SW3_RX_DMA2_RINGBUFSIZE 0x00AE50 +#define ACP_SW3_RX_DMA2_FIFOADDR 0x00AE54 +#define ACP_SW3_RX_DMA2_FIFOSIZE 0x00AE58 +#define ACP_SW3_RX_DMA2_BURST_SIZE 0x00AE5C +#define ACP_SW3_RX_DMA2_LINKPOSITIONCNTR 0x00AE60 +#define ACP_SW3_RX_DMA2_LINEARPOSITIONCNTR_HIGH 0x00AE64 +#define ACP_SW3_RX_DMA2_LINEARPOSITIONCNTR_LOW 0x00AE68 +#define ACP_SW3_RX_DMA2_INTR_WATERMARK_SIZE 0x00AE6C +#define ACP_SW3_RX_DMA3_RINGBUFADDR 0x00AE70 +#define ACP_SW3_RX_DMA3_RINGBUFSIZE 0x00AE74 +#define ACP_SW3_RX_DMA3_FIFOADDR 0x00AE78 +#define ACP_SW3_RX_DMA3_FIFOSIZE 0x00AE7C +#define ACP_SW3_RX_DMA3_BURST_SIZE 0x00AE80 +#define ACP_SW3_RX_DMA3_LINKPOSITIONCNTR 0x00AE84 +#define ACP_SW3_RX_DMA3_LINEARPOSITIONCNTR_HIGH 0x00AE88 +#define ACP_SW3_RX_DMA3_LINEARPOSITIONCNTR_LOW 0x00AE8C +#define ACP_SW3_RX_DMA3_INTR_WATERMARK_SIZE 0x00AE90 +#define ACP_SW3_RX_DMA4_RINGBUFADDR 0x00AE94 +#define ACP_SW3_RX_DMA4_RINGBUFSIZE 0x00AE98 +#define ACP_SW3_RX_DMA4_FIFOADDR 0x00AE9C +#define ACP_SW3_RX_DMA4_FIFOSIZE 0x00AEA0 +#define ACP_SW3_RX_DMA4_BURST_SIZE 0x00AEA4 +#define ACP_SW3_RX_DMA4_LINKPOSITIONCNTR 0x00AEA8 +#define ACP_SW3_RX_DMA4_LINEARPOSITIONCNTR_HIGH 0x00AEAC +#define ACP_SW3_RX_DMA4_LINEARPOSITIONCNTR_LOW 0x00AEB0 +#define ACP_SW3_RX_DMA4_INTR_WATERMARK_SIZE 0x00AEB4 +#define ACP_SW3_RX_DMA5_RINGBUFADDR 0x00AEB8 +#define ACP_SW3_RX_DMA5_RINGBUFSIZE 0x00AEBC +#define ACP_SW3_RX_DMA5_FIFOADDR 0x00AEC0 +#define ACP_SW3_RX_DMA5_FIFOSIZE 0x00AEC4 +#define ACP_SW3_RX_DMA5_BURST_SIZE 0x00AEC8 +#define ACP_SW3_RX_DMA5_LINKPOSITIONCNTR 0x00AECC +#define ACP_SW3_RX_DMA5_LINEARPOSITIONCNTR_HIGH 0x00AED0 +#define ACP_SW3_RX_DMA5_LINEARPOSITIONCNTR_LOW 0x00AED4 +#define ACP_SW3_RX_DMA5_INTR_WATERMARK_SIZE 0x00AED8 +#define ACP_SW3_RX_DMA6_RINGBUFADDR 0x00AEDC +#define ACP_SW3_RX_DMA6_RINGBUFSIZE 0x00AEE0 +#define ACP_SW3_RX_DMA6_FIFOADDR 0x00AEE4 +#define ACP_SW3_RX_DMA6_FIFOSIZE 0x00AEE8 +#define ACP_SW3_RX_DMA6_BURST_SIZE 0x00AEEC +#define ACP_SW3_RX_DMA6_LINKPOSITIONCNTR 0x00AEF0 +#define ACP_SW3_RX_DMA6_LINEARPOSITIONCNTR_HIGH 0x00AEF4 +#define ACP_SW3_RX_DMA6_LINEARPOSITIONCNTR_LOW 0x00AEF8 +#define ACP_SW3_RX_DMA6_INTR_WATERMARK_SIZE 0x00AEFC +#define ACP_SW3_RX_DMA7_RINGBUFADDR 0x00AF00 +#define ACP_SW3_RX_DMA7_RINGBUFSIZE 0x00AF04 +#define ACP_SW3_RX_DMA7_FIFOADDR 0x00AF08 +#define ACP_SW3_RX_DMA7_FIFOSIZE 0x00AF0C +#define ACP_SW3_RX_DMA7_BURST_SIZE 0x00AF10 +#define ACP_SW3_RX_DMA7_LINKPOSITIONCNTR 0x00AF14 +#define ACP_SW3_RX_DMA7_LINEARPOSITIONCNTR_HIGH 0x00AF18 +#define ACP_SW3_RX_DMA7_LINEARPOSITIONCNTR_LOW 0x00AF1C +#define ACP_SW3_RX_DMA7_INTR_WATERMARK_SIZE 0x00AF20 +#define ACP_SW3_TX_DMA0_RINGBUFADDR 0x00AF24 +#define ACP_SW3_TX_DMA0_RINGBUFSIZE 0x00AF28 +#define ACP_SW3_TX_DMA0_FIFOADDR 0x00AF2C +#define ACP_SW3_TX_DMA0_FIFOSIZE 0x00AF30 +#define ACP_SW3_TX_DMA0_BURST_SIZE 0x00AF34 +#define ACP_SW3_TX_DMA0_LINKPOSITIONCNTR 0x00AF38 +#define ACP_SW3_TX_DMA0_LINEARPOSITIONCNTR_HIGH 0x00AF3C +#define ACP_SW3_TX_DMA0_LINEARPOSITIONCNTR_LOW 0x00AF40 +#define ACP_SW3_TX_DMA0_INTR_WATERMARK_SIZE 0x00AF44 +#define ACP_SW3_TX_DMA1_RINGBUFADDR 0x00AF48 +#define ACP_SW3_TX_DMA1_RINGBUFSIZE 0x00AF4C +#define ACP_SW3_TX_DMA1_FIFOADDR 0x00AF50 +#define ACP_SW3_TX_DMA1_FIFOSIZE 0x00AF54 +#define ACP_SW3_TX_DMA1_BURST_SIZE 0x00AF58 +#define ACP_SW3_TX_DMA1_LINKPOSITIONCNTR 0x00AF5C +#define ACP_SW3_TX_DMA1_LINEARPOSITIONCNTR_HIGH 0x00AF60 +#define ACP_SW3_TX_DMA1_LINEARPOSITIONCNTR_LOW 0x00AF64 +#define ACP_SW3_TX_DMA1_INTR_WATERMARK_SIZE 0x00AF68 +#define ACP_SW3_TX_DMA2_RINGBUFADDR 0x00AF6C +#define ACP_SW3_TX_DMA2_RINGBUFSIZE 0x00AF70 +#define ACP_SW3_TX_DMA2_FIFOADDR 0x00AF74 +#define ACP_SW3_TX_DMA2_FIFOSIZE 0x00AF78 +#define ACP_SW3_TX_DMA2_BURST_SIZE 0x00AF7C +#define ACP_SW3_TX_DMA2_LINKPOSITIONCNTR 0x00AF80 +#define ACP_SW3_TX_DMA2_LINEARPOSITIONCNTR_HIGH 0x00AF84 +#define ACP_SW3_TX_DMA2_LINEARPOSITIONCNTR_LOW 0x00AF88 +#define ACP_SW3_TX_DMA2_INTR_WATERMARK_SIZE 0x00AF8C +#define ACP_SW3_TX_DMA3_RINGBUFADDR 0x00AF90 +#define ACP_SW3_TX_DMA3_RINGBUFSIZE 0x00AF94 +#define ACP_SW3_TX_DMA3_FIFOADDR 0x00AF98 +#define ACP_SW3_TX_DMA3_FIFOSIZE 0x00AF9C +#define ACP_SW3_TX_DMA3_BURST_SIZE 0x00AFA0 +#define ACP_SW3_TX_DMA3_LINKPOSITIONCNTR 0x00AFA4 +#define ACP_SW3_TX_DMA3_LINEARPOSITIONCNTR_HIGH 0x00AFA8 +#define ACP_SW3_TX_DMA3_LINEARPOSITIONCNTR_LOW 0x00AFAC +#define ACP_SW3_TX_DMA3_INTR_WATERMARK_SIZE 0x00AFB0 +#define ACP_SW3_TX_DMA4_RINGBUFADDR 0x00AFB4 +#define ACP_SW3_TX_DMA4_RINGBUFSIZE 0x00AFB8 +#define ACP_SW3_TX_DMA4_FIFOADDR 0x00AFBC +#define ACP_SW3_TX_DMA4_FIFOSIZE 0x00AFC0 +#define ACP_SW3_TX_DMA4_BURST_SIZE 0x00AFC4 +#define ACP_SW3_TX_DMA4_LINKPOSITIONCNTR 0x00AFC8 +#define ACP_SW3_TX_DMA4_LINEARPOSITIONCNTR_HIGH 0x00AFCC +#define ACP_SW3_TX_DMA4_LINEARPOSITIONCNTR_LOW 0x00AFD0 +#define ACP_SW3_TX_DMA4_INTR_WATERMARK_SIZE 0x00AFD4 +#define ACP_SW3_TX_DMA5_RINGBUFADDR 0x00AFD8 +#define ACP_SW3_TX_DMA5_RINGBUFSIZE 0x00AFDC +#define ACP_SW3_TX_DMA5_FIFOADDR 0x00AFE0 +#define ACP_SW3_TX_DMA5_FIFOSIZE 0x00AFE4 +#define ACP_SW3_TX_DMA5_BURST_SIZE 0x00AFE8 +#define ACP_SW3_TX_DMA5_LINKPOSITIONCNTR 0x00AFEC +#define ACP_SW3_TX_DMA5_LINEARPOSITIONCNTR_HIGH 0x00AFF0 +#define ACP_SW3_TX_DMA5_LINEARPOSITIONCNTR_LOW 0x00AFF4 +#define ACP_SW3_TX_DMA5_INTR_WATERMARK_SIZE 0x00AFF8 +#define ACP_SW3_TX_DMA6_RINGBUFADDR 0x00AFFC +#define ACP_SW3_TX_DMA6_RINGBUFSIZE 0x00B000 +#define ACP_SW3_TX_DMA6_FIFOADDR 0x00B004 +#define ACP_SW3_TX_DMA6_FIFOSIZE 0x00B008 +#define ACP_SW3_TX_DMA6_BURST_SIZE 0x00B00C +#define ACP_SW3_TX_DMA6_LINKPOSITIONCNTR 0x00B010 +#define ACP_SW3_TX_DMA6_LINEARPOSITIONCNTR_HIGH 0x00B014 +#define ACP_SW3_TX_DMA6_LINEARPOSITIONCNTR_LOW 0x00B018 +#define ACP_SW3_TX_DMA6_INTR_WATERMARK_SIZE 0x00B01C +#define ACP_SW3_TX_DMA7_RINGBUFADDR 0x00B020 +#define ACP_SW3_TX_DMA7_RINGBUFSIZE 0x00B024 +#define ACP_SW3_TX_DMA7_FIFOADDR 0x00B028 +#define ACP_SW3_TX_DMA7_FIFOSIZE 0x00B02C +#define ACP_SW3_TX_DMA7_BURST_SIZE 0x00B030 +#define ACP_SW3_TX_DMA7_LINKPOSITIONCNTR 0x00B034 +#define ACP_SW3_TX_DMA7_LINEARPOSITIONCNTR_HIGH 0x00B038 +#define ACP_SW3_TX_DMA7_LINEARPOSITIONCNTR_LOW 0x00B03C +#define ACP_SW3_TX_DMA7_INTR_WATERMARK_SIZE 0x00B040 +#define ACP_SW3_RX_DMA0_POS_TRACK 0x00B044 +#define ACP_SW3_RX_DMA0_POS 0x00B048 +#define ACP_SW3_RX_DMA1_POS_TRACK 0x00B04C +#define ACP_SW3_RX_DMA1_POS 0x00B050 +#define ACP_SW3_RX_DMA2_POS_TRACK 0x00B054 +#define ACP_SW3_RX_DMA2_POS 0x00B058 +#define ACP_SW3_RX_DMA3_POS_TRACK 0x00B05C +#define ACP_SW3_RX_DMA3_POS 0x00B060 +#define ACP_SW3_RX_DMA4_POS_TRACK 0x00B064 +#define ACP_SW3_RX_DMA4_POS 0x00B068 +#define ACP_SW3_RX_DMA5_POS_TRACK 0x00B06C +#define ACP_SW3_RX_DMA5_POS 0x00B070 +#define ACP_SW3_RX_DMA6_POS_TRACK 0x00B074 +#define ACP_SW3_RX_DMA6_POS 0x00B078 +#define ACP_SW3_RX_DMA7_POS_TRACK 0x00B07C +#define ACP_SW3_RX_DMA7_POS 0x00B080 +#define ACP_SW3_TX_DMA0_POS_TRACK 0x00B084 +#define ACP_SW3_TX_DMA0_POS 0x00B088 +#define ACP_SW3_TX_DMA1_POS_TRACK 0x00B08C +#define ACP_SW3_TX_DMA1_POS 0x00B090 +#define ACP_SW3_TX_DMA2_POS_TRACK 0x00B094 +#define ACP_SW3_TX_DMA2_POS 0x00B098 +#define ACP_SW3_TX_DMA3_POS_TRACK 0x00B09C +#define ACP_SW3_TX_DMA3_POS 0x00B0A0 +#define ACP_SW3_TX_DMA4_POS_TRACK 0x00B0A4 +#define ACP_SW3_TX_DMA4_POS 0x00B0A8 +#define ACP_SW3_TX_DMA5_POS_TRACK 0x00B0AC +#define ACP_SW3_TX_DMA5_POS 0x00B0B0 +#define ACP_SW3_TX_DMA6_POS_TRACK 0x00B0B4 +#define ACP_SW3_TX_DMA6_POS 0x00B0B8 +#define ACP_SW3_TX_DMA7_POS_TRACK 0x00B0BC +#define ACP_SW3_TX_DMA7_POS 0x00B0C0 +#define ACP_SW3_FIFO_ERROR_REASON 0x00B0C4 +#define ACP_SW3_FIFO_ERROR_INTR_MASK 0x00B0C8 +#define ACP_SW3_ERROR_REASON1 0x00B0CC +#define ACP_SW3_ERROR_INTR_MASK1 0x00B0D0 +#define ACP_SW3_ERROR_REASON2 0x00B0D4 +#define ACP_SW3_ERROR_INTR_MASK2 0x00B0D8 + +#define ACP_SW3_CORB_BASE_ADDRESS 0x00B100 +#define ACP_SW3_CORB_WRITE_POINTER 0x00B104 +#define ACP_SW3_CORB_READ_POINTER 0x00B108 +#define ACP_SW3_CORB_CONTROL 0x00B10C +#define ACP_SW3_CORB_SIZE 0x00B114 +#define ACP_SW3_RIRB_BASE_ADDRESS 0x00B118 +#define ACP_SW3_RIRB_WRITE_POINTER 0x00B11C +#define ACP_SW3_RIRB_RESPONSE_INTERRUPT_COUNT 0x00B120 +#define ACP_SW3_RIRB_CONTROL 0x00B124 +#define ACP_SW3_RIRB_SIZE 0x00B128 +#define ACP_SW3_RIRB_FIFO_MIN_THDL 0x00B12C +#define ACP_SW3_IMM_CMD_UPPER_WORD 0x00B130 +#define ACP_SW3_IMM_CMD_LOWER_QWORD 0x00B134 +#define ACP_SW3_IMM_RESP_UPPER_WORD 0x00B138 +#define ACP_SW3_IMM_RESP_LOWER_QWORD 0x00B13C +#define ACP_SW3_IMM_CMD_STS 0x00B140 +#define ACP_SW3_BRA_BASE_ADDRESS 0x00B144 +#define ACP_SW3_BRA_TRANSFER_SIZE 0x00B148 +#define ACP_SW3_BRA_DMA_BUSY 0x00B14C +#define ACP_SW3_BRA_RESP 0x00B150 +#define ACP_SW3_BRA_RESP_FRAME_ADDR 0x00B154 +#define ACP_SW3_BRA_CURRENT_TRANSFER_SIZE 0x00B158 +#define ACP_SW3_STATE_CHANGE_STATUS_0TO7 0x00B15C +#define ACP_SW3_STATE_CHANGE_STATUS_8TO11 0x00B160 +#define ACP_SW3_STATE_CHANGE_STATUS_MASK_0TO7 0x00B164 +#define ACP_SW3_STATE_CHANGE_STATUS_MASK_8TO11 0x00B168 +#define ACP_SW3_CLK_FREQUENCY_CTRL_BANK0 0x00B16C +#define ACP_SW3_CLK_FREQUENCY_CTRL_BANK1 0x00B170 +#define ACP_SW3_ERROR_INTR_MASK 0x00B174 +#define ACP_SW3_PHY_TEST_MODE_DATA_OFF 0x00B178 +#define ACP_SW3_DATA_TO_PDM_EN 0x00B17C + +#define ACP_SW3_EN 0x00B200 +#define ACP_SW3_EN_STATUS 0x00B204 +#define ACP_SW3_FRAMESIZE_BANK0 0x00B208 +#define ACP_SW3_FRAMESIZE_BANK1 0x00B20C +#define ACP_SW3_SSP_COUNTER 0x00B210 +#define ACP_SW3_TX_STREAM0_EN 0x00B214 +#define ACP_SW3_TX_STREAM1_EN 0x00B218 +#define ACP_SW3_TX_STREAM2_EN 0x00B21C +#define ACP_SW3_TX_STREAM3_EN 0x00B220 +#define ACP_SW3_TX_STREAM4_EN 0x00B224 +#define ACP_SW3_TX_STREAM5_EN 0x00B228 +#define ACP_SW3_TX_STREAM6_EN 0x00B22C +#define ACP_SW3_TX_STREAM7_EN 0x00B230 +#define ACP_SW3_TX_STREAM0_EN_STATUS 0x00B234 +#define ACP_SW3_TX_STREAM1_EN_STATUS 0x00B238 +#define ACP_SW3_TX_STREAM2_EN_STATUS 0x00B23C +#define ACP_SW3_TX_STREAM3_EN_STATUS 0x00B240 +#define ACP_SW3_TX_STREAM4_EN_STATUS 0x00B244 +#define ACP_SW3_TX_STREAM5_EN_STATUS 0x00B248 +#define ACP_SW3_TX_STREAM6_EN_STATUS 0x00B24C +#define ACP_SW3_TX_STREAM7_EN_STATUS 0x00B250 +#define ACP_SW3_TX_DP0_FRAME_FORMAT 0x00B254 +#define ACP_SW3_TX_DP1_FRAME_FORMAT 0x00B258 +#define ACP_SW3_TX_DP2_FRAME_FORMAT 0x00B25C +#define ACP_SW3_TX_DP3_FRAME_FORMAT 0x00B260 +#define ACP_SW3_TX_DP4_FRAME_FORMAT 0x00B264 +#define ACP_SW3_TX_DP5_FRAME_FORMAT 0x00B268 +#define ACP_SW3_TX_DP6_FRAME_FORMAT 0x00B26C +#define ACP_SW3_TX_DP7_FRAME_FORMAT 0x00B270 +#define ACP_SW3_TX_DP0_0_SAMPLEINTERVAL_BANK0 0x00B280 +#define ACP_SW3_TX_DP0_0_HCTRL_BANK0 0x00B284 +#define ACP_SW3_TX_DP0_0_HCTRL_OFFSET_BANK0 0x00B288 +#define ACP_SW3_TX_DP0_0_LANE_CTRL_BANK0 0x00B28C +#define ACP_SW3_TX_DP0_0_CHANNEL_ENABLE_BANK0 0x00B290 +#define ACP_SW3_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B294 +#define ACP_SW3_TX_DP0_0_SAMPLEINTERVAL_BANK1 0x00B298 +#define ACP_SW3_TX_DP0_0_HCTRL_BANK1 0x00B29C +#define ACP_SW3_TX_DP0_0_HCTRL_OFFSET_BANK1 0x00B2A0 +#define ACP_SW3_TX_DP0_0_LANE_CTRL_BANK1 0x00B2A4 +#define ACP_SW3_TX_DP0_0_CHANNEL_ENABLE_BANK1 0x00B2A8 +#define ACP_SW3_TX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B2AC +#define ACP_SW3_TX_DP0_1_SAMPLEINTERVAL_BANK0 0x00B2B0 +#define ACP_SW3_TX_DP0_1_HCTRL_BANK0 0x00B2B4 +#define ACP_SW3_TX_DP0_1_HCTRL_OFFSET_BANK0 0x00B2B8 +#define ACP_SW3_TX_DP0_1_LANE_CTRL_BANK0 0x00B2BC +#define ACP_SW3_TX_DP0_1_CHANNEL_ENABLE_BANK0 0x00B2C0 +#define ACP_SW3_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B2C4 +#define ACP_SW3_TX_DP0_1_SAMPLEINTERVAL_BANK1 0x00B2C8 +#define ACP_SW3_TX_DP0_1_HCTRL_BANK1 0x00B2CC +#define ACP_SW3_TX_DP0_1_HCTRL_OFFSET_BANK1 0x00B2D0 +#define ACP_SW3_TX_DP0_1_LANE_CTRL_BANK1 0x00B2D4 +#define ACP_SW3_TX_DP0_1_CHANNEL_ENABLE_BANK1 0x00B2D8 +#define ACP_SW3_TX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B2DC +#define ACP_SW3_TX_DP0_2_SAMPLEINTERVAL_BANK0 0x00B2E0 +#define ACP_SW3_TX_DP0_2_HCTRL_BANK0 0x00B2E4 +#define ACP_SW3_TX_DP0_2_HCTRL_OFFSET_BANK0 0x00B2E8 +#define ACP_SW3_TX_DP0_2_LANE_CTRL_BANK0 0x00B2EC +#define ACP_SW3_TX_DP0_2_CHANNEL_ENABLE_BANK0 0x00B2F0 +#define ACP_SW3_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B2F4 +#define ACP_SW3_TX_DP0_2_SAMPLEINTERVAL_BANK1 0x00B2F8 +#define ACP_SW3_TX_DP0_2_HCTRL_BANK1 0x00B2FC +#define ACP_SW3_TX_DP0_2_HCTRL_OFFSET_BANK1 0x00B300 +#define ACP_SW3_TX_DP0_2_LANE_CTRL_BANK1 0x00B304 +#define ACP_SW3_TX_DP0_2_CHANNEL_ENABLE_BANK1 0x00B308 +#define ACP_SW3_TX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B30C +#define ACP_SW3_TX_DP0_3_SAMPLEINTERVAL_BANK0 0x00B310 +#define ACP_SW3_TX_DP0_3_HCTRL_BANK0 0x00B314 +#define ACP_SW3_TX_DP0_3_HCTRL_OFFSET_BANK0 0x00B318 +#define ACP_SW3_TX_DP0_3_LANE_CTRL_BANK0 0x00B31C +#define ACP_SW3_TX_DP0_3_CHANNEL_ENABLE_BANK0 0x00B320 +#define ACP_SW3_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B324 +#define ACP_SW3_TX_DP0_3_SAMPLEINTERVAL_BANK1 0x00B328 +#define ACP_SW3_TX_DP0_3_HCTRL_BANK1 0x00B32C +#define ACP_SW3_TX_DP0_3_HCTRL_OFFSET_BANK1 0x00B330 +#define ACP_SW3_TX_DP0_3_LANE_CTRL_BANK1 0x00B334 +#define ACP_SW3_TX_DP0_3_CHANNEL_ENABLE_BANK1 0x00B338 +#define ACP_SW3_TX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B33C +#define ACP_SW3_TX_DP1_SAMPLEINTERVAL_BANK0 0x00B370 +#define ACP_SW3_TX_DP1_HCTRL_BANK0 0x00B374 +#define ACP_SW3_TX_DP1_HCTRL_OFFSET_BANK0 0x00B378 +#define ACP_SW3_TX_DP1_LANE_CTRL_BANK0 0x00B37C +#define ACP_SW3_TX_DP1_CHANNEL_ENABLE_BANK0 0x00B380 +#define ACP_SW3_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B384 +#define ACP_SW3_TX_DP1_SAMPLEINTERVAL_BANK1 0x00B388 +#define ACP_SW3_TX_DP1_HCTRL_BANK1 0x00B38C +#define ACP_SW3_TX_DP1_HCTRL_OFFSET_BANK1 0x00B390 +#define ACP_SW3_TX_DP1_LANE_CTRL_BANK1 0x00B394 +#define ACP_SW3_TX_DP1_CHANNEL_ENABLE_BANK1 0x00B398 +#define ACP_SW3_TX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B39C +#define ACP_SW3_TX_DP2_SAMPLEINTERVAL_BANK0 0x00B3A0 +#define ACP_SW3_TX_DP2_HCTRL_BANK0 0x00B3A4 +#define ACP_SW3_TX_DP2_HCTRL_OFFSET_BANK0 0x00B3A8 +#define ACP_SW3_TX_DP2_LANE_CTRL_BANK0 0x00B3AC +#define ACP_SW3_TX_DP2_CHANNEL_ENABLE_BANK0 0x00B3B0 +#define ACP_SW3_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B3B4 +#define ACP_SW3_TX_DP2_SAMPLEINTERVAL_BANK1 0x00B3B8 +#define ACP_SW3_TX_DP2_HCTRL_BANK1 0x00B3BC +#define ACP_SW3_TX_DP2_HCTRL_OFFSET_BANK1 0x00B3C0 +#define ACP_SW3_TX_DP2_LANE_CTRL_BANK1 0x00B3C4 +#define ACP_SW3_TX_DP2_CHANNEL_ENABLE_BANK1 0x00B3C8 +#define ACP_SW3_TX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B3CC +#define ACP_SW3_TX_DP3_SAMPLEINTERVAL_BANK0 0x00B3D0 +#define ACP_SW3_TX_DP3_HCTRL_BANK0 0x00B3D4 +#define ACP_SW3_TX_DP3_HCTRL_OFFSET_BANK0 0x00B3D8 +#define ACP_SW3_TX_DP3_LANE_CTRL_BANK0 0x00B3DC +#define ACP_SW3_TX_DP3_CHANNEL_ENABLE_BANK0 0x00B3E0 +#define ACP_SW3_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B3E4 +#define ACP_SW3_TX_DP3_SAMPLEINTERVAL_BANK1 0x00B3E8 +#define ACP_SW3_TX_DP3_HCTRL_BANK1 0x00B3EC +#define ACP_SW3_TX_DP3_HCTRL_OFFSET_BANK1 0x00B3F0 +#define ACP_SW3_TX_DP3_LANE_CTRL_BANK1 0x00B3F4 +#define ACP_SW3_TX_DP3_CHANNEL_ENABLE_BANK1 0x00B3F8 +#define ACP_SW3_TX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B3FC +#define ACP_SW3_TX_DP4_SAMPLEINTERVAL_BANK0 0x00B400 +#define ACP_SW3_TX_DP4_HCTRL_BANK0 0x00B404 +#define ACP_SW3_TX_DP4_HCTRL_OFFSET_BANK0 0x00B408 +#define ACP_SW3_TX_DP4_LANE_CTRL_BANK0 0x00B40C +#define ACP_SW3_TX_DP4_CHANNEL_ENABLE_BANK0 0x00B410 +#define ACP_SW3_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B414 +#define ACP_SW3_TX_DP4_SAMPLEINTERVAL_BANK1 0x00B418 +#define ACP_SW3_TX_DP4_HCTRL_BANK1 0x00B41C +#define ACP_SW3_TX_DP4_HCTRL_OFFSET_BANK1 0x00B420 +#define ACP_SW3_TX_DP4_LANE_CTRL_BANK1 0x00B424 +#define ACP_SW3_TX_DP4_CHANNEL_ENABLE_BANK1 0x00B428 +#define ACP_SW3_TX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B42C +#define ACP_SW3_TX_DP5_SAMPLEINTERVAL_BANK0 0x00B430 +#define ACP_SW3_TX_DP5_HCTRL_BANK0 0x00B434 +#define ACP_SW3_TX_DP5_HCTRL_OFFSET_BANK0 0x00B438 +#define ACP_SW3_TX_DP5_LANE_CTRL_BANK0 0x00B43C +#define ACP_SW3_TX_DP5_CHANNEL_ENABLE_BANK0 0x00B440 +#define ACP_SW3_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B444 +#define ACP_SW3_TX_DP5_SAMPLEINTERVAL_BANK1 0x00B448 +#define ACP_SW3_TX_DP5_HCTRL_BANK1 0x00B44C +#define ACP_SW3_TX_DP5_HCTRL_OFFSET_BANK1 0x00B450 +#define ACP_SW3_TX_DP5_LANE_CTRL_BANK1 0x00B454 +#define ACP_SW3_TX_DP5_CHANNEL_ENABLE_BANK1 0x00B458 +#define ACP_SW3_TX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B45C +#define ACP_SW3_TX_DP6_SAMPLEINTERVAL_BANK0 0x00B460 +#define ACP_SW3_TX_DP6_HCTRL_BANK0 0x00B464 +#define ACP_SW3_TX_DP6_HCTRL_OFFSET_BANK0 0x00B468 +#define ACP_SW3_TX_DP6_LANE_CTRL_BANK0 0x00B46C +#define ACP_SW3_TX_DP6_CHANNEL_ENABLE_BANK0 0x00B470 +#define ACP_SW3_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B474 +#define ACP_SW3_TX_DP6_SAMPLEINTERVAL_BANK1 0x00B478 +#define ACP_SW3_TX_DP6_HCTRL_BANK1 0x00B47C +#define ACP_SW3_TX_DP6_HCTRL_OFFSET_BANK1 0x00B480 +#define ACP_SW3_TX_DP6_LANE_CTRL_BANK1 0x00B484 +#define ACP_SW3_TX_DP6_CHANNEL_ENABLE_BANK1 0x00B488 +#define ACP_SW3_TX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B48C +#define ACP_SW3_TX_DP7_SAMPLEINTERVAL_BANK0 0x00B490 +#define ACP_SW3_TX_DP7_HCTRL_BANK0 0x00B494 +#define ACP_SW3_TX_DP7_HCTRL_OFFSET_BANK0 0x00B498 +#define ACP_SW3_TX_DP7_LANE_CTRL_BANK0 0x00B49C +#define ACP_SW3_TX_DP7_CHANNEL_ENABLE_BANK0 0x00B4A0 +#define ACP_SW3_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B4A4 +#define ACP_SW3_TX_DP7_SAMPLEINTERVAL_BANK1 0x00B4A8 +#define ACP_SW3_TX_DP7_HCTRL_BANK1 0x00B4AC +#define ACP_SW3_TX_DP7_HCTRL_OFFSET_BANK1 0x00B4B0 +#define ACP_SW3_TX_DP7_LANE_CTRL_BANK1 0x00B4B4 +#define ACP_SW3_TX_DP7_CHANNEL_ENABLE_BANK1 0x00B4B8 +#define ACP_SW3_TX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B4BC +#define ACP_SW3_RX_STREAM0_EN 0x00B514 +#define ACP_SW3_RX_STREAM1_EN 0x00B518 +#define ACP_SW3_RX_STREAM2_EN 0x00B51C +#define ACP_SW3_RX_STREAM3_EN 0x00B520 +#define ACP_SW3_RX_STREAM4_EN 0x00B524 +#define ACP_SW3_RX_STREAM5_EN 0x00B528 +#define ACP_SW3_RX_STREAM6_EN 0x00B52C +#define ACP_SW3_RX_STREAM7_EN 0x00B530 +#define ACP_SW3_RX_STREAM0_EN_STATUS 0x00B534 +#define ACP_SW3_RX_STREAM1_EN_STATUS 0x00B538 +#define ACP_SW3_RX_STREAM2_EN_STATUS 0x00B53C +#define ACP_SW3_RX_STREAM3_EN_STATUS 0x00B540 +#define ACP_SW3_RX_STREAM4_EN_STATUS 0x00B544 +#define ACP_SW3_RX_STREAM5_EN_STATUS 0x00B548 +#define ACP_SW3_RX_STREAM6_EN_STATUS 0x00B54C +#define ACP_SW3_RX_STREAM7_EN_STATUS 0x00B550 +#define ACP_SW3_RX_DP0_FRAME_FORMAT 0x00B554 +#define ACP_SW3_RX_DP1_FRAME_FORMAT 0x00B558 +#define ACP_SW3_RX_DP2_FRAME_FORMAT 0x00B55C +#define ACP_SW3_RX_DP3_FRAME_FORMAT 0x00B560 +#define ACP_SW3_RX_DP4_FRAME_FORMAT 0x00B564 +#define ACP_SW3_RX_DP5_FRAME_FORMAT 0x00B568 +#define ACP_SW3_RX_DP6_FRAME_FORMAT 0x00B56C +#define ACP_SW3_RX_DP7_FRAME_FORMAT 0x00B570 +#define ACP_SW3_RX_DP0_0_SAMPLEINTERVAL_BANK0 0x00B580 +#define ACP_SW3_RX_DP0_0_HCTRL_BANK0 0x00B584 +#define ACP_SW3_RX_DP0_0_HCTRL_OFFSET_BANK0 0x00B588 +#define ACP_SW3_RX_DP0_0_LANE_CTRL_BANK0 0x00B58C +#define ACP_SW3_RX_DP0_0_CHANNEL_ENABLE_BANK0 0x00B590 +#define ACP_SW3_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B594 +#define ACP_SW3_RX_DP0_0_SAMPLEINTERVAL_BANK1 0x00B598 +#define ACP_SW3_RX_DP0_0_HCTRL_BANK1 0x00B59C +#define ACP_SW3_RX_DP0_0_HCTRL_OFFSET_BANK1 0x00B5A0 +#define ACP_SW3_RX_DP0_0_LANE_CTRL_BANK1 0x00B5A4 +#define ACP_SW3_RX_DP0_0_CHANNEL_ENABLE_BANK1 0x00B5A8 +#define ACP_SW3_RX_DP0_0_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B5AC +#define ACP_SW3_RX_DP0_1_SAMPLEINTERVAL_BANK0 0x00B5B0 +#define ACP_SW3_RX_DP0_1_HCTRL_BANK0 0x00B5B4 +#define ACP_SW3_RX_DP0_1_HCTRL_OFFSET_BANK0 0x00B5B8 +#define ACP_SW3_RX_DP0_1_LANE_CTRL_BANK0 0x00B5BC +#define ACP_SW3_RX_DP0_1_CHANNEL_ENABLE_BANK0 0x00B5C0 +#define ACP_SW3_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B5C4 +#define ACP_SW3_RX_DP0_1_SAMPLEINTERVAL_BANK1 0x00B5C8 +#define ACP_SW3_RX_DP0_1_HCTRL_BANK1 0x00B5CC +#define ACP_SW3_RX_DP0_1_HCTRL_OFFSET_BANK1 0x00B5D0 +#define ACP_SW3_RX_DP0_1_LANE_CTRL_BANK1 0x00B5D4 +#define ACP_SW3_RX_DP0_1_CHANNEL_ENABLE_BANK1 0x00B5D8 +#define ACP_SW3_RX_DP0_1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B5DC +#define ACP_SW3_RX_DP0_2_SAMPLEINTERVAL_BANK0 0x00B5E0 +#define ACP_SW3_RX_DP0_2_HCTRL_BANK0 0x00B5E4 +#define ACP_SW3_RX_DP0_2_HCTRL_OFFSET_BANK0 0x00B5E8 +#define ACP_SW3_RX_DP0_2_LANE_CTRL_BANK0 0x00B5EC +#define ACP_SW3_RX_DP0_2_CHANNEL_ENABLE_BANK0 0x00B5F0 +#define ACP_SW3_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B5F4 +#define ACP_SW3_RX_DP0_2_SAMPLEINTERVAL_BANK1 0x00B5F8 +#define ACP_SW3_RX_DP0_2_HCTRL_BANK1 0x00B5FC +#define ACP_SW3_RX_DP0_2_HCTRL_OFFSET_BANK1 0x00B600 +#define ACP_SW3_RX_DP0_2_LANE_CTRL_BANK1 0x00B604 +#define ACP_SW3_RX_DP0_2_CHANNEL_ENABLE_BANK1 0x00B608 +#define ACP_SW3_RX_DP0_2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B60C +#define ACP_SW3_RX_DP0_3_SAMPLEINTERVAL_BANK0 0x00B610 +#define ACP_SW3_RX_DP0_3_HCTRL_BANK0 0x00B614 +#define ACP_SW3_RX_DP0_3_HCTRL_OFFSET_BANK0 0x00B618 +#define ACP_SW3_RX_DP0_3_LANE_CTRL_BANK0 0x00B61C +#define ACP_SW3_RX_DP0_3_CHANNEL_ENABLE_BANK0 0x00B620 +#define ACP_SW3_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B624 +#define ACP_SW3_RX_DP0_3_SAMPLEINTERVAL_BANK1 0x00B628 +#define ACP_SW3_RX_DP0_3_HCTRL_BANK1 0x00B62C +#define ACP_SW3_RX_DP0_3_HCTRL_OFFSET_BANK1 0x00B630 +#define ACP_SW3_RX_DP0_3_LANE_CTRL_BANK1 0x00B634 +#define ACP_SW3_RX_DP0_3_CHANNEL_ENABLE_BANK1 0x00B638 +#define ACP_SW3_RX_DP0_3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B63C +#define ACP_SW3_RX_DP1_SAMPLEINTERVAL_BANK0 0x00B670 +#define ACP_SW3_RX_DP1_HCTRL_BANK0 0x00B674 +#define ACP_SW3_RX_DP1_HCTRL_OFFSET_BANK0 0x00B678 +#define ACP_SW3_RX_DP1_LANE_CTRL_BANK0 0x00B67C +#define ACP_SW3_RX_DP1_CHANNEL_ENABLE_BANK0 0x00B680 +#define ACP_SW3_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B684 +#define ACP_SW3_RX_DP1_SAMPLEINTERVAL_BANK1 0x00B688 +#define ACP_SW3_RX_DP1_HCTRL_BANK1 0x00B68C +#define ACP_SW3_RX_DP1_HCTRL_OFFSET_BANK1 0x00B690 +#define ACP_SW3_RX_DP1_LANE_CTRL_BANK1 0x00B694 +#define ACP_SW3_RX_DP1_CHANNEL_ENABLE_BANK1 0x00B698 +#define ACP_SW3_RX_DP1_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B69C +#define ACP_SW3_RX_DP2_SAMPLEINTERVAL_BANK0 0x00B6A0 +#define ACP_SW3_RX_DP2_HCTRL_BANK0 0x00B6A4 +#define ACP_SW3_RX_DP2_HCTRL_OFFSET_BANK0 0x00B6A8 +#define ACP_SW3_RX_DP2_LANE_CTRL_BANK0 0x00B6AC +#define ACP_SW3_RX_DP2_CHANNEL_ENABLE_BANK0 0x00B6B0 +#define ACP_SW3_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B6B4 +#define ACP_SW3_RX_DP2_SAMPLEINTERVAL_BANK1 0x00B6B8 +#define ACP_SW3_RX_DP2_HCTRL_BANK1 0x00B6BC +#define ACP_SW3_RX_DP2_HCTRL_OFFSET_BANK1 0x00B6C0 +#define ACP_SW3_RX_DP2_LANE_CTRL_BANK1 0x00B6C4 +#define ACP_SW3_RX_DP2_CHANNEL_ENABLE_BANK1 0x00B6C8 +#define ACP_SW3_RX_DP2_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B6CC +#define ACP_SW3_RX_DP3_SAMPLEINTERVAL_BANK0 0x00B6D0 +#define ACP_SW3_RX_DP3_HCTRL_BANK0 0x00B6D4 +#define ACP_SW3_RX_DP3_HCTRL_OFFSET_BANK0 0x00B6D8 +#define ACP_SW3_RX_DP3_LANE_CTRL_BANK0 0x00B6DC +#define ACP_SW3_RX_DP3_CHANNEL_ENABLE_BANK0 0x00B6E0 +#define ACP_SW3_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B6E4 +#define ACP_SW3_RX_DP3_SAMPLEINTERVAL_BANK1 0x00B6E8 +#define ACP_SW3_RX_DP3_HCTRL_BANK1 0x00B6EC +#define ACP_SW3_RX_DP3_HCTRL_OFFSET_BANK1 0x00B6F0 +#define ACP_SW3_RX_DP3_LANE_CTRL_BANK1 0x00B6F4 +#define ACP_SW3_RX_DP3_CHANNEL_ENABLE_BANK1 0x00B6F8 +#define ACP_SW3_RX_DP3_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B6FC +#define ACP_SW3_RX_DP4_SAMPLEINTERVAL_BANK0 0x00B700 +#define ACP_SW3_RX_DP4_HCTRL_BANK0 0x00B704 +#define ACP_SW3_RX_DP4_HCTRL_OFFSET_BANK0 0x00B708 +#define ACP_SW3_RX_DP4_LANE_CTRL_BANK0 0x00B70C +#define ACP_SW3_RX_DP4_CHANNEL_ENABLE_BANK0 0x00B710 +#define ACP_SW3_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B714 +#define ACP_SW3_RX_DP4_SAMPLEINTERVAL_BANK1 0x00B718 +#define ACP_SW3_RX_DP4_HCTRL_BANK1 0x00B71C +#define ACP_SW3_RX_DP4_HCTRL_OFFSET_BANK1 0x00B720 +#define ACP_SW3_RX_DP4_LANE_CTRL_BANK1 0x00B724 +#define ACP_SW3_RX_DP4_CHANNEL_ENABLE_BANK1 0x00B728 +#define ACP_SW3_RX_DP4_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B72C +#define ACP_SW3_RX_DP5_SAMPLEINTERVAL_BANK0 0x00B730 +#define ACP_SW3_RX_DP5_HCTRL_BANK0 0x00B734 +#define ACP_SW3_RX_DP5_HCTRL_OFFSET_BANK0 0x00B738 +#define ACP_SW3_RX_DP5_LANE_CTRL_BANK0 0x00B73C +#define ACP_SW3_RX_DP5_CHANNEL_ENABLE_BANK0 0x00B740 +#define ACP_SW3_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B744 +#define ACP_SW3_RX_DP5_SAMPLEINTERVAL_BANK1 0x00B748 +#define ACP_SW3_RX_DP5_HCTRL_BANK1 0x00B74C +#define ACP_SW3_RX_DP5_HCTRL_OFFSET_BANK1 0x00B750 +#define ACP_SW3_RX_DP5_LANE_CTRL_BANK1 0x00B754 +#define ACP_SW3_RX_DP5_CHANNEL_ENABLE_BANK1 0x00B758 +#define ACP_SW3_RX_DP5_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B75C +#define ACP_SW3_RX_DP6_SAMPLEINTERVAL_BANK0 0x00B760 +#define ACP_SW3_RX_DP6_HCTRL_BANK0 0x00B764 +#define ACP_SW3_RX_DP6_HCTRL_OFFSET_BANK0 0x00B768 +#define ACP_SW3_RX_DP6_LANE_CTRL_BANK0 0x00B76C +#define ACP_SW3_RX_DP6_CHANNEL_ENABLE_BANK0 0x00B770 +#define ACP_SW3_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B774 +#define ACP_SW3_RX_DP6_SAMPLEINTERVAL_BANK1 0x00B778 +#define ACP_SW3_RX_DP6_HCTRL_BANK1 0x00B77C +#define ACP_SW3_RX_DP6_HCTRL_OFFSET_BANK1 0x00B780 +#define ACP_SW3_RX_DP6_LANE_CTRL_BANK1 0x00B784 +#define ACP_SW3_RX_DP6_CHANNEL_ENABLE_BANK1 0x00B788 +#define ACP_SW3_RX_DP6_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B78C +#define ACP_SW3_RX_DP7_SAMPLEINTERVAL_BANK0 0x00B790 +#define ACP_SW3_RX_DP7_HCTRL_BANK0 0x00B794 +#define ACP_SW3_RX_DP7_HCTRL_OFFSET_BANK0 0x00B798 +#define ACP_SW3_RX_DP7_LANE_CTRL_BANK0 0x00B79C +#define ACP_SW3_RX_DP7_CHANNEL_ENABLE_BANK0 0x00B7A0 +#define ACP_SW3_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK0 0x00B7A4 +#define ACP_SW3_RX_DP7_SAMPLEINTERVAL_BANK1 0x00B7A8 +#define ACP_SW3_RX_DP7_HCTRL_BANK1 0x00B7AC +#define ACP_SW3_RX_DP7_HCTRL_OFFSET_BANK1 0x00B7B0 +#define ACP_SW3_RX_DP7_LANE_CTRL_BANK1 0x00B7B4 +#define ACP_SW3_RX_DP7_CHANNEL_ENABLE_BANK1 0x00B7B8 +#define ACP_SW3_RX_DP7_BLOCK_PKGMODE_GRPCTRL_BANK1 0x00B7BC +#define ACP_SW3_BPT_PORT_EN 0x00B7C0 +#define ACP_SW3_BPT_PORT_EN_STATUS 0x00B7C4 +#define ACP_SW3_BPT_PORT_FRAME_FORMAT 0x00B7C8 +#define ACP_SW3_BPT_PORT_SAMPLEINTERVAL_BANK0 0x00B7CC +#define ACP_SW3_BPT_PORT_HCTRL_BANK0 0x00B7D0 +#define ACP_SW3_BPT_PORT_OFFSET_BANK0 0x00B7D4 +#define ACP_SW3_BPT_PORT_LANE_SELECT_BANK0 0x00B7D8 +#define ACP_SW3_BPT_PORT_CHANNEL_ENABLE_BANK0 0x00B7DC +#define ACP_SW3_BPT_PORT_SAMPLEINTERVAL_BANK1 0x00B7E0 +#define ACP_SW3_BPT_PORT_HCTRL_BANK1 0x00B7E4 +#define ACP_SW3_BPT_PORT_OFFSET_BANK1 0x00B7E8 +#define ACP_SW3_BPT_PORT_LANE_SELECT_BANK1 0x00B7EC +#define ACP_SW3_BPT_PORT_CHANNEL_ENABLE_BANK1 0x00B7F0 +#define ACP_SW3_BPT_PORT_FIRST_BYTE_ADDR 0x00B7F4 +#define ACP_SW3_CLK_RESUME_CTRL 0x00B7F8 +#define ACP_SW3_CLK_RESUME_DELAY_CNTR 0x00B7FC +#define ACP_SW3_BUS_RESET_CTRL 0x00B800 +#define ACP_SW3_PRBS_ERR_STATUS 0x00B804 +#define ACP_SW3_WALLCLK_MISC 0x00B808 +#define ACP_SW3_WALL_CLK_COUNTER 0x00B80C +#define ACP_SW3_PING_STATUS_REGISTER_LOW 0x00B810 +#define ACP_SW3_PING_STATUS_REGISTER_HIGH 0x00B814 +#define ACP_SW3_PING_STATUS_CURRENT_BANK_SEL 0x00B818 +#define ACP_SW3_TZD_CHANGE 0x00B81C +#define ACP_SW3_WALLCLK_INTR_CNTL 0x00B820 + +#define ACP_PDM_ENABLE 0x002C04 +#define ACP_PDM_DMA_ENABLE 0x002C08 +#define ACP_PDM_RX_RINGBUFADDR 0x002C0C +#define ACP_PDM_RX_RINGBUFSIZE 0x002C10 +#define ACP_PDM_RX_LINKPOSITIONCNTR 0x002C14 +#define ACP_PDM_RX_LINEARPOSITIONCNTR_HIGH 0x002C18 +#define ACP_PDM_RX_LINEARPOSITIONCNTR_LOW 0x002C1C +#define ACP_PDM_RX_INTR_WATERMARK_SIZE 0x002C20 +#define ACP_PDM_FIFO_FLUSH 0x002C24 +#define ACP_PDM_NO_OF_CHANNELS 0x002C28 +#define ACP_PDM_DECIMATION_FACTOR 0x002C2C +#define ACP_PDM_VAD_CTRL 0x002C30 +#define ACP_PDM_WAKE 0x002C54 +#define ACP_PDM_BUFFER_STATUS 0x002C58 +#define ACP_PDM_MISC_CTRL 0x002C5C +#define ACP_PDM_CLK_CTRL 0x002C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x002C64 +#define ACP_PDM_ERROR_STATUS_REGISTER 0x002C68 +#define ACP_PDM_CLKDIV 0x002C6C +#define ACP_PDM_WALLCLK_MISC 0x002C70 +#define ACP_PDM_WALL_CLK_COUNTER 0x002C74 +#define ACP_PDM_SW_ENABLE_REG 0x002CC4 +#define ACP_PDM_SW_CTRLREG 0x002CC8 +#define ACP_PDM_WALLCLK_INTR_CNTL 0x002CCC + +#define ACP_PDM_2_ENABLE 0x002D04 +#define ACP_PDM_2_DMA_ENABLE 0x002D08 +#define ACP_PDM_2_RX_RINGBUFADDR_96K 0x002D0C +#define ACP_PDM_2_RX_RINGBUFADDR_48K 0x002D10 +#define ACP_PDM_2_RX_RINGBUFADDR_16K 0x002D14 +#define ACP_PDM_2_RX_RINGBUFSIZE_96K 0x002D18 +#define ACP_PDM_2_RX_RINGBUFSIZE_48K 0x002D1C +#define ACP_PDM_2_RX_RINGBUFSIZE_16K 0x002D20 +#define ACP_PDM_2_RX_LINKPOSITIONCNTR_96K 0x002D24 +#define ACP_PDM_2_RX_LINKPOSITIONCNTR_48K 0x002D28 +#define ACP_PDM_2_RX_LINKPOSITIONCNTR_16K 0x002D2C +#define ACP_PDM_2_RX_LINEARPOSITIONCNTR_HIGH_96K 0x002D30 +#define ACP_PDM_2_RX_LINEARPOSITIONCNTR_LOW_96K 0x002D34 +#define ACP_PDM_2_RX_LINEARPOSITIONCNTR_HIGH_48K 0x002D38 +#define ACP_PDM_2_RX_LINEARPOSITIONCNTR_LOW_48K 0x002D3C +#define ACP_PDM_2_RX_LINEARPOSITIONCNTR_HIGH_16K 0x002D40 +#define ACP_PDM_2_RX_LINEARPOSITIONCNTR_LOW_16K 0x002D44 +#define ACP_PDM_2_RX_INTR_WATERMARK_SIZE_96K 0x002D48 +#define ACP_PDM_2_RX_INTR_WATERMARK_SIZE_48K 0x002D4C +#define ACP_PDM_2_RX_INTR_WATERMARK_SIZE_16K 0x002D50 +#define ACP_PDM_2_FIFO_FLUSH_96K 0x002D54 +#define ACP_PDM_2_FIFO_FLUSH_48K 0x002D58 +#define ACP_PDM_2_FIFO_FLUSH_16K 0x002D5C +#define ACP_PDM_2_NO_OF_CHANNELS 0x002D60 +#define ACP_PDM_2_DECIMATION_FACTOR 0x002D64 +#define ACP_PDM_2_VAD_CTRL 0x002D68 +#define ACP_PDM_2_WAKE 0x002D6C +#define ACP_PDM_2_BUFFER_STATUS_96K 0x002D70 +#define ACP_PDM_2_BUFFER_STATUS_48K 0x002D74 +#define ACP_PDM_2_BUFFER_STATUS_16K 0x002D78 +#define ACP_PDM_2_MISC_CTRL 0x002D7C +#define ACP_PDM_2_CLK_CTRL 0x002D80 +#define ACP_PDM_2_VAD_DYNAMIC_CLK_GATING_EN 0x002D84 +#define ACP_PDM_2_ERROR_STATUS_REGISTER 0x002D8C +#define ACP_PDM_2_CLKDIV 0x002D90 +#define ACP_PDM_2_WALLCLK_MISC 0x002D94 +#define ACP_PDM_2_WALL_CLK_COUNTER 0x002D98 +#define ACP_PDM_2_SW_ENABLE_REG 0x002D9C +#define ACP_PDM_2_SW_CTRLREG 0x002DA0 +#define ACP_PDM_2_WALLCLK_INTR_CNTL 0x002DA4 + +#define ACP_SCRATCH_REG_0 0x0010000 +#endif diff --git a/include/sound/core.h b/include/sound/core.h index 4093ec82a0a1..404785b7d885 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -75,6 +75,27 @@ struct snd_device { #define snd_device(n) list_entry(n, struct snd_device, list) +/* + * A simple reference counter with a wait queue; + * typically used for usage counts, and you can synchronize at finishing + * via snd_refcount_sync(), which is woken up when the refcount reaches to + * zero again. + */ +struct snd_refcount { + atomic_t count; + wait_queue_head_t waiter; +}; + +void snd_refcount_init(struct snd_refcount *ref); + +static inline void snd_refcount_get(struct snd_refcount *ref) +{ + atomic_inc(&ref->count); +} + +void snd_refcount_put(struct snd_refcount *ref); +void snd_refcount_sync(struct snd_refcount *ref); + /* main structure for soundcard */ struct snd_card { @@ -139,15 +160,16 @@ struct snd_card { #ifdef CONFIG_PM unsigned int power_state; /* power state */ - atomic_t power_ref; wait_queue_head_t power_sleep; - wait_queue_head_t power_ref_sleep; + struct snd_refcount power_ref; #endif #if IS_ENABLED(CONFIG_SND_MIXER_OSS) struct snd_mixer_oss *mixer_oss; int mixer_oss_change_count; #endif + + unsigned char private_data_area[] __aligned(__alignof__(unsigned long long)); }; #define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev) @@ -174,7 +196,7 @@ static inline void snd_power_change_state(struct snd_card *card, unsigned int st */ static inline void snd_power_ref(struct snd_card *card) { - atomic_inc(&card->power_ref); + snd_refcount_get(&card->power_ref); } /** @@ -183,8 +205,7 @@ static inline void snd_power_ref(struct snd_card *card) */ static inline void snd_power_unref(struct snd_card *card) { - if (atomic_dec_and_test(&card->power_ref)) - wake_up(&card->power_ref_sleep); + snd_refcount_put(&card->power_ref); } /** @@ -196,7 +217,7 @@ static inline void snd_power_unref(struct snd_card *card) */ static inline void snd_power_sync_ref(struct snd_card *card) { - wait_event(card->power_ref_sleep, !atomic_read(&card->power_ref)); + snd_refcount_sync(&card->power_ref); } /* init.c */ @@ -317,6 +338,8 @@ static inline void snd_card_unref(struct snd_card *card) put_device(&card->card_dev); } +DEFINE_FREE(snd_card_unref, struct snd_card *, if (_T) snd_card_unref(_T)) + #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) /* device.c */ diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index c3b10587cb4c..2490b72c0a7a 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -286,6 +286,8 @@ struct snd_ctl_elem_value; #define CS35L56_MBOX_TIMEOUT_US 5000 #define CS35L56_MBOX_POLL_US 250 +#define CS35L56_FW_REQ_ACTIVE_TIMEOUT_MS 250 + #define CS35L56_PS0_POLL_US 500 #define CS35L56_PS0_TIMEOUT_US 50000 #define CS35L56_PS3_POLL_US 500 diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h index 3f7f365ed248..2c0a976e00ab 100644 --- a/include/sound/emux_synth.h +++ b/include/sound/emux_synth.h @@ -125,7 +125,6 @@ struct snd_emux { */ struct snd_emux_port { - struct snd_midi_channel_set chset; struct snd_emux *emu; char port_mode; /* operation mode */ @@ -138,6 +137,7 @@ struct snd_emux_port { #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) struct snd_seq_oss_arg *oss_arg; #endif + struct snd_midi_channel_set chset; }; /* port_mode */ diff --git a/include/sound/hda-mlink.h b/include/sound/hda-mlink.h index 4327317be6af..fed69998c93f 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -60,7 +60,7 @@ struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus); struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid); -int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable); +void hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable); /* microphone privacy specific function supported by ACE3+ architecture */ void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid, @@ -186,10 +186,9 @@ hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus) { return NULL; } static inline struct mutex * hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid) { return NULL; } -static inline int +static inline void hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) { - return 0; } static inline void diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 24581080e26a..17945ab5e6e2 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -188,8 +188,7 @@ struct hda_codec { /* PCM to create, set by hda_codec_ops.build_pcms callback */ struct list_head pcm_list_head; - refcount_t pcm_ref; - wait_queue_head_t remove_sleep; + struct snd_refcount pcm_ref; /* codec specific info */ void *spec; @@ -259,6 +258,7 @@ struct hda_codec { unsigned int forced_resume:1; /* forced resume for jack */ unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */ unsigned int ctl_dev_id:1; /* old control element id build behaviour */ + unsigned int eld_jack_detect:1; /* Machine jack-detection by ELD */ unsigned long power_on_acct; unsigned long power_off_acct; @@ -438,9 +438,12 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); static inline void snd_hda_codec_pcm_get(struct hda_pcm *pcm) { - refcount_inc(&pcm->codec->pcm_ref); + snd_refcount_get(&pcm->codec->pcm_ref); +} +static inline void snd_hda_codec_pcm_put(struct hda_pcm *pcm) +{ + snd_refcount_put(&pcm->codec->pcm_ref); } -void snd_hda_codec_pcm_put(struct hda_pcm *pcm); int snd_hda_codec_prepare(struct hda_codec *codec, struct hda_pcm_stream *hinfo, diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h index 0a6f8dabf8c4..2d86f62f9408 100644 --- a/include/sound/pxa2xx-lib.h +++ b/include/sound/pxa2xx-lib.h @@ -2,55 +2,7 @@ #ifndef PXA2XX_LIB_H #define PXA2XX_LIB_H -#include -#include - -/* PCM */ -struct snd_pcm_substream; -struct snd_pcm_hw_params; -struct snd_soc_pcm_runtime; -struct snd_pcm; -struct snd_soc_component; - -extern int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params); -extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd); -extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream); -extern int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream); -extern int pxa2xx_pcm_open(struct snd_pcm_substream *substream); -extern int pxa2xx_pcm_close(struct snd_pcm_substream *substream); -extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm); -extern int pxa2xx_soc_pcm_new(struct snd_soc_component *component, - struct snd_soc_pcm_runtime *rtd); -extern int pxa2xx_soc_pcm_open(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -extern int pxa2xx_soc_pcm_close(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -extern int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params); -extern int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, int cmd); -extern snd_pcm_uframes_t -pxa2xx_soc_pcm_pointer(struct snd_soc_component *component, - struct snd_pcm_substream *substream); - -/* AC97 */ - -extern int pxa2xx_ac97_read(int slot, unsigned short reg); -extern int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val); - -extern bool pxa2xx_ac97_try_warm_reset(void); -extern bool pxa2xx_ac97_try_cold_reset(void); -extern void pxa2xx_ac97_finish_reset(void); - -extern int pxa2xx_ac97_hw_suspend(void); -extern int pxa2xx_ac97_hw_resume(void); - -extern int pxa2xx_ac97_hw_probe(struct platform_device *dev); -extern void pxa2xx_ac97_hw_remove(struct platform_device *dev); +#include /* modem registers, used by touchscreen driver */ u32 pxa2xx_ac97_read_modr(void); diff --git a/include/sound/sdca.h b/include/sound/sdca.h index 67ff3c88705d..2bdf4e333e04 100644 --- a/include/sound/sdca.h +++ b/include/sound/sdca.h @@ -26,6 +26,8 @@ struct sdca_dev; * @name: Human-readable string. * @type: Function topology type. * @adr: ACPI address (used for SDCA register access). + * @duplicate: Internal flag to indicate if other functions of the same type + * exist. */ struct sdca_function_desc { struct fwnode_handle *node; @@ -33,6 +35,8 @@ struct sdca_function_desc { const char *name; u32 type; u8 adr; + + bool duplicate; }; /** diff --git a/include/sound/sdca_asoc.h b/include/sound/sdca_asoc.h index 46a61a52decc..ca35d5a44370 100644 --- a/include/sound/sdca_asoc.h +++ b/include/sound/sdca_asoc.h @@ -13,6 +13,7 @@ struct device; struct regmap; struct sdca_function_data; +struct sdca_pde_delay; struct snd_ctl_elem_value; struct snd_kcontrol; struct snd_kcontrol_new; @@ -99,4 +100,9 @@ int sdca_asoc_q78_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int sdca_asoc_q78_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int sdca_asoc_pde_poll_actual_ps(struct device *dev, struct regmap *regmap, + int function_id, int entity_id, + int from_ps, int to_ps, + const struct sdca_pde_delay *pde_delays, + int num_delays); #endif // __SDCA_ASOC_H__ diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h index 0e871c786513..b1489178b0ef 100644 --- a/include/sound/sdca_function.h +++ b/include/sound/sdca_function.h @@ -1452,7 +1452,6 @@ static inline u32 sdca_range_search(struct sdca_control_range *range, } int sdca_parse_function(struct device *dev, struct sdw_slave *sdw, - struct sdca_function_desc *desc, struct sdca_function_data *function); const char *sdca_find_terminal_name(enum sdca_terminal_type type); diff --git a/include/sound/sdca_jack.h b/include/sound/sdca_jack.h index 3ec22046d3eb..181541f0f4d8 100644 --- a/include/sound/sdca_jack.h +++ b/include/sound/sdca_jack.h @@ -18,10 +18,13 @@ struct snd_soc_jack; * struct jack_state - Jack state structure to keep data between interrupts * @kctl: Pointer to the ALSA control attached to this jack * @jack: Pointer to the ASoC jack struct for this jack + * @mask: Possible reported jack status bits for this jack */ struct jack_state { struct snd_kcontrol *kctl; struct snd_soc_jack *jack; + + unsigned int mask; }; int sdca_jack_alloc_state(struct sdca_interrupt *interrupt); diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h index a72380c202e9..3137d4c5f5a8 100644 --- a/include/sound/seq_device.h +++ b/include/sound/seq_device.h @@ -22,6 +22,7 @@ struct snd_seq_device { void *private_data; /* private data for the caller */ void (*private_free)(struct snd_seq_device *device); struct device dev; + unsigned char args[]; /* driver-specific argument */ }; #define to_seq_dev(_dev) \ @@ -64,7 +65,7 @@ void snd_seq_device_load_drivers(void); int snd_seq_device_new(struct snd_card *card, int device, const char *id, int argsize, struct snd_seq_device **result); -#define SNDRV_SEQ_DEVICE_ARGPTR(dev) (void *)((char *)(dev) + sizeof(struct snd_seq_device)) +#define SNDRV_SEQ_DEVICE_ARGPTR(dev) ((void *)(dev)->args) int __must_check __snd_seq_driver_register(struct snd_seq_driver *drv, struct module *mod); diff --git a/include/sound/seq_midi_emul.h b/include/sound/seq_midi_emul.h index 88799d1e1f53..afc765437870 100644 --- a/include/sound/seq_midi_emul.h +++ b/include/sound/seq_midi_emul.h @@ -55,14 +55,14 @@ struct snd_midi_channel_set { int client; /* Client for this port */ int port; /* The port number */ - int max_channels; /* Size of the channels array */ - struct snd_midi_channel *channels; - unsigned char midi_mode; /* MIDI operating mode */ unsigned char gs_master_volume; /* SYSEX master volume: 0-127 */ unsigned char gs_chorus_mode; unsigned char gs_reverb_mode; + int max_channels; /* Size of the channels array */ + struct snd_midi_channel channels[] __counted_by(max_channels); + }; struct snd_midi_op { diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h index 30f508a56766..ac749bb2b836 100644 --- a/include/sound/snd_wavefront.h +++ b/include/sound/snd_wavefront.h @@ -12,6 +12,7 @@ struct _snd_wavefront_midi; struct _snd_wavefront_card; struct _snd_wavefront; +struct snd_wss; typedef struct _snd_wavefront_midi snd_wavefront_midi_t; typedef struct _snd_wavefront_card snd_wavefront_card_t; @@ -46,6 +47,8 @@ extern void snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *); extern void snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *); extern void snd_wavefront_midi_interrupt (snd_wavefront_card_t *); extern int snd_wavefront_midi_start (snd_wavefront_card_t *); +void snd_wavefront_midi_suspend(snd_wavefront_card_t *card); +void snd_wavefront_midi_resume(snd_wavefront_card_t *card); struct _snd_wavefront { unsigned long irq; /* "you were one, one of the few ..." */ @@ -93,6 +96,7 @@ struct _snd_wavefront { int samples_used; /* how many */ char interrupts_are_midi; /* h/w MPU interrupts enabled ? */ char rom_samples_rdonly; /* can we write on ROM samples */ + char midi_in_to_synth; /* route external MIDI to synth */ spinlock_t irq_lock; wait_queue_head_t interrupt_sleeper; snd_wavefront_midi_t midi; /* ICS2115 MIDI interface */ @@ -101,6 +105,7 @@ struct _snd_wavefront { struct _snd_wavefront_card { snd_wavefront_t wavefront; + struct snd_wss *chip; #ifdef CONFIG_PNP struct pnp_dev *wss; struct pnp_dev *ctrl; @@ -110,8 +115,10 @@ struct _snd_wavefront_card { }; extern void snd_wavefront_internal_interrupt (snd_wavefront_card_t *card); +void snd_wavefront_cache_firmware(snd_wavefront_t *dev); extern int snd_wavefront_start (snd_wavefront_t *dev); extern int snd_wavefront_detect (snd_wavefront_card_t *card); +int snd_wavefront_resume_synth(snd_wavefront_card_t *card); extern int snd_wavefront_cmd (snd_wavefront_t *, int, unsigned char *, unsigned char *); diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index ecc02e955279..1f1e7d45f553 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -47,6 +47,8 @@ int snd_soc_card_late_probe(struct snd_soc_card *card); void snd_soc_card_fixup_controls(struct snd_soc_card *card); int snd_soc_card_remove(struct snd_soc_card *card); +void snd_soc_card_set_topology_name(struct snd_soc_card *card, const char *preifx); + int snd_soc_card_set_bias_level(struct snd_soc_card *card, struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 7e158d27ae8d..11bc9527653f 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -199,9 +199,7 @@ struct snd_soc_component_driver { bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */ int be_pcm_base; /* base device ID for all BE PCMs */ -#ifdef CONFIG_DEBUG_FS const char *debugfs_prefix; -#endif }; struct snd_soc_component { @@ -250,7 +248,6 @@ struct snd_soc_component { void *mark_pm; struct dentry *debugfs_root; - const char *debugfs_prefix; }; #define for_each_component_dais(component, dai)\ diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 6a42812bba8c..ba3ae56c6b06 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -17,6 +17,7 @@ struct snd_pcm_substream; struct snd_soc_dapm_widget; struct snd_compr_stream; +struct clk; /* * DAI hardware audio formats. @@ -80,10 +81,10 @@ struct snd_compr_stream; /* * define GATED -> CONT. GATED will be selected if both are selected. * see - * snd_soc_runtime_get_dai_fmt() + * soc_dai_convert_possiblefmt_to_daifmt() */ #define SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT 16 -#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT) #define SND_SOC_POSSIBLE_DAIFMT_GATED (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT) #define SND_SOC_POSSIBLE_DAIFMT_CONT (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT) @@ -139,14 +140,6 @@ struct snd_compr_stream; #define SND_SOC_DAIFMT_BP_FC SND_SOC_DAIFMT_CBP_CFC #define SND_SOC_DAIFMT_BC_FC SND_SOC_DAIFMT_CBC_CFC -/* Describes the possible PCM format */ -#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT 48 -#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) -#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFP (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) -#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFP (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) -#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFC (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) -#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFC (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) - #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 #define SND_SOC_DAIFMT_INV_MASK 0x0f00 @@ -188,9 +181,10 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); +void snd_soc_dai_set_bclk_clk(struct snd_soc_dai *dai, struct clk *bclk); + /* Digital Audio interface formatting */ -int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd); -u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority); +unsigned int snd_soc_dai_auto_select_format(const struct snd_soc_pcm_runtime *rtd); int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, @@ -473,6 +467,10 @@ struct snd_soc_dai { unsigned int symmetric_channels; unsigned int symmetric_sample_bits; + /* shared BCLK clock for cross-DAI rate constraints */ + struct clk *bclk; + unsigned int bclk_ratio; /* BCLK = rate * bclk_ratio (0 = use channels * sample_bits) */ + /* parent platform/codec */ struct snd_soc_component *component; diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 4f8fb7622a13..33c4a3e9c1d4 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -636,6 +636,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_s void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); +int snd_soc_dapm_ignore_suspend_widgets(struct snd_soc_card *card); int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); @@ -673,6 +674,7 @@ int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, /* dapm sys fs - used by the core */ extern struct attribute *snd_soc_dapm_dev_attrs[]; void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent); +void snd_soc_dapm_debugfs_pop_time(struct dentry *parent); /* dapm audio pin control and status */ int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); @@ -685,6 +687,7 @@ int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin); +bool snd_soc_dapm_pin_has_prefix(struct snd_soc_card *card, const char *pin); void snd_soc_dapm_mark_endpoints_dirty(struct snd_soc_card *card); /* dapm path query */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 5e3eb617d832..10ad80f930c2 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -431,7 +431,7 @@ struct snd_soc_jack_pin; int snd_soc_register_card(struct snd_soc_card *card); void snd_soc_unregister_card(struct snd_soc_card *card); int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card); -int devm_snd_soc_register_deferrable_card(struct device *dev, struct snd_soc_card *card); +#define devm_snd_soc_register_deferrable_card(d, c) devm_snd_soc_register_card(d, c) #ifdef CONFIG_PM_SLEEP int snd_soc_suspend(struct device *dev); int snd_soc_resume(struct device *dev); @@ -976,9 +976,6 @@ struct snd_soc_card { const char *long_name; const char *driver_name; const char *components; -#ifdef CONFIG_DMI - char dmi_longname[80]; -#endif /* CONFIG_DMI */ #ifdef CONFIG_PCI /* @@ -990,7 +987,7 @@ struct snd_soc_card { bool pci_subsystem_set; #endif /* CONFIG_PCI */ - char topology_shortname[32]; + char *topology_shortname; struct device *dev; struct snd_card *snd_card; @@ -1057,10 +1054,14 @@ struct snd_soc_card { int num_dapm_widgets; const struct snd_soc_dapm_route *dapm_routes; int num_dapm_routes; + const char **ignore_suspend_widgets; + int num_ignore_suspend_widgets; const struct snd_soc_dapm_widget *of_dapm_widgets; int num_of_dapm_widgets; const struct snd_soc_dapm_route *of_dapm_routes; int num_of_dapm_routes; + const char **of_ignore_suspend_widgets; + int num_of_ignore_suspend_widgets; /* lists of probed devices belonging to this card */ struct list_head component_dev_list; @@ -1081,11 +1082,8 @@ struct snd_soc_card { #ifdef CONFIG_PM_SLEEP struct work_struct deferred_resume_work; #endif - u32 pop_time; - /* bit field */ unsigned int instantiated:1; - unsigned int topology_shortname_created:1; unsigned int fully_routed:1; unsigned int probed:1; unsigned int component_chaining:1; @@ -1339,6 +1337,7 @@ void snd_soc_of_parse_node_prefix(struct device_node *np, 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); +int snd_soc_of_parse_ignore_suspend_widgets(struct snd_soc_card *card, const char *propname); unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt); unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame); diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h index 489083183673..79c21966220b 100644 --- a/include/sound/soc_sdw_utils.h +++ b/include/sound/soc_sdw_utils.h @@ -223,6 +223,17 @@ int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card, struct asoc_sdw_codec_info *info, bool playback); +/* es9356 codec support */ +int asoc_sdw_es9356_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_es9356_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_es9356_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + /* CS AMP support */ int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card, int *num_dais, int *num_devs); @@ -272,7 +283,14 @@ int asoc_sdw_ti_amp_init(struct snd_soc_card *card, struct asoc_sdw_codec_info *info, bool playback); int asoc_sdw_ti_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_ti_tac5xx2_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai); int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card, const char *name_prefix); +int asoc_sdw_ti_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_ti_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_es9356_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_es9356_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_es9356_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); #endif diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index 95296bb4a33a..d45f805b5d18 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -120,6 +120,7 @@ enum audio_device { TAS2568, TAS2570, TAS2572, + TAS2573, TAS2574, TAS2781, TAS5802, diff --git a/include/sound/timer.h b/include/sound/timer.h index 83bafe70cf33..e549eab7145b 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -75,6 +75,7 @@ struct snd_timer { struct list_head ack_list_head; struct list_head sack_list_head; /* slow ack list head */ struct work_struct task_work; + struct kref kref; int max_instances; /* upper limit of timer instances */ int num_instances; /* current number of timer instances */ }; @@ -131,4 +132,9 @@ int snd_timer_pause(struct snd_timer_instance *timeri); void snd_timer_interrupt(struct snd_timer *timer, unsigned long ticks_left); +struct snd_timer *snd_timeri_timer_get(struct snd_timer_instance *timeri); +void snd_timeri_timer_put(struct snd_timer *timer); + +DEFINE_FREE(snd_timeri_timer, struct snd_timer *, if (_T) snd_timeri_timer_put(_T)) + #endif /* __SOUND_TIMER_H */ diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 15487837e894..a4d230a19c56 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -206,24 +206,6 @@ void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv) } EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_unregister); -/** - * snd_ac97_codec_get_platdata - get platform_data - * @adev: the ac97 codec device - * - * For legacy platforms, in order to have platform_data in codec drivers - * available, while ac97 device are auto-created upon probe, this retrieves the - * platdata which was setup on ac97 controller registration. - * - * Returns the platform data pointer - */ -void *snd_ac97_codec_get_platdata(const struct ac97_codec_device *adev) -{ - struct ac97_controller *ac97_ctrl = adev->ac97_ctrl; - - return ac97_ctrl->codecs_pdata[adev->num]; -} -EXPORT_SYMBOL_GPL(snd_ac97_codec_get_platdata); - static void ac97_ctrl_codecs_unregister(struct ac97_controller *ac97_ctrl) { int i; @@ -337,7 +319,6 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl) * @dev: the device providing the ac97 DC function * @slots_available: mask of the ac97 codecs that can be scanned and probed * bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3 - * @codecs_pdata: codec platform data * * Register a digital controller which can control up to 4 ac97 codecs. This is * the controller side of the AC97 AC-link, while the slave side are the codecs. @@ -346,18 +327,15 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl) */ struct ac97_controller *snd_ac97_controller_register( const struct ac97_controller_ops *ops, struct device *dev, - unsigned short slots_available, void **codecs_pdata) + unsigned short slots_available) { struct ac97_controller *ac97_ctrl; - int ret, i; + int ret; ac97_ctrl = kzalloc_obj(*ac97_ctrl); if (!ac97_ctrl) return ERR_PTR(-ENOMEM); - for (i = 0; i < AC97_BUS_MAX_CODECS && codecs_pdata; i++) - ac97_ctrl->codecs_pdata[i] = codecs_pdata[i]; - ac97_ctrl->ops = ops; ac97_ctrl->slots_available = slots_available; ac97_ctrl->parent = dev; diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c index 8a44297964f5..ad7fb6b0c2c0 100644 --- a/sound/ac97_bus.c +++ b/sound/ac97_bus.c @@ -73,7 +73,6 @@ int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id, if (snd_ac97_check_id(ac97, id, id_mask)) return 0; - return -ENODEV; } EXPORT_SYMBOL_GPL(snd_ac97_reset); @@ -81,6 +80,7 @@ EXPORT_SYMBOL_GPL(snd_ac97_reset); const struct bus_type ac97_bus_type = { .name = "ac97", }; +EXPORT_SYMBOL(ac97_bus_type); static int __init ac97_bus_init(void) { @@ -96,7 +96,5 @@ static void __exit ac97_bus_exit(void) module_exit(ac97_bus_exit); -EXPORT_SYMBOL(ac97_bus_type); - MODULE_DESCRIPTION("Legacy AC97 bus interface"); MODULE_LICENSE("GPL"); diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index c3ebb6de4789..7bb541577a26 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -948,6 +948,8 @@ static void layout_attached_codec(struct aoa_codec *codec) if (lineout == 1) ldev->gpio.methods->set_lineout(codec->gpio, 1); ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); + if (!ctl) + return; if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) strscpy(ctl->id.name, "Headphone Switch"); ldev->lineout_ctrl = ctl; @@ -961,12 +963,16 @@ static void layout_attached_codec(struct aoa_codec *codec) if (ldev->have_lineout_detect) { ctl = snd_ctl_new1(&lineout_detect_choice, ldev); + if (!ctl) + return; if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) strscpy(ctl->id.name, "Headphone Detect Autoswitch"); aoa_snd_ctl_add(ctl); ctl = snd_ctl_new1(&lineout_detected, ldev); + if (!ctl) + return; if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) strscpy(ctl->id.name, "Headphone Detected"); diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index e4d7288d1e1e..09054ce8074f 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig @@ -19,10 +19,3 @@ config SND_ARMAACI select SND_AC97_CODEC endif # SND_ARM - -config SND_PXA2XX_LIB - tristate - select SND_DMAENGINE_PCM - -config SND_PXA2XX_LIB_AC97 - bool diff --git a/sound/arm/Makefile b/sound/arm/Makefile index 99325a66cf77..6b91eb796b9b 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -5,7 +5,3 @@ obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o snd-aaci-y := aaci.o - -obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o -snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o -snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o diff --git a/sound/core/control.c b/sound/core/control.c index 5e51857635e6..7a8dc506221e 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1550,7 +1550,6 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf, unsigned int size) { struct user_element *ue = snd_kcontrol_chip(kctl); - unsigned int *container; unsigned int mask = 0; int i; int change; @@ -1564,17 +1563,16 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf, if (check_user_elem_overflow(ue->card, (ssize_t)(size - ue->tlv_data_size))) return -ENOMEM; - container = vmemdup_user(buf, size); + unsigned int *container __free(kvfree) = vmemdup_user(buf, size); + if (IS_ERR(container)) return PTR_ERR(container); change = ue->tlv_data_size != size; if (!change) change = memcmp(ue->tlv_data, container, size) != 0; - if (!change) { - kvfree(container); + if (!change) return 0; - } if (ue->tlv_data == NULL) { /* Now TLV data is available. */ @@ -1587,7 +1585,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf, kvfree(ue->tlv_data); } - ue->tlv_data = container; + ue->tlv_data = no_free_ptr(container); ue->tlv_data_size = size; // decremented at private_free. ue->card->user_ctl_alloc_size += size; @@ -1628,7 +1626,6 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kctl, int op_flag, /* called in controls_rwsem write lock */ static int snd_ctl_elem_init_enum_names(struct user_element *ue) { - char *names, *p; size_t buf_len, name_len; unsigned int i; const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr; @@ -1641,27 +1638,28 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue) if (check_user_elem_overflow(ue->card, buf_len)) return -ENOMEM; - names = vmemdup_user((const void __user *)user_ptrval, buf_len); + char *names __free(kvfree) = vmemdup_user((const void __user *)user_ptrval, + buf_len); + if (IS_ERR(names)) return PTR_ERR(names); /* check that there are enough valid names */ - p = names; + char *p = names; + for (i = 0; i < ue->info.value.enumerated.items; ++i) { - if (buf_len == 0) { - kvfree(names); + if (buf_len == 0) return -EINVAL; - } + name_len = strnlen(p, buf_len); - if (name_len == 0 || name_len >= 64 || name_len == buf_len) { - kvfree(names); + if (name_len == 0 || name_len >= 64 || name_len == buf_len) return -EINVAL; - } + p += name_len + 1; buf_len -= name_len + 1; } - ue->priv_data = names; + ue->priv_data = no_free_ptr(names); ue->info.value.enumerated.names_ptr = 0; // increment the allocation size; decremented again at private_free. ue->card->user_ctl_alloc_size += ue->info.value.enumerated.names_length; @@ -2293,7 +2291,6 @@ EXPORT_SYMBOL_GPL(snd_ctl_request_layer); */ void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops) { - struct snd_card *card; int card_number; scoped_guard(rwsem_write, &snd_ctl_layer_rwsem) { @@ -2301,11 +2298,12 @@ void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops) snd_ctl_layer = lops; } for (card_number = 0; card_number < SNDRV_CARDS; card_number++) { - card = snd_card_ref(card_number); + struct snd_card *card __free(snd_card_unref) = + snd_card_ref(card_number); + if (card) { scoped_guard(rwsem_read, &card->controls_rwsem) lops->lregister(card); - snd_card_unref(card); } } } diff --git a/sound/core/control_led.c b/sound/core/control_led.c index d92b36ab5ec6..8cbacee57ce7 100644 --- a/sound/core/control_led.c +++ b/sound/core/control_led.c @@ -240,8 +240,6 @@ static void snd_ctl_led_notify(struct snd_card *card, unsigned int mask, } } -DEFINE_FREE(snd_card_unref, struct snd_card *, if (_T) snd_card_unref(_T)) - static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id, unsigned int group, bool set) { @@ -758,18 +756,17 @@ static int __init snd_ctl_led_init(void) static void __exit snd_ctl_led_exit(void) { struct snd_ctl_led *led; - struct snd_card *card; unsigned int group, card_number; snd_ctl_disconnect_layer(&snd_ctl_led_lops); for (card_number = 0; card_number < SNDRV_CARDS; card_number++) { if (!snd_ctl_led_card_valid[card_number]) continue; - card = snd_card_ref(card_number); - if (card) { + struct snd_card *card __free(snd_card_unref) = + snd_card_ref(card_number); + + if (card) snd_ctl_led_sysfs_remove(card); - snd_card_unref(card); - } } for (group = 0; group < MAX_LED; group++) { led = &snd_ctl_leds[group]; diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 9fcd1c03dc5b..92c585f8eeb1 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -20,7 +20,7 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_HRTIMER)); #define NANO_SEC 1000000000UL /* 10^9 in sec */ -static unsigned int resolution; +static unsigned int resolution __ro_after_init; struct snd_hrtimer { struct snd_timer *timer; diff --git a/sound/core/init.c b/sound/core/init.c index 0c316189e947..56dde5bd73c4 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -181,7 +181,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid, if (extra_size < 0) extra_size = 0; - card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); + card = kzalloc_flex(*card, private_data_area, extra_size); if (!card) return -ENOMEM; @@ -232,7 +232,8 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid, int err; *card_ret = NULL; - card = devres_alloc(__snd_card_release, sizeof(*card) + extra_size, + card = devres_alloc(__snd_card_release, + struct_size(card, private_data_area, extra_size), GFP_KERNEL); if (!card) return -ENOMEM; @@ -280,7 +281,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent, int err; if (extra_size > 0) - card->private_data = (char *)card + sizeof(struct snd_card); + card->private_data = card->private_data_area; if (xid) strscpy(card->id, xid, sizeof(card->id)); err = 0; @@ -327,8 +328,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent, mutex_init(&card->memory_mutex); #ifdef CONFIG_PM init_waitqueue_head(&card->power_sleep); - init_waitqueue_head(&card->power_ref_sleep); - atomic_set(&card->power_ref, 0); + snd_refcount_init(&card->power_ref); #endif init_waitqueue_head(&card->remove_sleep); card->sync_irq = -1; @@ -1139,7 +1139,7 @@ EXPORT_SYMBOL(snd_card_file_remove); * typically around calling control ops. * * The caller needs to pull down the refcount via snd_power_unref() later - * no matter whether the error is returned from this function or not. + * when this function returns 0. * * Return: Zero if successful, or a negative error code. */ @@ -1152,7 +1152,11 @@ int snd_power_ref_and_wait(struct snd_card *card) card->shutdown || snd_power_get_state(card) == SNDRV_CTL_POWER_D0, snd_power_unref(card), snd_power_ref(card)); - return card->shutdown ? -ENODEV : 0; + if (card->shutdown) { + snd_power_unref(card); + return -ENODEV; + } + return 0; } EXPORT_SYMBOL_GPL(snd_power_ref_and_wait); @@ -1169,7 +1173,8 @@ int snd_power_wait(struct snd_card *card) int ret; ret = snd_power_ref_and_wait(card); - snd_power_unref(card); + if (!ret) + snd_power_unref(card); return ret; } EXPORT_SYMBOL(snd_power_wait); diff --git a/sound/core/jack.c b/sound/core/jack.c index 5e8a2f3f4196..96e0733ede77 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -250,18 +250,15 @@ static const char * const jack_events_name[] = { /* the recommended buffer size is 256 */ static int parse_mask_bits(unsigned int mask_bits, char *buf, size_t buf_size) { + int len = scnprintf(buf, buf_size, "0x%04x", mask_bits); int i; - scnprintf(buf, buf_size, "0x%04x", mask_bits); - for (i = 0; i < ARRAY_SIZE(jack_events_name); i++) - if (mask_bits & (1 << i)) { - strlcat(buf, " ", buf_size); - strlcat(buf, jack_events_name[i], buf_size); - } - strlcat(buf, "\n", buf_size); + if (mask_bits & (1 << i)) + len += scnprintf(buf + len, buf_size - len, " %s", jack_events_name[i]); + len += scnprintf(buf + len, buf_size - len, "\n"); - return strlen(buf); + return len; } static ssize_t jack_kctl_mask_bits_read(struct file *file, diff --git a/sound/core/misc.c b/sound/core/misc.c index 833124c8e4fa..4772b2a3b808 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -174,3 +174,27 @@ void snd_fasync_free(struct snd_fasync *fasync) kfree(fasync); } EXPORT_SYMBOL_GPL(snd_fasync_free); + +/* + * generic refcount helper + */ + +void snd_refcount_init(struct snd_refcount *ref) +{ + atomic_set(&ref->count, 0); + init_waitqueue_head(&ref->waiter); +} +EXPORT_SYMBOL_GPL(snd_refcount_init); + +void snd_refcount_put(struct snd_refcount *ref) +{ + if (atomic_dec_and_test(&ref->count)) + wake_up(&ref->waiter); +} +EXPORT_SYMBOL_GPL(snd_refcount_put); + +void snd_refcount_sync(struct snd_refcount *ref) +{ + wait_event(ref->waiter, !atomic_read(&ref->count)); +} +EXPORT_SYMBOL_GPL(snd_refcount_sync); diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 746eaf93e1a5..9826d9a0be6d 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -32,8 +32,8 @@ #define OSS_ALSAEMULVER _SIOR ('M', 249, int) -static int dsp_map[SNDRV_CARDS]; -static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; +static int dsp_map[SNDRV_CARDS] __ro_after_init; +static int adsp_map[SNDRV_CARDS] __ro_after_init = {[0 ... (SNDRV_CARDS-1)] = 1}; static bool nonblock_open = 1; MODULE_AUTHOR("Jaroslav Kysela , Abramo Bagnara "); diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 14b4a390a219..5f4d6945a7df 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -146,7 +146,7 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug, return -ENXIO; if (snd_BUG_ON(!src_format || !dst_format)) return -ENXIO; - plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL); + plugin = kzalloc_flex(*plugin, extra_data, extra); if (plugin == NULL) return -ENOMEM; plugin->name = name; diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 5313f50f17da..55ecf87586c4 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -293,7 +293,7 @@ static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, return -ENOTTY; if (substream->stream != dir) return -EINVAL; - if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) + if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (get_user(buf, &data32->buf) || @@ -338,7 +338,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, return -ENOTTY; if (substream->stream != dir) return -EINVAL; - if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) + if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN) return -EBADFD; ch = substream->runtime->channels; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 302643c1c192..7dc0060617f1 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -645,6 +645,14 @@ snd_pcm_state_t snd_pcm_get_state(struct snd_pcm_substream *substream) } EXPORT_SYMBOL_GPL(snd_pcm_get_state); +static bool snd_pcm_state_open_or_disconnected(struct snd_pcm_substream *substream) +{ + snd_pcm_state_t state = snd_pcm_get_state(substream); + + return state == SNDRV_PCM_STATE_OPEN || + state == SNDRV_PCM_STATE_DISCONNECTED; +} + static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream, int event) { @@ -1973,13 +1981,15 @@ static int snd_pcm_reset(struct snd_pcm_substream *substream) static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, snd_pcm_state_t state) { - struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_state_t cur_state = snd_pcm_get_state(substream); int f_flags = (__force int)state; - if (runtime->state == SNDRV_PCM_STATE_OPEN || - runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + if (cur_state == SNDRV_PCM_STATE_OPEN || + cur_state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; - if (snd_pcm_running(substream)) + if (cur_state == SNDRV_PCM_STATE_RUNNING || + (cur_state == SNDRV_PCM_STATE_DRAINING && + substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) return -EBUSY; substream->f_flags = f_flags; return 0; @@ -2139,7 +2149,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, card = substream->pcm->card; runtime = substream->runtime; - if (runtime->state == SNDRV_PCM_STATE_OPEN) + if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (file) { @@ -3303,10 +3313,9 @@ static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream, struct snd_xferi __user *_xferi) { struct snd_xferi xferi; - struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t result; - if (runtime->state == SNDRV_PCM_STATE_OPEN) + if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (put_user(0, &_xferi->result)) return -EFAULT; @@ -3329,7 +3338,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream, void *bufs __free(kfree) = NULL; snd_pcm_sframes_t result; - if (runtime->state == SNDRV_PCM_STATE_OPEN) + if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (runtime->channels > 128) return -EINVAL; @@ -3392,7 +3401,7 @@ static int snd_pcm_common_ioctl(struct file *file, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; - if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; res = snd_power_wait(substream->pcm->card); @@ -3523,7 +3532,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, snd_pcm_uframes_t *frames = arg; snd_pcm_sframes_t result; - if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; switch (cmd) { @@ -3568,8 +3577,7 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->state == SNDRV_PCM_STATE_OPEN || - runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + if (snd_pcm_state_open_or_disconnected(substream)) return -EBADFD; if (!frame_aligned(runtime, count)) return -EINVAL; @@ -3593,8 +3601,7 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->state == SNDRV_PCM_STATE_OPEN || - runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + if (snd_pcm_state_open_or_disconnected(substream)) return -EBADFD; if (!frame_aligned(runtime, count)) return -EINVAL; @@ -3620,8 +3627,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->state == SNDRV_PCM_STATE_OPEN || - runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + if (snd_pcm_state_open_or_disconnected(substream)) return -EBADFD; if (!user_backed_iter(to)) return -EINVAL; @@ -3660,8 +3666,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->state == SNDRV_PCM_STATE_OPEN || - runtime->state == SNDRV_PCM_STATE_DISCONNECTED) + if (snd_pcm_state_open_or_disconnected(substream)) return -EBADFD; if (!user_backed_iter(from)) return -EINVAL; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 3b1034a44938..4dfd9d53e6d3 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -28,8 +28,8 @@ MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA."); MODULE_LICENSE("GPL"); #ifdef CONFIG_SND_OSSEMUL -static int midi_map[SNDRV_CARDS]; -static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; +static int midi_map[SNDRV_CARDS] __ro_after_init; +static int amidi_map[SNDRV_CARDS] __ro_after_init = {[0 ... (SNDRV_CARDS-1)] = 1}; module_param_array(midi_map, int, NULL, 0444); MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device."); module_param_array(amidi_map, int, NULL, 0444); diff --git a/sound/core/seq/oss/seq_oss_event.c b/sound/core/seq/oss/seq_oss_event.c index 76fb81077eef..122735862044 100644 --- a/sound/core/seq/oss/seq_oss_event.c +++ b/sound/core/seq/oss/seq_oss_event.c @@ -39,8 +39,10 @@ static int set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct s */ int -snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev) +snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, + struct snd_seq_event *ev, snd_use_lock_t **lockp) { + *lockp = NULL; switch (q->s.code) { case SEQ_EXTENDED: return extended_event(dp, q, ev); @@ -69,7 +71,7 @@ snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd if (snd_seq_oss_midi_open(dp, q->s.dev, SNDRV_SEQ_OSS_FILE_WRITE)) break; if (snd_seq_oss_midi_filemode(dp, q->s.dev) & SNDRV_SEQ_OSS_FILE_WRITE) - return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev); + return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev, lockp); break; case SEQ_ECHO: diff --git a/sound/core/seq/oss/seq_oss_event.h b/sound/core/seq/oss/seq_oss_event.h index b4f723949a17..54da1f810b3a 100644 --- a/sound/core/seq/oss/seq_oss_event.h +++ b/sound/core/seq/oss/seq_oss_event.h @@ -91,9 +91,11 @@ union evrec { #define ev_is_long(ev) ((ev)->s.code >= 128) #define ev_length(ev) ((ev)->s.code >= 128 ? LONG_EVENT_SIZE : SHORT_EVENT_SIZE) -int snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev); +int snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, + struct snd_seq_event *ev, snd_use_lock_t **lockp); int snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *q); int snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop); +DEFINE_FREE(seq_oss_use_lock, snd_use_lock_t *, if (_T) snd_use_lock_free(_T)) #endif /* __SEQ_OSS_EVENT_H */ diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index d3e6a8a8d823..1aece46c8b06 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -27,8 +27,8 @@ static int maxqlen = SNDRV_SEQ_OSS_MAX_QLEN; module_param(maxqlen, int, 0444); MODULE_PARM_DESC(maxqlen, "maximum queue length"); -static int system_client = -1; /* ALSA sequencer client number */ -static int system_port = -1; +static int system_client __ro_after_init = -1; /* ALSA sequencer client number */ +static int system_port __ro_after_init = -1; static int num_clients; static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS]; diff --git a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c index ccf682689ec9..f1a79776773f 100644 --- a/sound/core/seq/oss/seq_oss_ioctl.c +++ b/sound/core/seq/oss/seq_oss_ioctl.c @@ -51,9 +51,11 @@ static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg) memset(&tmpev, 0, sizeof(tmpev)); snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port); tmpev.time.tick = 0; - if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) { + + snd_use_lock_t *lock __free(seq_oss_use_lock) = NULL; + + if (!snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev, &lock)) snd_seq_oss_dispatch(dp, &tmpev, 0, 0); - } return 0; } @@ -175,4 +177,3 @@ snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long ca } return 0; } - diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index b50a49ca42ff..70f94df65144 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -593,7 +593,8 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq * non-zero : invalid - ignored */ int -snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev) +snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, + struct snd_seq_event *ev, snd_use_lock_t **lockp) { struct seq_oss_midi *mdev __free(seq_oss_midi) = get_mididev(dp, dev); @@ -602,6 +603,9 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru return -ENODEV; if (snd_midi_event_encode_byte(mdev->coder, c, ev)) { snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port); + /* the caller must release this later */ + *lockp = &mdev->use_lock; + snd_use_lock_use(*lockp); return 0; } return -EINVAL; diff --git a/sound/core/seq/oss/seq_oss_midi.h b/sound/core/seq/oss/seq_oss_midi.h index bcc1683773df..4819d4170bf6 100644 --- a/sound/core/seq/oss/seq_oss_midi.h +++ b/sound/core/seq/oss/seq_oss_midi.h @@ -26,7 +26,7 @@ void snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode); int snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev); void snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev); int snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, - struct snd_seq_event *ev); + struct snd_seq_event *ev, snd_use_lock_t **lockp); int snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private); int snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev); int snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf); diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c index c880d4771169..d5dc76501ada 100644 --- a/sound/core/seq/oss/seq_oss_readq.c +++ b/sound/core/seq/oss/seq_oss_readq.c @@ -34,16 +34,10 @@ snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen) { struct seq_oss_readq *q; - q = kzalloc_obj(*q); + q = kzalloc_flex(*q, q, maxlen); if (!q) return NULL; - q->q = kzalloc_objs(union evrec, maxlen); - if (!q->q) { - kfree(q); - return NULL; - } - q->maxlen = maxlen; q->qlen = 0; q->head = q->tail = 0; @@ -61,10 +55,7 @@ snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen) void snd_seq_oss_readq_delete(struct seq_oss_readq *q) { - if (q) { - kfree(q->q); - kfree(q); - } + kfree(q); } /* @@ -73,13 +64,17 @@ snd_seq_oss_readq_delete(struct seq_oss_readq *q) void snd_seq_oss_readq_clear(struct seq_oss_readq *q) { - if (q->qlen) { - q->qlen = 0; - q->head = q->tail = 0; + scoped_guard(spinlock_irqsave, &q->lock) { + if (q->qlen) { + q->qlen = 0; + q->head = 0; + q->tail = 0; + } + q->input_time = (unsigned long)-1; } + /* if someone sleeping, wake'em up */ wake_up(&q->midi_sleep); - q->input_time = (unsigned long)-1; } /* @@ -136,11 +131,11 @@ int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev, /* * copy an event to input queue: * return zero if enqueued + * caller must hold lock */ -int -snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev) +static int snd_seq_oss_readq_put_event_locked(struct seq_oss_readq *q, + union evrec *ev) { - guard(spinlock_irqsave)(&q->lock); if (q->qlen >= q->maxlen - 1) return -ENOMEM; @@ -148,12 +143,27 @@ snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev) q->tail = (q->tail + 1) % q->maxlen; q->qlen++; - /* wake up sleeper */ - wake_up(&q->midi_sleep); - return 0; } +/* + * copy an event to input queue: + * return zero if enqueued + */ +int +snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev) +{ + int rc; + + scoped_guard(spinlock_irqsave, &q->lock) { + rc = snd_seq_oss_readq_put_event_locked(q, ev); + if (!rc) + wake_up(&q->midi_sleep); + } + + return rc; +} + /* * pop queue @@ -209,23 +219,31 @@ snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *w int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode) { - if (curt != q->input_time) { - union evrec rec; - memset(&rec, 0, sizeof(rec)); - switch (seq_mode) { - case SNDRV_SEQ_OSS_MODE_SYNTH: - rec.echo = (curt << 8) | SEQ_WAIT; - snd_seq_oss_readq_put_event(q, &rec); - break; - case SNDRV_SEQ_OSS_MODE_MUSIC: - rec.t.code = EV_TIMING; - rec.t.cmd = TMR_WAIT_ABS; - rec.t.time = curt; - snd_seq_oss_readq_put_event(q, &rec); - break; + int queued = 0; + + scoped_guard(spinlock_irqsave, &q->lock) { + if (curt != q->input_time) { + union evrec rec; + + memset(&rec, 0, sizeof(rec)); + switch (seq_mode) { + case SNDRV_SEQ_OSS_MODE_SYNTH: + rec.echo = (curt << 8) | SEQ_WAIT; + queued = !snd_seq_oss_readq_put_event_locked(q, &rec); + break; + case SNDRV_SEQ_OSS_MODE_MUSIC: + rec.t.code = EV_TIMING; + rec.t.cmd = TMR_WAIT_ABS; + rec.t.time = curt; + queued = !snd_seq_oss_readq_put_event_locked(q, &rec); + break; + } + q->input_time = curt; } - q->input_time = curt; } + if (queued) + wake_up(&q->midi_sleep); + return 0; } diff --git a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_oss_readq.h index 38d0c4682b29..d8e1e7504d8f 100644 --- a/sound/core/seq/oss/seq_oss_readq.h +++ b/sound/core/seq/oss/seq_oss_readq.h @@ -10,13 +10,13 @@ #define __SEQ_OSS_READQ_H #include "seq_oss_device.h" +#include "seq_oss_event.h" /* * definition of read queue */ struct seq_oss_readq { - union evrec *q; int qlen; int maxlen; int head, tail; @@ -24,6 +24,7 @@ struct seq_oss_readq { unsigned long input_time; wait_queue_head_t midi_sleep; spinlock_t lock; + union evrec q[] __counted_by(maxlen); }; struct seq_oss_readq *snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen); diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c index 307ef98c44c7..6e417b10a102 100644 --- a/sound/core/seq/oss/seq_oss_rw.c +++ b/sound/core/seq/oss/seq_oss_rw.c @@ -57,7 +57,8 @@ snd_seq_oss_read(struct seq_oss_devinfo *dp, char __user *buf, int count) break; } ev_len = ev_length(&rec); - if (ev_len < count) { + if (count < ev_len) { + err = -EINVAL; snd_seq_oss_readq_unlock(readq, flags); break; } @@ -164,7 +165,9 @@ insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt) event.type = SNDRV_SEQ_EVENT_NOTEOFF; snd_seq_oss_fill_addr(dp, &event, dp->addr.client, dp->addr.port); - if (snd_seq_oss_process_event(dp, rec, &event)) + snd_use_lock_t *lock __free(seq_oss_use_lock) = NULL; + + if (snd_seq_oss_process_event(dp, rec, &event, &lock)) return 0; /* invalid event - no need to insert queue */ event.time.tick = snd_seq_oss_timer_cur_tick(dp->timer); diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 5719637575a9..28782e1776fa 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -441,6 +441,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, memcpy(&tmpev, &cell->event, aligned_size); tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK; + tmpev.data.ext.ptr = NULL; if (copy_to_user(buf, &tmpev, aligned_size)) { err = -EFAULT; break; @@ -535,18 +536,44 @@ static int bounce_error_event(struct snd_seq_client *client, ! client->accept_input) return 0; /* ignored */ + if (event->type == SNDRV_SEQ_EVENT_BOUNCE || + event->type == SNDRV_SEQ_EVENT_KERNEL_ERROR) + return err; /* avoid re-bouncing */ + /* set up quoted error */ memset(&bounce_ev, 0, sizeof(bounce_ev)); - bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR; - bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; + + if (client->type == USER_CLIENT) { + /* + * For user clients, send SNDRV_SEQ_EVENT_BOUNCE with the + * original event embedded as variable-length data. This + * avoids exposing data.quote.event (a kernel pointer) to + * userspace. The variable-length path in snd_seq_event_dup() + * copies the event data from data.ext.ptr into chained cells, + * and snd_seq_expand_var_event() copies only the data content + * -- never the pointer -- to userspace. + */ + bounce_ev.type = SNDRV_SEQ_EVENT_BOUNCE; + bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE; + bounce_ev.data.ext.len = sizeof(struct snd_seq_event); + bounce_ev.data.ext.ptr = (char *)event; + } else { + /* + * For kernel clients, quote the event pointer directly. + * Kernel consumers can safely dereference the pointer. + */ + bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR; + bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED; + bounce_ev.data.quote.origin = event->dest; + bounce_ev.data.quote.event = event; + bounce_ev.data.quote.value = -err; /* use positive value */ + } + bounce_ev.queue = SNDRV_SEQ_QUEUE_DIRECT; bounce_ev.source.client = SNDRV_SEQ_CLIENT_SYSTEM; bounce_ev.source.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; bounce_ev.dest.client = client->number; bounce_ev.dest.port = event->source.port; - bounce_ev.data.quote.origin = event->dest; - bounce_ev.data.quote.event = event; - bounce_ev.data.quote.value = -err; /* use positive value */ result = snd_seq_deliver_single_event(NULL, &bounce_ev, atomic, hop + 1); if (result < 0) { client->event_lost++; @@ -1287,7 +1314,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) port_idx = -1; if (port_idx >= SNDRV_SEQ_ADDRESS_UNKNOWN) return -EINVAL; - err = snd_seq_create_port(client, port_idx, &port); + err = snd_seq_create_port(client, &port); if (err < 0) return err; @@ -1306,9 +1333,13 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) } } - info->addr = port->addr; - snd_seq_set_port_info(port, info); + err = snd_seq_insert_port(client, port_idx, port); + if (err < 0) { + kfree(port); + return err; + } + info->addr = port->addr; if (info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT) client->ump_endpoint_port = port->addr.port; snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index 8abe80985dad..a6bd66ab40af 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c @@ -72,7 +72,7 @@ struct snd_seq_dummy_port { int connect; }; -static int my_client = -1; +static int my_client __ro_after_init = -1; /* * event input callback - just redirect events to subscribers diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index ebe1394c18a9..cffa8d430374 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c @@ -101,13 +101,17 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event) { struct snd_seq_event_cell *cell; + struct snd_seq_pool *pool; + bool linked; int err; if (snd_BUG_ON(!f)) return -EINVAL; guard(snd_seq_fifo)(f); - err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL, NULL); /* always non-blocking */ +retry: + pool = READ_ONCE(f->pool); + err = snd_seq_event_dup(pool, event, &cell, 1, NULL, NULL); /* always non-blocking */ if (err < 0) { if ((err == -ENOMEM) || (err == -EAGAIN)) atomic_inc(&f->overflow); @@ -115,14 +119,24 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f, } /* append new cells to fifo */ + linked = false; scoped_guard(spinlock_irqsave, &f->lock) { - if (f->tail != NULL) - f->tail->next = cell; - f->tail = cell; - if (f->head == NULL) - f->head = cell; - cell->next = NULL; - f->cells++; + if (cell->pool == f->pool) { + if (f->tail) + f->tail->next = cell; + f->tail = cell; + if (!f->head) + f->head = cell; + cell->next = NULL; + f->cells++; + linked = true; + } + } + + if (!linked) { + /* Retry against the replacement pool after resize publishes it. */ + snd_seq_cell_free(cell); + goto retry; } /* wakeup client */ @@ -194,13 +208,21 @@ int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, struct snd_seq_event_cell *cell) { + bool linked = false; + if (cell) { - guard(spinlock_irqsave)(&f->lock); - cell->next = f->head; - f->head = cell; - if (!f->tail) - f->tail = cell; - f->cells++; + scoped_guard(spinlock_irqsave, &f->lock) { + if (cell->pool == f->pool) { + cell->next = f->head; + f->head = cell; + if (!f->tail) + f->tail = cell; + f->cells++; + linked = true; + } + } + if (!linked) + snd_seq_cell_free(cell); } } @@ -237,7 +259,7 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize) oldpool = f->pool; oldhead = f->head; /* exchange pools */ - f->pool = newpool; + WRITE_ONCE(f->pool, newpool); f->head = NULL; f->tail = NULL; f->cells = 0; diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index aaf808316c30..ca9f6db0022c 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -211,7 +211,7 @@ int snd_seq_expand_var_event_at(const struct snd_seq_event *event, int count, len -= offset; if (len > count) len = count; - err = expand_var_event(event, offset, count, buf, true); + err = expand_var_event(event, offset, len, buf, true); if (err < 0) return err; return len; diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index ca3f5fc30992..2eb12199c92f 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c @@ -24,6 +24,7 @@ Possible options for midisynth module: #include #include #include +#include "seq_lock.h" MODULE_AUTHOR("Frank van de Pol , Jaroslav Kysela "); MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth."); @@ -42,6 +43,8 @@ struct seq_midisynth { int device; int subdevice; struct snd_rawmidi_file input_rfile; + spinlock_t output_lock; /* protects output_rfile publication */ + snd_use_lock_t output_use_lock; /* in-flight event_input users */ struct snd_rawmidi_file output_rfile; int seq_client; int seq_port; @@ -125,31 +128,42 @@ static int event_process_midi(struct snd_seq_event *ev, int direct, struct seq_midisynth *msynth = private_data; unsigned char msg[10]; /* buffer for constructing midi messages */ struct snd_rawmidi_substream *substream; + int err = 0; int len; if (snd_BUG_ON(!msynth)) return -EINVAL; - substream = msynth->output_rfile.output; - if (substream == NULL) - return -ENODEV; + + scoped_guard(spinlock_irqsave, &msynth->output_lock) { + substream = msynth->output_rfile.output; + if (!substream) + return -ENODEV; + snd_use_lock_use(&msynth->output_use_lock); + } + if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { /* special case, to save space */ if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) { /* invalid event */ pr_debug("ALSA: seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); - return 0; + goto out; } snd_seq_dump_var_event(ev, __dump_midi, substream); snd_midi_event_reset_decode(msynth->parser); } else { - if (msynth->parser == NULL) - return -EIO; + if (!msynth->parser) { + err = -EIO; + goto out; + } len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); if (len < 0) - return 0; + goto out; if (dump_midi(substream, msg, len) < 0) snd_midi_event_reset_decode(msynth->parser); } - return 0; + +out: + snd_use_lock_free(&msynth->output_use_lock); + return err; } @@ -163,6 +177,8 @@ static int snd_seq_midisynth_new(struct seq_midisynth *msynth, msynth->card = card; msynth->device = device; msynth->subdevice = subdevice; + spin_lock_init(&msynth->output_lock); + snd_use_lock_init(&msynth->output_use_lock); return 0; } @@ -215,12 +231,13 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info { int err; struct seq_midisynth *msynth = private_data; + struct snd_rawmidi_file rfile = {}; struct snd_rawmidi_params params; /* open midi port */ err = snd_rawmidi_kernel_open(msynth->rmidi, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, - &msynth->output_rfile); + &rfile); if (err < 0) { pr_debug("ALSA: seq_midi: midi output open failed!!!\n"); return err; @@ -229,12 +246,14 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info params.avail_min = 1; params.buffer_size = output_buffer_size; params.no_active_sensing = 1; - err = snd_rawmidi_output_params(msynth->output_rfile.output, ¶ms); + err = snd_rawmidi_output_params(rfile.output, ¶ms); if (err < 0) { - snd_rawmidi_kernel_release(&msynth->output_rfile); + snd_rawmidi_kernel_release(&rfile); return err; } snd_midi_event_reset_decode(msynth->parser); + scoped_guard(spinlock_irqsave, &msynth->output_lock) + msynth->output_rfile = rfile; return 0; } @@ -242,11 +261,19 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info) { struct seq_midisynth *msynth = private_data; + struct snd_rawmidi_file rfile = {}; - if (snd_BUG_ON(!msynth->output_rfile.output)) + scoped_guard(spinlock_irqsave, &msynth->output_lock) { + rfile = msynth->output_rfile; + msynth->output_rfile = (struct snd_rawmidi_file){}; + } + + if (snd_BUG_ON(!rfile.output)) return -EINVAL; - snd_rawmidi_drain_output(msynth->output_rfile.output); - return snd_rawmidi_kernel_release(&msynth->output_rfile); + + snd_use_lock_sync(&msynth->output_use_lock); + snd_rawmidi_drain_output(rfile.output); + return snd_rawmidi_kernel_release(&rfile); } /* delete given midi synth port */ diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index fd067c85c524..a90ebc7b3811 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -81,9 +81,6 @@ snd_midi_process_event(const struct snd_midi_op *ops, pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n"); return; } - if (chanset->channels == NULL) - return; - if (snd_seq_ev_is_channel_type(ev)) { dest_channel = ev->data.note.channel; if (dest_channel >= chanset->max_channels) { @@ -642,23 +639,6 @@ static void snd_midi_channel_init(struct snd_midi_channel *p, int n) p->drum_channel = 1; /* Default ch 10 as drums */ } -/* - * Allocate and initialise a set of midi channel control blocks. - */ -static struct snd_midi_channel *snd_midi_channel_init_set(int n) -{ - struct snd_midi_channel *chan; - int i; - - chan = kmalloc_objs(struct snd_midi_channel, n); - if (chan) { - for (i = 0; i < n; i++) - snd_midi_channel_init(chan+i, i); - } - - return chan; -} - /* * reset all midi channels */ @@ -687,13 +667,18 @@ reset_all_channels(struct snd_midi_channel_set *chset) struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n) { struct snd_midi_channel_set *chset; + int i; + + chset = kmalloc_flex(*chset, channels, n); + if (!chset) + return NULL; + + chset->max_channels = n; + chset->private_data = NULL; + + for (i = 0; i < n; i++) + snd_midi_channel_init(&chset->channels[i], i); - chset = kmalloc_obj(*chset); - if (chset) { - chset->channels = snd_midi_channel_init_set(n); - chset->private_data = NULL; - chset->max_channels = n; - } return chset; } EXPORT_SYMBOL(snd_midi_channel_alloc_set); @@ -717,7 +702,6 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset) { if (chset == NULL) return; - kfree(chset->channels); kfree(chset); } EXPORT_SYMBOL(snd_midi_channel_free_set); diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 31ab4681c601..6612e92d801f 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -108,14 +108,13 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) } -/* create a port, port number or a negative error code is returned +/* create a port, 0 on success or a negative error code is returned * the caller needs to unref the port via snd_seq_port_unlock() appropriately */ -int snd_seq_create_port(struct snd_seq_client *client, int port, +int snd_seq_create_port(struct snd_seq_client *client, struct snd_seq_client_port **port_ret) { - struct snd_seq_client_port *new_port, *p; - int num; + struct snd_seq_client_port *new_port; *port_ret = NULL; @@ -141,15 +140,25 @@ int snd_seq_create_port(struct snd_seq_client *client, int port, port_subs_info_init(&new_port->c_dest); snd_use_lock_use(&new_port->use_lock); + *port_ret = new_port; + + return 0; +} + +/* insert the port; return the port address or a negative error code */ +int snd_seq_insert_port(struct snd_seq_client *client, int port, + struct snd_seq_client_port *new_port) +{ + struct snd_seq_client_port *p; + int num; + num = max(port, 0); guard(mutex)(&client->ports_mutex); guard(write_lock_irq)(&client->ports_lock); struct list_head *insert_before = &client->ports_list_head; list_for_each_entry(p, &client->ports_list_head, list) { - if (p->addr.port == port) { - kfree(new_port); + if (p->addr.port == port) return -EBUSY; - } if (p->addr.port > num) { insert_before = &p->list; break; @@ -161,8 +170,8 @@ int snd_seq_create_port(struct snd_seq_client *client, int port, list_add_tail(&new_port->list, insert_before); client->num_ports++; new_port->addr.port = num; /* store the port number in the port */ - sprintf(new_port->name, "port-%d", num); - *port_ret = new_port; + if (!new_port->name[0]) + sprintf(new_port->name, "port-%d", num); return num; } diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h index 40ed6cf7cb90..b689c0f4867c 100644 --- a/sound/core/seq/seq_ports.h +++ b/sound/core/seq/seq_ports.h @@ -98,10 +98,14 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl DEFINE_FREE(snd_seq_port, struct snd_seq_client_port *, if (!IS_ERR_OR_NULL(_T)) snd_seq_port_unlock(_T)) -/* create a port, port number or a negative error code is returned */ -int snd_seq_create_port(struct snd_seq_client *client, int port_index, +/* create a port, 0 on success or a negative error code is returned */ +int snd_seq_create_port(struct snd_seq_client *client, struct snd_seq_client_port **port_ret); +/* insert the port; return the port address or a negative error code */ +int snd_seq_insert_port(struct snd_seq_client *client, int port, + struct snd_seq_client_port *new_port); + /* delete a port */ int snd_seq_delete_port(struct snd_seq_client *client, int port); diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c index 25c0ed8f9f0f..d5bad1c585f6 100644 --- a/sound/core/seq/seq_prioq.c +++ b/sound/core/seq/seq_prioq.c @@ -132,7 +132,7 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f, struct snd_seq_event_cell * cell) { struct snd_seq_event_cell *cur, *prev; - int count; + int remaining; int prior; if (snd_BUG_ON(!f || !cell)) @@ -162,10 +162,16 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f, prev = NULL; /* previous cell */ cur = f->head; /* cursor */ - count = 10000; /* FIXME: enough big, isn't it? */ + remaining = f->cells; while (cur != NULL) { /* compare timestamps */ int rel = compare_timestamp_rel(&cell->event, &cur->event); + + if (remaining-- <= 0) { + pr_err("ALSA: seq: inconsistent prioq cell count\n"); + return -EINVAL; + } + if (rel < 0) /* new cell has earlier schedule time, */ break; @@ -176,10 +182,6 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f, /* move cursor to next cell */ prev = cur; cur = cur->next; - if (! --count) { - pr_err("ALSA: seq: cannot find a pointer.. infinite loop?\n"); - return -EINVAL; - } } /* insert it before cursor */ diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 9bef2f792498..4cd7211ccf48 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -333,10 +333,10 @@ int snd_seq_timer_stop(struct snd_seq_timer *tmr) static int initialize_timer(struct snd_seq_timer *tmr) { - struct snd_timer *t; unsigned long freq; - t = tmr->timeri->timer; + struct snd_timer *t __free(snd_timeri_timer) = + snd_timeri_timer_get(tmr->timeri); if (!t) return -EINVAL; @@ -456,7 +456,12 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry, ti = tmr->timeri; if (!ti) break; - snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name); + + struct snd_timer *t __free(snd_timeri_timer) = + snd_timeri_timer_get(ti); + snd_iprintf(buffer, "Timer for queue %i : %s\n", + q->queue, + t ? t->name : "DEAD"); resolution = snd_timer_resolution(ti) * tmr->ticks; snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000); snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base); diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c index 1b062d6b17ea..8be1f3ab5b63 100644 --- a/sound/core/seq_device.c +++ b/sound/core/seq_device.c @@ -234,7 +234,10 @@ int snd_seq_device_new(struct snd_card *card, int device, const char *id, if (snd_BUG_ON(!id)) return -EINVAL; - dev = kzalloc(sizeof(*dev) + argsize, GFP_KERNEL); + if (argsize < 0) + return -EINVAL; + + dev = kzalloc_flex(*dev, args, argsize); if (!dev) return -ENOMEM; diff --git a/sound/core/timer.c b/sound/core/timer.c index 3d72379e57a8..51c6ac4df9f4 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -132,8 +132,8 @@ static LIST_HEAD(snd_timer_slave_list); /* list of open master instances that can accept slave links */ static LIST_HEAD(snd_timer_master_list); -/* lock for slave active lists */ -static DEFINE_SPINLOCK(slave_active_lock); +/* rwlock for timer instance (for trigger actions) */ +static DEFINE_RWLOCK(timeri_lock); #define MAX_SLAVE_INSTANCES 1000 static int num_slaves; @@ -229,6 +229,44 @@ static void snd_timer_request(struct snd_timer_id *tid) #endif +/* + * refcount management of timer object + */ +static void snd_timer_kref_release(struct kref *kref); + +static inline void snd_timer_ref_get(struct snd_timer *timer) +{ + kref_get(&timer->kref); +} + +static inline void snd_timer_ref_put(struct snd_timer *timer) +{ + kref_put(&timer->kref, snd_timer_kref_release); +} + +/* + * Return the assigned timer for the instance, NULL if not present; + * the caller is responsible to call snd_timeri_timer_put(), or use auto-cleanup + */ +struct snd_timer *snd_timeri_timer_get(struct snd_timer_instance *timeri) +{ + struct snd_timer *t; + + guard(read_lock_irqsave)(&timeri_lock); + t = timeri->timer; + if (!t) + return NULL; + snd_timer_ref_get(t); + return t; +} +EXPORT_SYMBOL_GPL(snd_timeri_timer_get); + +void snd_timeri_timer_put(struct snd_timer *timer) +{ + snd_timer_ref_put(timer); +} +EXPORT_SYMBOL_GPL(snd_timeri_timer_put); + /* move the slave if it belongs to the master; return 1 if match */ static int check_matching_master_slave(struct snd_timer_instance *master, struct snd_timer_instance *slave) @@ -240,7 +278,8 @@ static int check_matching_master_slave(struct snd_timer_instance *master, return -EBUSY; list_move_tail(&slave->open_list, &master->slave_list_head); master->timer->num_instances++; - guard(spinlock_irq)(&slave_active_lock); + snd_timer_ref_get(master->timer); + guard(write_lock_irq)(&timeri_lock); guard(spinlock)(&master->timer->lock); slave->master = master; slave->timer = master->timer; @@ -386,6 +425,7 @@ int snd_timer_open(struct snd_timer_instance *timeri, if (snd_timer_has_slave_key(timeri)) list_add_tail(&timeri->master_list, &snd_timer_master_list); timer->num_instances++; + snd_timer_ref_get(timer); err = snd_timer_check_master(timeri); list_added: if (err < 0) @@ -406,12 +446,13 @@ static void remove_slave_links(struct snd_timer_instance *timeri, { struct snd_timer_instance *slave, *tmp; - guard(spinlock_irq)(&slave_active_lock); + guard(write_lock_irq)(&timeri_lock); guard(spinlock)(&timer->lock); timeri->timer = NULL; list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, open_list) { list_move_tail(&slave->open_list, &snd_timer_slave_list); timer->num_instances--; + snd_timer_ref_put(timer); slave->master = NULL; slave->timer = NULL; list_del_init(&slave->ack_list); @@ -461,17 +502,16 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri, remove_slave_links(timeri, timer); /* slave doesn't need to release timer resources below */ - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) - timer = NULL; - } + if (!(timeri->flags & SNDRV_TIMER_IFLG_SLAVE)) { + if (list_empty(&timer->open_list_head) && timer->hw.close) + timer->hw.close(timer); + /* release a card refcount for safe disconnection */ + if (timer->card) + *card_devp_to_put = &timer->card->card_dev; + module_put(timer->module); + } - if (timer) { - if (list_empty(&timer->open_list_head) && timer->hw.close) - timer->hw.close(timer); - /* release a card refcount for safe disconnection */ - if (timer->card) - *card_devp_to_put = &timer->card->card_dev; - module_put(timer->module); + snd_timer_ref_put(timer); } } @@ -503,12 +543,13 @@ static unsigned long snd_timer_hw_resolution(struct snd_timer *timer) unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) { - struct snd_timer * timer; unsigned long ret = 0; if (timeri == NULL) return 0; - timer = timeri->timer; + + struct snd_timer *timer __free(snd_timeri_timer) + = snd_timeri_timer_get(timeri); if (timer) { guard(spinlock_irqsave)(&timer->lock); ret = snd_timer_hw_resolution(timer); @@ -560,7 +601,7 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, if (!timer) return -EINVAL; - guard(spinlock_irqsave)(&timer->lock); + guard(spinlock)(&timer->lock); if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) return -EINVAL; if (timer->card && timer->card->shutdown) @@ -608,7 +649,6 @@ static int snd_timer_start1(struct snd_timer_instance *timeri, static int snd_timer_start_slave(struct snd_timer_instance *timeri, bool start) { - guard(spinlock_irqsave)(&slave_active_lock); if (timeri->flags & SNDRV_TIMER_IFLG_DEAD) return -EINVAL; if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) @@ -632,7 +672,7 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) timer = timeri->timer; if (!timer) return -EINVAL; - guard(spinlock_irqsave)(&timer->lock); + guard(spinlock)(&timer->lock); list_del_init(&timeri->ack_list); list_del_init(&timeri->active_list); if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | @@ -671,7 +711,6 @@ static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop) { bool running; - guard(spinlock_irqsave)(&slave_active_lock); running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING; timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; if (timeri->timer) { @@ -692,6 +731,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) { if (timeri == NULL || ticks < 1) return -EINVAL; + guard(read_lock_irqsave)(&timeri_lock); if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) return snd_timer_start_slave(timeri, true); else @@ -706,6 +746,7 @@ EXPORT_SYMBOL(snd_timer_start); */ int snd_timer_stop(struct snd_timer_instance *timeri) { + guard(read_lock_irqsave)(&timeri_lock); if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) return snd_timer_stop_slave(timeri, true); else @@ -722,6 +763,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri) if (!(timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) return -EINVAL; + guard(read_lock_irqsave)(&timeri_lock); if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) return snd_timer_start_slave(timeri, false); else @@ -734,6 +776,7 @@ EXPORT_SYMBOL(snd_timer_continue); */ int snd_timer_pause(struct snd_timer_instance * timeri) { + guard(read_lock_irqsave)(&timeri_lock); if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) return snd_timer_stop_slave(timeri, false); else @@ -961,6 +1004,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, spin_lock_init(&timer->lock); INIT_WORK(&timer->task_work, snd_timer_work); timer->max_instances = 1000; /* default limit per timer */ + kref_init(&timer->kref); if (card != NULL) { timer->module = card->module; err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops); @@ -975,6 +1019,15 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, } EXPORT_SYMBOL(snd_timer_new); +static void snd_timer_kref_release(struct kref *kref) +{ + struct snd_timer *timer = container_of(kref, struct snd_timer, kref); + + if (timer->private_free) + timer->private_free(timer); + kfree(timer); +} + static int snd_timer_free(struct snd_timer *timer) { struct snd_timer_instance *ti, *n; @@ -982,20 +1035,21 @@ static int snd_timer_free(struct snd_timer *timer) if (!timer) return 0; - guard(mutex)(®ister_mutex); - if (! list_empty(&timer->open_list_head)) { - list_for_each_entry_safe(ti, n, &timer->open_list_head, open_list) { - struct device *card_dev_to_put = NULL; + scoped_guard(mutex, ®ister_mutex) { + if (!list_empty(&timer->open_list_head)) { + list_for_each_entry_safe(ti, n, &timer->open_list_head, open_list) { + struct device *card_dev_to_put = NULL; - snd_timer_close_locked(ti, &card_dev_to_put); - put_device(card_dev_to_put); + snd_timer_close_locked(ti, &card_dev_to_put); + put_device(card_dev_to_put); + } } + list_del(&timer->device_list); } - list_del(&timer->device_list); - if (timer->private_free) - timer->private_free(timer); - kfree(timer); + disable_work_sync(&timer->task_work); + + snd_timer_ref_put(timer); return 0; } @@ -1778,12 +1832,13 @@ static int snd_timer_user_info(struct file *file, struct snd_timer_info __user *_info) { struct snd_timer_user *tu; - struct snd_timer *t; tu = file->private_data; if (!tu->timeri) return -EBADFD; - t = tu->timeri->timer; + + struct snd_timer *t __free(snd_timeri_timer) = + snd_timeri_timer_get(tu->timeri); if (!t) return -EBADFD; @@ -1808,14 +1863,14 @@ static int snd_timer_user_params(struct file *file, { struct snd_timer_user *tu; struct snd_timer_params params; - struct snd_timer *t; int err; - guard(mutex)(®ister_mutex); tu = file->private_data; if (!tu->timeri) return -EBADFD; - t = tu->timeri->timer; + + struct snd_timer *t __free(snd_timeri_timer) = + snd_timeri_timer_get(tu->timeri); if (!t) return -EBADFD; if (copy_from_user(¶ms, _params, sizeof(params))) diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 4ae9eaeb5afb..25ee81c1668b 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c @@ -49,12 +49,13 @@ static int snd_timer_user_info_compat(struct file *file, { struct snd_timer_user *tu; struct snd_timer_info32 info; - struct snd_timer *t; tu = file->private_data; if (!tu->timeri) return -EBADFD; - t = tu->timeri->timer; + + struct snd_timer *t __free(snd_timeri_timer) = + snd_timeri_timer_get(tu->timeri); if (!t) return -EBADFD; memset(&info, 0, sizeof(info)); diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index a37a1695f51c..06bfe09eae1a 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -100,8 +100,7 @@ struct loopback_cable { spinlock_t lock; struct loopback_pcm *streams[2]; /* in-flight peer stops running outside cable->lock */ - atomic_t stop_count; - wait_queue_head_t stop_wait; + struct snd_refcount stop_count; struct snd_pcm_hardware hw; /* flags */ unsigned int valid; @@ -371,7 +370,7 @@ static int loopback_check_format(struct loopback_cable *cable, int stream) return -EIO; else if (cruntime->state == SNDRV_PCM_STATE_RUNNING) { /* close must not free the peer runtime below */ - atomic_inc(&cable->stop_count); + snd_refcount_get(&cable->stop_count); stop_capture = true; } } @@ -404,8 +403,7 @@ static int loopback_check_format(struct loopback_cable *cable, int stream) if (stop_capture) { snd_pcm_stop(dpcm_capt->substream, SNDRV_PCM_STATE_DRAINING); - if (atomic_dec_and_test(&cable->stop_count)) - wake_up(&cable->stop_wait); + snd_refcount_put(&cable->stop_count); } return 0; @@ -728,7 +726,6 @@ static void loopback_jiffies_timer_function(struct timer_list *t) if (dpcm->period_update_pending) { dpcm->period_update_pending = 0; period_elapsed = true; - break; } } } @@ -1071,7 +1068,7 @@ static void free_cable(struct snd_pcm_substream *substream) } /* Pair with the stop_count increment in loopback_check_format(). */ - wait_event(cable->stop_wait, !atomic_read(&cable->stop_count)); + snd_refcount_sync(&cable->stop_count); if (other_alive) return; @@ -1275,8 +1272,7 @@ static int loopback_open(struct snd_pcm_substream *substream) goto unlock; } spin_lock_init(&cable->lock); - atomic_set(&cable->stop_count, 0); - init_waitqueue_head(&cable->stop_wait); + snd_refcount_init(&cable->stop_count); cable->hw = loopback_pcm_hardware; if (loopback->timer_source) cable->ops = &loopback_snd_timer_ops; diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index d3f9424088d4..c217c427bf1e 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -46,7 +46,7 @@ module_param_array(uart_enter, bool, NULL, 0444); MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open."); static struct platform_device *platform_devices[SNDRV_CARDS]; -static int pnp_registered; +static int pnp_registered __ro_after_init; static unsigned int snd_mpu401_devices; static int snd_mpu401_create(struct device *devptr, int dev, @@ -123,7 +123,7 @@ static struct platform_driver snd_mpu401_driver = { static const struct pnp_device_id snd_mpu401_pnpids[] = { { .id = "PNPb006" }, - { .id = "" } + { } }; MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c index 7f93557b51ec..5d5281e4deb7 100644 --- a/sound/drivers/pcmtest.c +++ b/sound/drivers/pcmtest.c @@ -113,7 +113,7 @@ struct pcmtst_buf_iter { struct timer_list timer_instance; }; -static struct snd_pcm_hardware snd_pcmtst_hw = { +static struct snd_pcm_hardware snd_pcmtst_hw __ro_after_init = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_NONINTERLEAVED | @@ -137,7 +137,7 @@ struct pattern_buf { u32 len; }; -static int buf_allocated; +static int buf_allocated __ro_after_init; static struct pattern_buf patt_bufs[MAX_CHANNELS_NUM]; static inline void inc_buf_pos(struct pcmtst_buf_iter *v_iter, size_t by, size_t bytes) diff --git a/sound/hda/codecs/Kconfig b/sound/hda/codecs/Kconfig index addbc9424336..dcf340e5a0c1 100644 --- a/sound/hda/codecs/Kconfig +++ b/sound/hda/codecs/Kconfig @@ -69,6 +69,7 @@ comment "Set to Y if you want auto-loading the codec driver" config SND_HDA_CODEC_CA0132 tristate "Build Creative CA0132 codec support" + select SND_HDA_GENERIC help Say Y or M here to include Creative CA0132 codec support in snd-hda-intel driver. diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c index be565ffaade0..3fe11983d6ca 100644 --- a/sound/hda/codecs/ca0132.c +++ b/sound/hda/codecs/ca0132.c @@ -24,6 +24,7 @@ #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" +#include "generic.h" #include "ca0132_regs.h" @@ -1060,6 +1061,8 @@ enum dsp_download_state { */ struct ca0132_spec { + struct hda_gen_spec gen; + const struct snd_kcontrol_new *mixers[5]; unsigned int num_mixers; const struct hda_verb *base_init_verbs; @@ -1174,6 +1177,7 @@ enum { QUIRK_R3D, QUIRK_AE5, QUIRK_AE7, + QUIRK_GENERIC, QUIRK_NONE = HDA_FIXUP_ID_NOT_SET, }; @@ -1292,6 +1296,20 @@ static const struct hda_pintbl ae7_pincfgs[] = { {} }; +static const struct hda_pintbl ca0132_generic_pincfgs[] = { + { 0x0b, 0x41014111 }, + { 0x0c, 0x414520f0 }, /* SPDIF out */ + { 0x0d, 0x01014010 }, /* lineout */ + { 0x0e, 0x41c501f0 }, + { 0x0f, 0x411111f0 }, /* disabled */ + { 0x10, 0x411111f0 }, /* disabled */ + { 0x11, 0x41012014 }, + { 0x12, 0x37a790f0 }, /* mic */ + { 0x13, 0x77a701f0 }, + { 0x18, 0x500000f0 }, + {} +}; + static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4), SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE), @@ -1304,6 +1322,7 @@ static const struct hda_quirk ca0132_quirks[] = { SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI), SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI), + SND_PCI_QUIRK(0x1458, 0xA046, "Gigabyte GA-Z170X-Gaming G1", QUIRK_GENERIC), SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI), SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI), @@ -1325,6 +1344,7 @@ static const struct hda_model_fixup ca0132_quirk_models[] = { { .id = QUIRK_R3D, .name = "r3d" }, { .id = QUIRK_AE5, .name = "ae5" }, { .id = QUIRK_AE7, .name = "ae7" }, + { .id = QUIRK_GENERIC, .name = "generic" }, {} }; @@ -9897,14 +9917,57 @@ static void sbz_detect_quirk(struct hda_codec *codec) } } +static void ca0132_generic_init_hook(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); +} + +static int ca0132_generic_probe(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->gen.autocfg; + int err; + + snd_hda_gen_spec_init(&spec->gen); + + snd_hda_apply_pincfgs(codec, ca0132_generic_pincfgs); + + ca0132_init_chip(codec); + + err = ca0132_prepare_verbs(codec); + if (err < 0) + return err; + + err = snd_hda_parse_pin_def_config(codec, cfg, NULL); + if (err < 0) + return err; + err = snd_hda_gen_parse_auto_config(codec, cfg); + if (err < 0) + return err; + + spec->gen.init_hook = ca0132_generic_init_hook; + spec->gen.automute_speaker = 0; + spec->gen.automute_lo = 0; + + snd_hda_sequence_write(codec, spec->spec_init_verbs); + return 0; +} + static void ca0132_codec_remove(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + snd_hda_gen_remove(codec); + return; + case QUIRK_ZXR_DBPRO: return dbpro_free(codec); - else + default: return ca0132_free(codec); + } } static int ca0132_codec_probe(struct hda_codec *codec, @@ -9921,14 +9984,21 @@ static int ca0132_codec_probe(struct hda_codec *codec, codec->spec = spec; spec->codec = codec; - /* Detect codec quirk */ - snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); - if (ca0132_quirk(spec) == QUIRK_SBZ) - sbz_detect_quirk(codec); - + /* These must be set before any path is taken */ codec->pcm_format_first = 1; codec->no_sticky_stream = 1; + /* Detect codec quirk */ + snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL); + switch (ca0132_quirk(spec)) { + case QUIRK_SBZ: + sbz_detect_quirk(codec); + break; + case QUIRK_GENERIC: + return ca0132_generic_probe(codec); + default: + break; + } spec->dsp_state = DSP_DOWNLOAD_INIT; spec->num_mixers = 1; @@ -10029,36 +10099,51 @@ static int ca0132_codec_build_controls(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_controls(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_controls(codec); - else + default: return ca0132_build_controls(codec); + } } static int ca0132_codec_build_pcms(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_build_pcms(codec); + case QUIRK_ZXR_DBPRO: return dbpro_build_pcms(codec); - else + default: return ca0132_build_pcms(codec); + } } static int ca0132_codec_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) + switch (ca0132_quirk(spec)) { + case QUIRK_GENERIC: + return snd_hda_gen_init(codec); + case QUIRK_ZXR_DBPRO: return dbpro_init(codec); - else + default: return ca0132_init(codec); + } } static int ca0132_codec_suspend(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; + if (ca0132_quirk(spec) == QUIRK_GENERIC) + return 0; + cancel_delayed_work_sync(&spec->unsol_hp_work); return 0; } diff --git a/sound/hda/codecs/hdmi/hdmi.c b/sound/hda/codecs/hdmi/hdmi.c index f20d1715da62..1f4d646724ed 100644 --- a/sound/hda/codecs/hdmi/hdmi.c +++ b/sound/hda/codecs/hdmi/hdmi.c @@ -1549,6 +1549,7 @@ static const struct snd_pci_quirk force_connect_list[] = { SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1), SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1), SND_PCI_QUIRK(0x103c, 0x845a, "HP EliteDesk 800 G4 DM 65W", 1), + SND_PCI_QUIRK(0x103c, 0x8595, "HP EliteDesk 800 G5 Mini", 1), SND_PCI_QUIRK(0x103c, 0x83f3, "HP ProDesk 400", 1), SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), @@ -2285,6 +2286,7 @@ EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_acomp_init, "SND_HDA_CODEC_HDMI"); enum { MODEL_GENERIC, MODEL_GF, + MODEL_LOONGSON, }; static int generichdmi_probe(struct hda_codec *codec, @@ -2302,6 +2304,11 @@ static int generichdmi_probe(struct hda_codec *codec, if (id->driver_data == MODEL_GF) codec->no_sticky_stream = 1; + if (id->driver_data == MODEL_LOONGSON) { + if (codec->bus && codec->bus->pci->revision == 0x2) + codec->eld_jack_detect = 1; /* Jack-detection by ELD */ + } + return 0; } @@ -2319,7 +2326,7 @@ static const struct hda_codec_ops generichdmi_codec_ops = { /* */ static const struct hda_device_id snd_hda_id_generichdmi[] = { - HDA_CODEC_ID_MODEL(0x00147a47, "Loongson HDMI", MODEL_GENERIC), + HDA_CODEC_ID_MODEL(0x00147a47, "Loongson HDMI", MODEL_LOONGSON), HDA_CODEC_ID_MODEL(0x10951390, "SiI1390 HDMI", MODEL_GENERIC), HDA_CODEC_ID_MODEL(0x10951392, "SiI1392 HDMI", MODEL_GENERIC), HDA_CODEC_ID_MODEL(0x11069f84, "VX11 HDMI/DP", MODEL_GENERIC), diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index dcbc669842e0..5d09baa6d32e 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -3338,6 +3338,18 @@ static void alc256_fixup_acer_sfg16_micmute_led(struct hda_codec *codec, alc_fixup_hp_gpio_led(codec, action, 0, 0x04); } +static void alc287_fixup_acer_micmute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + alc_fixup_hp_gpio_led(codec, action, 0, 0x10); + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->micmute_led_polarity = 1; + spec->gpio_mask |= 0x10; + spec->gpio_dir |= 0x10; + } +} /* for alc295_fixup_hp_top_speakers */ #include "../helpers/hp_x360.c" @@ -4076,6 +4088,7 @@ enum { ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, ALC298_FIXUP_LENOVO_C940_DUET7, ALC287_FIXUP_LENOVO_YOGA_BOOK_9I, + ALC287_FIXUP_LENOVO_YOGA_PRO7, ALC287_FIXUP_13S_GEN2_SPEAKERS, ALC256_FIXUP_SET_COEF_DEFAULTS, ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE, @@ -4155,6 +4168,7 @@ enum { ALC236_FIXUP_HP_DMIC, ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO, ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX, + ALC287_FIXUP_ACER_MICMUTE_LED, }; /* A special fixup for Lenovo C940 and Yoga Duet 7; @@ -6101,6 +6115,13 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK, }, + [ALC287_FIXUP_LENOVO_YOGA_PRO7] = { + .type = HDA_FIXUP_FUNC, + /* Reuse the DAC routing selected for ThinkPad X1 Gen7 */ + .v.func = alc285_fixup_thinkpad_x1_gen7, + .chained = true, + .chain_id = ALC269_FIXUP_LENOVO_XPAD_ACPI, + }, [ALC623_FIXUP_LENOVO_THINKSTATION_P340] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_no_shutup, @@ -6727,7 +6748,13 @@ static const struct hda_fixup alc269_fixups[] = { .v.func = cs35l41_fixup_i2c_two, .chained = true, .chain_id = ALC245_FIXUP_HP_X360_MUTE_LEDS - } + }, + [ALC287_FIXUP_ACER_MICMUTE_LED] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc287_fixup_acer_micmute_led, + .chained = true, + .chain_id = ALC2XX_FIXUP_HEADSET_MIC, + }, }; static const struct hda_quirk alc269_fixup_tbl[] = { @@ -6777,7 +6804,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC), SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x1539, "Acer Nitro 5 AN515-57", ALC2XX_FIXUP_HEADSET_MIC), - SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC287_FIXUP_ACER_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1640, "Acer Aspire A315-44P", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED), @@ -7072,6 +7099,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8a06, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8a1b, "HP 255 15.6 inch G9 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), SND_PCI_QUIRK(0x103c, 0x8a1f, "HP Laptop 14s-dr5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), @@ -7379,9 +7407,11 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x197e, "ASUS VivoBook X509DAP", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1982, "ASUS B1400CEPE", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x19f4, "ASUS UM3405GA", ALC294_FIXUP_ASUS_I2C_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x1a63, "ASUS UX3405MA", ALC294_FIXUP_ASUS_SPI_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2), @@ -7713,6 +7743,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = { HDA_CODEC_QUIRK(0x17aa, 0x38cf, "Lenovo Yoga Pro 7 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6), SND_PCI_QUIRK(0x17aa, 0x384a, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), + /* Yoga Pro 7 14IRH8 shares PCI SSID 17aa:3852 with Yoga 7 14ITL5; + * use codec SSID to distinguish them + */ + HDA_CODEC_QUIRK(0x17aa, 0x38b1, "Lenovo Yoga Pro 7 14IRH8", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), @@ -7769,11 +7803,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x38df, "Y990 YG DUAL", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), - SND_PCI_QUIRK(0x17aa, 0x38fc, "Lenovo Yoga Pro 7 15ASH11", ALC245_FIXUP_BASS_HP_DAC), + SND_PCI_QUIRK(0x17aa, 0x38fc, "Lenovo Yoga Pro 7 15ASH11", ALC287_FIXUP_LENOVO_YOGA_PRO7), SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x3911, "Lenovo Yoga Pro 7 14IAH10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), + SND_PCI_QUIRK(0x17aa, 0x3912, "Lenovo Xiaoxin 14 GT", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC), SND_PCI_QUIRK(0x17aa, 0x391a, "Lenovo Yoga Slim 7 14AKP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TXNW2781_I2C), diff --git a/sound/hda/codecs/realtek/alc882.c b/sound/hda/codecs/realtek/alc882.c index 529fecd5baa0..fd466b6985f0 100644 --- a/sound/hda/codecs/realtek/alc882.c +++ b/sound/hda/codecs/realtek/alc882.c @@ -61,6 +61,7 @@ enum { ALC887_FIXUP_ASUS_HMIC, ALCS1200A_FIXUP_MIC_VREF, ALC888VD_FIXUP_MIC_100VREF, + ALC898_FIXUP_CLEVO_P775TM1, }; static void alc889_fixup_coef(struct hda_codec *codec, @@ -236,6 +237,19 @@ static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec, alc_fixup_headset_mode_no_hp_mic(codec, fix, action); } +/* On Clevo P775TM1, VREF of pin 0x1b enables the external headphone amp */ +static void alc898_fixup_clevo_p775tm1(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action != HDA_FIXUP_ACT_PRE_PROBE) + return; + + snd_hda_set_pin_ctl_cache(codec, 0x1b, PIN_VREF80); + spec->gen.keep_vref_in_automute = 1; +} + static void alc887_asus_hp_automute_hook(struct hda_codec *codec, struct hda_jack_callback *jack) { @@ -560,6 +574,12 @@ static const struct hda_fixup alc882_fixups[] = { {} } }, + [ALC898_FIXUP_CLEVO_P775TM1] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc898_fixup_clevo_p775tm1, + .chained = true, + .chain_id = ALC882_FIXUP_EAPD, + }, }; static const struct hda_quirk alc882_fixup_tbl[] = { @@ -664,6 +684,7 @@ static const struct hda_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x7709, "Clevo P775TM1", ALC898_FIXUP_CLEVO_P775TM1), SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED), SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), @@ -719,6 +740,7 @@ static const struct hda_model_fixup alc882_fixup_models[] = { {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"}, {.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"}, {.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"}, + {.id = ALC898_FIXUP_CLEVO_P775TM1, .name = "clevo-p775tm1"}, {} }; diff --git a/sound/hda/codecs/side-codecs/Kconfig b/sound/hda/codecs/side-codecs/Kconfig index e51964c0a091..2a2e8804bf9e 100644 --- a/sound/hda/codecs/side-codecs/Kconfig +++ b/sound/hda/codecs/side-codecs/Kconfig @@ -28,6 +28,7 @@ config SND_HDA_SCODEC_CS35L41_I2C depends on ACPI depends on EFI depends on SND_SOC + imply SERIAL_MULTI_INSTANTIATE select SND_SOC_CS35L41_LIB select SND_HDA_SCODEC_CS35L41 select SND_SOC_CS_AMP_LIB @@ -44,6 +45,7 @@ config SND_HDA_SCODEC_CS35L41_SPI depends on ACPI depends on EFI depends on SND_SOC + imply SERIAL_MULTI_INSTANTIATE select SND_SOC_CS35L41_LIB select SND_HDA_SCODEC_CS35L41 select SND_SOC_CS_AMP_LIB diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c index acfccc848f82..64a5bd895fd1 100644 --- a/sound/hda/codecs/side-codecs/cs35l41_hda.c +++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c @@ -1325,6 +1325,43 @@ static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ct return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l41_hda_fw_ids); } +static void cs35l41_remove_controls(struct cs35l41_hda *cs35l41) +{ + if (!cs35l41->codec) + return; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->mute_override_ctl); + cs35l41->mute_override_ctl = NULL; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_load_ctl); + cs35l41->fw_load_ctl = NULL; + + snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_type_ctl); + cs35l41->fw_type_ctl = NULL; +} + +static int cs35l41_add_control(struct cs35l41_hda *cs35l41, + struct snd_kcontrol_new *ctl, + struct snd_kcontrol **kctl) +{ + int ret; + + *kctl = snd_ctl_new1(ctl, cs35l41); + if (!*kctl) + return -ENOMEM; + + ret = snd_ctl_add(cs35l41->codec->card, *kctl); + if (ret) { + dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", ctl->name, ret); + *kctl = NULL; + return ret; + } + + dev_dbg(cs35l41->dev, "Added Control %s\n", ctl->name); + + return 0; +} + static int cs35l41_create_controls(struct cs35l41_hda *cs35l41) { char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -1360,32 +1397,23 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41) scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status", cs35l41->amp_name); - ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_type_ctl.name, ret); - return ret; - } + ret = cs35l41_add_control(cs35l41, &fw_type_ctl, &cs35l41->fw_type_ctl); + if (ret) + goto err; - dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name); + ret = cs35l41_add_control(cs35l41, &fw_load_ctl, &cs35l41->fw_load_ctl); + if (ret) + goto err; - ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_load_ctl.name, ret); - return ret; - } - - dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name); - - ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41)); - if (ret) { - dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name, - ret); - return ret; - } - - dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name); + ret = cs35l41_add_control(cs35l41, &mute_override_ctl, &cs35l41->mute_override_ctl); + if (ret) + goto err; return 0; + +err: + cs35l41_remove_controls(cs35l41); + return ret; } static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands) @@ -1522,6 +1550,10 @@ static void cs35l41_hda_unbind(struct device *dev, struct device *master, void * device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev); unlock_system_sleep(sleep_flags); memset(comp, 0, sizeof(*comp)); + + cs35l41_remove_controls(cs35l41); + cancel_work_sync(&cs35l41->fw_load_work); + cs35l41->codec = NULL; } } @@ -2060,6 +2092,7 @@ void cs35l41_hda_remove(struct device *dev) struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); component_del(cs35l41->dev, &cs35l41_hda_comp_ops); + cancel_work_sync(&cs35l41->fw_load_work); pm_runtime_get_sync(cs35l41->dev); pm_runtime_dont_use_autosuspend(cs35l41->dev); diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.h b/sound/hda/codecs/side-codecs/cs35l41_hda.h index 7d003c598e93..56ec07c0bb74 100644 --- a/sound/hda/codecs/side-codecs/cs35l41_hda.h +++ b/sound/hda/codecs/side-codecs/cs35l41_hda.h @@ -57,6 +57,8 @@ enum control_bus { SPI }; +struct snd_kcontrol; + struct cs35l41_hda { struct device *dev; struct regmap *regmap; @@ -75,6 +77,9 @@ struct cs35l41_hda { int speaker_id; struct mutex fw_mutex; struct work_struct fw_load_work; + struct snd_kcontrol *fw_type_ctl; + struct snd_kcontrol *fw_load_ctl; + struct snd_kcontrol *mute_override_ctl; struct regmap_irq_chip_data *irq_data; bool firmware_running; diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c b/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c index e77495413c21..96d8cc6c2324 100644 --- a/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c @@ -39,8 +39,8 @@ static void cs35l41_hda_i2c_remove(struct i2c_client *clt) } static const struct i2c_device_id cs35l41_hda_i2c_id[] = { - { "cs35l41-hda" }, - {} + { .name = "cs35l41-hda" }, + { } }; static const struct acpi_device_id cs35l41_acpi_hda_match[] = { diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c index 1072f17385ac..e2f51612a73d 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c @@ -51,10 +51,10 @@ static void cs35l56_hda_i2c_remove(struct i2c_client *clt) } static const struct i2c_device_id cs35l56_hda_i2c_id[] = { - { "cs35l54-hda", 0x3554 }, - { "cs35l56-hda", 0x3556 }, - { "cs35l57-hda", 0x3557 }, - {} + { .name = "cs35l54-hda", .driver_data = 0x3554 }, + { .name = "cs35l56-hda", .driver_data = 0x3556 }, + { .name = "cs35l57-hda", .driver_data = 0x3557 }, + { } }; static const struct acpi_device_id cs35l56_acpi_hda_match[] = { diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c index 67240ce184e1..93bf12116626 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c @@ -588,6 +588,9 @@ static void tas2781_hda_unbind(struct device *dev, comp->playback_hook = NULL; } + request_firmware_nowait_cancel(tas_hda->priv->dev, tas_hda->priv, + tasdev_fw_ready); + tas2781_hda_remove_controls(tas_hda); tasdevice_config_info_remove(tas_hda->priv); @@ -791,8 +794,8 @@ static const struct dev_pm_ops tas2781_hda_pm_ops = { }; static const struct i2c_device_id tas2781_hda_i2c_id[] = { - { "tas2781-hda" }, - {} + { .name = "tas2781-hda" }, + { } }; static const struct acpi_device_id tas2781_acpi_hda_match[] = { diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c index 0e4f3553f273..3978d58ad020 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c @@ -190,15 +190,15 @@ static void tas2781_spi_reset(struct tasdevice_priv *tas_dev) gpiod_set_value_cansleep(tas_dev->reset, 0); fsleep(800); gpiod_set_value_cansleep(tas_dev->reset, 1); - } else { - ret = tasdevice_dev_write(tas_dev, tas_dev->index, - TASDEVICE_REG_SWRESET, TASDEVICE_REG_SWRESET_RESET); - if (ret < 0) { - dev_err(tas_dev->dev, "dev sw-reset fail, %d\n", ret); - return; - } - fsleep(1000); } + + ret = tasdevice_dev_write(tas_dev, tas_dev->index, + TASDEVICE_REG_SWRESET, TASDEVICE_REG_SWRESET_RESET); + if (ret < 0) { + dev_err(tas_dev->dev, "dev sw-reset fail, %d\n", ret); + return; + } + fsleep(1000); } static int tascodec_spi_init(struct tasdevice_priv *tas_priv, @@ -593,7 +593,7 @@ static int tas2781_hda_spi_snd_ctls(struct tas2781_hda *h) return rc; } i++; - snprintf(name, sizeof(name), "Froce Speaker-%d FW Load", p->index); + snprintf(name, sizeof(name), "Force Speaker-%d FW Load", p->index); tas2781_snd_ctls[i].name = name; h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p); rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]); @@ -750,6 +750,9 @@ static void tas2781_hda_unbind(struct device *dev, struct device *master, comp->playback_hook = NULL; } + request_firmware_nowait_cancel(tas_priv->dev, tas_priv, + tasdev_fw_ready); + tas2781_hda_remove_controls(tas_hda); tasdevice_config_info_remove(tas_priv); diff --git a/sound/hda/common/bind.c b/sound/hda/common/bind.c index bb1090b65699..6a728a773556 100644 --- a/sound/hda/common/bind.c +++ b/sound/hda/common/bind.c @@ -162,8 +162,7 @@ static int hda_codec_driver_remove(struct device *dev) snd_hda_codec_disconnect_pcms(codec); snd_hda_jack_tbl_disconnect(codec); - if (!refcount_dec_and_test(&codec->pcm_ref)) - wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref)); + snd_refcount_sync(&codec->pcm_ref); snd_power_sync_ref(codec->bus->card); if (driver->ops->remove) diff --git a/sound/hda/common/codec.c b/sound/hda/common/codec.c index 81f266b9b850..ef533770179b 100644 --- a/sound/hda/common/codec.c +++ b/sound/hda/common/codec.c @@ -689,13 +689,6 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) /* * PCM device */ -void snd_hda_codec_pcm_put(struct hda_pcm *pcm) -{ - if (refcount_dec_and_test(&pcm->codec->pcm_ref)) - wake_up(&pcm->codec->remove_sleep); -} -EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_put); - struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec, const char *fmt, ...) { @@ -716,7 +709,7 @@ struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec, } list_add_tail(&pcm->list, &codec->pcm_list_head); - refcount_inc(&codec->pcm_ref); + snd_hda_codec_pcm_get(pcm); return pcm; } EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_new); @@ -787,7 +780,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) remove_conn_list(codec); snd_hdac_regmap_exit(&codec->core); codec->configured = 0; - refcount_set(&codec->pcm_ref, 1); /* reset refcount */ + snd_refcount_init(&codec->pcm_ref); /* reset refcount */ } EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind); @@ -927,8 +920,7 @@ snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr, INIT_LIST_HEAD(&codec->conn_list); INIT_LIST_HEAD(&codec->pcm_list_head); INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); - refcount_set(&codec->pcm_ref, 1); - init_waitqueue_head(&codec->remove_sleep); + snd_refcount_init(&codec->pcm_ref); return codec; } diff --git a/sound/hda/common/jack.c b/sound/hda/common/jack.c index 98ba1c4d5ba4..e0a5cc38540b 100644 --- a/sound/hda/common/jack.c +++ b/sound/hda/common/jack.c @@ -58,6 +58,12 @@ static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id) AC_VERB_GET_PIN_SENSE, dev_id); if (codec->inv_jack_detect) val ^= AC_PINSENSE_PRESENCE; + if (codec->eld_jack_detect) { + if (val & AC_PINSENSE_ELDV) + val |= AC_PINSENSE_PRESENCE; + else + val &= ~AC_PINSENSE_PRESENCE; + } return val; } diff --git a/sound/hda/controllers/Kconfig b/sound/hda/controllers/Kconfig index 72855f2df451..5d6a77e68588 100644 --- a/sound/hda/controllers/Kconfig +++ b/sound/hda/controllers/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config SND_HDA_INTEL tristate "HD Audio PCI" - depends on SND_PCI + depends on PCI select SND_HDA select SND_INTEL_DSP_CONFIG help diff --git a/sound/hda/core/i915.c b/sound/hda/core/i915.c index 44438c799f95..6c068b135b7d 100644 --- a/sound/hda/core/i915.c +++ b/sound/hda/core/i915.c @@ -130,22 +130,22 @@ static int i915_gfx_present(struct pci_dev *hdac_pci) /* List of known platforms with no i915 support. */ static const struct pci_device_id denylist[] = { /* CNL */ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a40), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a41), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a42), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a44), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a49), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4a), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4c), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a50), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a51), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a52), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a54), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a59), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5a), 0x030000, 0xff0000 }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5c), 0x030000, 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a40), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a41), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a42), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a44), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a49), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4a), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4c), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a50), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a51), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a52), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a54), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a59), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5a), .class = 0x030000, .class_mask = 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5c), .class = 0x030000, .class_mask = 0xff0000 }, /* LKF */ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9840), 0x030000, 0xff0000 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9840), .class = 0x030000, .class_mask = 0xff0000 }, {} }; struct pci_dev *display_dev = NULL; diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 3d1f19321b9e..ecff521957cb 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -103,8 +103,8 @@ MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver."); module_param_hw_array(mpuirq, int, irq, NULL, 0444); MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port."); #ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; #endif #define CMI8330_RMUX3D 16 diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index e36cc147651a..ecce31b348b0 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -69,9 +69,9 @@ module_param_hw_array(dma2, int, dma, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); #ifdef CONFIG_PNP -static int isa_registered; -static int pnpc_registered; -static int pnp_registered; +static int isa_registered __ro_after_init; +static int pnpc_registered __ro_after_init; +static int pnp_registered __ro_after_init; #endif /* CONFIG_PNP */ struct snd_card_cs4236 { @@ -94,7 +94,7 @@ static const struct pnp_device_id snd_cs423x_pnpbiosids[] = { /* Guillemot Turtlebeach something appears to be cs4232 compatible * (untested) */ { .id = "GIM0100" }, - { .id = "" } + { } }; MODULE_DEVICE_TABLE(pnp, snd_cs423x_pnpbiosids); diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 1da7b400a17b..3cadbf7cf238 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1762,6 +1762,8 @@ static int snd_es18xx_mixer(struct snd_card *card) for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) { struct snd_kcontrol *kctl; kctl = snd_ctl_new1(&snd_es18xx_base_controls[idx], chip); + if (!kctl) + return -ENOMEM; if (chip->caps & ES18XX_HWV) { switch (idx) { case 0: @@ -1823,6 +1825,8 @@ static int snd_es18xx_mixer(struct snd_card *card) for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_hw_volume_controls); idx++) { struct snd_kcontrol *kctl; kctl = snd_ctl_new1(&snd_es18xx_hw_volume_controls[idx], chip); + if (!kctl) + return -ENOMEM; if (idx == 0) chip->hw_volume = kctl; else @@ -1924,14 +1928,14 @@ module_param_hw_array(dma2, int, dma, NULL, 0444); MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); #ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -static int pnpc_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; +static int pnpc_registered __ro_after_init; static const struct pnp_device_id snd_audiodrive_pnpbiosids[] = { { .id = "ESS1869" }, { .id = "ESS1879" }, - { .id = "" } /* end */ + { } /* end */ }; MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids); diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index a0757e1ede46..08ccb4d80ade 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -851,6 +851,8 @@ int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index) kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus); else kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus); + if (!kctl) + return -ENOMEM; kctl->id.index = control_index; err = snd_ctl_add(card, kctl); if (err < 0) diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 6c3a2977dcb3..115f900fa063 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -111,8 +111,8 @@ struct snd_interwave { #ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; static const struct pnp_card_device_id snd_interwave_pnpids[] = { #ifndef SNDRV_STB diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 5b729bb02ef6..0d5f4461a7bc 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -1199,8 +1199,8 @@ static int snd_msnd_pnp_resume(struct pnp_card_link *pcard) } #endif -static int isa_registered; -static int pnp_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; static const struct pnp_card_device_id msnd_pnpids[] = { /* Pinnacle PnP */ diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 8c1767697b62..66b1e361c101 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -69,9 +69,9 @@ module_param_array(opl3sa3_ymode, int, NULL, 0444); MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi."); #ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; -static int pnpc_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; +static int pnpc_registered __ro_after_init; #endif /* control ports */ @@ -125,7 +125,7 @@ struct snd_opl3sa2 { static const struct pnp_device_id snd_opl3sa2_pnpbiosids[] = { { .id = "YMH0021" }, { .id = "NMX2210" }, /* Gateway Solo 2500 */ - { .id = "" } /* end */ + { } /* end */ }; MODULE_DEVICE_TABLE(pnp, snd_opl3sa2_pnpbiosids); diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index c320af3e9a05..e5870e5e07db 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -88,6 +88,25 @@ MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard."); #define OPTi9XX_MC_REG(n) n +enum { + MIRO_ACI_MASTER, + MIRO_ACI_MIC, + MIRO_ACI_LINE, + MIRO_ACI_CD, + MIRO_ACI_SYNTH, + MIRO_ACI_PCM, + MIRO_ACI_LINE1, + MIRO_ACI_LINE2, + MIRO_ACI_EQ1, + MIRO_ACI_EQ2, + MIRO_ACI_EQ3, + MIRO_ACI_EQ4, + MIRO_ACI_EQ5, + MIRO_ACI_EQ6, + MIRO_ACI_EQ7, + MIRO_ACI_COUNT, +}; + struct snd_miro { unsigned short hardware; unsigned char password; @@ -102,6 +121,7 @@ struct snd_miro { spinlock_t lock; struct snd_pcm *pcm; + struct snd_wss *codec; long wss_base; int irq; @@ -113,6 +133,12 @@ struct snd_miro { struct snd_card *card; struct snd_miro_aci *aci; +#ifdef CONFIG_PM + unsigned char aci_saved[MIRO_ACI_COUNT][2]; + unsigned char aci_saved_amp; + unsigned char aci_saved_preamp; + unsigned char aci_saved_solomode; +#endif }; static struct snd_miro_aci aci_device; @@ -664,6 +690,44 @@ static const unsigned char aci_init_values[][2] = { { ACI_SET_MASTER + 1, 0x20 }, }; +#ifdef CONFIG_PM +static const unsigned char snd_miro_saved_get_regs[MIRO_ACI_COUNT] = { + [MIRO_ACI_MASTER] = ACI_GET_MASTER, + [MIRO_ACI_MIC] = ACI_GET_MIC, + [MIRO_ACI_LINE] = ACI_GET_LINE, + [MIRO_ACI_CD] = ACI_GET_CD, + [MIRO_ACI_SYNTH] = ACI_GET_SYNTH, + [MIRO_ACI_PCM] = ACI_GET_PCM, + [MIRO_ACI_LINE1] = ACI_GET_LINE1, + [MIRO_ACI_LINE2] = ACI_GET_LINE2, + [MIRO_ACI_EQ1] = ACI_GET_EQ1, + [MIRO_ACI_EQ2] = ACI_GET_EQ2, + [MIRO_ACI_EQ3] = ACI_GET_EQ3, + [MIRO_ACI_EQ4] = ACI_GET_EQ4, + [MIRO_ACI_EQ5] = ACI_GET_EQ5, + [MIRO_ACI_EQ6] = ACI_GET_EQ6, + [MIRO_ACI_EQ7] = ACI_GET_EQ7, +}; + +static const unsigned char snd_miro_saved_set_regs[MIRO_ACI_COUNT] = { + [MIRO_ACI_MASTER] = ACI_SET_MASTER, + [MIRO_ACI_MIC] = ACI_SET_MIC, + [MIRO_ACI_LINE] = ACI_SET_LINE, + [MIRO_ACI_CD] = ACI_SET_CD, + [MIRO_ACI_SYNTH] = ACI_SET_SYNTH, + [MIRO_ACI_PCM] = ACI_SET_PCM, + [MIRO_ACI_LINE1] = ACI_SET_LINE1, + [MIRO_ACI_LINE2] = ACI_SET_LINE2, + [MIRO_ACI_EQ1] = ACI_SET_EQ1, + [MIRO_ACI_EQ2] = ACI_SET_EQ2, + [MIRO_ACI_EQ3] = ACI_SET_EQ3, + [MIRO_ACI_EQ4] = ACI_SET_EQ4, + [MIRO_ACI_EQ5] = ACI_SET_EQ5, + [MIRO_ACI_EQ6] = ACI_SET_EQ6, + [MIRO_ACI_EQ7] = ACI_SET_EQ7, +}; +#endif + static int snd_set_aci_init_values(struct snd_miro *miro) { int idx, error; @@ -702,11 +766,116 @@ static int snd_set_aci_init_values(struct snd_miro *miro) } aci->aci_amp = 0; aci->aci_preamp = 0; - aci->aci_solomode = 1; + aci->aci_solomode = 0; return 0; } +static int snd_miro_aci_force_known_state(struct snd_miro_aci *aci) +{ + int i, err; + + for (i = 0; i < 3; i++) { + err = snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1); + if (err < 0) + return err; + } + + return 0; +} + +static int snd_miro_aci_initialize(struct snd_miro_aci *aci) +{ + int err; + + err = snd_aci_cmd(aci, ACI_INIT, -1, -1); + if (err < 0) + return err; + err = snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP); + if (err < 0) + return err; + + return snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP); +} + +#ifdef CONFIG_PM +static int snd_miro_save_aci_state(struct snd_miro *miro) +{ + struct snd_miro_aci *aci = miro->aci; + int i, limit, value; + + limit = aci->aci_product == 'C' ? MIRO_ACI_COUNT : MIRO_ACI_LINE2 + 1; + for (i = 0; i < limit; i++) { + value = aci_getvalue(aci, snd_miro_saved_get_regs[i]); + if (value < 0) + return value; + miro->aci_saved[i][1] = value; + + value = aci_getvalue(aci, snd_miro_saved_get_regs[i] + 1); + if (value < 0) + return value; + miro->aci_saved[i][0] = value; + } + + miro->aci_saved_amp = aci->aci_amp; + if (aci->aci_version <= 176) { + miro->aci_saved_preamp = aci->aci_preamp; + } else { + value = aci_getvalue(aci, ACI_GET_PREAMP); + if (value < 0) + return value; + miro->aci_saved_preamp = value; + } + + value = aci_getvalue(aci, ACI_S_GENERAL); + if (value < 0) + return value; + miro->aci_saved_solomode = !(value & 0x20); + + return 0; +} + +static int snd_miro_restore_aci_state(struct snd_miro *miro) +{ + struct snd_miro_aci *aci = miro->aci; + int i, limit, err, left_reg; + + err = snd_set_aci_init_values(miro); + if (err < 0) + return err; + + limit = aci->aci_product == 'C' ? MIRO_ACI_COUNT : MIRO_ACI_LINE2 + 1; + for (i = 0; i < limit; i++) { + left_reg = snd_miro_saved_set_regs[i] == ACI_SET_MASTER ? + snd_miro_saved_set_regs[i] + 1 : + snd_miro_saved_set_regs[i] + 8; + err = aci_setvalue(aci, left_reg, miro->aci_saved[i][0]); + if (err < 0) + return err; + err = aci_setvalue(aci, snd_miro_saved_set_regs[i], + miro->aci_saved[i][1]); + if (err < 0) + return err; + } + + err = aci_setvalue(aci, ACI_SET_POWERAMP, miro->aci_saved_amp); + if (err < 0) + return err; + err = aci_setvalue(aci, ACI_SET_PREAMP, miro->aci_saved_preamp); + if (err < 0) + return err; + err = aci_setvalue(aci, ACI_SET_SOLOMODE, miro->aci_saved_solomode); + if (err < 0) + return err; + + aci->aci_amp = miro->aci_saved_amp; + aci->aci_preamp = miro->aci_saved_preamp; + aci->aci_solomode = miro->aci_saved_solomode; + + return 0; +} +#endif + static int snd_miro_mixer(struct snd_card *card, struct snd_miro *miro) { @@ -1203,7 +1372,7 @@ static int snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro *miro) { unsigned char regval; - int i; + int err; struct snd_miro_aci *aci = &aci_device; miro->aci = aci; @@ -1224,12 +1393,12 @@ static int snd_card_miro_aci_detect(struct snd_card *card, return -ENOMEM; } - /* force ACI into a known state */ - for (i = 0; i < 3; i++) - if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) { - dev_err(card->dev, "can't force aci into known state.\n"); - return -ENXIO; - } + /* force ACI into a known state */ + err = snd_miro_aci_force_known_state(aci); + if (err < 0) { + dev_err(card->dev, "can't force aci into known state.\n"); + return -ENXIO; + } aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); @@ -1246,9 +1415,8 @@ static int snd_card_miro_aci_detect(struct snd_card *card, return -ENXIO; } - if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 || - snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || - snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { + err = snd_miro_aci_initialize(aci); + if (err < 0) { dev_err(card->dev, "can't initialize aci.\n"); return -ENXIO; } @@ -1299,6 +1467,7 @@ static int snd_miro_probe(struct snd_card *card) WSS_HW_DETECT, 0, &codec); if (error < 0) return error; + miro->codec = codec; error = snd_wss_pcm(codec, 0); if (error < 0) @@ -1408,6 +1577,7 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) return error; miro = card->private_data; + miro->card = card; error = snd_card_miro_detect(card, miro); if (error < 0) { @@ -1470,12 +1640,69 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n) return 0; } +#ifdef CONFIG_PM +static int snd_miro_suspend(struct snd_card *card) +{ + struct snd_miro *miro = card->private_data; + int error; + + error = snd_miro_save_aci_state(miro); + if (error < 0) + return error; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + miro->codec->suspend(miro->codec); + return 0; +} + +static int snd_miro_resume(struct snd_card *card) +{ + struct snd_miro *miro = card->private_data; + int error; + + error = snd_miro_configure(miro); + if (error < 0) + return error; + error = snd_miro_aci_force_known_state(miro->aci); + if (error < 0) { + dev_err(card->dev, "can't force aci into known state\n"); + return error; + } + error = snd_miro_aci_initialize(miro->aci); + if (error < 0) { + dev_err(card->dev, "can't initialize aci\n"); + return error; + } + error = snd_miro_restore_aci_state(miro); + if (error < 0) + return error; + + miro->codec->resume(miro->codec); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} + +static int snd_miro_isa_suspend(struct device *dev, unsigned int n, + pm_message_t state) +{ + return snd_miro_suspend(dev_get_drvdata(dev)); +} + +static int snd_miro_isa_resume(struct device *dev, unsigned int n) +{ + return snd_miro_resume(dev_get_drvdata(dev)); +} +#endif + #define DEV_NAME "miro" static struct isa_driver snd_miro_driver = { .match = snd_miro_isa_match, .probe = snd_miro_isa_probe, - /* FIXME: suspend/resume */ +#ifdef CONFIG_PM + .suspend = snd_miro_isa_suspend, + .resume = snd_miro_isa_resume, +#endif .driver = { .name = DEV_NAME }, @@ -1591,12 +1818,29 @@ static void snd_miro_pnp_remove(struct pnp_card_link *pcard) snd_miro_pnp_is_probed = 0; } +#ifdef CONFIG_PM +static int snd_miro_pnp_suspend(struct pnp_card_link *pcard, + pm_message_t state) +{ + return snd_miro_suspend(pnp_get_card_drvdata(pcard)); +} + +static int snd_miro_pnp_resume(struct pnp_card_link *pcard) +{ + return snd_miro_resume(pnp_get_card_drvdata(pcard)); +} +#endif + static struct pnp_card_driver miro_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, .name = "miro", .id_table = snd_miro_pnpids, .probe = snd_miro_pnp_probe, .remove = snd_miro_pnp_remove, +#ifdef CONFIG_PM + .suspend = snd_miro_pnp_suspend, + .resume = snd_miro_pnp_resume, +#endif }; #endif diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 208d1942a015..866d7f5c58a0 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -99,8 +99,8 @@ MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth."); #endif #ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; #endif struct snd_card_sb16 { diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 553ceb92d298..ce8a59650e38 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -71,8 +71,8 @@ module_param_array(joystick, bool, NULL, 0444); MODULE_PARM_DESC(joystick, "Enable gameport."); #ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; static const struct pnp_card_device_id sscape_pnpids[] = { { .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */ diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 07c68568091d..5b1917cc19ce 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -71,8 +71,8 @@ module_param_array(use_cs4232_midi, bool, NULL, 0444); MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)"); #ifdef CONFIG_PNP -static int isa_registered; -static int pnp_registered; +static int isa_registered __ro_after_init; +static int pnp_registered __ro_after_init; static const struct pnp_card_device_id snd_wavefront_pnpids[] = { /* Tropez */ @@ -353,6 +353,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) dev_err(card->dev, "can't allocate WSS device\n"); return err; } + acard->chip = chip; err = snd_wss_pcm(chip, 0); if (err < 0) @@ -400,6 +401,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) acard->wavefront.irq = ics2115_irq[dev]; card->sync_irq = acard->wavefront.irq; acard->wavefront.base = ics2115_port[dev]; + snd_wavefront_cache_firmware(&acard->wavefront); wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard); if (wavefront_synth == NULL) { @@ -553,12 +555,51 @@ static int snd_wavefront_isa_probe(struct device *pdev, return 0; } +#ifdef CONFIG_PM +static int snd_wavefront_suspend(struct snd_card *card) +{ + snd_wavefront_card_t *acard = card->private_data; + + snd_wavefront_midi_suspend(acard); + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + acard->chip->suspend(acard->chip); + return 0; +} + +static int snd_wavefront_resume(struct snd_card *card) +{ + snd_wavefront_card_t *acard = card->private_data; + int err; + + acard->chip->resume(acard->chip); + err = snd_wavefront_resume_synth(acard); + if (err < 0) + return err; + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} + +static int snd_wavefront_isa_suspend(struct device *dev, unsigned int id, + pm_message_t state) +{ + return snd_wavefront_suspend(dev_get_drvdata(dev)); +} + +static int snd_wavefront_isa_resume(struct device *dev, unsigned int id) +{ + return snd_wavefront_resume(dev_get_drvdata(dev)); +} +#endif + #define DEV_NAME "wavefront" static struct isa_driver snd_wavefront_driver = { .match = snd_wavefront_isa_match, .probe = snd_wavefront_isa_probe, - /* FIXME: suspend, resume */ +#ifdef CONFIG_PM + .suspend = snd_wavefront_isa_suspend, + .resume = snd_wavefront_isa_resume, +#endif .driver = { .name = DEV_NAME }, @@ -600,12 +641,28 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard, return 0; } +#ifdef CONFIG_PM +static int snd_wavefront_pnpc_suspend(struct pnp_card_link *pcard, + pm_message_t state) +{ + return snd_wavefront_suspend(pnp_get_card_drvdata(pcard)); +} + +static int snd_wavefront_pnpc_resume(struct pnp_card_link *pcard) +{ + return snd_wavefront_resume(pnp_get_card_drvdata(pcard)); +} +#endif + static struct pnp_card_driver wavefront_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, .name = "wavefront", .id_table = snd_wavefront_pnpids, .probe = snd_wavefront_pnp_detect, - /* FIXME: suspend,resume */ +#ifdef CONFIG_PM + .suspend = snd_wavefront_pnpc_suspend, + .resume = snd_wavefront_pnpc_resume, +#endif }; #endif /* CONFIG_PNP */ diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c index 69d87c4cafae..fb184d9ef284 100644 --- a/sound/isa/wavefront/wavefront_midi.c +++ b/sound/isa/wavefront/wavefront_midi.c @@ -455,6 +455,49 @@ snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) card->wavefront.midi.isvirtual = 0; } +void +snd_wavefront_midi_suspend(snd_wavefront_card_t *card) + +{ + snd_wavefront_midi_t *midi = &card->wavefront.midi; + + if (!midi->istimer) + return; + + timer_delete_sync(&midi->timer); + + guard(spinlock_irqsave)(&midi->virtual); + midi->istimer = 0; +} + +void +snd_wavefront_midi_resume(snd_wavefront_card_t *card) + +{ + snd_wavefront_midi_t *midi = &card->wavefront.midi; + int istimer = 0; + bool pending_output = false; + + midi->timer_card = card; + + scoped_guard(spinlock_irqsave, &midi->virtual) { + if (midi->mode[internal_mpu] & MPU401_MODE_OUTPUT_TRIGGER) + istimer++; + if (midi->mode[external_mpu] & MPU401_MODE_OUTPUT_TRIGGER) + istimer++; + if (!istimer) + return; + + midi->istimer = istimer; + timer_setup(&midi->timer, snd_wavefront_midi_output_timer, 0); + mod_timer(&midi->timer, 1 + jiffies); + pending_output = true; + } + + if (pending_output) + snd_wavefront_midi_output_write(card); +} + int snd_wavefront_midi_start (snd_wavefront_card_t *card) @@ -466,6 +509,7 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card) dev = &card->wavefront; midi = &dev->midi; + midi->timer_card = card; /* The ICS2115 MPU-401 interface doesn't do anything until its set into UART mode. @@ -511,6 +555,8 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card) dev_warn(card->wavefront.card->dev, "can't enable MIDI-IN-2-synth routing.\n"); /* XXX error ? */ + } else { + dev->midi_in_to_synth = 1; } /* Turn on Virtual MIDI, but first *always* turn it off, @@ -553,4 +599,3 @@ const struct snd_rawmidi_ops snd_wavefront_midi_input = .close = snd_wavefront_midi_input_close, .trigger = snd_wavefront_midi_input_trigger, }; - diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 33b563707a58..2f57a6795d22 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -1626,6 +1626,14 @@ wavefront_synth_control (snd_wavefront_card_t *acard, "support for sample aliases still being considered.\n"); break; + case WFC_MISYNTH_OFF: + dev->midi_in_to_synth = 0; + break; + + case WFC_MISYNTH_ON: + dev->midi_in_to_synth = 1; + break; + case WFC_VMIDI_OFF: snd_wavefront_midi_disable_virtual (acard); break; @@ -1639,6 +1647,83 @@ wavefront_synth_control (snd_wavefront_card_t *acard, return 0; } +static int +wavefront_restore_midi_state(snd_wavefront_card_t *acard, char isvirtual, + char midi_in_to_synth) +{ + snd_wavefront_t *dev = &acard->wavefront; + unsigned char rbuf[4], wbuf[4]; + + if (dev->midi_in_to_synth != midi_in_to_synth) { + if (snd_wavefront_cmd(dev, midi_in_to_synth ? + WFC_MISYNTH_ON : WFC_MISYNTH_OFF, + rbuf, wbuf)) { + dev_err(dev->card->dev, + "cannot restore MIDI-IN routing after resume\n"); + return -EIO; + } + dev->midi_in_to_synth = midi_in_to_synth; + } + + if (dev->midi.isvirtual != isvirtual) { + if (snd_wavefront_cmd(dev, isvirtual ? + WFC_VMIDI_ON : WFC_VMIDI_OFF, + rbuf, wbuf)) { + dev_err(dev->card->dev, + "cannot restore virtual MIDI mode after resume\n"); + return -EIO; + } + if (isvirtual) + snd_wavefront_midi_enable_virtual(acard); + else + snd_wavefront_midi_disable_virtual(acard); + } + + return 0; +} + +int snd_wavefront_resume_synth(snd_wavefront_card_t *acard) +{ + snd_wavefront_t *dev = &acard->wavefront; + char was_virtual = dev->midi.isvirtual; + char midi_in_to_synth = dev->midi_in_to_synth; + char rom_samples_rdonly = dev->rom_samples_rdonly; + int err; + + err = snd_wavefront_detect(acard); + if (err < 0) + dev->israw = 1; + + if (dev->israw) { + dev->fx_initialized = 0; + err = snd_wavefront_start(dev); + if (err < 0) + return err; + } else { + dev->has_fx = (snd_wavefront_fx_detect(dev) == 0); + wavefront_get_sample_status(dev, 0); + wavefront_get_program_status(dev); + wavefront_get_patch_status(dev); + outb(0x80 | 0x40 | 0x20, dev->control_port); + } + + dev->rom_samples_rdonly = rom_samples_rdonly; + dev->midi.base = dev->base; + + err = snd_wavefront_midi_start(acard); + if (err < 0) + return err; + + err = wavefront_restore_midi_state(acard, was_virtual, + midi_in_to_synth); + if (err < 0) + return err; + + snd_wavefront_midi_resume(acard); + + return 0; +} + int snd_wavefront_synth_open (struct snd_hwdep *hw, struct file *file) @@ -2032,6 +2117,17 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path) return 1; } +void snd_wavefront_cache_firmware(snd_wavefront_t *dev) +{ + int err; + + err = firmware_request_cache(dev->card->dev, ospath); + if (err < 0) + dev_warn(dev->card->dev, + "unable to cache firmware %s for resume: %d\n", + ospath, err); +} + static int wavefront_do_reset (snd_wavefront_t *dev) diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index a718b75bb6a0..e80f730d0803 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -574,11 +574,6 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft, uWritten = 0 ; } -/* FIXME: I think that this may be the wrong behaviour when we get strapped - for time and the cpu is close to being (or actually) behind in sending data. - - because we've lost the time that the N samples, already in the buffer, - would have given us to get here with the next lot from the user. -*/ /* The interrupt doesn't start to play the last, incomplete frame. * Thus we can append to it without disabling the interrupts! (Note * also that write_sq.rear isn't affected by the interrupt.) @@ -598,6 +593,11 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft, write_sq.syncing &= ~2 ; /* take out POST status */ spin_unlock_irqrestore(&dmasound.lock, flags); + /* Start any already-complete fragments before we spend + * more time extending the incomplete tail fragment. + */ + sq_play(); + if (write_sq.count > 0 && (bLeft = write_sq.block_size-write_sq.rear_size) > 0) { dest = write_sq.buffers[write_sq.rear]; diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 571d89a6a8da..f07c5f4c2380 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -247,8 +247,8 @@ struct snd_ali { }; static const struct pci_device_id snd_ali_ids[] = { - {PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0}, - {0, } + { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451) }, + { } }; MODULE_DEVICE_TABLE(pci, snd_ali_ids); diff --git a/sound/pci/als300.c b/sound/pci/als300.c index a73893a2cbd6..00f0720169c3 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -127,9 +127,9 @@ struct snd_als300_substream_data { }; static const struct pci_device_id snd_als300_ids[] = { - { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 }, - { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS }, - { 0, } + { PCI_DEVICE(0x4005, 0x0300), .driver_data = DEVICE_ALS300 }, + { PCI_DEVICE(0x4005, 0x0308), .driver_data = DEVICE_ALS300_PLUS }, + { } }; MODULE_DEVICE_TABLE(pci, snd_als300_ids); diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 636f309c9424..6396aa6c3bf0 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -102,8 +102,8 @@ struct snd_card_als4000 { }; static const struct pci_device_id snd_als4000_ids[] = { - { 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */ - { 0, } + { PCI_DEVICE(0x4005, 0x4000) }, /* ALS4000 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_als4000_ids); diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index b1c7ed7f1604..4dbc79899c09 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -2933,13 +2933,16 @@ static void snd_asihpi_remove(struct pci_dev *pci_dev) } static const struct pci_device_id asihpi_pci_tbl[] = { - {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t)HPI_6205}, - {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t)HPI_6000}, - {0,} + { + PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, + HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID), + .driver_data = (kernel_ulong_t)HPI_6205, + }, { + PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, + HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID), + .driver_data = (kernel_ulong_t)HPI_6000, + }, + {} }; MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl); diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c index 19f0da2e6501..5f69c04c672a 100644 --- a/sound/pci/asihpi/hpicmn.c +++ b/sound/pci/asihpi/hpicmn.c @@ -647,17 +647,12 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache, struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, const u32 size_in_bytes, u8 *p_dsp_control_buffer) { - struct hpi_control_cache *p_cache = kmalloc_obj(*p_cache); + struct hpi_control_cache *p_cache; + + p_cache = kzalloc_flex(*p_cache, p_info, control_count); if (!p_cache) return NULL; - p_cache->p_info = - kzalloc_objs(*p_cache->p_info, control_count); - if (!p_cache->p_info) { - kfree(p_cache); - return NULL; - } - p_cache->cache_size_in_bytes = size_in_bytes; p_cache->control_count = control_count; p_cache->p_cache = p_dsp_control_buffer; @@ -667,10 +662,7 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, void hpi_free_control_cache(struct hpi_control_cache *p_cache) { - if (p_cache) { - kfree(p_cache->p_info); - kfree(p_cache); - } + kfree(p_cache); } static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h index 8ec656cf8848..40af7329587a 100644 --- a/sound/pci/asihpi/hpicmn.h +++ b/sound/pci/asihpi/hpicmn.h @@ -37,10 +37,10 @@ struct hpi_control_cache { u16 adap_idx; u32 control_count; u32 cache_size_in_bytes; - /** pointer to allocated memory of lookup pointers. */ - struct hpi_control_cache_info **p_info; /** pointer to DSP's control cache. */ u8 *p_cache; + /** pointer to allocated memory of lookup pointers. */ + struct hpi_control_cache_info *p_info[] __counted_by(control_count); }; struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index); diff --git a/sound/pci/asihpi/hpipcida.h b/sound/pci/asihpi/hpipcida.h index 0673e8278070..6dceff2b4741 100644 --- a/sound/pci/asihpi/hpipcida.h +++ b/sound/pci/asihpi/hpipcida.h @@ -15,12 +15,12 @@ */ { -HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t) HPI_6205} -, { -HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, - HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0, - (kernel_ulong_t) HPI_6000} -, { -0} + PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205, + HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID), + .driver_data = (kernel_ulong_t) HPI_6205, +}, { + PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040, + HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID), + .driver_data = (kernel_ulong_t) HPI_6000, +}, +{ } diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 2a0c59d5afa5..b738295b41e5 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -272,11 +272,11 @@ struct atiixp { /* */ static const struct pci_device_id snd_atiixp_ids[] = { - { PCI_VDEVICE(ATI, 0x4341), 0 }, /* SB200 */ - { PCI_VDEVICE(ATI, 0x4361), 0 }, /* SB300 */ - { PCI_VDEVICE(ATI, 0x4370), 0 }, /* SB400 */ - { PCI_VDEVICE(ATI, 0x4382), 0 }, /* SB600 */ - { 0, } + { PCI_VDEVICE(ATI, 0x4341) }, /* SB200 */ + { PCI_VDEVICE(ATI, 0x4361) }, /* SB300 */ + { PCI_VDEVICE(ATI, 0x4370) }, /* SB400 */ + { PCI_VDEVICE(ATI, 0x4382) }, /* SB600 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_atiixp_ids); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 91f31e2ad3d3..8aaeb197ce45 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -247,9 +247,9 @@ struct atiixp_modem { /* */ static const struct pci_device_id snd_atiixp_ids[] = { - { PCI_VDEVICE(ATI, 0x434d), 0 }, /* SB200 */ - { PCI_VDEVICE(ATI, 0x4378), 0 }, /* SB400 */ - { 0, } + { PCI_VDEVICE(ATI, 0x434d) }, /* SB200 */ + { PCI_VDEVICE(ATI, 0x4378) }, /* SB400 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_atiixp_ids); diff --git a/sound/pci/au88x0/au8810.c b/sound/pci/au88x0/au8810.c index b2bfa50bfe30..f712e32d3370 100644 --- a/sound/pci/au88x0/au8810.c +++ b/sound/pci/au88x0/au8810.c @@ -2,8 +2,8 @@ #include "au8810.h" #include "au88x0.h" static const struct pci_device_id snd_vortex_ids[] = { - {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), 1,}, - {0,} + { PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), .driver_data = 1 }, + { } }; #include "au88x0_core.c" diff --git a/sound/pci/au88x0/au8820.c b/sound/pci/au88x0/au8820.c index dbc2263b49c6..aa841b615182 100644 --- a/sound/pci/au88x0/au8820.c +++ b/sound/pci/au88x0/au8820.c @@ -2,8 +2,8 @@ #include "au8820.h" #include "au88x0.h" static const struct pci_device_id snd_vortex_ids[] = { - {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1), 0,}, - {0,} + { PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1), .driver_data = 0 }, + { } }; #include "au88x0_synth.c" diff --git a/sound/pci/au88x0/au8830.c b/sound/pci/au88x0/au8830.c index e963c4e2f026..aeb8d458c629 100644 --- a/sound/pci/au88x0/au8830.c +++ b/sound/pci/au88x0/au8830.c @@ -2,8 +2,8 @@ #include "au8830.h" #include "au88x0.h" static const struct pci_device_id snd_vortex_ids[] = { - {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2), 0,}, - {0,} + { PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2), .driver_data = 0 }, + { } }; #include "au88x0_synth.c" diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index e2c501f4394c..60a87322eae4 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -142,9 +142,8 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard."); static const struct pci_device_id snd_aw2_ids[] = { - {PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0, 0, - 0, 0, 0}, - {0} + { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0, 0) }, + { } }; MODULE_DEVICE_TABLE(pci, snd_aw2_ids); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 6cdf76e2b7d2..ccca82417657 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -305,9 +305,9 @@ struct snd_azf3328 { }; static const struct pci_device_id snd_azf3328_ids[] = { - { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */ - { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */ - { 0, } + { PCI_DEVICE(0x122D, 0x50DC) }, /* PCI168/3328 */ + { PCI_DEVICE(0x122D, 0x80DA) }, /* 3328 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_azf3328_ids); diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 35392f6525b3..cf923f551211 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1820,8 +1820,8 @@ static SIMPLE_DEV_PM_OPS(snd_ca0106_pm, snd_ca0106_suspend, snd_ca0106_resume); // PCI IDs static const struct pci_device_id snd_ca0106_ids[] = { - { PCI_VDEVICE(CREATIVE, 0x0007), 0 }, /* Audigy LS or Live 24bit */ - { 0, } + { PCI_VDEVICE(CREATIVE, 0x0007) }, /* Audigy LS or Live 24bit */ + { } }; MODULE_DEVICE_TABLE(pci, snd_ca0106_ids); diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index cd73b6833639..9d9f784e3a8c 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -2637,16 +2637,22 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) } if (cm->can_ac3_hw) { kctl = snd_ctl_new1(&snd_cmipci_spdif_default, cm); + if (!kctl) + return -ENOMEM; kctl->id.device = pcm_spdif_device; err = snd_ctl_add(card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_cmipci_spdif_mask, cm); + if (!kctl) + return -ENOMEM; kctl->id.device = pcm_spdif_device; err = snd_ctl_add(card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_cmipci_spdif_stream, cm); + if (!kctl) + return -ENOMEM; kctl->id.device = pcm_spdif_device; err = snd_ctl_add(card, kctl); if (err < 0) @@ -2721,12 +2727,12 @@ static void snd_cmipci_proc_init(struct cmipci *cm) } static const struct pci_device_id snd_cmipci_ids[] = { - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0}, - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B), 0}, - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, - {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B), 0}, - {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, - {0,}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A) }, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B) }, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738) }, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B) }, + {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738) }, + { } }; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index d00b2c9fb1e3..f51f4bb63766 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -476,8 +476,8 @@ struct cs4281 { static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id); static const struct pci_device_id snd_cs4281_ids[] = { - { PCI_VDEVICE(CIRRUS, 0x6005), 0, }, /* CS4281 */ - { 0, } + { PCI_VDEVICE(CIRRUS, 0x6005) }, /* CS4281 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_cs4281_ids); diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 9c1995737eb7..0cb7c2a2929f 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c @@ -43,10 +43,10 @@ module_param_array(mmap_valid, bool, NULL, 0444); MODULE_PARM_DESC(mmap_valid, "Support OSS mmap."); static const struct pci_device_id snd_cs46xx_ids[] = { - { PCI_VDEVICE(CIRRUS, 0x6001), 0, }, /* CS4280 */ - { PCI_VDEVICE(CIRRUS, 0x6003), 0, }, /* CS4612 */ - { PCI_VDEVICE(CIRRUS, 0x6004), 0, }, /* CS4615 */ - { 0, } + { PCI_VDEVICE(CIRRUS, 0x6001) }, /* CS4280 */ + { PCI_VDEVICE(CIRRUS, 0x6003) }, /* CS4612 */ + { PCI_VDEVICE(CIRRUS, 0x6004) }, /* CS4615 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_cs46xx_ids); diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index e3ee76bd8482..9abe1d53c3c5 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -221,10 +221,6 @@ ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); static void ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); -/* FIXME: this static looks like it would fail if more than one card was */ -/* installed. */ -static struct snd_kcontrol *kctls[2] = {NULL}; - static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) { switch (alsa_index) { @@ -481,17 +477,18 @@ static struct snd_kcontrol_new mic_source_ctl = { static void do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) { + struct ct_mixer *mixer = atc->mixer; if (MIXER_LINEIN_C_S == type) { atc->select_line_in(atc); - set_switch_state(atc->mixer, MIXER_MIC_C_S, 0); + set_switch_state(mixer, MIXER_MIC_C_S, 0); snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE, - &kctls[1]->id); + &mixer->line_mic_kctls[1]->id); } else if (MIXER_MIC_C_S == type) { atc->select_mic_in(atc); - set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0); + set_switch_state(mixer, MIXER_LINEIN_C_S, 0); snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE, - &kctls[0]->id); + &mixer->line_mic_kctls[0]->id); } } @@ -778,9 +775,9 @@ ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new) switch (new->private_value) { case MIXER_LINEIN_C_S: - kctls[0] = kctl; break; + mixer->line_mic_kctls[0] = kctl; break; case MIXER_MIC_C_S: - kctls[1] = kctl; break; + mixer->line_mic_kctls[1] = kctl; break; default: break; } @@ -965,35 +962,20 @@ static int ct_mixer_get_resources(struct ct_mixer *mixer) static int ct_mixer_get_mem(struct ct_mixer **rmixer) { struct ct_mixer *mixer; - int err; + size_t alloc_size; *rmixer = NULL; /* Allocate mem for mixer obj */ - mixer = kzalloc_obj(*mixer); + alloc_size = struct_size(mixer, amixers, NUM_CT_AMIXERS * CHN_NUM); + alloc_size += sizeof(*mixer->sums) * NUM_CT_SUMS * CHN_NUM; + mixer = kzalloc(alloc_size, GFP_KERNEL); if (!mixer) return -ENOMEM; - mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *), - GFP_KERNEL); - if (!mixer->amixers) { - err = -ENOMEM; - goto error1; - } - mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *), - GFP_KERNEL); - if (!mixer->sums) { - err = -ENOMEM; - goto error2; - } + mixer->sums = (struct sum **)(mixer->amixers + (NUM_CT_AMIXERS * CHN_NUM)); *rmixer = mixer; return 0; - -error2: - kfree(mixer->amixers); -error1: - kfree(mixer); - return err; } static int ct_mixer_topology_build(struct ct_mixer *mixer) @@ -1228,8 +1210,6 @@ int ct_mixer_destroy(struct ct_mixer *mixer) } /* Release mem assigned to mixer object */ - kfree(mixer->sums); - kfree(mixer->amixers); kfree(mixer); return 0; diff --git a/sound/pci/ctxfi/ctmixer.h b/sound/pci/ctxfi/ctmixer.h index e812f6c93b41..0c0963bba99c 100644 --- a/sound/pci/ctxfi/ctmixer.h +++ b/sound/pci/ctxfi/ctmixer.h @@ -17,6 +17,8 @@ #include "ctatc.h" #include "ctresource.h" +struct snd_kcontrol; + #define INIT_VOL 0x1c00 enum MIXER_PORT_T { @@ -41,8 +43,8 @@ enum MIXER_PORT_T { struct ct_mixer { struct ct_atc *atc; - void **amixers; /* amixer resources for volume control */ - void **sums; /* sum resources for signal collection */ + struct sum **sums; /* sum resources for signal collection */ + struct snd_kcontrol *line_mic_kctls[2]; /* line/mic capture switch controls */ unsigned int switch_state; /* A bit-map to indicate state of switches */ int (*get_output_ports)(struct ct_mixer *mixer, enum MIXER_PORT_T type, @@ -55,6 +57,7 @@ struct ct_mixer { #ifdef CONFIG_PM_SLEEP int (*resume)(struct ct_mixer *mixer); #endif + struct amixer *amixers[]; /* amixer resources for volume control */ }; int ct_alsa_mix_create(struct ct_atc *atc, diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c index 326997bb885d..46dc1f509234 100644 --- a/sound/pci/ctxfi/ctsrc.c +++ b/sound/pci/ctxfi/ctsrc.c @@ -668,13 +668,6 @@ static int srcimp_rsc_init(struct srcimp *srcimp, if (err) return err; - /* Reserve memory for imapper nodes */ - srcimp->imappers = kzalloc_objs(struct imapper, desc->msr); - if (!srcimp->imappers) { - err = -ENOMEM; - goto error1; - } - /* Set srcimp specific operations */ srcimp->rsc.ops = &srcimp_basic_rsc_ops; srcimp->ops = &srcimp_ops; @@ -683,16 +676,10 @@ static int srcimp_rsc_init(struct srcimp *srcimp, srcimp->rsc.ops->master(&srcimp->rsc); return 0; - -error1: - rsc_uninit(&srcimp->rsc); - return err; } static int srcimp_rsc_uninit(struct srcimp *srcimp) { - kfree(srcimp->imappers); - srcimp->imappers = NULL; srcimp->ops = NULL; srcimp->mgr = NULL; rsc_uninit(&srcimp->rsc); @@ -711,7 +698,7 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr, *rsrcimp = NULL; /* Allocate mem for SRCIMP resource */ - srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL); + srcimp = kzalloc_flex(*srcimp, imappers, desc->msr); if (!srcimp) return -ENOMEM; diff --git a/sound/pci/ctxfi/ctsrc.h b/sound/pci/ctxfi/ctsrc.h index e6366cc6a7ae..7ba94adde920 100644 --- a/sound/pci/ctxfi/ctsrc.h +++ b/sound/pci/ctxfi/ctsrc.h @@ -103,10 +103,10 @@ struct srcimp_rsc_ops; struct srcimp { struct rsc rsc; unsigned char idx[8]; - struct imapper *imappers; unsigned int mapped; /* A bit-map indicating which conj rsc is mapped */ struct srcimp_mgr *mgr; const struct srcimp_rsc_ops *ops; + struct imapper imappers[]; }; struct srcimp_rsc_ops { diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c index e295c71c7a39..48c25bd3f401 100644 --- a/sound/pci/echoaudio/darla20.c +++ b/sound/pci/echoaudio/darla20.c @@ -52,8 +52,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0}, /* DSP 56301 Darla20 rev.0 */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0010) }, /* DSP 56301 Darla20 rev.0 */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c index ae816e78f599..c8cdd1b052df 100644 --- a/sound/pci/echoaudio/darla24.c +++ b/sound/pci/echoaudio/darla24.c @@ -56,9 +56,9 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0}, /* DSP 56301 Darla24 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0}, /* DSP 56301 Darla24 rev.1 */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0040) }, /* DSP 56301 Darla24 rev.0 */ + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0041) }, /* DSP 56301 Darla24 rev.1 */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c index 3d37bb4030ec..e8b476e07307 100644 --- a/sound/pci/echoaudio/echo3g.c +++ b/sound/pci/echoaudio/echo3g.c @@ -70,8 +70,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0}, /* Echo 3G */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0100) }, /* Echo 3G */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c index 4f864ddc9530..b5f88922e19a 100644 --- a/sound/pci/echoaudio/gina20.c +++ b/sound/pci/echoaudio/gina20.c @@ -56,8 +56,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0}, /* DSP 56301 Gina20 rev.0 */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0020) }, /* DSP 56301 Gina20 rev.0 */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c index eff69e83ca0a..fe0e510209ed 100644 --- a/sound/pci/echoaudio/gina24.c +++ b/sound/pci/echoaudio/gina24.c @@ -74,11 +74,11 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56301 Gina24 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56301 Gina24 rev.1 */ - {0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56361 Gina24 rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56361 Gina24 rev.1 */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0050) }, /* DSP 56301 Gina24 rev.0 */ + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0051) }, /* DSP 56301 Gina24 rev.1 */ + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0050) }, /* DSP 56361 Gina24 rev.0 */ + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0051) }, /* DSP 56361 Gina24 rev.1 */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c index a9f2efc58f6e..496cc5aa9516 100644 --- a/sound/pci/echoaudio/indigo.c +++ b/sound/pci/echoaudio/indigo.c @@ -57,8 +57,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0090, 0, 0, 0}, /* Indigo */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0090) }, /* Indigo */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c index 14e9769ceba1..45ad92e8f531 100644 --- a/sound/pci/echoaudio/indigodj.c +++ b/sound/pci/echoaudio/indigodj.c @@ -57,8 +57,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x00B0, 0, 0, 0}, /* Indigo DJ*/ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00B0) }, /* Indigo DJ*/ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c index a14a7dc8c87d..b1878ecb8375 100644 --- a/sound/pci/echoaudio/indigodjx.c +++ b/sound/pci/echoaudio/indigodjx.c @@ -57,8 +57,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x00E0, 0, 0, 0}, /* Indigo DJx*/ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00E0) }, /* Indigo DJx*/ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c index 97e024450d19..2c6a6f74b0bd 100644 --- a/sound/pci/echoaudio/indigoio.c +++ b/sound/pci/echoaudio/indigoio.c @@ -58,8 +58,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x00A0, 0, 0, 0}, /* Indigo IO*/ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00A0) }, /* Indigo IO*/ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c index a017c966b4dc..dfaa563317ad 100644 --- a/sound/pci/echoaudio/indigoiox.c +++ b/sound/pci/echoaudio/indigoiox.c @@ -58,8 +58,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x00D0, 0, 0, 0}, /* Indigo IOx */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00D0) }, /* Indigo IOx */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c index 7e38bc9c025d..82c089f7b452 100644 --- a/sound/pci/echoaudio/layla20.c +++ b/sound/pci/echoaudio/layla20.c @@ -65,9 +65,9 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0030, 0, 0, 0}, /* DSP 56301 Layla20 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0031, 0, 0, 0}, /* DSP 56301 Layla20 rev.1 */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0030) }, /* DSP 56301 Layla20 rev.0 */ + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0031) }, /* DSP 56301 Layla20 rev.1 */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c index 95c52210fb65..efd676467a37 100644 --- a/sound/pci/echoaudio/layla24.c +++ b/sound/pci/echoaudio/layla24.c @@ -76,8 +76,8 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0060, 0, 0, 0}, /* DSP 56361 Layla24 rev.0 */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0060) }, /* DSP 56361 Layla24 rev.0 */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c index a2d4b0003b57..950aaec74a43 100644 --- a/sound/pci/echoaudio/mia.c +++ b/sound/pci/echoaudio/mia.c @@ -66,9 +66,9 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0080, 0, 0, 0}, /* DSP 56361 Mia rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0081, 0, 0, 0}, /* DSP 56361 Mia rev.1 */ - {0,} + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0080) }, /* DSP 56361 Mia rev.0 */ + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0081) }, /* DSP 56361 Mia rev.1 */ + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c index 1b45a2b5066f..4f999324f388 100644 --- a/sound/pci/echoaudio/mona.c +++ b/sound/pci/echoaudio/mona.c @@ -81,13 +81,19 @@ static const struct firmware card_fw[] = { }; static const struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56301 Mona rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56301 Mona rev.1 */ - {0x1057, 0x1801, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56301 Mona rev.2 */ - {0x1057, 0x3410, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56361 Mona rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56361 Mona rev.1 */ - {0x1057, 0x3410, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56361 Mona rev.2 */ - {0,} + /* DSP 56301 Mona rev.0 */ + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0070) }, + /* DSP 56301 Mona rev.1 */ + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0071) }, + /* DSP 56301 Mona rev.2 */ + { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0072) }, + /* DSP 56361 Mona rev.0 */ + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0070) }, + /* DSP 56361 Mona rev.1 */ + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0071) }, + /* DSP 56361 Mona rev.2 */ + { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0072) }, + { } }; static const struct snd_pcm_hardware pcm_hardware_skel = { diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 548e7d049901..3b21bd2883b6 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -58,10 +58,10 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model."); * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 */ static const struct pci_device_id snd_emu10k1_ids[] = { - { PCI_VDEVICE(CREATIVE, 0x0002), 0 }, /* EMU10K1 */ - { PCI_VDEVICE(CREATIVE, 0x0004), 1 }, /* Audigy */ - { PCI_VDEVICE(CREATIVE, 0x0008), 1 }, /* Audigy 2 Value SB0400 */ - { 0, } + { PCI_VDEVICE(CREATIVE, 0x0002), .driver_data = 0 }, /* EMU10K1 */ + { PCI_VDEVICE(CREATIVE, 0x0004), .driver_data = 1 }, /* Audigy */ + { PCI_VDEVICE(CREATIVE, 0x0008), .driver_data = 1 }, /* Audigy 2 Value SB0400 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 1b207ca25814..ed4630c8342b 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c @@ -1518,8 +1518,8 @@ static int snd_emu10k1x_probe(struct pci_dev *pci, // PCI IDs static const struct pci_device_id snd_emu10k1x_ids[] = { - { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */ - { 0, } + { PCI_VDEVICE(CREATIVE, 0x0006) }, /* Dell OEM version (EMU10K1) */ + { } }; MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids); diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 657056a59175..0b9eb55a2121 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -426,14 +426,14 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id); static const struct pci_device_id snd_audiopci_ids[] = { #ifdef CHIP1370 - { PCI_VDEVICE(ENSONIQ, 0x5000), 0, }, /* ES1370 */ + { PCI_VDEVICE(ENSONIQ, 0x5000) }, /* ES1370 */ #endif #ifdef CHIP1371 - { PCI_VDEVICE(ENSONIQ, 0x1371), 0, }, /* ES1371 */ - { PCI_VDEVICE(ENSONIQ, 0x5880), 0, }, /* ES1373 - CT5880 */ - { PCI_VDEVICE(ECTIVA, 0x8938), 0, }, /* Ectiva EV1938 */ + { PCI_VDEVICE(ENSONIQ, 0x1371) }, /* ES1371 */ + { PCI_VDEVICE(ENSONIQ, 0x5880) }, /* ES1373 - CT5880 */ + { PCI_VDEVICE(ECTIVA, 0x8938) }, /* Ectiva EV1938 */ #endif - { 0, } + { } }; MODULE_DEVICE_TABLE(pci, snd_audiopci_ids); diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 280125eff362..217beb9376ac 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -222,8 +222,8 @@ struct es1938 { static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id); static const struct pci_device_id snd_es1938_ids[] = { - { PCI_VDEVICE(ESS, 0x1969), 0, }, /* Solo-1 */ - { 0, } + { PCI_VDEVICE(ESS, 0x1969) }, /* Solo-1 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_es1938_ids); @@ -1655,6 +1655,8 @@ static int snd_es1938_mixer(struct es1938 *chip) for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) { struct snd_kcontrol *kctl; kctl = snd_ctl_new1(&snd_es1938_controls[idx], chip); + if (!kctl) + return -ENOMEM; switch (idx) { case 0: chip->master_volume = kctl; diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index b7282b3fa1b1..f04628c8cbb7 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -549,13 +549,26 @@ struct es1968 { static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id); static const struct pci_device_id snd_es1968_ids[] = { - /* Maestro 1 */ - { 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO }, - /* Maestro 2 */ - { 0x125d, 0x1968, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2 }, - /* Maestro 2E */ - { 0x125d, 0x1978, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2E }, - { 0, } + { + /* Maestro 1 */ + PCI_DEVICE(0x1285, 0x0100), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + .driver_data = TYPE_MAESTRO, + }, { + /* Maestro 2 */ + PCI_DEVICE(0x125d, 0x1968), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + .driver_data = TYPE_MAESTRO2, + }, { + /* Maestro 2E */ + PCI_DEVICE(0x125d, 0x1978), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + .driver_data = TYPE_MAESTRO2E, + }, + { } }; MODULE_DEVICE_TABLE(pci, snd_es1968_ids); diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 4ca992449ea3..9cc96b807dd7 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -240,9 +240,18 @@ static inline u16 fm801_ioread16(struct fm801 *chip, unsigned short offset) } static const struct pci_device_id snd_fm801_ids[] = { - { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ - { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */ - { 0, } + { + /* FM801 */ + PCI_DEVICE(0x1319, 0x0801), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + /* Gallant Odyssey Sound 4 */ + PCI_DEVICE(0x5213, 0x0510), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, + { } }; MODULE_DEVICE_TABLE(pci, snd_fm801_ids); diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 1191a2686dfd..d6abff2978f3 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1891,6 +1891,8 @@ static int aureon_add_controls(struct snd_ice1712 *ice) for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) { struct snd_kcontrol *kctl; kctl = snd_ctl_new1(&cs8415_controls[i], ice); + if (!kctl) + return -ENOMEM; if (i > 1) kctl->id.device = ice->pcm->device; err = snd_ctl_add(ice->card, kctl); diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 1e39b985bef2..7d1a357ed90d 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -86,8 +86,8 @@ MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE."); static const struct pci_device_id snd_ice1712_ids[] = { - { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712), 0 }, /* ICE1712 */ - { 0, } + { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712) }, /* ICE1712 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_ice1712_ids); @@ -2346,21 +2346,29 @@ int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice) if (snd_BUG_ON(!ice->pcm_pro)) return -EIO; kctl = snd_ctl_new1(&snd_ice1712_spdif_default, ice); + if (!kctl) + return -ENOMEM; kctl->id.device = ice->pcm_pro->device; err = snd_ctl_add(ice->card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_ice1712_spdif_maskc, ice); + if (!kctl) + return -ENOMEM; kctl->id.device = ice->pcm_pro->device; err = snd_ctl_add(ice->card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_ice1712_spdif_maskp, ice); + if (!kctl) + return -ENOMEM; kctl->id.device = ice->pcm_pro->device; err = snd_ctl_add(ice->card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_ice1712_spdif_stream, ice); + if (!kctl) + return -ENOMEM; kctl->id.device = ice->pcm_pro->device; err = snd_ctl_add(ice->card, kctl); if (err < 0) diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 65bf48647d08..859bb87393b4 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -62,8 +62,8 @@ MODULE_PARM_DESC(model, "Use the given board model."); /* Both VT1720 and VT1724 have the same PCI IDs */ static const struct pci_device_id snd_vt1724_ids[] = { - { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724), 0 }, - { 0, } + { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724) }, + { } }; MODULE_DEVICE_TABLE(pci, snd_vt1724_ids); @@ -730,13 +730,22 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream, static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); + bool released = false; int i; - guard(mutex)(&ice->open_mutex); - /* unmark surround channels */ - for (i = 0; i < 3; i++) - if (ice->pcm_reserved[i] == substream) + scoped_guard(mutex, &ice->open_mutex) { + /* unmark surround channels */ + for (i = 0; i < 3; i++) { + if (ice->pcm_reserved[i] != substream) + continue; ice->pcm_reserved[i] = NULL; + released = true; + } + } + + if (released && ice->pcm_ds) + wake_up(&ice->pcm_ds->open_wait); + return 0; } @@ -1364,7 +1373,7 @@ static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream) scoped_guard(mutex, &ice->open_mutex) { /* already used by PDMA0? */ if (ice->pcm_reserved[substream->number]) - return -EBUSY; /* FIXME: should handle blocking mode properly */ + return -EAGAIN; } runtime->private_data = (void *)&vt1724_playback_dma_regs[substream->number]; ice->playback_con_substream_ds[substream->number] = substream; @@ -2379,16 +2388,22 @@ static int snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice) return err; kctl = snd_ctl_new1(&snd_vt1724_spdif_default, ice); + if (!kctl) + return -ENOMEM; kctl->id.device = ice->pcm->device; err = snd_ctl_add(ice->card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_vt1724_spdif_maskc, ice); + if (!kctl) + return -ENOMEM; kctl->id.device = ice->pcm->device; err = snd_ctl_add(ice->card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_vt1724_spdif_maskp, ice); + if (!kctl) + return -ENOMEM; kctl->id.device = ice->pcm->device; err = snd_ctl_add(ice->card, kctl); if (err < 0) diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 3b53c5e63c29..e2ea9016a73e 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -384,30 +384,100 @@ struct intel8x0 { }; static const struct pci_device_id snd_intel8x0_ids[] = { - { PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL }, /* 82801AA */ - { PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL }, /* 82901AB */ - { PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL }, /* 82801BA */ - { PCI_VDEVICE(INTEL, 0x2485), DEVICE_INTEL }, /* ICH3 */ - { PCI_VDEVICE(INTEL, 0x24c5), DEVICE_INTEL_ICH4 }, /* ICH4 */ - { PCI_VDEVICE(INTEL, 0x24d5), DEVICE_INTEL_ICH4 }, /* ICH5 */ - { PCI_VDEVICE(INTEL, 0x25a6), DEVICE_INTEL_ICH4 }, /* ESB */ - { PCI_VDEVICE(INTEL, 0x266e), DEVICE_INTEL_ICH4 }, /* ICH6 */ - { PCI_VDEVICE(INTEL, 0x27de), DEVICE_INTEL_ICH4 }, /* ICH7 */ - { PCI_VDEVICE(INTEL, 0x2698), DEVICE_INTEL_ICH4 }, /* ESB2 */ - { PCI_VDEVICE(INTEL, 0x7195), DEVICE_INTEL }, /* 440MX */ - { PCI_VDEVICE(SI, 0x7012), DEVICE_SIS }, /* SI7012 */ - { PCI_VDEVICE(NVIDIA, 0x01b1), DEVICE_NFORCE }, /* NFORCE */ - { PCI_VDEVICE(NVIDIA, 0x003a), DEVICE_NFORCE }, /* MCP04 */ - { PCI_VDEVICE(NVIDIA, 0x006a), DEVICE_NFORCE }, /* NFORCE2 */ - { PCI_VDEVICE(NVIDIA, 0x0059), DEVICE_NFORCE }, /* CK804 */ - { PCI_VDEVICE(NVIDIA, 0x008a), DEVICE_NFORCE }, /* CK8 */ - { PCI_VDEVICE(NVIDIA, 0x00da), DEVICE_NFORCE }, /* NFORCE3 */ - { PCI_VDEVICE(NVIDIA, 0x00ea), DEVICE_NFORCE }, /* CK8S */ - { PCI_VDEVICE(NVIDIA, 0x026b), DEVICE_NFORCE }, /* MCP51 */ - { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */ - { PCI_VDEVICE(AMD, 0x7445), DEVICE_INTEL }, /* AMD768 */ - { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ - { 0, } + { + /* 82801AA */ + PCI_VDEVICE(INTEL, 0x2415), + .driver_data = DEVICE_INTEL, + }, { + /* 82901AB */ + PCI_VDEVICE(INTEL, 0x2425), + .driver_data = DEVICE_INTEL, + }, { + /* 82801BA */ + PCI_VDEVICE(INTEL, 0x2445), + .driver_data = DEVICE_INTEL, + }, { + /* ICH3 */ + PCI_VDEVICE(INTEL, 0x2485), + .driver_data = DEVICE_INTEL, + }, { + /* ICH4 */ + PCI_VDEVICE(INTEL, 0x24c5), + .driver_data = DEVICE_INTEL_ICH4, + }, { + /* ICH5 */ + PCI_VDEVICE(INTEL, 0x24d5), + .driver_data = DEVICE_INTEL_ICH4, + }, { + /* ESB */ + PCI_VDEVICE(INTEL, 0x25a6), + .driver_data = DEVICE_INTEL_ICH4, + }, { + /* ICH6 */ + PCI_VDEVICE(INTEL, 0x266e), + .driver_data = DEVICE_INTEL_ICH4, + }, { + /* ICH7 */ + PCI_VDEVICE(INTEL, 0x27de), + .driver_data = DEVICE_INTEL_ICH4, + }, { + /* ESB2 */ + PCI_VDEVICE(INTEL, 0x2698), + .driver_data = DEVICE_INTEL_ICH4, + }, { + /* 440MX */ + PCI_VDEVICE(INTEL, 0x7195), + .driver_data = DEVICE_INTEL, + }, { + /* SI7012 */ + PCI_VDEVICE(SI, 0x7012), + .driver_data = DEVICE_SIS, + }, { + /* NFORCE */ + PCI_VDEVICE(NVIDIA, 0x01b1), + .driver_data = DEVICE_NFORCE, + }, { + /* MCP04 */ + PCI_VDEVICE(NVIDIA, 0x003a), + .driver_data = DEVICE_NFORCE, + }, { + /* NFORCE2 */ + PCI_VDEVICE(NVIDIA, 0x006a), + .driver_data = DEVICE_NFORCE, + }, { + /* CK804 */ + PCI_VDEVICE(NVIDIA, 0x0059), + .driver_data = DEVICE_NFORCE, + }, { + /* CK8 */ + PCI_VDEVICE(NVIDIA, 0x008a), + .driver_data = DEVICE_NFORCE, + }, { + /* NFORCE3 */ + PCI_VDEVICE(NVIDIA, 0x00da), + .driver_data = DEVICE_NFORCE, + }, { + /* CK8S */ + PCI_VDEVICE(NVIDIA, 0x00ea), + .driver_data = DEVICE_NFORCE, + }, { + /* MCP51 */ + PCI_VDEVICE(NVIDIA, 0x026b), + .driver_data = DEVICE_NFORCE, + }, { + /* AMD8111 */ + PCI_VDEVICE(AMD, 0x746d), + .driver_data = DEVICE_INTEL, + }, { + /* AMD768 */ + PCI_VDEVICE(AMD, 0x7445), + .driver_data = DEVICE_INTEL, + }, { + /* Ali5455 */ + PCI_VDEVICE(AL, 0x5455), + .driver_data = DEVICE_ALI, + }, + { } }; MODULE_DEVICE_TABLE(pci, snd_intel8x0_ids); diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 84e1b7ea34e2..27dbf6125427 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -190,26 +190,78 @@ struct intel8x0m { }; static const struct pci_device_id snd_intel8x0m_ids[] = { - { PCI_VDEVICE(INTEL, 0x2416), DEVICE_INTEL }, /* 82801AA */ - { PCI_VDEVICE(INTEL, 0x2426), DEVICE_INTEL }, /* 82901AB */ - { PCI_VDEVICE(INTEL, 0x2446), DEVICE_INTEL }, /* 82801BA */ - { PCI_VDEVICE(INTEL, 0x2486), DEVICE_INTEL }, /* ICH3 */ - { PCI_VDEVICE(INTEL, 0x24c6), DEVICE_INTEL }, /* ICH4 */ - { PCI_VDEVICE(INTEL, 0x24d6), DEVICE_INTEL }, /* ICH5 */ - { PCI_VDEVICE(INTEL, 0x266d), DEVICE_INTEL }, /* ICH6 */ - { PCI_VDEVICE(INTEL, 0x27dd), DEVICE_INTEL }, /* ICH7 */ - { PCI_VDEVICE(INTEL, 0x7196), DEVICE_INTEL }, /* 440MX */ - { PCI_VDEVICE(AMD, 0x7446), DEVICE_INTEL }, /* AMD768 */ - { PCI_VDEVICE(SI, 0x7013), DEVICE_SIS }, /* SI7013 */ - { PCI_VDEVICE(NVIDIA, 0x01c1), DEVICE_NFORCE }, /* NFORCE */ - { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */ - { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */ - { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */ - { PCI_VDEVICE(AMD, 0x746e), DEVICE_INTEL }, /* AMD8111 */ + { + /* 82801AA */ + PCI_VDEVICE(INTEL, 0x2416), + .driver_data = DEVICE_INTEL, + }, { + /* 82901AB */ + PCI_VDEVICE(INTEL, 0x2426), + .driver_data = DEVICE_INTEL + }, { + /* 82801BA */ + PCI_VDEVICE(INTEL, 0x2446), + .driver_data = DEVICE_INTEL + }, { + /* ICH3 */ + PCI_VDEVICE(INTEL, 0x2486), + .driver_data = DEVICE_INTEL + }, { + /* ICH4 */ + PCI_VDEVICE(INTEL, 0x24c6), + .driver_data = DEVICE_INTEL, + }, { + /* ICH5 */ + PCI_VDEVICE(INTEL, 0x24d6), + .driver_data = DEVICE_INTEL, + }, { + /* ICH6 */ + PCI_VDEVICE(INTEL, 0x266d), + .driver_data = DEVICE_INTEL, + }, { + /* ICH7 */ + PCI_VDEVICE(INTEL, 0x27dd), + .driver_data = DEVICE_INTEL, + }, { + /* 440MX */ + PCI_VDEVICE(INTEL, 0x7196), + .driver_data = DEVICE_INTEL, + }, { + /* AMD768 */ + PCI_VDEVICE(AMD, 0x7446), + .driver_data = DEVICE_INTEL, + }, { + /* SI7013 */ + PCI_VDEVICE(SI, 0x7013), + .driver_data = DEVICE_SIS, + }, { + /* NFORCE */ + PCI_VDEVICE(NVIDIA, 0x01c1), + .driver_data = DEVICE_NFORCE, + }, { + /* NFORCE2 */ + PCI_VDEVICE(NVIDIA, 0x0069), + .driver_data = DEVICE_NFORCE, + }, { + /* NFORCE2s */ + PCI_VDEVICE(NVIDIA, 0x0089), + .driver_data = DEVICE_NFORCE, + }, { + /* NFORCE3 */ + PCI_VDEVICE(NVIDIA, 0x00d9), + .driver_data = DEVICE_NFORCE, + }, { + /* AMD8111 */ + PCI_VDEVICE(AMD, 0x746e), + .driver_data = DEVICE_INTEL #if 0 - { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */ + }, { + /* Ali5455 */ + PCI_VDEVICE(AL, 0x5455), + .driver_data = DEVICE_ALI, #endif - { 0, } + }, + { } }; MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids); diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 3353980d5cd8..dd45ffa171e1 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -779,23 +779,40 @@ struct snd_m3 { * pci ids */ static const struct pci_device_id snd_m3_ids[] = { - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2LE, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_1, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_HW, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_2, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {0,}, + { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2LE), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_1), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_HW), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_2), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, + { }, }; MODULE_DEVICE_TABLE(pci, snd_m3_ids); diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index a7760a23bfe9..f451554cff5f 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -48,8 +48,8 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard."); */ static const struct pci_device_id snd_mixart_ids[] = { - { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */ - { 0, } + { PCI_VDEVICE(MOTOROLA, 0x0003) }, /* MC8240 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_mixart_ids); diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index da74b923bc88..a7da55d9c025 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -245,10 +245,10 @@ struct nm256 { * PCI ids */ static const struct pci_device_id snd_nm256_ids[] = { - {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO), 0}, - {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO), 0}, - {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO), 0}, - {0,}, + { PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO) }, + { PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO) }, + { PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO) }, + { }, }; MODULE_DEVICE_TABLE(pci, snd_nm256_ids); diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index e6f869cf8ca2..a4212b2558ee 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c @@ -25,6 +25,11 @@ * GPIO 6 -> S/PDIF from optical (0) or coaxial (1) input * GPIO 8 -> enable headphone amplifier * + * eClaro model: + * GPIO 2 -> M0 of CS5361 + * GPIO 3 -> M1 of CS5361 + * GPIO 8 -> enable headphone amplifier + * * CM9780: * * LINE_OUT -> input of ADC @@ -51,6 +56,7 @@ #include "oxygen.h" #include "xonar_dg.h" #include "ak4396.h" +#include "cs4362a.h" #include "wm8785.h" MODULE_AUTHOR("Clemens Ladisch "); @@ -74,6 +80,7 @@ enum { MODEL_MERIDIAN_2G, MODEL_CLARO, MODEL_CLARO_HALO, + MODEL_ECLARO, MODEL_FANTASIA, MODEL_SERENADE, MODEL_2CH_OUTPUT, @@ -113,6 +120,8 @@ static const struct pci_device_id oxygen_ids[] = { { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, /* HT-Omega Claro halo */ { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, + /* HT-Omega eClaro */ + { OXYGEN_PCI_SUBID(0x7284, 0x9783), .driver_data = MODEL_ECLARO }, { } }; MODULE_DEVICE_TABLE(pci, oxygen_ids); @@ -130,27 +139,35 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); #define GPIO_CLARO_DIG_COAX 0x0040 #define GPIO_CLARO_HP 0x0100 +#define GPIO_ECLARO_CS4362A_NRESET 0x0001 /* GPIO 0: CS4362A RESET# (active-low) */ +#define GPIO_ECLARO_FRONT_ENABLE 0x0020 /* GPIO 5: front output stage enable */ + +/* CS4362A SPI: 3-byte frame [0x30, reg, value] on CE1, 1280 ns/bit clock */ +#define ECLARO_CS4362A_SPI_CONTROL \ + (OXYGEN_SPI_TRIGGER | OXYGEN_SPI_DATA_LENGTH_3 | \ + OXYGEN_SPI_CLOCK_1280 | (1 << OXYGEN_SPI_CODEC_SHIFT) | \ + OXYGEN_SPI_CEN_LATCH_CLOCK_HI) + struct generic_data { unsigned int dacs; + u8 spi_map[4]; + u16 spi_prefix[4]; u8 ak4396_regs[4][5]; + u8 cs4362a_regs[15]; u16 wm8785_regs[3]; }; static void ak4396_write(struct oxygen *chip, unsigned int codec, u8 reg, u8 value) { - /* maps ALSA channel pair number to SPI output */ - static const u8 codec_spi_map[4] = { - 0, 1, 2, 4 - }; struct generic_data *data = chip->model_data; oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | OXYGEN_SPI_DATA_LENGTH_2 | OXYGEN_SPI_CLOCK_160 | - (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | + (data->spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | OXYGEN_SPI_CEN_LATCH_CLOCK_HI, - AK4396_WRITE | (reg << 8) | value); + data->spi_prefix[codec] | (reg << 8) | value); data->ak4396_regs[codec][reg] = value; } @@ -163,6 +180,51 @@ static void ak4396_write_cached(struct oxygen *chip, unsigned int codec, ak4396_write(chip, codec, reg, value); } +static void eclaro_cs4362a_write(struct oxygen *chip, u8 reg, u8 value) +{ + struct generic_data *data = chip->model_data; + int err; + + if (reg < ARRAY_SIZE(data->cs4362a_regs)) + data->cs4362a_regs[reg] = value; + + err = oxygen_write_spi(chip, ECLARO_CS4362A_SPI_CONTROL, + (0x30u << 16) | ((u32)reg << 8) | value); + if (err) + dev_err(chip->card->dev, + "CS4362A SPI timeout: reg=0x%02x val=0x%02x\n", + reg, value); +} + +static void eclaro_cs4362a_write_cached(struct oxygen *chip, u8 reg, u8 value) +{ + struct generic_data *data = chip->model_data; + + if (value != data->cs4362a_regs[reg]) + eclaro_cs4362a_write(chip, reg, value); +} + +static void eclaro_cs4362a_registers_init(struct oxygen *chip) +{ + struct generic_data *data = chip->model_data; + + eclaro_cs4362a_write(chip, 1, CS4362A_CPEN | CS4362A_PDN); + eclaro_cs4362a_write(chip, 2, CS4362A_DIF_LJUST); + eclaro_cs4362a_write(chip, 3, CS4362A_SOFT_RAMP | CS4362A_AMUTE); + eclaro_cs4362a_write(chip, 4, data->cs4362a_regs[4]); + eclaro_cs4362a_write(chip, 5, 0); + eclaro_cs4362a_write(chip, 6, data->cs4362a_regs[6]); + eclaro_cs4362a_write(chip, 7, data->cs4362a_regs[7]); + eclaro_cs4362a_write(chip, 8, data->cs4362a_regs[8]); + eclaro_cs4362a_write(chip, 9, data->cs4362a_regs[9]); + eclaro_cs4362a_write(chip, 10, data->cs4362a_regs[10]); + eclaro_cs4362a_write(chip, 11, data->cs4362a_regs[11]); + eclaro_cs4362a_write(chip, 12, data->cs4362a_regs[12]); + eclaro_cs4362a_write(chip, 13, data->cs4362a_regs[13]); + eclaro_cs4362a_write(chip, 14, data->cs4362a_regs[14]); + eclaro_cs4362a_write(chip, 1, CS4362A_CPEN); +} + static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) { struct generic_data *data = chip->model_data; @@ -199,8 +261,13 @@ static void ak4396_registers_init(struct oxygen *chip) static void ak4396_init(struct oxygen *chip) { struct generic_data *data = chip->model_data; + static const u8 default_spi_map[4] = { 0, 1, 2, 4 }; + unsigned int i; data->dacs = chip->model.dac_channels_pcm / 2; + memcpy(data->spi_map, default_spi_map, sizeof(default_spi_map)); + for (i = 0; i < 4; ++i) + data->spi_prefix[i] = AK4396_WRITE; data->ak4396_regs[0][AK4396_CONTROL_2] = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; ak4396_registers_init(chip); @@ -322,6 +389,102 @@ static void claro_resume(struct oxygen *chip) claro_enable_hp(chip); } +#define GPIO_CS5361_M_MASK 0x000c +#define GPIO_CS5361_M_SINGLE 0x0000 +#define GPIO_CS5361_M_DOUBLE 0x0004 +#define GPIO_CS5361_M_QUAD 0x0008 + +static void cs5361_init(struct oxygen *chip) +{ + oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS5361_M_MASK); + oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, + GPIO_CS5361_M_SINGLE, GPIO_CS5361_M_MASK); +} + +static void set_cs5361_params(struct oxygen *chip, + struct snd_pcm_hw_params *params) +{ + unsigned int value; + + if (params_rate(params) <= 54000) + value = GPIO_CS5361_M_SINGLE; + else if (params_rate(params) <= 108000) + value = GPIO_CS5361_M_DOUBLE; + else + value = GPIO_CS5361_M_QUAD; + oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, + value, GPIO_CS5361_M_MASK); +} + +static void eclaro_init(struct oxygen *chip) +{ + struct generic_data *data = chip->model_data; + + oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); + oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); + + /* Single AK4396VF on SPI CE0/CA=00 handles front L/R */ + data->dacs = 1; + data->spi_map[0] = 0; + data->spi_prefix[0] = AK4396_WRITE; + data->ak4396_regs[0][AK4396_CONTROL_2] = + AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; + + ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS); + ak4396_write(chip, 0, AK4396_CONTROL_2, + data->ak4396_regs[0][AK4396_CONTROL_2]); + ak4396_write(chip, 0, AK4396_CONTROL_3, AK4396_PCM); + ak4396_write(chip, 0, AK4396_LCH_ATT, chip->dac_volume[0] * 2); + ak4396_write(chip, 0, AK4396_RCH_ATT, chip->dac_volume[1] * 2); + ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS | AK4396_RSTN); + + /* CS4362A (SPI CE1): surround/center-LFE/side L/R. + * GPIO 0 (RESET#, active-low) and GPIO 5 (front output enable) must + * be driven high. GPIOs 1 and 7 are outputs driven high. + */ + oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 0x00a3); + oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, 0x00a3); + usleep_range(1000, 2000); + + data->cs4362a_regs[4] = CS4362A_RMP_DN | CS4362A_DEM_NONE; + data->cs4362a_regs[6] = CS4362A_FM_SINGLE | + CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; + data->cs4362a_regs[7] = CS4362A_MUTE; + data->cs4362a_regs[9] = data->cs4362a_regs[6]; + data->cs4362a_regs[12] = data->cs4362a_regs[6]; + + eclaro_cs4362a_registers_init(chip); + + snd_component_add(chip->card, "AK4396"); + snd_component_add(chip->card, "CS4362A"); + cs5361_init(chip); + claro_enable_hp(chip); + snd_component_add(chip->card, "CS5361"); +} + +static void eclaro_resume(struct oxygen *chip) +{ + struct generic_data *data = chip->model_data; + + oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, + GPIO_ECLARO_CS4362A_NRESET | GPIO_ECLARO_FRONT_ENABLE); + oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, + GPIO_ECLARO_CS4362A_NRESET | GPIO_ECLARO_FRONT_ENABLE); + + /* AK4396 chip 0 */ + ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS | AK4396_RSTN); + ak4396_write(chip, 0, AK4396_CONTROL_2, + data->ak4396_regs[0][AK4396_CONTROL_2]); + ak4396_write(chip, 0, AK4396_CONTROL_3, AK4396_PCM); + ak4396_write(chip, 0, AK4396_LCH_ATT, chip->dac_volume[0] * 2); + ak4396_write(chip, 0, AK4396_RCH_ATT, chip->dac_volume[1] * 2); + + eclaro_cs4362a_registers_init(chip); + + cs5361_init(chip); + claro_enable_hp(chip); +} + static void stereo_resume(struct oxygen *chip) { ak4396_registers_init(chip); @@ -355,6 +518,76 @@ static void set_ak4396_params(struct oxygen *chip, } } +static void eclaro_set_dac_params(struct oxygen *chip, + struct snd_pcm_hw_params *params) +{ + struct generic_data *data = chip->model_data; + u8 ak_value, cs_fm; + + ak_value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_DFS_MASK; + if (params_rate(params) <= 54000) { + ak_value |= AK4396_DFS_NORMAL; + cs_fm = CS4362A_FM_SINGLE; + } else if (params_rate(params) <= 108000) { + ak_value |= AK4396_DFS_DOUBLE; + cs_fm = CS4362A_FM_DOUBLE; + } else { + ak_value |= AK4396_DFS_QUAD; + cs_fm = CS4362A_FM_QUAD; + } + + usleep_range(1000, 2000); + + if (ak_value != data->ak4396_regs[0][AK4396_CONTROL_2]) { + ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS); + ak4396_write(chip, 0, AK4396_CONTROL_2, ak_value); + ak4396_write(chip, 0, AK4396_CONTROL_1, + AK4396_DIF_24_MSB | AK4396_ACKS | AK4396_RSTN); + data->ak4396_regs[0][AK4396_CONTROL_2] = ak_value; + } + + /* Update CS4362A FM mode for all three DAC pairs */ + cs_fm |= data->cs4362a_regs[6] & ~CS4362A_FM_MASK; + eclaro_cs4362a_write_cached(chip, 6, cs_fm); + eclaro_cs4362a_write_cached(chip, 12, cs_fm); + cs_fm &= CS4362A_FM_MASK; + cs_fm |= data->cs4362a_regs[9] & ~CS4362A_FM_MASK; + eclaro_cs4362a_write_cached(chip, 9, cs_fm); +} + +static void update_eclaro_volume(struct oxygen *chip) +{ + u8 mute = chip->dac_mute ? CS4362A_MUTE : 0; + + ak4396_write_cached(chip, 0, AK4396_LCH_ATT, chip->dac_volume[0] * 2); + ak4396_write_cached(chip, 0, AK4396_RCH_ATT, chip->dac_volume[1] * 2); + + /* CS4362A attenuation is inverse: 0 = 0 dB, 127 = max attenuation. + * Pair 1 (regs 7/8) is wired to the side outputs (ALSA ch 6/7); + * pair 3 (regs 13/14) is wired to the rear outputs (ALSA ch 2/3). + */ + eclaro_cs4362a_write_cached(chip, 7, mute | (127 - chip->dac_volume[6])); + eclaro_cs4362a_write_cached(chip, 8, mute | (127 - chip->dac_volume[7])); + eclaro_cs4362a_write_cached(chip, 10, mute | (127 - chip->dac_volume[4])); + eclaro_cs4362a_write_cached(chip, 11, mute | (127 - chip->dac_volume[5])); + eclaro_cs4362a_write_cached(chip, 13, mute | (127 - chip->dac_volume[2])); + eclaro_cs4362a_write_cached(chip, 14, mute | (127 - chip->dac_volume[3])); +} + +static void update_eclaro_mute(struct oxygen *chip) +{ + struct generic_data *data = chip->model_data; + u8 value; + + value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE; + if (chip->dac_mute) + value |= AK4396_SMUTE; + ak4396_write_cached(chip, 0, AK4396_CONTROL_2, value); + + /* Re-apply volume+mute to CS4362A so the mute bit is set correctly */ + update_eclaro_volume(chip); +} + static void update_ak4396_volume(struct oxygen *chip) { struct generic_data *data = chip->model_data; @@ -702,6 +935,8 @@ static void dump_oxygen_registers(struct oxygen *chip, } static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); +/* CS4362A: 0.5 dB/step, raw=127 -> 0 dB, raw=0 -> -63.5 dB */ +static const DECLARE_TLV_DB_SCALE(eclaro_db_scale, -6350, 50, 0); static const struct oxygen_model model_generic = { .shortname = "C-Media CMI8788", @@ -745,6 +980,7 @@ static int get_oxygen_model(struct oxygen *chip, [MODEL_MERIDIAN_2G] = "AuzenTech X-Meridian 2G", [MODEL_CLARO] = "HT-Omega Claro", [MODEL_CLARO_HALO] = "HT-Omega Claro halo", + [MODEL_ECLARO] = "HT-Omega eClaro", [MODEL_FANTASIA] = "TempoTec HiFier Fantasia", [MODEL_SERENADE] = "TempoTec HiFier Serenade", [MODEL_HG2PCI] = "CMI8787-HG2PCI", @@ -788,6 +1024,28 @@ static int get_oxygen_model(struct oxygen *chip, CAPTURE_0_FROM_I2S_2 | CAPTURE_1_FROM_SPDIF; break; + case MODEL_ECLARO: + chip->model.init = eclaro_init; + chip->model.mixer_init = generic_mixer_init; + chip->model.cleanup = claro_cleanup; + chip->model.suspend = claro_suspend; + chip->model.resume = eclaro_resume; + chip->model.set_dac_params = eclaro_set_dac_params; + chip->model.set_adc_params = set_cs5361_params; + chip->model.update_dac_volume = update_eclaro_volume; + chip->model.update_dac_mute = update_eclaro_mute; + chip->model.dump_registers = dump_ak4396_registers; + chip->model.device_config = PLAYBACK_0_TO_I2S | + PLAYBACK_1_TO_SPDIF | + CAPTURE_0_FROM_I2S_2 | + CAPTURE_1_FROM_SPDIF; + chip->model.function_flags = OXYGEN_FUNCTION_SPI | + OXYGEN_FUNCTION_ENABLE_SPI_4_5; + chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); + chip->model.dac_volume_min = 0; + chip->model.dac_volume_max = 127; + chip->model.dac_tlv = eclaro_db_scale; + break; case MODEL_FANTASIA: case MODEL_SERENADE: case MODEL_2CH_OUTPUT: diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index e7d63972c2ca..25a640304430 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -89,41 +89,41 @@ enum { }; static const struct pci_device_id pcxhr_ids[] = { - { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, }, - { 0x10b5, 0x9056, 0x1369, 0xb021, 0, 0, PCI_ID_VX882E, }, - { 0x10b5, 0x9056, 0x1369, 0xb121, 0, 0, PCI_ID_PCX882E, }, - { 0x10b5, 0x9056, 0x1369, 0xb221, 0, 0, PCI_ID_VX881E, }, - { 0x10b5, 0x9056, 0x1369, 0xb321, 0, 0, PCI_ID_PCX881E, }, - { 0x10b5, 0x9656, 0x1369, 0xb401, 0, 0, PCI_ID_VX1222HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb601, 0, 0, PCI_ID_VX1221HR, }, - { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, }, - { 0x10b5, 0x9056, 0x1369, 0xb421, 0, 0, PCI_ID_VX1222E, }, - { 0x10b5, 0x9056, 0x1369, 0xb521, 0, 0, PCI_ID_PCX1222E, }, - { 0x10b5, 0x9056, 0x1369, 0xb621, 0, 0, PCI_ID_VX1221E, }, - { 0x10b5, 0x9056, 0x1369, 0xb721, 0, 0, PCI_ID_PCX1221E, }, - { 0x10b5, 0x9056, 0x1369, 0xba01, 0, 0, PCI_ID_VX222HR, }, - { 0x10b5, 0x9056, 0x1369, 0xba21, 0, 0, PCI_ID_VX222E, }, - { 0x10b5, 0x9056, 0x1369, 0xbd01, 0, 0, PCI_ID_PCX22HR, }, - { 0x10b5, 0x9056, 0x1369, 0xbd21, 0, 0, PCI_ID_PCX22E, }, - { 0x10b5, 0x9056, 0x1369, 0xbc01, 0, 0, PCI_ID_VX222HRMIC, }, - { 0x10b5, 0x9056, 0x1369, 0xbc21, 0, 0, PCI_ID_VX222E_MIC, }, - { 0x10b5, 0x9056, 0x1369, 0xbb01, 0, 0, PCI_ID_PCX924HR, }, - { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, }, - { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, }, - { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, }, - { 0x10b5, 0x9656, 0x1369, 0xd001, 0, 0, PCI_ID_VX442HR, }, - { 0x10b5, 0x9656, 0x1369, 0xd101, 0, 0, PCI_ID_PCX442HR, }, - { 0x10b5, 0x9056, 0x1369, 0xd021, 0, 0, PCI_ID_VX442E, }, - { 0x10b5, 0x9056, 0x1369, 0xd121, 0, 0, PCI_ID_PCX442E, }, - { 0x10b5, 0x9656, 0x1369, 0xd201, 0, 0, PCI_ID_VX822HR, }, - { 0x10b5, 0x9656, 0x1369, 0xd301, 0, 0, PCI_ID_PCX822HR, }, - { 0x10b5, 0x9056, 0x1369, 0xd221, 0, 0, PCI_ID_VX822E, }, - { 0x10b5, 0x9056, 0x1369, 0xd321, 0, 0, PCI_ID_PCX822E, }, - { 0, } + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb001), .driver_data = PCI_ID_VX882HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb101), .driver_data = PCI_ID_PCX882HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb201), .driver_data = PCI_ID_VX881HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb301), .driver_data = PCI_ID_PCX881HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb021), .driver_data = PCI_ID_VX882E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb121), .driver_data = PCI_ID_PCX882E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb221), .driver_data = PCI_ID_VX881E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb321), .driver_data = PCI_ID_PCX881E }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb401), .driver_data = PCI_ID_VX1222HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb501), .driver_data = PCI_ID_PCX1222HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb601), .driver_data = PCI_ID_VX1221HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb701), .driver_data = PCI_ID_PCX1221HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb421), .driver_data = PCI_ID_VX1222E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb521), .driver_data = PCI_ID_PCX1222E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb621), .driver_data = PCI_ID_VX1221E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb721), .driver_data = PCI_ID_PCX1221E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xba01), .driver_data = PCI_ID_VX222HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xba21), .driver_data = PCI_ID_VX222E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbd01), .driver_data = PCI_ID_PCX22HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbd21), .driver_data = PCI_ID_PCX22E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbc01), .driver_data = PCI_ID_VX222HRMIC }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbc21), .driver_data = PCI_ID_VX222E_MIC }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbb01), .driver_data = PCI_ID_PCX924HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbb21), .driver_data = PCI_ID_PCX924E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbf01), .driver_data = PCI_ID_PCX924HRMIC }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbf21), .driver_data = PCI_ID_PCX924E_MIC }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd001), .driver_data = PCI_ID_VX442HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd101), .driver_data = PCI_ID_PCX442HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd021), .driver_data = PCI_ID_VX442E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd121), .driver_data = PCI_ID_PCX442E }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd201), .driver_data = PCI_ID_VX822HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd301), .driver_data = PCI_ID_PCX822HR }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd221), .driver_data = PCI_ID_VX822E }, + { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd321), .driver_data = PCI_ID_PCX822E }, + { } }; MODULE_DEVICE_TABLE(pci, pcxhr_ids); @@ -180,16 +180,18 @@ static const struct board_parameters pcxhr_board_params[] = { (x->fw_file_set == 0) || \ (x->fw_file_set == 2)) -static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg, - unsigned int* realfreq) +int pcxhr_pll_freq_register(unsigned int freq, unsigned int max_freq, + unsigned int *pllreg, unsigned int *realfreq) { unsigned int reg; - if (freq < 6900 || freq > 110000) + if (freq < 6900 || freq > max_freq) return -EINVAL; reg = (28224000 * 2) / freq; reg = (reg - 1) / 2; - if (reg < 0x200) + if (reg < 0x100) + *pllreg = reg + 0xc00; + else if (reg < 0x200) *pllreg = reg + 0x800; else if (reg < 0x400) *pllreg = reg & 0x1ff; @@ -260,7 +262,8 @@ static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate, default : val = PCXHR_FREQ_PLL; /* get the value for the pll register */ - err = pcxhr_pll_freq_register(rate, &pllreg, &realfreq); + err = pcxhr_pll_freq_register(rate, 110000, &pllreg, + &realfreq); if (err) return err; pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h index 1b85200d00dd..011227b1fe79 100644 --- a/sound/pci/pcxhr/pcxhr.h +++ b/sound/pci/pcxhr/pcxhr.h @@ -190,6 +190,8 @@ struct pcxhr_hostport }; /* exported */ +int pcxhr_pll_freq_register(unsigned int freq, unsigned int max_freq, + unsigned int *pllreg, unsigned int *realfreq); int pcxhr_create_pcm(struct snd_pcxhr *chip); int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate); int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c index 80d22e22ea30..76beb443d983 100644 --- a/sound/pci/pcxhr/pcxhr_mix22.c +++ b/sound/pci/pcxhr/pcxhr_mix22.c @@ -305,36 +305,6 @@ int hr222_sub_init(struct pcxhr_mgr *mgr) } -/* calc PLL register */ -/* TODO : there is a very similar fct in pcxhr.c */ -static int hr222_pll_freq_register(unsigned int freq, - unsigned int *pllreg, - unsigned int *realfreq) -{ - unsigned int reg; - - if (freq < 6900 || freq > 219000) - return -EINVAL; - reg = (28224000 * 2) / freq; - reg = (reg - 1) / 2; - if (reg < 0x100) - *pllreg = reg + 0xC00; - else if (reg < 0x200) - *pllreg = reg + 0x800; - else if (reg < 0x400) - *pllreg = reg & 0x1ff; - else if (reg < 0x800) { - *pllreg = ((reg >> 1) & 0x1ff) + 0x200; - reg &= ~1; - } else { - *pllreg = ((reg >> 2) & 0x1ff) + 0x400; - reg &= ~3; - } - if (realfreq) - *realfreq = (28224000 / (reg + 1)); - return 0; -} - int hr222_sub_set_clock(struct pcxhr_mgr *mgr, unsigned int rate, int *changed) @@ -345,7 +315,8 @@ int hr222_sub_set_clock(struct pcxhr_mgr *mgr, switch (mgr->use_clock_type) { case HR22_CLOCK_TYPE_INTERNAL: - err = hr222_pll_freq_register(rate, &pllreg, &realfreq); + err = pcxhr_pll_freq_register(rate, 219000, + &pllreg, &realfreq); if (err) return err; diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index ca9bbf554650..454a30a2c07e 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -211,10 +211,10 @@ struct rme32 { }; static const struct pci_device_id snd_rme32_ids[] = { - {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32), 0,}, - {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8), 0,}, - {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO), 0,}, - {0,} + { PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32) }, + { PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8) }, + { PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO) }, + { } }; MODULE_DEVICE_TABLE(pci, snd_rme32_ids); diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 58b8ebf1a24e..892fcc598557 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -242,11 +242,11 @@ struct rme96 { }; static const struct pci_device_id snd_rme96_ids[] = { - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96), 0, }, - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8), 0, }, - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO), 0, }, - { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST), 0, }, - { 0, } + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96) }, + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8) }, + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO) }, + { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) }, + { } }; MODULE_DEVICE_TABLE(pci, snd_rme96_ids); diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index a4c72799d034..a885d544acd6 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -227,8 +227,8 @@ struct sonicvibes { }; static const struct pci_device_id snd_sonic_ids[] = { - { PCI_VDEVICE(S3, 0xca00), 0, }, - { 0, } + { PCI_VDEVICE(S3, 0xca00) }, + { } }; MODULE_DEVICE_TABLE(pci, snd_sonic_ids); diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index ddb6ccc72e44..8dcbd022ca1f 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -36,12 +36,16 @@ module_param_array(wavetable_size, int, NULL, 0444); MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth."); static const struct pci_device_id snd_trident_ids[] = { - {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), - PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0}, - {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), - 0, 0, 0}, - {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, 0}, - { 0, } + { + PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX), + .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8, + .class_mask = 0xffff00, + }, { + PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX), + }, { + PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018) + }, + { } }; MODULE_DEVICE_TABLE(pci, snd_trident_ids); diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 41b322fbd9ef..24ee1302f27d 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -389,10 +389,10 @@ struct via82xx { static const struct pci_device_id snd_via82xx_ids[] = { /* 0x1106, 0x3058 */ - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), TYPE_CARD_VIA686, }, /* 686A */ + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), .driver_data = TYPE_CARD_VIA686 }, /* 686A */ /* 0x1106, 0x3059 */ - { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_5), TYPE_CARD_VIA8233, }, /* VT8233 */ - { 0, } + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_5), .driver_data = TYPE_CARD_VIA8233 }, /* VT8233 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_via82xx_ids); diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index a6f176d612e3..9b84d3fb9eaf 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -246,8 +246,8 @@ struct via82xx_modem { }; static const struct pci_device_id snd_via82xx_modem_ids[] = { - { PCI_VDEVICE(VIA, 0x3068), TYPE_CARD_VIA82XX_MODEM, }, - { 0, } + { PCI_VDEVICE(VIA, 0x3068), .driver_data = TYPE_CARD_VIA82XX_MODEM }, + { } }; MODULE_DEVICE_TABLE(pci, snd_via82xx_modem_ids); diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 693a4e471cf7..0b89ca859e66 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -47,9 +47,9 @@ enum { }; static const struct pci_device_id snd_vx222_ids[] = { - { 0x10b5, 0x9050, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_OLD, }, /* PLX */ - { 0x10b5, 0x9030, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_NEW, }, /* PLX */ - { 0, } + { PCI_DEVICE_SUB(0x10b5, 0x9050, 0x1369, PCI_ANY_ID), .driver_data = VX_PCI_VX222_OLD }, /* PLX */ + { PCI_DEVICE_SUB(0x10b5, 0x9030, 0x1369, PCI_ANY_ID), .driver_data = VX_PCI_VX222_NEW }, /* PLX */ + { } }; MODULE_DEVICE_TABLE(pci, snd_vx222_ids); diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 764ca59e98d1..d3fb047c9a45 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c @@ -46,13 +46,13 @@ module_param_array(rear_switch, bool, NULL, 0444); MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); static const struct pci_device_id snd_ymfpci_ids[] = { - { PCI_VDEVICE(YAMAHA, 0x0004), 0, }, /* YMF724 */ - { PCI_VDEVICE(YAMAHA, 0x000d), 0, }, /* YMF724F */ - { PCI_VDEVICE(YAMAHA, 0x000a), 0, }, /* YMF740 */ - { PCI_VDEVICE(YAMAHA, 0x000c), 0, }, /* YMF740C */ - { PCI_VDEVICE(YAMAHA, 0x0010), 0, }, /* YMF744 */ - { PCI_VDEVICE(YAMAHA, 0x0012), 0, }, /* YMF754 */ - { 0, } + { PCI_VDEVICE(YAMAHA, 0x0004) }, /* YMF724 */ + { PCI_VDEVICE(YAMAHA, 0x000d) }, /* YMF724F */ + { PCI_VDEVICE(YAMAHA, 0x000a) }, /* YMF740 */ + { PCI_VDEVICE(YAMAHA, 0x000c) }, /* YMF740C */ + { PCI_VDEVICE(YAMAHA, 0x0010) }, /* YMF744 */ + { PCI_VDEVICE(YAMAHA, 0x0012) }, /* YMF754 */ + { } }; MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids); diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index b9a09568afc9..2ccb976e68e0 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -1781,16 +1781,22 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch) if (snd_BUG_ON(!chip->pcm_spdif)) return -ENXIO; kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip); + if (!kctl) + return -ENOMEM; kctl->id.device = chip->pcm_spdif->device; err = snd_ctl_add(chip->card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_ymfpci_spdif_mask, chip); + if (!kctl) + return -ENOMEM; kctl->id.device = chip->pcm_spdif->device; err = snd_ctl_add(chip->card, kctl); if (err < 0) return err; kctl = snd_ctl_new1(&snd_ymfpci_spdif_stream, chip); + if (!kctl) + return -ENOMEM; kctl->id.device = chip->pcm_spdif->device; err = snd_ctl_add(chip->card, kctl); if (err < 0) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 53139766fafb..9f4f1f4ac3f8 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -174,5 +174,15 @@ config SND_SOC_AMD_PS_MACH Say m if you have such a device. If unsure select "N". +config SND_SOC_AMD_ACP7X + tristate "AMD Audio Coprocessor-v7.x support" + depends on X86 && PCI && ACPI + help + This option enables Audio Coprocessor i.e ACP7.x + variants support(ACP7.D/7.E/7.F). By enabling this flag build + will be triggered for ACP PCI driver. + Say m if you have such a device. + If unsure select "N". + endif endmenu diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile index 23b25ff0d800..ef2b36d47705 100644 --- a/sound/soc/amd/Makefile +++ b/sound/soc/amd/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP6x) += yc/ obj-$(CONFIG_SND_AMD_ACP_CONFIG) += acp/ obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o obj-$(CONFIG_SND_SOC_AMD_PS) += ps/ +obj-$(CONFIG_SND_SOC_AMD_ACP7X) += acp7x/ diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c index 09b475c83c49..e8b6819cc4b4 100644 --- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -303,13 +303,14 @@ static int create_sdw_dailink(struct snd_soc_card *card, static int create_sdw_dailinks(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, int *be_id, - struct asoc_sdw_dailink *soc_dais, + struct asoc_sdw_dailink *soc_dais, int num_dais, struct snd_soc_codec_conf **codec_conf) { struct device *dev = card->dev; struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private; struct snd_soc_dai_link_component *sdw_platform_component; + int i; int ret; sdw_platform_component = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component), @@ -329,7 +330,7 @@ static int create_sdw_dailinks(struct snd_soc_card *card, } /* generate DAI links by each sdw link */ - while (soc_dais->initialised) { + for (i = 0; i < num_dais && soc_dais->initialised; i++) { int current_be_id = 0; ret = create_sdw_dailink(card, soc_dais, dai_links, @@ -463,7 +464,7 @@ static int soc_card_dai_links_create(struct snd_soc_card *card) /* SDW */ if (sdw_be_num) { ret = create_sdw_dailinks(card, &dai_links, &be_id, - soc_dais, &codec_conf); + soc_dais, num_ends, &codec_conf); if (ret) return ret; } diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c index a0fd8a6f9970..a423853f3a97 100644 --- a/sound/soc/amd/acp/acp-sdw-sof-mach.c +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -220,13 +220,14 @@ static int create_sdw_dailink(struct snd_soc_card *card, static int create_sdw_dailinks(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, int *be_id, - struct asoc_sdw_dailink *sof_dais, + struct asoc_sdw_dailink *sof_dais, int num_dais, struct snd_soc_codec_conf **codec_conf) { + int i; int ret; /* generate DAI links by each sdw link */ - while (sof_dais->initialised) { + for (i = 0; i < num_dais && sof_dais->initialised; i++) { int current_be_id = 0; ret = create_sdw_dailink(card, sof_dais, dai_links, @@ -334,7 +335,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) /* SDW */ if (sdw_be_num) { ret = create_sdw_dailinks(card, &dai_links, &be_id, - sof_dais, &codec_conf); + sof_dais, num_ends, &codec_conf); if (ret) return ret; } diff --git a/sound/soc/amd/acp7x/Makefile b/sound/soc/amd/acp7x/Makefile new file mode 100644 index 000000000000..9426e3b47c08 --- /dev/null +++ b/sound/soc/amd/acp7x/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only +# ACP7.x variants platform Support +snd-pci-acp7x-y := pci-acp7x.o acp7x-common.o + +obj-$(CONFIG_SND_SOC_AMD_ACP7X) += snd-pci-acp7x.o diff --git a/sound/soc/amd/acp7x/acp7x-common.c b/sound/soc/amd/acp7x/acp7x-common.c new file mode 100644 index 000000000000..df94864a1693 --- /dev/null +++ b/sound/soc/amd/acp7x/acp7x-common.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD ACP PCI driver callback routines for ACP7.x + * platforms. + * + * Copyright 2026 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include + +#include "acp7x.h" + +static int acp7x_power_on(void __iomem *acp_base) +{ + u32 val = 0; + + val = readl(acp_base + ACP_PGFSM_STATUS); + if (!(val & ACP7X_PGFSM_STATUS_MASK)) + return 0; + + writel(ACP7X_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); + val = readl(acp_base + ACP_PGFSM_CONTROL); + return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, + ((val & ACP7X_PGFSM_STATUS_MASK) == 0), DELAY_US, ACP7X_TIMEOUT); +} + +static int acp7x_reset(void __iomem *acp_base) +{ + u32 val; + int ret; + + writel(1, acp_base + ACP_SOFT_RESET); + ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, + val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK, + DELAY_US, ACP7X_TIMEOUT); + if (ret) + return ret; + + writel(0, acp_base + ACP_SOFT_RESET); + return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP7X_TIMEOUT); +} + +static int acp7x_init(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp7x_power_on(acp_base); + if (ret) { + dev_err(dev, "ACP power on failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_CONTROL); + ret = acp7x_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static int acp7x_deinit(void __iomem *acp_base, struct device *dev) +{ + int ret; + + ret = acp7x_reset(acp_base); + if (ret) { + dev_err(dev, "ACP reset failed\n"); + return ret; + } + writel(0x01, acp_base + ACP_ZSC_DSP_CTRL); + return 0; +} + +static int __maybe_unused snd_acp7x_suspend(struct device *dev) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp_hw_deinit(adata, dev); + if (ret) + dev_err(dev, "ACP de-init failed\n"); + return ret; +} + +static int __maybe_unused snd_acp7x_runtime_resume(struct device *dev) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp_hw_init(adata, dev); + if (ret) { + dev_err(dev, "ACP init failed\n"); + return ret; + } + return 0; +} + +static int __maybe_unused snd_acp7x_resume(struct device *dev) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = dev_get_drvdata(dev); + ret = acp_hw_init(adata, dev); + if (ret) + dev_err(dev, "ACP init failed\n"); + + return ret; +} + +void acp7x_hw_init_ops(struct acp_hw_ops *hw_ops) +{ + hw_ops->acp_init = acp7x_init; + hw_ops->acp_deinit = acp7x_deinit; + hw_ops->acp_suspend = snd_acp7x_suspend; + hw_ops->acp_resume = snd_acp7x_resume; + hw_ops->acp_suspend_runtime = snd_acp7x_suspend; + hw_ops->acp_resume_runtime = snd_acp7x_runtime_resume; +} diff --git a/sound/soc/amd/acp7x/acp7x.h b/sound/soc/amd/acp7x/acp7x.h new file mode 100644 index 000000000000..ddb5eabf6828 --- /dev/null +++ b/sound/soc/amd/acp7x/acp7x.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * AMD Common ACP header file for ACP7.X variants(ACP7.D/7.E/7.F) + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef __SOUND_SOC_AMD_ACP7X_H +#define __SOUND_SOC_AMD_ACP7X_H + +#include +#include +#include +#include +#include + +#include + +#define ACP_DEVICE_ID 0x15E2 +#define ACP7X_REG_START 0x1240000 +#define ACP7X_REG_END 0x125C000 + +#define ACP7D_PCI_REV 0x7D +#define ACP7E_PCI_REV 0x7E +#define ACP7F_PCI_REV 0x7F + +/* Common register helper bits used by acp7x-common.c */ +#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 + +#define DELAY_US 5 +#define ACP7X_TIMEOUT 5000 + +#define ACP7X_PGFSM_CNTL_POWER_ON_MASK 7 +#define ACP7X_PGFSM_STATUS_MASK 0x3F + +/* time in ms for runtime suspend delay */ +#define ACP_SUSPEND_DELAY_MS 2000 + +struct acp_hw_ops { + int (*acp_init)(void __iomem *acp_base, struct device *dev); + int (*acp_deinit)(void __iomem *acp_base, struct device *dev); + int (*acp_suspend)(struct device *dev); + int (*acp_resume)(struct device *dev); + int (*acp_suspend_runtime)(struct device *dev); + int (*acp_resume_runtime)(struct device *dev); +}; + +struct acp7x_dev_data { + void __iomem *acp7x_base; + struct acp_hw_ops *hw_ops; + u32 addr; + u32 reg_range; + u32 acp_rev; +}; + +void acp7x_hw_init_ops(struct acp_hw_ops *hw_ops); + +static inline int acp_hw_init(struct acp7x_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_init) + return adata->hw_ops->acp_init(adata->acp7x_base, dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_deinit(struct acp7x_dev_data *adata, struct device *dev) +{ + if (adata && adata->hw_ops && adata->hw_ops->acp_deinit) + return adata->hw_ops->acp_deinit(adata->acp7x_base, dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_suspend(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend) + return adata->hw_ops->acp_suspend(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_resume(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume) + return adata->hw_ops->acp_resume(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_suspend_runtime(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_suspend_runtime) + return adata->hw_ops->acp_suspend_runtime(dev); + return -EOPNOTSUPP; +} + +static inline int acp_hw_runtime_resume(struct device *dev) +{ + struct acp7x_dev_data *adata = dev_get_drvdata(dev); + + if (adata && adata->hw_ops && adata->hw_ops->acp_resume_runtime) + return adata->hw_ops->acp_resume_runtime(dev); + return -EOPNOTSUPP; +} + +int snd_amd_acp_find_config(struct pci_dev *pci); + +#endif /* __SOUND_SOC_AMD_ACP7X_H */ diff --git a/sound/soc/amd/acp7x/pci-acp7x.c b/sound/soc/amd/acp7x/pci-acp7x.c new file mode 100644 index 000000000000..d29a149cf175 --- /dev/null +++ b/sound/soc/amd/acp7x/pci-acp7x.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD common ACP PCI driver for ACP7.x variants + * which includes ACP7.D/7.E/7.F and future variants + * with same register layout. + * + * Copyright 2026 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "acp7x.h" + +static int acp_hw_init_ops(struct acp7x_dev_data *adata, struct pci_dev *pci) +{ + adata->hw_ops = devm_kzalloc(&pci->dev, sizeof(struct acp_hw_ops), + GFP_KERNEL); + if (!adata->hw_ops) + return -ENOMEM; + + switch (adata->acp_rev) { + case ACP7D_PCI_REV: + case ACP7E_PCI_REV: + case ACP7F_PCI_REV: + acp7x_hw_init_ops(adata->hw_ops); + break; + default: + dev_err(&pci->dev, "ACP device not found\n"); + return -ENODEV; + } + return 0; +} + +static int snd_acp7x_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + struct acp7x_dev_data *adata; + u32 addr; + u32 flag; + int ret; + + flag = snd_amd_acp_find_config(pci); + if (flag) + return -ENODEV; + /* ACP PCI revision id check for ACP7.x platforms */ + switch (pci->revision) { + case ACP7D_PCI_REV: + case ACP7E_PCI_REV: + case ACP7F_PCI_REV: + break; + default: + return -ENODEV; + } + if (pci_enable_device(pci)) { + dev_err(&pci->dev, "pci_enable_device failed\n"); + return -ENODEV; + } + + ret = pci_request_regions(pci, "AMD ACP7.x audio"); + if (ret < 0) { + dev_err(&pci->dev, "pci_request_regions failed\n"); + goto disable_pci; + } + adata = devm_kzalloc(&pci->dev, sizeof(struct acp7x_dev_data), + GFP_KERNEL); + if (!adata) { + ret = -ENOMEM; + goto release_regions; + } + addr = pci_resource_start(pci, 0); + adata->acp7x_base = devm_ioremap(&pci->dev, addr, + pci_resource_len(pci, 0)); + if (!adata->acp7x_base) { + ret = -ENOMEM; + goto release_regions; + } + adata->addr = addr; + adata->reg_range = ACP7X_REG_END - ACP7X_REG_START; + adata->acp_rev = pci->revision; + pci_set_master(pci); + pci_set_drvdata(pci, adata); + ret = acp_hw_init_ops(adata, pci); + if (ret) { + dev_err(&pci->dev, "ACP hw ops init failed\n"); + goto release_regions; + } + ret = acp_hw_init(adata, &pci->dev); + if (ret) + goto release_regions; + + pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&pci->dev); + pm_runtime_put_noidle(&pci->dev); + pm_runtime_allow(&pci->dev); + return 0; + +release_regions: + pci_release_regions(pci); +disable_pci: + pci_disable_device(pci); + + return ret; +} + +static int __maybe_unused snd_acp_suspend(struct device *dev) +{ + return acp_hw_suspend(dev); +} + +static int __maybe_unused snd_acp_runtime_resume(struct device *dev) +{ + return acp_hw_runtime_resume(dev); +} + +static int __maybe_unused snd_acp_resume(struct device *dev) +{ + return acp_hw_resume(dev); +} + +static const struct dev_pm_ops acp7x_pm_ops = { + SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume) +}; + +static void snd_acp7x_remove(struct pci_dev *pci) +{ + struct acp7x_dev_data *adata; + int ret; + + adata = pci_get_drvdata(pci); + ret = acp_hw_deinit(adata, &pci->dev); + if (ret) + dev_err(&pci->dev, "ACP de-init failed\n"); + pm_runtime_forbid(&pci->dev); + pm_runtime_get_noresume(&pci->dev); + pci_release_regions(pci); + pci_disable_device(pci); +} + +static const struct pci_device_id snd_acp7x_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, + .class_mask = 0xffffff }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, snd_acp7x_ids); + +static struct pci_driver acp7x_pci_driver = { + .name = KBUILD_MODNAME, + .id_table = snd_acp7x_ids, + .probe = snd_acp7x_probe, + .remove = snd_acp7x_remove, + .driver = { + .pm = &acp7x_pm_ops, + } +}; + +module_pci_driver(acp7x_pci_driver); + +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("AMD ACP PCI driver for ACP7.X"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c index 9751cf0784a6..4ecda224157b 100644 --- a/sound/soc/amd/ps/pci-ps.c +++ b/sound/soc/amd/ps/pci-ps.c @@ -329,7 +329,8 @@ static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev) break; } if (i == acp_data->info.count || !link->num_adr) - break; + if (!mach->machine_check || mach->machine_check(acp_data->sdw)) + break; } if (mach && mach->link_mask) { mach->mach_params.links = mach->links; diff --git a/sound/soc/amd/ps/ps-mach.c b/sound/soc/amd/ps/ps-mach.c index ff8ad036b077..3e49c255c025 100644 --- a/sound/soc/amd/ps/ps-mach.c +++ b/sound/soc/amd/ps/ps-mach.c @@ -45,7 +45,6 @@ static struct snd_soc_card acp63_card = { static int acp63_probe(struct platform_device *pdev) { - struct acp63_pdm *machine = NULL; struct snd_soc_card *card; int ret; @@ -53,7 +52,6 @@ static int acp63_probe(struct platform_device *pdev) card = platform_get_drvdata(pdev); acp63_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(card, machine); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { return dev_err_probe(&pdev->dev, ret, diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c index 3249f74a0197..516c3d4f4ede 100644 --- a/sound/soc/amd/renoir/acp3x-rn.c +++ b/sound/soc/amd/renoir/acp3x-rn.c @@ -44,14 +44,12 @@ static struct snd_soc_card acp_card = { static int acp_probe(struct platform_device *pdev) { int ret; - struct acp_pdm *machine = NULL; struct snd_soc_card *card; card = &acp_card; acp_card.dev = &pdev->dev; platform_set_drvdata(pdev, card); - snd_soc_card_set_drvdata(card, machine); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { return dev_err_probe(&pdev->dev, ret, diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c index ce229f5d0d46..a405cc2c11a3 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -821,7 +821,6 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { static int acp6x_probe(struct platform_device *pdev) { const struct dmi_system_id *dmi_id; - struct acp6x_pdm *machine = NULL; struct snd_soc_card *card; struct acpi_device *adev; acpi_handle handle; @@ -868,7 +867,6 @@ static int acp6x_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Enabling ACP DMIC support via %s", dmi_id ? "DMI" : "ACPI"); acp6x_card.dev = &pdev->dev; - snd_soc_card_set_drvdata(card, machine); ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { return dev_err_probe(&pdev->dev, ret, diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c index 39269cc7def6..492165c0e1ea 100644 --- a/sound/soc/apple/mca.c +++ b/sound/soc/apple/mca.c @@ -307,7 +307,7 @@ static bool mca_fe_clocks_in_use(struct mca_cluster *cl) struct mca_cluster *be_cl; int stream, i; - mutex_lock(&mca->port_mutex); + guard(mutex)(&mca->port_mutex); for (i = 0; i < mca->nclusters; i++) { be_cl = &mca->clusters[i]; @@ -316,12 +316,10 @@ static bool mca_fe_clocks_in_use(struct mca_cluster *cl) for_each_pcm_streams(stream) { if (be_cl->clocks_in_use[stream]) { - mutex_unlock(&mca->port_mutex); return true; } } } - mutex_unlock(&mca->port_mutex); return false; } @@ -765,9 +763,8 @@ static int mca_be_startup(struct snd_pcm_substream *substream, cl->base + REG_PORT_CLOCK_SEL); writel_relaxed(PORT_DATA_SEL_TXA(fe_cl->no), cl->base + REG_PORT_DATA_SEL); - mutex_lock(&mca->port_mutex); - cl->port_driver = fe_cl->no; - mutex_unlock(&mca->port_mutex); + scoped_guard(mutex, &mca->port_mutex) + cl->port_driver = fe_cl->no; cl->port_started[substream->stream] = true; return 0; @@ -788,9 +785,8 @@ static void mca_be_shutdown(struct snd_pcm_substream *substream, */ writel_relaxed(0, cl->base + REG_PORT_ENABLES); writel_relaxed(0, cl->base + REG_PORT_DATA_SEL); - mutex_lock(&mca->port_mutex); - cl->port_driver = -1; - mutex_unlock(&mca->port_mutex); + scoped_guard(mutex, &mca->port_mutex) + cl->port_driver = -1; } } diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index 1f8c60d2de82..6693bdcbb8f5 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -236,34 +237,34 @@ static int atmel_classd_component_probe(struct snd_soc_component *component) u32 mask, val; mask = CLASSD_MR_PWMTYP_MASK; - val = pdata->pwm_type << CLASSD_MR_PWMTYP_SHIFT; + val = FIELD_PREP(CLASSD_MR_PWMTYP_MASK, pdata->pwm_type); mask |= CLASSD_MR_NON_OVERLAP_MASK; if (pdata->non_overlap_enable) { - val |= (CLASSD_MR_NON_OVERLAP_EN - << CLASSD_MR_NON_OVERLAP_SHIFT); + val |= FIELD_PREP(CLASSD_MR_NON_OVERLAP_MASK, + CLASSD_MR_NON_OVERLAP_EN); mask |= CLASSD_MR_NOVR_VAL_MASK; switch (pdata->non_overlap_time) { case 5: - val |= (CLASSD_MR_NOVR_VAL_5NS - << CLASSD_MR_NOVR_VAL_SHIFT); + val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK, + CLASSD_MR_NOVR_VAL_5NS); break; case 10: - val |= (CLASSD_MR_NOVR_VAL_10NS - << CLASSD_MR_NOVR_VAL_SHIFT); + val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK, + CLASSD_MR_NOVR_VAL_10NS); break; case 15: - val |= (CLASSD_MR_NOVR_VAL_15NS - << CLASSD_MR_NOVR_VAL_SHIFT); + val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK, + CLASSD_MR_NOVR_VAL_15NS); break; case 20: - val |= (CLASSD_MR_NOVR_VAL_20NS - << CLASSD_MR_NOVR_VAL_SHIFT); + val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK, + CLASSD_MR_NOVR_VAL_20NS); break; default: - val |= (CLASSD_MR_NOVR_VAL_10NS - << CLASSD_MR_NOVR_VAL_SHIFT); + val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK, + CLASSD_MR_NOVR_VAL_10NS); dev_warn(component->dev, "non-overlapping value %d is invalid, the default value 10 is specified\n", pdata->non_overlap_time); @@ -370,8 +371,10 @@ atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream, return ret; mask = CLASSD_INTPMR_DSP_CLK_FREQ_MASK | CLASSD_INTPMR_FRAME_MASK; - val = (sample_rates[best].dsp_clk << CLASSD_INTPMR_DSP_CLK_FREQ_SHIFT) - | (sample_rates[best].sample_rate << CLASSD_INTPMR_FRAME_SHIFT); + val = FIELD_PREP(CLASSD_INTPMR_DSP_CLK_FREQ_MASK, + sample_rates[best].dsp_clk) | + FIELD_PREP(CLASSD_INTPMR_FRAME_MASK, + sample_rates[best].sample_rate); snd_soc_component_update_bits(component, CLASSD_INTPMR, mask, val); @@ -395,8 +398,8 @@ static int atmel_classd_cpu_dai_prepare(struct snd_pcm_substream *substream, snd_soc_component_update_bits(component, CLASSD_MR, CLASSD_MR_LEN_MASK | CLASSD_MR_REN_MASK, - (CLASSD_MR_LEN_DIS << CLASSD_MR_LEN_SHIFT) - |(CLASSD_MR_REN_DIS << CLASSD_MR_REN_SHIFT)); + FIELD_PREP(CLASSD_MR_LEN_MASK, CLASSD_MR_LEN_DIS) | + FIELD_PREP(CLASSD_MR_REN_MASK, CLASSD_MR_REN_DIS)); return 0; } @@ -418,8 +421,8 @@ static int atmel_classd_cpu_dai_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - val = (CLASSD_MR_LEN_DIS << CLASSD_MR_LEN_SHIFT) - | (CLASSD_MR_REN_DIS << CLASSD_MR_REN_SHIFT); + val = FIELD_PREP(CLASSD_MR_LEN_MASK, CLASSD_MR_LEN_DIS) | + FIELD_PREP(CLASSD_MR_REN_MASK, CLASSD_MR_REN_DIS); break; default: return -EINVAL; diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c index 521bee4998f8..2c47aabdca95 100644 --- a/sound/soc/atmel/mchp-spdifrx.c +++ b/sound/soc/atmel/mchp-spdifrx.c @@ -6,6 +6,7 @@ // // Author: Codrin Ciubotariu +#include #include #include #include @@ -41,6 +42,13 @@ #define SPDIFRX_VERSION 0xFC /* Version Register */ + +/* 32-bit word byte masks */ +#define SPDIFRX_BYTE_0_MASK GENMASK(7, 0) +#define SPDIFRX_BYTE_1_MASK GENMASK(15, 8) +#define SPDIFRX_BYTE_2_MASK GENMASK(23, 16) +#define SPDIFRX_BYTE_3_MASK GENMASK(31, 24) + /* * ---- Control Register (Write-only) ---- */ @@ -55,7 +63,7 @@ #define SPDIFRX_MR_RXEN_ENABLE (1 << 0) /* SPDIF Receiver Enabled */ /* Validity Bit Mode */ -#define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1) +#define SPDIFRX_MR_VBMODE_MASK GENMASK(1, 1) #define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \ (0 << 1) /* Load sample regardless of validity bit value */ #define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \ @@ -74,7 +82,7 @@ /* Sample Data Width */ #define SPDIFRX_MR_DATAWIDTH_MASK GENMASK(5, 4) #define SPDIFRX_MR_DATAWIDTH(width) \ - (((6 - (width) / 4) << 4) & SPDIFRX_MR_DATAWIDTH_MASK) + FIELD_PREP(SPDIFRX_MR_DATAWIDTH_MASK, 6 - ((width) / 4)) /* Packed Data Mode in Receive Holding Register */ #define SPDIFRX_MR_PACK_MASK GENMASK(7, 7) @@ -118,15 +126,14 @@ #define SPDIFRX_RSR_LOWF BIT(2) #define SPDIFRX_RSR_NOSIGNAL BIT(3) #define SPDIFRX_RSR_IFS_MASK GENMASK(27, 16) -#define SPDIFRX_RSR_IFS(reg) \ - (((reg) & SPDIFRX_RSR_IFS_MASK) >> 16) +#define SPDIFRX_RSR_IFS(reg) FIELD_GET(SPDIFRX_RSR_IFS_MASK, reg) /* * ---- Version Register (Read-only) ---- */ #define SPDIFRX_VERSION_MASK GENMASK(11, 0) #define SPDIFRX_VERSION_MFN_MASK GENMASK(18, 16) -#define SPDIFRX_VERSION_MFN(reg) (((reg) & SPDIFRX_VERSION_MFN_MASK) >> 16) +#define SPDIFRX_VERSION_MFN(reg) FIELD_GET(SPDIFRX_VERSION_MFN_MASK, reg) static bool mchp_spdifrx_readable_reg(struct device *dev, unsigned int reg) { @@ -317,10 +324,10 @@ static void mchp_spdifrx_channel_status_read(struct mchp_spdifrx_dev *dev, for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat[channel].data) / 4; i++) { regmap_read(dev->regmap, SPDIFRX_CHSR(channel, i), &val); - *ch_stat++ = val & 0xFF; - *ch_stat++ = (val >> 8) & 0xFF; - *ch_stat++ = (val >> 16) & 0xFF; - *ch_stat++ = (val >> 24) & 0xFF; + *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_0_MASK, val); + *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_1_MASK, val); + *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_2_MASK, val); + *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_3_MASK, val); } } @@ -334,10 +341,10 @@ static void mchp_spdifrx_channel_user_data_read(struct mchp_spdifrx_dev *dev, for (i = 0; i < ARRAY_SIZE(ctrl->user_data[channel].data) / 4; i++) { regmap_read(dev->regmap, SPDIFRX_CHUD(channel, i), &val); - *user_data++ = val & 0xFF; - *user_data++ = (val >> 8) & 0xFF; - *user_data++ = (val >> 16) & 0xFF; - *user_data++ = (val >> 24) & 0xFF; + *user_data++ = FIELD_GET(SPDIFRX_BYTE_0_MASK, val); + *user_data++ = FIELD_GET(SPDIFRX_BYTE_1_MASK, val); + *user_data++ = FIELD_GET(SPDIFRX_BYTE_2_MASK, val); + *user_data++ = FIELD_GET(SPDIFRX_BYTE_3_MASK, val); } } diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index e0ce0232eb1e..47706ae0a31f 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -1298,7 +1298,6 @@ static int audio_clk_init(struct platform_device *pdev, static int cygnus_ssp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *child_node; struct cygnus_audio *cygaud; int err; int node_count; @@ -1331,16 +1330,15 @@ static int cygnus_ssp_probe(struct platform_device *pdev) active_port_count = 0; - for_each_available_child_of_node(pdev->dev.of_node, child_node) { + for_each_available_child_of_node_scoped(pdev->dev.of_node, child_node) { err = parse_ssp_child_node(pdev, child_node, cygaud, &cygnus_ssp_dai[active_port_count]); /* negative is err, 0 is active and good, 1 is disabled */ - if (err < 0) { - of_node_put(child_node); + if (err < 0) return err; - } - else if (!err) { + + if (!err) { dev_dbg(dev, "Activating DAI: %s\n", cygnus_ssp_dai[active_port_count].name); active_port_count++; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 269c31ce0814..252f683be3c1 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -93,6 +93,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_CS4271_I2C imply SND_SOC_CS4271_SPI imply SND_SOC_CS42XX8_I2C + imply SND_SOC_CS42XX8_SPI imply SND_SOC_CS43130 imply SND_SOC_CS4341 imply SND_SOC_CS4349 @@ -122,6 +123,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_ES8328_I2C imply SND_SOC_ES8375 imply SND_SOC_ES8389 + imply SND_SOC_ES9356 imply SND_SOC_ES7134 imply SND_SOC_ES7241 imply SND_SOC_FRAMER @@ -264,6 +266,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_STA529 imply SND_SOC_STAC9766 imply SND_SOC_STI_SAS + imply SND_SOC_TAC5XX2_SDW imply SND_SOC_TAS2552 imply SND_SOC_TAS2562 imply SND_SOC_TAS2764 @@ -275,6 +278,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TAS571X imply SND_SOC_TAS5720 imply SND_SOC_TAS6424 + imply SND_SOC_TAS675X imply SND_SOC_TDA7419 imply SND_SOC_TFA9879 imply SND_SOC_TFA989X @@ -884,7 +888,7 @@ config SND_SOC_CS35L56_SPI config SND_SOC_CS35L56_SDW tristate "Cirrus Logic CS35L56 CODEC (SDW)" depends on SOUNDWIRE - select REGMAP + select REGMAP_SOUNDWIRE select SND_SOC_CS35L56 select SND_SOC_CS35L56_SHARED help @@ -1074,6 +1078,12 @@ config SND_SOC_CS4271_SPI config SND_SOC_CS42XX8 tristate +config SND_SOC_CS42XX8_SPI + tristate "Cirrus Logic CS42448/CS42888 CODEC (SPI)" + depends on SPI_MASTER + select SND_SOC_CS42XX8 + select REGMAP_SPI + config SND_SOC_CS42XX8_I2C tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)" depends on I2C @@ -1297,6 +1307,13 @@ config SND_SOC_ES8389 tristate "Everest Semi ES8389 CODEC" depends on I2C +config SND_SOC_ES9356 + tristate "Everest Semi ES9356 CODEC SDW" + depends on SND_SOC_SDCA + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + config SND_SOC_FRAMER tristate "Framer codec" depends on GENERIC_FRAMER @@ -2136,6 +2153,16 @@ config SND_SOC_STAC9766 config SND_SOC_STI_SAS tristate "codec Audio support for STI SAS codec" +config SND_SOC_TAC5XX2_SDW + tristate "Texas Instruments TAC5XX2 SoundWire Smart Amplifier" + depends on SOUNDWIRE + depends on SND_SOC_SDCA + help + This option enables support for Texas Instruments TAC5XX2 family + of SoundWire Smart Amplifiers. This includes TAC5572, TAC5672, + TAC5682 and TAS2883. To compile this driver as a module, choose + M here: the module will be called snd-soc-tac5xx2. + config SND_SOC_TAS2552 tristate "Texas Instruments TAS2552 Mono Audio amplifier" depends on I2C @@ -2234,6 +2261,17 @@ config SND_SOC_TAS6424 Enable support for Texas Instruments TAS6424 high-efficiency digital input quad-channel Class-D audio power amplifiers. +config SND_SOC_TAS675X + tristate "Texas Instruments TAS675x Quad-Channel Audio Amplifier" + depends on I2C + select REGMAP_I2C + help + Enable support for Texas Instruments TAS675x quad-channel Class-D + audio power amplifiers (TAS6754, TAS67524). The devices support I2S + and TDM interfaces with real-time voltage and current sense feedback + via SDOUT, and provide DC/AC/real-time load diagnostics for speaker + monitoring. + config SND_SOC_TDA7419 tristate "ST TDA7419 audio processor" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 172861d17cfd..aa0396e5b575 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -103,6 +103,7 @@ snd-soc-cs4271-i2c-y := cs4271-i2c.o snd-soc-cs4271-spi-y := cs4271-spi.o snd-soc-cs42xx8-y := cs42xx8.o snd-soc-cs42xx8-i2c-y := cs42xx8-i2c.o +snd-soc-cs42xx8-spi-y := cs42xx8-spi.o snd-soc-cs43130-y := cs43130.o snd-soc-cs4341-y := cs4341.o snd-soc-cs4349-y := cs4349.o @@ -138,6 +139,7 @@ snd-soc-es8328-i2c-y := es8328-i2c.o snd-soc-es8328-spi-y := es8328-spi.o snd-soc-es8375-y := es8375.o snd-soc-es8389-y := es8389.o +snd-soc-es9356-y := es9356.o snd-soc-framer-y := framer-codec.o snd-soc-fs-amp-lib-y := fs-amp-lib.o snd-soc-fs210x-y := fs210x.o @@ -313,11 +315,13 @@ snd-soc-sta350-y := sta350.o snd-soc-sta529-y := sta529.o snd-soc-stac9766-y := stac9766.o snd-soc-sti-sas-y := sti-sas.o +snd-soc-tac5xx2-sdw-y := tac5xx2-sdw.o snd-soc-tas5086-y := tas5086.o snd-soc-tas571x-y := tas571x.o snd-soc-tas5720-y := tas5720.o snd-soc-tas5805m-y := tas5805m.o snd-soc-tas6424-y := tas6424.o +snd-soc-tas675x-y := tas675x.o snd-soc-tda7419-y := tda7419.o snd-soc-tas2770-y := tas2770.o snd-soc-tas2781-comlib-y := tas2781-comlib.o @@ -540,6 +544,7 @@ obj-$(CONFIG_SND_SOC_CS4271_I2C) += snd-soc-cs4271-i2c.o obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o +obj-$(CONFIG_SND_SOC_CS42XX8_SPI) += snd-soc-cs42xx8-spi.o obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o @@ -575,6 +580,7 @@ obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o obj-$(CONFIG_SND_SOC_ES8375) += snd-soc-es8375.o obj-$(CONFIG_SND_SOC_ES8389) += snd-soc-es8389.o +obj-$(CONFIG_SND_SOC_ES9356) += snd-soc-es9356.o obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o obj-$(CONFIG_SND_SOC_FS_AMP_LIB)+= snd-soc-fs-amp-lib.o obj-$(CONFIG_SND_SOC_FS210X) += snd-soc-fs210x.o @@ -746,6 +752,7 @@ obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o +obj-$(CONFIG_SND_SOC_TAC5XX2_SDW) += snd-soc-tac5xx2-sdw.o obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o obj-$(CONFIG_SND_SOC_TAS2562) += snd-soc-tas2562.o obj-$(CONFIG_SND_SOC_TAS2764) += snd-soc-tas2764.o @@ -760,6 +767,7 @@ obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o obj-$(CONFIG_SND_SOC_TAS5805M) += snd-soc-tas5805m.o obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o +obj-$(CONFIG_SND_SOC_TAS675X) += snd-soc-tas675x.o obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c index 6aa168e01fbb..d4d6560bdb80 100644 --- a/sound/soc/codecs/ad193x-i2c.c +++ b/sound/soc/codecs/ad193x-i2c.c @@ -14,8 +14,8 @@ #include "ad193x.h" static const struct i2c_device_id ad193x_id[] = { - { "ad1936", AD193X }, - { "ad1937", AD193X }, + { .name = "ad1936", .driver_data = AD193X }, + { .name = "ad1937", .driver_data = AD193X }, { } }; MODULE_DEVICE_TABLE(i2c, ad193x_id); diff --git a/sound/soc/codecs/adau1372-i2c.c b/sound/soc/codecs/adau1372-i2c.c index 73f83be38f74..4217b7fc349c 100644 --- a/sound/soc/codecs/adau1372-i2c.c +++ b/sound/soc/codecs/adau1372-i2c.c @@ -21,7 +21,7 @@ static int adau1372_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adau1372_i2c_ids[] = { - { "adau1372" }, + { .name = "adau1372" }, { } }; MODULE_DEVICE_TABLE(i2c, adau1372_i2c_ids); diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c index d7363f9d53bb..879afeb81c42 100644 --- a/sound/soc/codecs/adau1372.c +++ b/sound/soc/codecs/adau1372.c @@ -813,6 +813,11 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable) if (adau1372->use_pll) { ret = adau1372_enable_pll(adau1372); if (ret) { + if (!adau1372->pd_gpio) + regmap_update_bits(adau1372->regmap, + ADAU1372_REG_CLK_CTRL, + ADAU1372_CLK_CTRL_PLL_EN, + 0); regcache_cache_only(adau1372->regmap, true); if (adau1372->pd_gpio) gpiod_set_value(adau1372->pd_gpio, 1); diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 16b9b2658341..5dd961b233ce 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1599,7 +1599,7 @@ static int adau1373_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adau1373_i2c_id[] = { - { "adau1373" }, + { .name = "adau1373" }, { } }; MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 6876462d8bdb..329ab01b62c0 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -860,10 +860,10 @@ static int adau1701_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adau1701_i2c_id[] = { - { "adau1401" }, - { "adau1401a" }, - { "adau1701" }, - { "adau1702" }, + { .name = "adau1401" }, + { .name = "adau1401a" }, + { .name = "adau1701" }, + { .name = "adau1702" }, { } }; MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c index eba7e4f42c78..a329e5bddb99 100644 --- a/sound/soc/codecs/adau1761-i2c.c +++ b/sound/soc/codecs/adau1761-i2c.c @@ -33,10 +33,10 @@ static void adau1761_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id adau1761_i2c_ids[] = { - { "adau1361", ADAU1361 }, - { "adau1461", ADAU1761 }, - { "adau1761", ADAU1761 }, - { "adau1961", ADAU1361 }, + { .name = "adau1361", .driver_data = ADAU1361 }, + { .name = "adau1461", .driver_data = ADAU1761 }, + { .name = "adau1761", .driver_data = ADAU1761 }, + { .name = "adau1961", .driver_data = ADAU1361 }, { } }; MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids); diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c index cb67fde8d9a8..0e7954148af7 100644 --- a/sound/soc/codecs/adau1781-i2c.c +++ b/sound/soc/codecs/adau1781-i2c.c @@ -33,8 +33,8 @@ static void adau1781_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id adau1781_i2c_ids[] = { - { "adau1381", ADAU1381 }, - { "adau1781", ADAU1781 }, + { .name = "adau1381", .driver_data = ADAU1381 }, + { .name = "adau1781", .driver_data = ADAU1781 }, { } }; MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids); diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c index 441c8079246a..fc7ed5c1dd74 100644 --- a/sound/soc/codecs/adau1977-i2c.c +++ b/sound/soc/codecs/adau1977-i2c.c @@ -28,9 +28,9 @@ static int adau1977_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adau1977_i2c_ids[] = { - { "adau1977", ADAU1977 }, - { "adau1978", ADAU1978 }, - { "adau1979", ADAU1978 }, + { .name = "adau1977", .driver_data = ADAU1977 }, + { .name = "adau1978", .driver_data = ADAU1978 }, + { .name = "adau1979", .driver_data = ADAU1978 }, { } }; MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids); diff --git a/sound/soc/codecs/adau7118-i2c.c b/sound/soc/codecs/adau7118-i2c.c index f9dc8f4ef9a4..7cccb4c6cff7 100644 --- a/sound/soc/codecs/adau7118-i2c.c +++ b/sound/soc/codecs/adau7118-i2c.c @@ -68,8 +68,8 @@ static const struct of_device_id adau7118_of_match[] = { MODULE_DEVICE_TABLE(of, adau7118_of_match); static const struct i2c_device_id adau7118_id[] = { - {"adau7118"}, - {} + { .name = "adau7118" }, + { } }; MODULE_DEVICE_TABLE(i2c, adau7118_id); diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c index 8b96c41f0354..9e5f8e866acb 100644 --- a/sound/soc/codecs/adav803.c +++ b/sound/soc/codecs/adav803.c @@ -14,7 +14,7 @@ #include "adav80x.h" static const struct i2c_device_id adav803_id[] = { - { "adav803" }, + { .name = "adav803" }, { } }; MODULE_DEVICE_TABLE(i2c, adav803_id); diff --git a/sound/soc/codecs/ak4118.c b/sound/soc/codecs/ak4118.c index 23e868e4e3fb..03dadba0b038 100644 --- a/sound/soc/codecs/ak4118.c +++ b/sound/soc/codecs/ak4118.c @@ -395,8 +395,8 @@ MODULE_DEVICE_TABLE(of, ak4118_of_match); #endif static const struct i2c_device_id ak4118_id_table[] = { - { "ak4118" }, - {} + { .name = "ak4118" }, + { } }; MODULE_DEVICE_TABLE(i2c, ak4118_id_table); diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index aadc46a47280..37555674cd15 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -430,7 +430,7 @@ static int ak4535_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ak4535_i2c_id[] = { - { "ak4535" }, + { .name = "ak4535" }, { } }; MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index de9e43185555..3e0696b5abf5 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -303,7 +303,7 @@ static const struct of_device_id ak4613_of_match[] = { MODULE_DEVICE_TABLE(of, ak4613_of_match); static const struct i2c_device_id ak4613_i2c_id[] = { - { "ak4613", (kernel_ulong_t)&ak4613_regmap_cfg }, + { .name = "ak4613", .driver_data = (kernel_ulong_t)&ak4613_regmap_cfg }, { } }; MODULE_DEVICE_TABLE(i2c, ak4613_i2c_id); @@ -748,11 +748,6 @@ static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd, return 0; } -/* - * Select below from Sound Card, not Auto - * SND_SOC_DAIFMT_CBC_CFC - * SND_SOC_DAIFMT_CBP_CFP - */ static const u64 ak4613_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_LEFT_J; diff --git a/sound/soc/codecs/ak4619.c b/sound/soc/codecs/ak4619.c index daf6e15b7077..d9c9f6b20028 100644 --- a/sound/soc/codecs/ak4619.c +++ b/sound/soc/codecs/ak4619.c @@ -778,17 +778,13 @@ static int ak4619_dai_startup(struct snd_pcm_substream *substream, } static u64 ak4619_dai_formats[] = { - /* - * Select below from Sound Card, not here - * SND_SOC_DAIFMT_CBC_CFC - * SND_SOC_DAIFMT_CBP_CFP - */ - /* First Priority */ SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_LEFT_J, /* Second Priority */ + SND_SOC_POSSIBLE_DAIFMT_I2S | + SND_SOC_POSSIBLE_DAIFMT_LEFT_J | SND_SOC_POSSIBLE_DAIFMT_DSP_A | SND_SOC_POSSIBLE_DAIFMT_DSP_B, }; @@ -831,7 +827,7 @@ static const struct of_device_id ak4619_of_match[] = { MODULE_DEVICE_TABLE(of, ak4619_of_match); static const struct i2c_device_id ak4619_i2c_id[] = { - { "ak4619", (kernel_ulong_t)&ak4619_regmap_cfg }, + { .name = "ak4619", .driver_data = (kernel_ulong_t)&ak4619_regmap_cfg }, { } }; MODULE_DEVICE_TABLE(i2c, ak4619_i2c_id); diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index fe035d2fc913..08ec2035b270 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -672,10 +672,10 @@ static const struct of_device_id ak4642_of_match[] = { MODULE_DEVICE_TABLE(of, ak4642_of_match); static const struct i2c_device_id ak4642_i2c_id[] = { - { "ak4642", (kernel_ulong_t)&ak4642_drvdata }, - { "ak4643", (kernel_ulong_t)&ak4643_drvdata }, - { "ak4648", (kernel_ulong_t)&ak4648_drvdata }, - {} + { .name = "ak4642", .driver_data = (kernel_ulong_t)&ak4642_drvdata }, + { .name = "ak4643", .driver_data = (kernel_ulong_t)&ak4643_drvdata }, + { .name = "ak4648", .driver_data = (kernel_ulong_t)&ak4648_drvdata }, + { } }; MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index d545aa2e0a39..aac54e9d54ee 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -646,7 +646,7 @@ static int ak4671_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ak4671_i2c_id[] = { - { "ak4671" }, + { .name = "ak4671" }, { } }; MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index ec229b315f9f..f5a666c49361 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c @@ -963,10 +963,10 @@ static const struct regmap_config alc5623_regmap = { }; static const struct i2c_device_id alc5623_i2c_table[] = { - {"alc5621", 0x21}, - {"alc5622", 0x22}, - {"alc5623", 0x23}, - {} + { .name = "alc5621", .driver_data = 0x21 }, + { .name = "alc5622", .driver_data = 0x22 }, + { .name = "alc5623", .driver_data = 0x23 }, + { } }; MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table); diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c index 72f4622204ff..2fd3dd7ef8b3 100644 --- a/sound/soc/codecs/alc5632.c +++ b/sound/soc/codecs/alc5632.c @@ -1092,8 +1092,8 @@ static const struct regmap_config alc5632_regmap = { }; static const struct i2c_device_id alc5632_i2c_table[] = { - {"alc5632", 0x5c}, - {} + { .name = "alc5632", .driver_data = 0x5c }, + { } }; MODULE_DEVICE_TABLE(i2c, alc5632_i2c_table); diff --git a/sound/soc/codecs/aw87390.c b/sound/soc/codecs/aw87390.c index 37ca42a25889..020213e0ca4b 100644 --- a/sound/soc/codecs/aw87390.c +++ b/sound/soc/codecs/aw87390.c @@ -599,8 +599,8 @@ static const struct of_device_id aw87390_of_match[] = { MODULE_DEVICE_TABLE(of, aw87390_of_match); static const struct i2c_device_id aw87390_i2c_id[] = { - { AW87390_I2C_NAME }, - { AW87391_I2C_NAME }, + { .name = AW87390_I2C_NAME }, + { .name = AW87391_I2C_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, aw87390_i2c_id); diff --git a/sound/soc/codecs/aw88081.c b/sound/soc/codecs/aw88081.c index 8c5bb3ea0227..d5e886a8f106 100644 --- a/sound/soc/codecs/aw88081.c +++ b/sound/soc/codecs/aw88081.c @@ -1137,6 +1137,7 @@ static int aw88081_dev_init(struct aw88081 *aw88081, struct aw_container *aw_cfg static int aw88081_request_firmware_file(struct aw88081 *aw88081) { const struct firmware *cont = NULL; + struct aw_container *aw_cfg; int ret; aw88081->aw_pa->fw_status = AW88081_DEV_FW_FAILED; @@ -1148,13 +1149,16 @@ static int aw88081_request_firmware_file(struct aw88081 *aw88081) dev_dbg(aw88081->aw_pa->dev, "loaded %s - size: %zu\n", AW88081_ACF_FILE, cont ? cont->size : 0); - aw88081->aw_cfg = devm_kzalloc(aw88081->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL); - if (!aw88081->aw_cfg) { + aw_cfg = devm_kzalloc(aw88081->aw_pa->dev, struct_size(aw_cfg, data, cont->size), GFP_KERNEL); + if (!aw_cfg) { release_firmware(cont); return -ENOMEM; } - aw88081->aw_cfg->len = (int)cont->size; - memcpy(aw88081->aw_cfg->data, cont->data, cont->size); + aw_cfg->len = (int)cont->size; + memcpy(aw_cfg->data, cont->data, cont->size); + + aw88081->aw_cfg = aw_cfg; + release_firmware(cont); ret = aw88395_dev_load_acf_check(aw88081->aw_pa, aw88081->aw_cfg); @@ -1240,8 +1244,8 @@ static const struct snd_soc_component_driver soc_codec_dev_aw88081 = { }; static const struct i2c_device_id aw88081_i2c_id[] = { - { AW88081_I2C_NAME, AW88081}, - { AW88083_I2C_NAME, AW88083}, + { .name = AW88081_I2C_NAME, .driver_data = AW88081 }, + { .name = AW88083_I2C_NAME, .driver_data = AW88083 }, { } }; MODULE_DEVICE_TABLE(i2c, aw88081_i2c_id); diff --git a/sound/soc/codecs/aw88166.c b/sound/soc/codecs/aw88166.c index ea277a940c44..3f15f4ac51f7 100644 --- a/sound/soc/codecs/aw88166.c +++ b/sound/soc/codecs/aw88166.c @@ -1801,7 +1801,7 @@ static int aw88166_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id aw88166_i2c_id[] = { - { AW88166_I2C_NAME }, + { .name = AW88166_I2C_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, aw88166_i2c_id); diff --git a/sound/soc/codecs/aw88261.c b/sound/soc/codecs/aw88261.c index a6805d5405cd..549783d3e75e 100644 --- a/sound/soc/codecs/aw88261.c +++ b/sound/soc/codecs/aw88261.c @@ -10,9 +10,12 @@ #include #include +#include #include #include #include +#include +#include #include "aw88261.h" #include "aw88395/aw88395_data_type.h" #include "aw88395/aw88395_device.h" @@ -27,64 +30,10 @@ static const struct regmap_config aw88261_remap_config = { static void aw88261_dev_set_volume(struct aw_device *aw_dev, unsigned int value) { - struct aw_volume_desc *vol_desc = &aw_dev->volume_desc; - unsigned int real_value, volume; - unsigned int reg_value; + unsigned int volume = min(value, (unsigned int)AW88261_MUTE_VOL); - volume = min((value + vol_desc->init_volume), (unsigned int)AW88261_MUTE_VOL); - real_value = DB_TO_REG_VAL(volume); - - regmap_read(aw_dev->regmap, AW88261_SYSCTRL2_REG, ®_value); - - real_value = (real_value | (reg_value & AW88261_VOL_START_MASK)); - - dev_dbg(aw_dev->dev, "value 0x%x , real_value:0x%x", value, real_value); - - regmap_write(aw_dev->regmap, AW88261_SYSCTRL2_REG, real_value); -} - -static void aw88261_dev_fade_in(struct aw_device *aw_dev) -{ - struct aw_volume_desc *desc = &aw_dev->volume_desc; - int fade_in_vol = desc->ctl_volume; - int fade_step = aw_dev->fade_step; - int i; - - if (fade_step == 0 || aw_dev->fade_in_time == 0) { - aw88261_dev_set_volume(aw_dev, fade_in_vol); - return; - } - - for (i = AW88261_MUTE_VOL; i >= fade_in_vol; i -= fade_step) { - aw88261_dev_set_volume(aw_dev, i); - usleep_range(aw_dev->fade_in_time, - aw_dev->fade_in_time + 10); - } - - if (i != fade_in_vol) - aw88261_dev_set_volume(aw_dev, fade_in_vol); -} - -static void aw88261_dev_fade_out(struct aw_device *aw_dev) -{ - struct aw_volume_desc *desc = &aw_dev->volume_desc; - int fade_step = aw_dev->fade_step; - int i; - - if (fade_step == 0 || aw_dev->fade_out_time == 0) { - aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL); - return; - } - - for (i = desc->ctl_volume; i <= AW88261_MUTE_VOL; i += fade_step) { - aw88261_dev_set_volume(aw_dev, i); - usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); - } - - if (i != AW88261_MUTE_VOL) { - aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL); - usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10); - } + regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL2_REG, + ~AW88261_VOL_MASK, DB_TO_REG_VAL(volume)); } static void aw88261_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag) @@ -120,13 +69,13 @@ static void aw88261_dev_amppd(struct aw_device *aw_dev, bool amppd) static void aw88261_dev_mute(struct aw_device *aw_dev, bool is_mute) { if (is_mute) { - aw88261_dev_fade_out(aw_dev); + aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL); regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, ~AW88261_HMUTE_MASK, AW88261_HMUTE_ENABLE_VALUE); } else { regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, ~AW88261_HMUTE_MASK, AW88261_HMUTE_DISABLE_VALUE); - aw88261_dev_fade_in(aw_dev); + aw88261_dev_set_volume(aw_dev, aw_dev->volume_desc.ctl_volume); } } @@ -151,21 +100,21 @@ static int aw88261_dev_get_iis_status(struct aw_device *aw_dev) if (ret) return ret; if ((reg_val & AW88261_BIT_PLL_CHECK) != AW88261_BIT_PLL_CHECK) { - dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val); + dev_dbg(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val); return -EINVAL; } return ret; } -static int aw88261_dev_check_mode1_pll(struct aw_device *aw_dev) +static int aw88261_dev_check_pll(struct aw_device *aw_dev) { int ret, i; for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { ret = aw88261_dev_get_iis_status(aw_dev); if (ret) { - dev_err(aw_dev->dev, "mode1 iis signal check error"); + dev_dbg(aw_dev->dev, "mode1 iis signal check error"); usleep_range(AW88261_2000_US, AW88261_2000_US + 10); } else { return ret; @@ -175,71 +124,74 @@ static int aw88261_dev_check_mode1_pll(struct aw_device *aw_dev) return -EPERM; } -static int aw88261_dev_check_mode2_pll(struct aw_device *aw_dev) -{ - unsigned int reg_val; - int ret, i; - - ret = regmap_read(aw_dev->regmap, AW88261_PLLCTRL1_REG, ®_val); - if (ret) - return ret; - - reg_val &= (~AW88261_CCO_MUX_MASK); - if (reg_val == AW88261_CCO_MUX_DIVIDED_VALUE) { - dev_dbg(aw_dev->dev, "CCO_MUX is already divider"); - return -EPERM; - } - - /* change mode2 */ - ret = regmap_update_bits(aw_dev->regmap, AW88261_PLLCTRL1_REG, - ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_DIVIDED_VALUE); - if (ret) - return ret; - - for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { - ret = aw88261_dev_get_iis_status(aw_dev); - if (ret) { - dev_err(aw_dev->dev, "mode2 iis signal check error"); - usleep_range(AW88261_2000_US, AW88261_2000_US + 10); - } else { - break; - } - } - - /* change mode1 */ - ret = regmap_update_bits(aw_dev->regmap, AW88261_PLLCTRL1_REG, - ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_BYPASS_VALUE); - if (ret == 0) { - usleep_range(AW88261_2000_US, AW88261_2000_US + 10); - for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) { - ret = aw88261_dev_check_mode1_pll(aw_dev); - if (ret) { - dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error"); - usleep_range(AW88261_2000_US, AW88261_2000_US + 10); - } else { - break; - } - } - } - - return ret; -} - -static int aw88261_dev_check_syspll(struct aw_device *aw_dev) +static int aw88261_dev_configure_syspll(struct aw88261 *aw88261) { + struct aw_device *aw_dev = aw88261->aw_pa; int ret; - ret = aw88261_dev_check_mode1_pll(aw_dev); - if (ret) { - dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check"); - ret = aw88261_dev_check_mode2_pll(aw_dev); - if (ret) { - dev_err(aw_dev->dev, "mode2 check iis failed"); - return ret; - } - } + /* Configure TDM slots (I2S is represented as no slots) */ + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG, + ~AW88261_SLOT_NUM_MASK, aw88261->slot_num_value); + if (ret) + return ret; - return ret; + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG, + ~AW88261_I2S_TX_SLOTVLD_MASK, + aw88261->tx_slotvld_mask); + if (ret) + return ret; + + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG, + ~AW88261_I2S_RXL_SLOTVLD_MASK, + aw88261->rxl_slotvld_mask); + if (ret) + return ret; + + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG, + ~AW88261_I2S_RXR_SLOTVLD_MASK, + aw88261->rxr_slotvld_mask); + if (ret) + return ret; + + /* PLL divider must be used for 8/16/32 kHz modes */ + ret = regmap_update_bits(aw_dev->regmap, AW88261_PLLCTRL1_REG, + ~AW88261_CCO_MUX_MASK, aw88261->cco_mux_value); + if (ret) + return ret; + + /* The word clock (WCK) defines the beginning of a frame */ + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG, + ~AW88261_I2SSR_MASK, aw88261->sr_value); + if (ret) + return ret; + + /* The bit clock (BCK) defines the length of a frame */ + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG, + ~AW88261_I2SBCK_MASK, + (aw88261->tdm_bck_value != AW88261_TDM_BCK_UNSET) + ? aw88261->tdm_bck_value : aw88261->bck_value); + if (ret) + return ret; + + /* The logical frame size is the width of data for 1 slot */ + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG, + ~AW88261_I2SFS_MASK, aw88261->fs_value); + if (ret) + return ret; + + /* The I2S interface mode (Philips standard, LSB/MSB justified) */ + ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG, + ~AW88261_I2SMD_MASK, aw88261->md_value); + if (ret) + return ret; + + /* The polarity of the bit clock (BCK) */ + ret = regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG, + ~AW88261_BCKINV_MASK, aw88261->bck_inv_value); + if (ret) + return ret; + + return aw88261_dev_check_pll(aw_dev); } static int aw88261_dev_check_sysst(struct aw_device *aw_dev) @@ -256,7 +208,7 @@ static int aw88261_dev_check_sysst(struct aw_device *aw_dev) check_val = reg_val & (~AW88261_BIT_SYSST_CHECK_MASK) & AW88261_BIT_SYSST_CHECK; if (check_val != AW88261_BIT_SYSST_CHECK) { - dev_err(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x", + dev_dbg(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x", reg_val, AW88261_BIT_SYSST_CHECK); usleep_range(AW88261_2000_US, AW88261_2000_US + 10); } else { @@ -284,22 +236,22 @@ static void aw88261_reg_force_set(struct aw88261 *aw88261) if (aw88261->frcset_en == AW88261_FRCSET_ENABLE) { /* set FORCE_PWM */ regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL3_REG, - AW88261_FORCE_PWM_MASK, AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE); + ~AW88261_FORCE_PWM_MASK, AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE); /* set BOOST_OS_WIDTH */ regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL5_REG, - AW88261_BST_OS_WIDTH_MASK, AW88261_BST_OS_WIDTH_50NS_VALUE); + ~AW88261_BST_OS_WIDTH_MASK, AW88261_BST_OS_WIDTH_50NS_VALUE); /* set BURST_LOOPR */ regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL6_REG, - AW88261_BST_LOOPR_MASK, AW88261_BST_LOOPR_340K_VALUE); + ~AW88261_BST_LOOPR_MASK, AW88261_BST_LOOPR_340K_VALUE); /* set RSQN_DLY */ regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL7_REG, - AW88261_RSQN_DLY_MASK, AW88261_RSQN_DLY_35NS_VALUE); + ~AW88261_RSQN_DLY_MASK, AW88261_RSQN_DLY_35NS_VALUE); /* set BURST_SSMODE */ regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL8_REG, - AW88261_BURST_SSMODE_MASK, AW88261_BURST_SSMODE_FAST_VALUE); + ~AW88261_BURST_SSMODE_MASK, AW88261_BURST_SSMODE_FAST_VALUE); /* set BST_BURST */ regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL9_REG, - AW88261_BST_BURST_MASK, AW88261_BST_BURST_30MA_VALUE); + ~AW88261_BST_BURST_MASK, AW88261_BST_BURST_30MA_VALUE); } else { dev_dbg(aw88261->aw_pa->dev, "needn't set reg value"); } @@ -550,7 +502,7 @@ static int aw88261_dev_start(struct aw88261 *aw88261) int ret; if (aw_dev->status == AW88261_DEV_PW_ON) { - dev_info(aw_dev->dev, "already power on"); + dev_dbg(aw_dev->dev, "already power on"); return 0; } @@ -558,9 +510,9 @@ static int aw88261_dev_start(struct aw88261 *aw88261) aw88261_dev_pwd(aw_dev, false); usleep_range(AW88261_2000_US, AW88261_2000_US + 10); - ret = aw88261_dev_check_syspll(aw_dev); + ret = aw88261_dev_configure_syspll(aw88261); if (ret) { - dev_err(aw_dev->dev, "pll check failed cannot start"); + dev_dbg(aw_dev->dev, "pll check failed"); goto pll_check_fail; } @@ -571,7 +523,7 @@ static int aw88261_dev_start(struct aw88261 *aw88261) /* check i2s status */ ret = aw88261_dev_check_sysst(aw_dev); if (ret) { - dev_err(aw_dev->dev, "sysst check failed"); + dev_dbg(aw_dev->dev, "sysst check failed"); goto sysst_check_fail; } @@ -672,31 +624,25 @@ static void aw88261_start_pa(struct aw88261 *aw88261) for (i = 0; i < AW88261_START_RETRIES; i++) { ret = aw88261_reg_update(aw88261, aw88261->phase_sync); if (ret) { - dev_err(aw88261->aw_pa->dev, "fw update failed, cnt:%d\n", i); + dev_dbg(aw88261->aw_pa->dev, + "aw88261_reg_update failed, cnt:%d, ret:%d\n", i, ret); continue; } ret = aw88261_dev_start(aw88261); if (ret) { - dev_err(aw88261->aw_pa->dev, "aw88261 device start failed. retry = %d", i); + dev_dbg(aw88261->aw_pa->dev, + "aw88261_dev_start failed, cnt:%d, ret:%d\n", i, ret); continue; } else { - dev_info(aw88261->aw_pa->dev, "start success\n"); + dev_dbg(aw88261->aw_pa->dev, "start success\n"); break; } } + if (ret != 0) + dev_err(aw88261->aw_pa->dev, "start failure (%d)\n", ret); } -static void aw88261_startup_work(struct work_struct *work) -{ - struct aw88261 *aw88261 = - container_of(work, struct aw88261, start_work.work); - - mutex_lock(&aw88261->lock); - aw88261_start_pa(aw88261); - mutex_unlock(&aw88261->lock); -} - -static void aw88261_start(struct aw88261 *aw88261, bool sync_start) +static void aw88261_start(struct aw88261 *aw88261) { if (aw88261->aw_pa->fw_status != AW88261_DEV_FW_OK) return; @@ -704,14 +650,226 @@ static void aw88261_start(struct aw88261 *aw88261, bool sync_start) if (aw88261->aw_pa->status == AW88261_DEV_PW_ON) return; - if (sync_start == AW88261_SYNC_START) - aw88261_start_pa(aw88261); - else - queue_delayed_work(system_dfl_wq, - &aw88261->start_work, - AW88261_START_WORK_DELAY_MS); + aw88261_start_pa(aw88261); } +static int aw88261_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + aw88261->bck_inv_value = AW88261_BCKINV_NOT_INVERT_VALUE; + break; + case SND_SOC_DAIFMT_IB_NF: + aw88261->bck_inv_value = AW88261_BCKINV_INVERTED_VALUE; + break; + default: + dev_err(aw88261->aw_pa->dev, "unsupported invert mode 0x%x\n", + fmt & SND_SOC_DAIFMT_INV_MASK); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_DSP_A: + aw88261->md_value = AW88261_I2SMD_PHILIPS_STANDARD_VALUE; + break; + case SND_SOC_DAIFMT_MSB: + case SND_SOC_DAIFMT_DSP_B: + aw88261->md_value = AW88261_I2SMD_MSB_JUSTIFIED_VALUE; + break; + case SND_SOC_DAIFMT_LSB: + aw88261->md_value = AW88261_I2SMD_LSB_JUSTIFIED_VALUE; + break; + default: + dev_err(aw88261->aw_pa->dev, "unsupported DAI format 0x%x\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); + return -EINVAL; + } + + return 0; +} + +static int aw88261_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + return 0; + + aw88261->cco_mux_value = AW88261_CCO_MUX_BYPASS_VALUE; + switch (params_rate(params)) { + case 8000: + aw88261->sr_value = AW88261_I2SSR_8KHZ_VALUE; + aw88261->cco_mux_value = AW88261_CCO_MUX_DIVIDED_VALUE; + break; + case 11025: + aw88261->sr_value = AW88261_I2SSR_11P025KHZ_VALUE; + break; + case 12000: + aw88261->sr_value = AW88261_I2SSR_12KHZ_VALUE; + break; + case 16000: + aw88261->sr_value = AW88261_I2SSR_16KHZ_VALUE; + aw88261->cco_mux_value = AW88261_CCO_MUX_DIVIDED_VALUE; + break; + case 22050: + aw88261->sr_value = AW88261_I2SSR_22P05KHZ_VALUE; + break; + case 24000: + aw88261->sr_value = AW88261_I2SSR_24KHZ_VALUE; + break; + case 32000: + aw88261->sr_value = AW88261_I2SSR_32KHZ_VALUE; + aw88261->cco_mux_value = AW88261_CCO_MUX_DIVIDED_VALUE; + break; + case 44100: + aw88261->sr_value = AW88261_I2SSR_44P1KHZ_VALUE; + break; + case 48000: + aw88261->sr_value = AW88261_I2SSR_48KHZ_VALUE; + break; + case 96000: + aw88261->sr_value = AW88261_I2SSR_96KHZ_VALUE; + break; + case 192000: + aw88261->sr_value = AW88261_I2SSR_192KHZ_VALUE; + break; + default: + dev_err(aw88261->aw_pa->dev, "unsupported sample rate %d\n", + params_rate(params)); + return -EINVAL; + } + + switch (params_width(params)) { + case 16: + aw88261->fs_value = AW88261_I2SFS_16_BITS_VALUE; + break; + case 20: + aw88261->fs_value = AW88261_I2SFS_20_BITS_VALUE; + break; + case 24: + aw88261->fs_value = AW88261_I2SFS_24_BITS_VALUE; + break; + case 32: + aw88261->fs_value = AW88261_I2SFS_32_BITS_VALUE; + break; + default: + dev_err(aw88261->aw_pa->dev, "unsupported bit width %d\n", + params_width(params)); + return -EINVAL; + } + + switch (params_physical_width(params)) { + case 16: + aw88261->bck_value = AW88261_I2SBCK_32FS_VALUE; + break; + case 24: + aw88261->bck_value = AW88261_I2SBCK_48FS_VALUE; + break; + case 32: + aw88261->bck_value = AW88261_I2SBCK_64FS_VALUE; + break; + default: + dev_err(aw88261->aw_pa->dev, "unsupported physical bit width %d\n", + params_physical_width(params)); + return -EINVAL; + } + + return 0; +} + +static int aw88261_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); + int chan; + + switch (slots) { + case 0: + /* Just reset everything TDM related to I2S values */ + aw88261->slot_num_value = AW88261_SLOT_NUM_I2S_MODE_VALUE; + aw88261->tdm_bck_value = AW88261_TDM_BCK_UNSET; + aw88261->tx_slotvld_mask = 0 << AW88261_I2S_TX_SLOTVLD_START_BIT; + aw88261->rxl_slotvld_mask = 0 << AW88261_I2S_RXL_SLOTVLD_START_BIT; + aw88261->rxr_slotvld_mask = 1 << AW88261_I2S_RXR_SLOTVLD_START_BIT; + return 0; + case 1: + aw88261->slot_num_value = AW88261_SLOT_NUM_TDM1S_VALUE; + break; + case 2: + aw88261->slot_num_value = AW88261_SLOT_NUM_TDM2S_VALUE; + break; + case 4: + aw88261->slot_num_value = AW88261_SLOT_NUM_TDM4S_VALUE; + break; + case 6: + aw88261->slot_num_value = AW88261_SLOT_NUM_TDM6S_VALUE; + break; + case 8: + aw88261->slot_num_value = AW88261_SLOT_NUM_TDM8S_VALUE; + break; + case 16: + aw88261->slot_num_value = AW88261_SLOT_NUM_TDM16S_VALUE; + break; + default: + dev_err(aw88261->aw_pa->dev, "unsupported slot count %d\n", slots); + return -EINVAL; + } + + switch (slot_width) { + case 16: + aw88261->tdm_bck_value = AW88261_I2SBCK_32FS_VALUE; + break; + case 20: + case 24: + aw88261->tdm_bck_value = AW88261_I2SBCK_48FS_VALUE; + break; + case 32: + aw88261->tdm_bck_value = AW88261_I2SBCK_64FS_VALUE; + break; + default: + dev_err(aw88261->aw_pa->dev, "unsupported slot width %d\n", + slot_width); + return -EINVAL; + } + + if (tx_mask != 0) { + if ((chan = __ffs(tx_mask)) > 16) + return -EINVAL; + + aw88261->tx_slotvld_mask = chan << AW88261_I2S_TX_SLOTVLD_START_BIT; + } + + if (rx_mask != 0) { + if ((chan = __ffs(rx_mask)) > 16) + return -EINVAL; + + aw88261->rxl_slotvld_mask = chan << AW88261_I2S_RXL_SLOTVLD_START_BIT; + } + + if ((rx_mask & ~BIT(chan)) != 0) { + if ((chan = __ffs(rx_mask & ~BIT(chan))) > 16) + return -EINVAL; + + aw88261->rxr_slotvld_mask = chan << AW88261_I2S_RXR_SLOTVLD_START_BIT; + } + + return 0; +} + +static const struct snd_soc_dai_ops aw88261_dai_ops = { + .set_fmt = aw88261_set_fmt, + .hw_params = aw88261_hw_params, + .set_tdm_slot = aw88261_set_tdm_slot, +}; + static struct snd_soc_dai_driver aw88261_dai[] = { { .name = "aw88261-aif", @@ -730,78 +888,10 @@ static struct snd_soc_dai_driver aw88261_dai[] = { .rates = AW88261_RATES, .formats = AW88261_FORMATS, }, + .ops = &aw88261_dai_ops, }, }; -static int aw88261_get_fade_in_time(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); - struct aw_device *aw_dev = aw88261->aw_pa; - - ucontrol->value.integer.value[0] = aw_dev->fade_in_time; - - return 0; -} - -static int aw88261_set_fade_in_time(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct aw_device *aw_dev = aw88261->aw_pa; - int time; - - time = ucontrol->value.integer.value[0]; - - if (time < mc->min || time > mc->max) - return -EINVAL; - - if (time != aw_dev->fade_in_time) { - aw_dev->fade_in_time = time; - return 1; - } - - return 0; -} - -static int aw88261_get_fade_out_time(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); - struct aw_device *aw_dev = aw88261->aw_pa; - - ucontrol->value.integer.value[0] = aw_dev->fade_out_time; - - return 0; -} - -static int aw88261_set_fade_out_time(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); - struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct aw_device *aw_dev = aw88261->aw_pa; - int time; - - time = ucontrol->value.integer.value[0]; - if (time < mc->min || time > mc->max) - return -EINVAL; - - if (time != aw_dev->fade_out_time) { - aw_dev->fade_out_time = time; - return 1; - } - - return 0; -} - static int aw88261_dev_set_profile_index(struct aw_device *aw_dev, int index) { /* check the index whether is valid */ @@ -880,7 +970,7 @@ static int aw88261_profile_set(struct snd_kcontrol *kcontrol, if (aw88261->aw_pa->status) { aw88261_dev_stop(aw88261->aw_pa); - aw88261_start(aw88261, AW88261_SYNC_START); + aw88261_start(aw88261); } mutex_unlock(&aw88261->lock); @@ -895,7 +985,8 @@ static int aw88261_volume_get(struct snd_kcontrol *kcontrol, struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; - ucontrol->value.integer.value[0] = vol_desc->ctl_volume; + ucontrol->value.integer.value[0] = + (AW88261_MUTE_VOL - vol_desc->ctl_volume) / 2; return 0; } @@ -908,13 +999,13 @@ static int aw88261_volume_set(struct snd_kcontrol *kcontrol, struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - int value; - - value = ucontrol->value.integer.value[0]; + int value = ucontrol->value.integer.value[0]; if (value < mc->min || value > mc->max) return -EINVAL; + value = AW88261_MUTE_VOL - (value * 2); + if (vol_desc->ctl_volume != value) { vol_desc->ctl_volume = value; aw88261_dev_set_volume(aw88261->aw_pa, vol_desc->ctl_volume); @@ -925,48 +1016,18 @@ static int aw88261_volume_set(struct snd_kcontrol *kcontrol, return 0; } -static int aw88261_get_fade_step(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *codec = snd_kcontrol_chip(kcontrol); - struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); - - ucontrol->value.integer.value[0] = aw88261->aw_pa->fade_step; - - return 0; -} - -static int aw88261_set_fade_step(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_component *codec = snd_kcontrol_chip(kcontrol); - struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int value; - - value = ucontrol->value.integer.value[0]; - if (value < mc->min || value > mc->max) - return -EINVAL; - - if (aw88261->aw_pa->fade_step != value) { - aw88261->aw_pa->fade_step = value; - return 1; - } - - return 0; -} +/* + * The field contains 4 bits in units of 6dB + 6 bits in units of 0.125dB + * which is too precise for TLV (!) so we have to multiply the scale by 2. + * + * The range is clamped at -90dB to prevent overflowing the 4-bit part. + */ +static const DECLARE_TLV_DB_SCALE(volume_tlv, -9000, 25, 0); static const struct snd_kcontrol_new aw88261_controls[] = { - SOC_SINGLE_EXT("PCM Playback Volume", AW88261_SYSCTRL2_REG, - 6, AW88261_MUTE_VOL, 0, aw88261_volume_get, - aw88261_volume_set), - SOC_SINGLE_EXT("Fade Step", 0, 0, AW88261_MUTE_VOL, 0, - aw88261_get_fade_step, aw88261_set_fade_step), - SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, - aw88261_get_fade_in_time, aw88261_set_fade_in_time), - SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN, - aw88261_get_fade_out_time, aw88261_set_fade_out_time), + SOC_SINGLE_EXT_TLV("PCM Playback Volume", AW88261_SYSCTRL2_REG, + 6, AW88261_CTL_MAX_VOL, 1, + aw88261_volume_get, aw88261_volume_set, volume_tlv), AW88261_PROFILE_EXT("Profile Set", aw88261_profile_info, aw88261_profile_get, aw88261_profile_set), }; @@ -980,7 +1041,7 @@ static int aw88261_playback_event(struct snd_soc_dapm_widget *w, mutex_lock(&aw88261->lock); switch (event) { case SND_SOC_DAPM_PRE_PMU: - aw88261_start(aw88261, AW88261_ASYNC_START); + aw88261_start(aw88261); break; case SND_SOC_DAPM_POST_PMD: aw88261_dev_stop(aw88261->aw_pa); @@ -1057,8 +1118,6 @@ static int aw88261_dev_init(struct aw88261 *aw88261, struct aw_container *aw_cfg if (ret) return ret; - aw_dev->fade_in_time = AW88261_500_US; - aw_dev->fade_out_time = AW88261_500_US; aw_dev->prof_cur = AW88261_INIT_PROFILE; aw_dev->prof_index = AW88261_INIT_PROFILE; @@ -1094,6 +1153,7 @@ static int aw88261_dev_init(struct aw88261 *aw88261, struct aw_container *aw_cfg static int aw88261_request_firmware_file(struct aw88261 *aw88261) { const struct firmware *cont = NULL; + struct aw_container *aw_cfg; const char *fw_name; int ret; @@ -1111,15 +1171,17 @@ static int aw88261_request_firmware_file(struct aw88261 *aw88261) dev_info(aw88261->aw_pa->dev, "loaded %s - size: %zu\n", fw_name, cont ? cont->size : 0); - aw88261->aw_cfg = devm_kzalloc(aw88261->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL); - if (!aw88261->aw_cfg) { + aw_cfg = devm_kzalloc(aw88261->aw_pa->dev, struct_size(aw_cfg, data, cont->size), GFP_KERNEL); + if (!aw_cfg) { release_firmware(cont); return -ENOMEM; } - aw88261->aw_cfg->len = (int)cont->size; - memcpy(aw88261->aw_cfg->data, cont->data, cont->size); + aw_cfg->len = (int)cont->size; + memcpy(aw_cfg->data, cont->data, cont->size); release_firmware(cont); + aw88261->aw_cfg = aw_cfg; + ret = aw88395_dev_load_acf_check(aw88261->aw_pa, aw88261->aw_cfg); if (ret) { dev_err(aw88261->aw_pa->dev, "load [%s] failed !", fw_name); @@ -1142,8 +1204,6 @@ static int aw88261_codec_probe(struct snd_soc_component *component) struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component); int ret; - INIT_DELAYED_WORK(&aw88261->start_work, aw88261_startup_work); - ret = aw88261_request_firmware_file(aw88261); if (ret) return dev_err_probe(aw88261->aw_pa->dev, ret, @@ -1167,16 +1227,8 @@ static int aw88261_codec_probe(struct snd_soc_component *component) return ret; } -static void aw88261_codec_remove(struct snd_soc_component *aw_codec) -{ - struct aw88261 *aw88261 = snd_soc_component_get_drvdata(aw_codec); - - cancel_delayed_work_sync(&aw88261->start_work); -} - static const struct snd_soc_component_driver soc_codec_dev_aw88261 = { .probe = aw88261_codec_probe, - .remove = aw88261_codec_remove, }; static void aw88261_parse_channel_dt(struct aw88261 *aw88261) @@ -1208,7 +1260,7 @@ static int aw88261_init(struct aw88261 *aw88261, struct i2c_client *i2c, struct return ret; } if (chip_id != AW88261_CHIP_ID) { - dev_err(&i2c->dev, "unsupported device"); + dev_err(&i2c->dev, "unsupported device id = %x", chip_id); return -ENXIO; } @@ -1229,8 +1281,7 @@ static int aw88261_init(struct aw88261 *aw88261, struct i2c_client *i2c, struct aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID; aw_dev->channel = 0; aw_dev->fw_status = AW88261_DEV_FW_FAILED; - aw_dev->fade_step = AW88261_VOLUME_STEP_DB; - aw_dev->volume_desc.ctl_volume = AW88261_VOL_DEFAULT_VALUE; + aw_dev->volume_desc.ctl_volume = AW88261_CTL_DEFAULT_VOL; aw_dev->volume_desc.mute_volume = AW88261_MUTE_VOL; aw88261_parse_channel_dt(aw88261); @@ -1249,6 +1300,17 @@ static int aw88261_i2c_probe(struct i2c_client *i2c) if (!aw88261) return -ENOMEM; + /* set defaults */ + aw88261->slot_num_value = AW88261_SLOT_NUM_I2S_MODE_VALUE; + aw88261->sr_value = AW88261_I2SSR_48KHZ_VALUE; + aw88261->cco_mux_value = AW88261_CCO_MUX_BYPASS_VALUE; + aw88261->fs_value = AW88261_I2SFS_24_BITS_VALUE; + aw88261->bck_value = AW88261_I2SBCK_64FS_VALUE; + aw88261->bck_inv_value = AW88261_BCKINV_NOT_INVERT_VALUE; + aw88261->tdm_bck_value = AW88261_TDM_BCK_UNSET; + aw88261->md_value = AW88261_I2SMD_PHILIPS_STANDARD_VALUE; + aw88261->rxr_slotvld_mask = 1 << AW88261_I2S_RXR_SLOTVLD_START_BIT; + mutex_init(&aw88261->lock); i2c_set_clientdata(i2c, aw88261); @@ -1274,7 +1336,7 @@ static int aw88261_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id aw88261_i2c_id[] = { - { "aw88261" }, + { .name = "aw88261" }, { } }; MODULE_DEVICE_TABLE(i2c, aw88261_i2c_id); diff --git a/sound/soc/codecs/aw88261.h b/sound/soc/codecs/aw88261.h index 1fee589608d6..270ccf375f36 100644 --- a/sound/soc/codecs/aw88261.h +++ b/sound/soc/codecs/aw88261.h @@ -116,6 +116,19 @@ #define AW88261_VCALK_SHIFT (0) #define AW88261_VCALKL_SHIFT (0) +#define AW88261_BCKINV_START_BIT (4) +#define AW88261_BCKINV_BITS_LEN (1) +#define AW88261_BCKINV_MASK \ + (~(((1<> AW88261_VOL_6DB_START) * \ @@ -403,11 +557,6 @@ .put = profile_set, \ } -enum { - AW88261_SYNC_START = 0, - AW88261_ASYNC_START, -}; - enum aw88261_id { AW88261_CHIP_ID = 0x2113, }; @@ -442,7 +591,6 @@ struct aw88261 { struct aw_device *aw_pa; struct mutex lock; struct gpio_desc *reset_gpio; - struct delayed_work start_work; struct regmap *regmap; struct aw_container *aw_cfg; @@ -451,6 +599,19 @@ struct aw88261 { unsigned int mute_st; unsigned int amppd_st; + unsigned int sr_value; + unsigned int cco_mux_value; + unsigned int fs_value; + unsigned int bck_value; + unsigned int bck_inv_value; + unsigned int tdm_bck_value; + unsigned int md_value; + + unsigned int slot_num_value; + unsigned int tx_slotvld_mask; + unsigned int rxl_slotvld_mask; + unsigned int rxr_slotvld_mask; + bool phase_sync; }; diff --git a/sound/soc/codecs/aw88395/aw88395.c b/sound/soc/codecs/aw88395/aw88395.c index dd09bac652f7..ee0e8bd8c54c 100644 --- a/sound/soc/codecs/aw88395/aw88395.c +++ b/sound/soc/codecs/aw88395/aw88395.c @@ -462,6 +462,7 @@ static void aw88395_hw_reset(struct aw88395 *aw88395) static int aw88395_request_firmware_file(struct aw88395 *aw88395) { const struct firmware *cont = NULL; + struct aw_container *aw_cfg; int ret; aw88395->aw_pa->fw_status = AW88395_DEV_FW_FAILED; @@ -475,15 +476,17 @@ static int aw88395_request_firmware_file(struct aw88395 *aw88395) dev_info(aw88395->aw_pa->dev, "loaded %s - size: %zu\n", AW88395_ACF_FILE, cont ? cont->size : 0); - aw88395->aw_cfg = devm_kzalloc(aw88395->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL); - if (!aw88395->aw_cfg) { + aw_cfg = devm_kzalloc(aw88395->aw_pa->dev, struct_size(aw_cfg, data, cont->size), GFP_KERNEL); + if (!aw_cfg) { release_firmware(cont); return -ENOMEM; } - aw88395->aw_cfg->len = (int)cont->size; - memcpy(aw88395->aw_cfg->data, cont->data, cont->size); + aw_cfg->len = (int)cont->size; + memcpy(aw_cfg->data, cont->data, cont->size); release_firmware(cont); + aw88395->aw_cfg = aw_cfg; + ret = aw88395_dev_load_acf_check(aw88395->aw_pa, aw88395->aw_cfg); if (ret < 0) { dev_err(aw88395->aw_pa->dev, "Load [%s] failed ....!", AW88395_ACF_FILE); @@ -557,7 +560,7 @@ static int aw88395_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id aw88395_i2c_id[] = { - { AW88395_I2C_NAME }, + { .name = AW88395_I2C_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, aw88395_i2c_id); diff --git a/sound/soc/codecs/aw88395/aw88395_device.h b/sound/soc/codecs/aw88395/aw88395_device.h index 3626f222899d..7b74eeb84c43 100644 --- a/sound/soc/codecs/aw88395/aw88395_device.h +++ b/sound/soc/codecs/aw88395/aw88395_device.h @@ -152,7 +152,7 @@ struct aw_cali_desc { struct aw_container { int len; - u8 data[]; + u8 data[] __counted_by(len); }; struct aw_device { diff --git a/sound/soc/codecs/aw88399.c b/sound/soc/codecs/aw88399.c index b588c27909b5..b2ec3503f7e2 100644 --- a/sound/soc/codecs/aw88399.c +++ b/sound/soc/codecs/aw88399.c @@ -2146,7 +2146,7 @@ static int aw88399_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id aw88399_i2c_id[] = { - { AW88399_I2C_NAME }, + { .name = AW88399_I2C_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, aw88399_i2c_id); diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c index fb5b950e584c..371e99205b58 100644 --- a/sound/soc/codecs/cs-amp-lib.c +++ b/sound/soc/codecs/cs-amp-lib.c @@ -748,10 +748,7 @@ static const char *cs_amp_devm_get_dell_ssidex(struct device *dev, char *ssidex_buf __free(kfree) = cs_amp_alloc_get_efi_variable(DELL_SSIDEXV2_EFI_NAME, &DELL_SSIDEXV2_EFI_GUID, NULL); - ret = PTR_ERR_OR_ZERO(ssidex_buf); - if (ret == -ENOENT) - return ERR_PTR(-ENOENT); - else if (ret < 0) + if (IS_ERR(ssidex_buf)) return ssidex_buf; /* diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 0bb4bdb3deec..c835088de578 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -555,8 +555,8 @@ MODULE_DEVICE_TABLE(of, cs35l32_of_match); static const struct i2c_device_id cs35l32_id[] = { - {"cs35l32"}, - {} + { .name = "cs35l32" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l32_id); diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index 98b4d371d931..f49edb9ea1f2 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -1262,8 +1262,8 @@ static const struct of_device_id cs35l33_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l33_of_match); static const struct i2c_device_id cs35l33_id[] = { - {"cs35l33"}, - {} + { .name = "cs35l33" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l33_id); diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index a5a8075598ff..e80984b22159 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -1175,8 +1175,8 @@ static const struct of_device_id cs35l34_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l34_of_match); static const struct i2c_device_id cs35l34_id[] = { - {"cs35l34"}, - {} + { .name = "cs35l34" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l34_id); diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index 7a01b1d9fc9d..b2439ec3c19f 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -1639,8 +1639,8 @@ static const struct of_device_id cs35l35_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l35_of_match); static const struct i2c_device_id cs35l35_id[] = { - {"cs35l35"}, - {} + { .name = "cs35l35" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l35_id); diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index 93818d7ec1a7..89645327945f 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -1918,8 +1918,8 @@ static const struct of_device_id cs35l36_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l36_of_match); static const struct i2c_device_id cs35l36_id[] = { - {"cs35l36"}, - {} + { .name = "cs35l36" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l36_id); diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c index 34097996b784..23f59f3025bd 100644 --- a/sound/soc/codecs/cs35l41-i2c.c +++ b/sound/soc/codecs/cs35l41-i2c.c @@ -20,11 +20,11 @@ #include "cs35l41.h" static const struct i2c_device_id cs35l41_id_i2c[] = { - { "cs35l40" }, - { "cs35l41" }, - { "cs35l51" }, - { "cs35l53" }, - {} + { .name = "cs35l40" }, + { .name = "cs35l41" }, + { .name = "cs35l51" }, + { .name = "cs35l53" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l41_id_i2c); diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index a09aa3b92ae1..3eba61e107a5 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -53,8 +53,8 @@ static const struct of_device_id cs35l45_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l45_of_match); static const struct i2c_device_id cs35l45_id_i2c[] = { - { "cs35l45" }, - {} + { .name = "cs35l45" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l45_id_i2c); diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c index 0492ddc4102d..0f64ab628b03 100644 --- a/sound/soc/codecs/cs35l56-i2c.c +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -72,9 +72,9 @@ static void cs35l56_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id cs35l56_id_i2c[] = { - { "cs35l56", 0x3556 }, - { "cs35l63", 0x3563 }, - {} + { .name = "cs35l56", .driver_data = 0x3556 }, + { .name = "cs35l63", .driver_data = 0x3563 }, + { } }; MODULE_DEVICE_TABLE(i2c, cs35l56_id_i2c); diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c index 88e0aac540d6..0a55b93b96f9 100644 --- a/sound/soc/codecs/cs35l56-sdw.c +++ b/sound/soc/codecs/cs35l56-sdw.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "cs35l56.h" @@ -59,8 +60,6 @@ static int cs35l56_sdw_slow_read(struct sdw_slave *peripheral, unsigned int reg, { int ret, i; - reg += CS35L56_SDW_ADDR_OFFSET; - for (i = 0; i < val_size; i += sizeof(u32)) { /* Poll for bus bridge idle */ ret = cs35l56_sdw_poll_mem_status(peripheral, @@ -97,57 +96,23 @@ static int cs35l56_sdw_slow_read(struct sdw_slave *peripheral, unsigned int reg, return 0; } -static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf) -{ - int ret; - - ret = sdw_nread_no_pm(peripheral, reg, 4, (u8 *)buf); - if (ret != 0) { - dev_err(&peripheral->dev, "Read failed @%#x:%d\n", reg, ret); - return ret; - } - - swab32s((u32 *)buf); - - return 0; -} - static int cs35l56_sdw_read(void *context, const void *reg_buf, const size_t reg_size, void *val_buf, size_t val_size) { struct sdw_slave *peripheral = context; - u8 *buf8 = val_buf; - unsigned int reg, bytes; + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + unsigned int reg_addr = get_unaligned_le32(reg_buf); int ret; - reg = le32_to_cpu(*(const __le32 *)reg_buf); + if (cs35l56_is_otp_register(reg_addr - CS35L56_SDW_ADDR_OFFSET)) + return cs35l56_sdw_slow_read(peripheral, reg_addr, (u8 *)val_buf, val_size); - if (cs35l56_is_otp_register(reg)) - return cs35l56_sdw_slow_read(peripheral, reg, buf8, val_size); + ret = regmap_raw_read(cs35l56->sdw_bus_regmap, reg_addr, val_buf, val_size); + if (ret) + return ret; - reg += CS35L56_SDW_ADDR_OFFSET; - - if (val_size == 4) - return cs35l56_sdw_read_one(peripheral, reg, val_buf); - - while (val_size) { - bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ - if (bytes > val_size) - bytes = val_size; - - ret = sdw_nread_no_pm(peripheral, reg, bytes, buf8); - if (ret != 0) { - dev_err(&peripheral->dev, "Read failed @%#x..%#x:%d\n", - reg, reg + bytes - 1, ret); - return ret; - } - - swab32_array((u32 *)buf8, bytes / 4); - val_size -= bytes; - reg += bytes; - buf8 += bytes; - } + swab32_array((u32 *)val_buf, val_size / sizeof(u32)); return 0; } @@ -161,58 +126,34 @@ static inline void cs35l56_swab_copy(void *dest, const void *src, size_t nbytes) *dest32++ = swab32(*src32++); } -static int cs35l56_sdw_write_one(struct sdw_slave *peripheral, unsigned int reg, const void *buf) -{ - u32 val_le = swab32(*(u32 *)buf); - int ret; - - ret = sdw_nwrite_no_pm(peripheral, reg, 4, (u8 *)&val_le); - if (ret != 0) { - dev_err(&peripheral->dev, "Write failed @%#x:%d\n", reg, ret); - return ret; - } - - return 0; -} - static int cs35l56_sdw_gather_write(void *context, const void *reg_buf, size_t reg_size, const void *val_buf, size_t val_size) { struct sdw_slave *peripheral = context; - const u8 *src_be = val_buf; - u32 val_le_buf[64]; /* Define u32 so it is 32-bit aligned */ - unsigned int reg, bytes; + struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); + unsigned int reg_addr = get_unaligned_le32(reg_buf); + u32 swab_buf[64]; /* Define u32 so it is 32-bit aligned */ int ret; - reg = le32_to_cpu(*(const __le32 *)reg_buf); - reg += CS35L56_SDW_ADDR_OFFSET; - - if (val_size == 4) - return cs35l56_sdw_write_one(peripheral, reg, src_be); - - while (val_size) { - bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */ - if (bytes > val_size) - bytes = val_size; - if (bytes > sizeof(val_le_buf)) - bytes = sizeof(val_le_buf); - - cs35l56_swab_copy(val_le_buf, src_be, bytes); - - ret = sdw_nwrite_no_pm(peripheral, reg, bytes, (u8 *)val_le_buf); - if (ret != 0) { - dev_err(&peripheral->dev, "Write failed @%#x..%#x:%d\n", - reg, reg + bytes - 1, ret); + while (val_size > sizeof(swab_buf)) { + cs35l56_swab_copy(swab_buf, val_buf, sizeof(swab_buf)); + ret = regmap_raw_write(cs35l56->sdw_bus_regmap, reg_addr, + swab_buf, sizeof(swab_buf)); + if (ret) return ret; - } - val_size -= bytes; - reg += bytes; - src_be += bytes; + val_size -= sizeof(swab_buf); + reg_addr += sizeof(swab_buf); + val_buf += sizeof(swab_buf); } - return 0; + if (val_size == 0) + return 0; + + cs35l56_swab_copy(swab_buf, val_buf, val_size); + + return regmap_raw_write(cs35l56->sdw_bus_regmap, reg_addr, swab_buf, val_size); } static int cs35l56_sdw_write(void *context, const void *val_buf, size_t val_size) @@ -231,7 +172,7 @@ static int cs35l56_sdw_write(void *context, const void *val_buf, size_t val_size * byte controls always have the same byte order, and firmware file blobs * can be written verbatim. */ -static const struct regmap_bus cs35l56_regmap_bus_sdw = { +static const struct regmap_bus cs35l56_regmap_swab_bus_sdw = { .read = cs35l56_sdw_read, .write = cs35l56_sdw_write, .gather_write = cs35l56_sdw_gather_write, @@ -239,6 +180,18 @@ static const struct regmap_bus cs35l56_regmap_bus_sdw = { .val_format_endian_default = REGMAP_ENDIAN_BIG, }; +/* Low-level SoundWire regmap to transfer the data over the bus */ +static const struct regmap_config cs35l56_sdw_bus_regmap = { + .name = "sdw-le32", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + .max_register = CS35L56_DSP1_PMEM_5114 + 0x8000, + .cache_type = REGCACHE_NONE, +}; + static int cs35l56_sdw_get_unique_id(struct cs35l56_private *cs35l56) { int ret; @@ -277,11 +230,8 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral) * cs35l56_init can return with !init_done if it triggered * a soft reset. */ - if (cs35l56->base.init_done) { - /* Enable SoundWire interrupts */ - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); - } + if (cs35l56->base.init_done) + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); out: pm_runtime_put_autosuspend(cs35l56->base.dev); @@ -306,15 +256,11 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral, pm_runtime_get_noresume(cs35l56->base.dev); /* - * Mask and clear until it has been handled. The read of GEN_INT_STAT_1 - * is required as per the SoundWire spec for interrupt status bits - * to clear. GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1. + * Mask and clear until it has been handled. * None of the interrupts are time-critical so use the * power-efficient queue. */ - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); + cs35l56_mask_soundwire_interrupts(peripheral); queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work); return 0; @@ -330,8 +276,7 @@ static void cs35l56_sdw_irq_work(struct work_struct *work) /* unmask interrupts */ if (!cs35l56->sdw_irq_no_unmask) - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); pm_runtime_put_autosuspend(cs35l56->base.dev); } @@ -385,7 +330,6 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, switch (status) { case SDW_SLAVE_ATTACHED: - cs35l56->sdw_in_clock_stop_1 = false; if (cs35l56->sdw_attached) break; @@ -407,57 +351,29 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral, return 0; } -static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, - enum sdw_clk_stop_mode mode, - enum sdw_clk_stop_type type) -{ - struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); - - dev_dbg(cs35l56->base.dev, "%s: clock_stop_mode%d stage:%d\n", __func__, mode, type); - - switch (type) { - case SDW_CLK_POST_PREPARE: - if (mode == SDW_CLK_STOP_MODE1) - cs35l56->sdw_in_clock_stop_1 = true; - else - cs35l56->sdw_in_clock_stop_1 = false; - return 0; - default: - return 0; - } -} - static const struct sdw_slave_ops cs35l56_sdw_ops = { .read_prop = cs35l56_sdw_read_prop, .interrupt_callback = cs35l56_sdw_interrupt, .update_status = cs35l56_sdw_update_status, - .clk_stop = cs35l56_sdw_clk_stop, }; static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs35l56) { struct sdw_slave *peripheral = cs35l56->sdw_peripheral; + int ret; - dev_dbg(cs35l56->base.dev, "attached:%u unattach_request:%u in_clock_stop_1:%u\n", - cs35l56->sdw_attached, peripheral->unattach_request, cs35l56->sdw_in_clock_stop_1); + dev_dbg(cs35l56->base.dev, "attached:%u unattach_request:%u\n", + cs35l56->sdw_attached, peripheral->unattach_request); - if (cs35l56->sdw_in_clock_stop_1 || peripheral->unattach_request) { - /* Cannot access registers until bus is re-initialized. */ - dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n"); - if (!wait_for_completion_timeout(&peripheral->initialization_complete, - msecs_to_jiffies(5000))) { - dev_err(cs35l56->base.dev, "initialization_complete timed out\n"); - return -ETIMEDOUT; - } + /* Cannot access registers until bus is re-initialized. */ + ret = sdw_slave_wait_for_init(peripheral, 5000); + if (ret) + return ret; - peripheral->unattach_request = 0; - cs35l56->sdw_in_clock_stop_1 = false; - - /* - * Don't call regcache_mark_dirty(), we can't be sure that the - * Manager really did issue a Bus Reset. - */ - } + /* + * Don't call regcache_mark_dirty(), we can't be sure that the + * Manager really did issue a Bus Reset. + */ return 0; } @@ -490,9 +406,7 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev) if (ret) return ret; - /* Re-enable SoundWire interrupts */ - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); return 0; } @@ -504,18 +418,7 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev) if (!cs35l56->base.init_done) return 0; - /* - * Disable SoundWire interrupts. - * Flush - don't cancel because that could leave an unbalanced pm_runtime_get. - */ - cs35l56->sdw_irq_no_unmask = true; - flush_work(&cs35l56->sdw_irq_work); - - /* Mask interrupts and flush in case sdw_irq_work was queued again */ - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - flush_work(&cs35l56->sdw_irq_work); + cs35l56_disable_sdw_interrupts(cs35l56); return cs35l56_system_suspend(dev); } @@ -562,8 +465,16 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi cs35l56->base.type = ((unsigned int)id->driver_data) & 0xff; - cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw, - peripheral, regmap_config); + /* Low-level regmap to transfer read/writes over SoundWire bus */ + cs35l56->sdw_bus_regmap = devm_regmap_init_sdw(peripheral, &cs35l56_sdw_bus_regmap); + if (IS_ERR(cs35l56->sdw_bus_regmap)) { + ret = PTR_ERR(cs35l56->sdw_bus_regmap); + return dev_err_probe(dev, ret, "Failed to allocate bus register map\n"); + } + + /* Wrapper regmap to simulate big-endian ordering */ + cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_swab_bus_sdw, + peripheral, regmap_config); if (IS_ERR(cs35l56->base.regmap)) { ret = PTR_ERR(cs35l56->base.regmap); return dev_err_probe(dev, ret, "Failed to allocate register map\n"); @@ -583,13 +494,7 @@ static void cs35l56_sdw_remove(struct sdw_slave *peripheral) { struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); - /* Disable SoundWire interrupts */ - cs35l56->sdw_irq_no_unmask = true; - flush_work(&cs35l56->sdw_irq_work); - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - flush_work(&cs35l56->sdw_irq_work); + cs35l56_disable_sdw_interrupts(cs35l56); cs35l56_remove(cs35l56); } diff --git a/sound/soc/codecs/cs35l56-shared-test.c b/sound/soc/codecs/cs35l56-shared-test.c index cfe7938065f9..4f52c8a192e5 100644 --- a/sound/soc/codecs/cs35l56-shared-test.c +++ b/sound/soc/codecs/cs35l56-shared-test.c @@ -29,6 +29,7 @@ struct cs35l56_shared_test_priv { struct faux_device *gpio_dev; struct cs35l56_shared_test_mock_gpio *gpio_priv; struct regmap *registers; + unsigned int reg_offset; struct cs35l56_base *cs35l56_base; u8 applied_pad_pull_state[CS35L56_MAX_GPIO]; }; @@ -194,6 +195,8 @@ static int cs35l56_shared_test_reg_read(void *context, unsigned int reg, unsigne { struct cs35l56_shared_test_priv *priv = context; + reg -= priv->reg_offset; + switch (reg) { case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG: case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1: @@ -214,6 +217,8 @@ static int cs35l56_shared_test_reg_write(void *context, unsigned int reg, unsign { struct cs35l56_shared_test_priv *priv = context; + reg -= priv->reg_offset; + switch (reg) { case CS35L56_UPDATE_REGS: return cs35l56_shared_test_updt_gpio_pres(priv, reg, val); @@ -673,6 +678,7 @@ static int cs35l56_shared_test_case_base_init(struct kunit *test, u8 type, u8 re priv->cs35l56_base->rev = rev; if (regmap_config) { + priv->reg_offset = regmap_config->reg_base; ret = cs35l56_shared_test_case_regmap_init(test, regmap_config); if (ret) return ret; diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 795e2764d67e..f14e2eaaa4ee 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -534,6 +534,7 @@ static void cs35l56_spi_system_reset(struct cs35l56_base *cs35l56_base) * The regmap must remain in cache-only until the chip has * booted, so use a bypassed read. */ + val = 0; ret = read_poll_timeout(regmap_read_bypassed, read_ret, (val > 0) && (val < 0xffffffff), CS35L56_HALO_STATE_POLL_US, @@ -1259,7 +1260,7 @@ ssize_t cs35l56_cal_data_debugfs_write(struct cs35l56_base *cs35l56_base, return -EMSGSIZE; ret = simple_write_to_buffer(&cal_data, sizeof(cal_data), ppos, from, count); - if (ret) + if (ret < 0) return ret; ret = cs35l56_stash_calibration(cs35l56_base, &cal_data); @@ -1293,6 +1294,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_create_cal_debugfs, "SND_SOC_CS35L56_SHARED"); void cs35l56_remove_cal_debugfs(struct cs35l56_base *cs35l56_base) { debugfs_remove_recursive(cs35l56_base->debugfs); + cs35l56_base->debugfs = ERR_PTR(-ENOENT); } EXPORT_SYMBOL_NS_GPL(cs35l56_remove_cal_debugfs, "SND_SOC_CS35L56_SHARED"); @@ -1880,6 +1882,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, "SND_SOC_CS35L56_SHARED"); const struct regmap_config cs35l56_regmap_sdw = { .reg_bits = 32, + .reg_base = 0x8000, .val_bits = 32, .reg_stride = 4, .reg_format_endian = REGMAP_ENDIAN_LITTLE, @@ -1915,6 +1918,7 @@ const struct regmap_config cs35l63_regmap_sdw = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .reg_base = 0x8000, .reg_format_endian = REGMAP_ENDIAN_LITTLE, .val_format_endian = REGMAP_ENDIAN_BIG, .max_register = CS35L56_DSP1_PMEM_5114, diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 4fbbdcc87151..570a68829ccd 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -37,6 +37,49 @@ #include "wm_adsp.h" #include "cs35l56.h" +void cs35l56_mask_soundwire_interrupts(struct sdw_slave *peripheral) +{ + /* + * The read of GEN_INT_STAT_1 is required as per the SoundWire spec + * for interrupt status bits to clear. + * GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1. + */ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); + sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1); + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_mask_soundwire_interrupts, "SND_SOC_CS35L56_CORE"); + +void cs35l56_unmask_soundwire_interrupts(struct sdw_slave *peripheral) +{ + sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, CS35L56_SDW_INT_MASK_CODEC_IRQ); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_unmask_soundwire_interrupts, "SND_SOC_CS35L56_CORE"); + +void cs35l56_disable_sdw_interrupts(struct cs35l56_private *cs35l56) +{ + if (!cs35l56->sdw_peripheral) + return; + + cs35l56->sdw_irq_no_unmask = true; + flush_work(&cs35l56->sdw_irq_work); + + /* Mask interrupts and flush in case sdw_irq_work was queued again */ + cs35l56_mask_soundwire_interrupts(cs35l56->sdw_peripheral); + flush_work(&cs35l56->sdw_irq_work); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_disable_sdw_interrupts, "SND_SOC_CS35L56_CORE"); + +void cs35l56_enable_sdw_interrupts(struct cs35l56_private *cs35l56) +{ + if (!cs35l56->sdw_peripheral) + return; + + cs35l56->sdw_irq_no_unmask = false; + cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral); +} +EXPORT_SYMBOL_NS_GPL(cs35l56_enable_sdw_interrupts, "SND_SOC_CS35L56_CORE"); + static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); @@ -426,6 +469,8 @@ static unsigned int cs35l56_make_tdm_config_word(unsigned int reg_val, unsigned reg_val &= ~(0x3f << channel_shift); reg_val |= bit_num << channel_shift; channel_shift += 8; + if (channel_shift > 24) + break; } return reg_val; @@ -788,14 +833,7 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing * Setting sdw_irq_no_unmask prevents the handler re-enabling * the SoundWire interrupt. */ - if (cs35l56->sdw_peripheral) { - cs35l56->sdw_irq_no_unmask = true; - flush_work(&cs35l56->sdw_irq_work); - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0); - sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1); - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF); - flush_work(&cs35l56->sdw_irq_work); - } + cs35l56_disable_sdw_interrupts(cs35l56); ret = cs35l56_firmware_shutdown(&cs35l56->base); if (ret) @@ -847,12 +885,7 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing err_unlock: mutex_unlock(&cs35l56->base.irq_lock); err: - /* Re-enable SoundWire interrupts */ - if (cs35l56->sdw_peripheral) { - cs35l56->sdw_irq_no_unmask = false; - sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, - CS35L56_SDW_INT_MASK_CODEC_IRQ); - } + cs35l56_enable_sdw_interrupts(cs35l56); } static void cs35l56_dsp_work(struct work_struct *work) @@ -1326,7 +1359,7 @@ VISIBLE_IF_KUNIT int cs35l56_set_fw_name(struct snd_soc_component *component) } EXPORT_SYMBOL_IF_KUNIT(cs35l56_set_fw_name); -static int cs35l56_component_probe(struct snd_soc_component *component) +static int _cs35l56_component_probe(struct snd_soc_component *component) { struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); @@ -1426,6 +1459,17 @@ static void cs35l56_component_remove(struct snd_soc_component *component) cs35l56->component = NULL; } +static int cs35l56_component_probe(struct snd_soc_component *component) +{ + int ret; + + ret = _cs35l56_component_probe(component); + if (ret < 0) + cs35l56_component_remove(component); + + return ret; +} + static int cs35l56_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { @@ -1480,6 +1524,7 @@ static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev) int cs35l56_system_suspend(struct device *dev) { struct cs35l56_private *cs35l56 = dev_get_drvdata(dev); + int ret; dev_dbg(dev, "system_suspend\n"); @@ -1495,7 +1540,11 @@ int cs35l56_system_suspend(struct device *dev) if (cs35l56->base.irq) disable_irq(cs35l56->base.irq); - return pm_runtime_force_suspend(dev); + ret = pm_runtime_force_suspend(dev); + if ((ret < 0) && cs35l56->base.irq) + enable_irq(cs35l56->base.irq); + + return ret; } EXPORT_SYMBOL_GPL(cs35l56_system_suspend); @@ -1964,11 +2013,14 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); if (ret < 0) { dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n"); - goto err; + goto err_remove_wm_adsp; } return 0; +err_remove_wm_adsp: + wm_adsp2_remove(&cs35l56->dsp); + err: gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); @@ -1994,7 +2046,8 @@ int cs35l56_init(struct cs35l56_private *cs35l56) if (cs35l56->base.init_done) return 0; - pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 100); + pm_runtime_set_autosuspend_delay(cs35l56->base.dev, + CS35L56_FW_REQ_ACTIVE_TIMEOUT_MS + 50); pm_runtime_use_autosuspend(cs35l56->base.dev); pm_runtime_set_active(cs35l56->base.dev); pm_runtime_enable(cs35l56->base.dev); @@ -2076,6 +2129,8 @@ void cs35l56_remove(struct cs35l56_private *cs35l56) destroy_workqueue(cs35l56->dsp_wq); + wm_adsp2_remove(&cs35l56->dsp); + pm_runtime_dont_use_autosuspend(cs35l56->base.dev); pm_runtime_suspend(cs35l56->base.dev); pm_runtime_disable(cs35l56->base.dev); diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h index cd71b23b2a3a..9acd2e7e17c9 100644 --- a/sound/soc/codecs/cs35l56.h +++ b/sound/soc/codecs/cs35l56.h @@ -37,12 +37,12 @@ struct cs35l56_private { struct snd_soc_component *component; struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; struct sdw_slave *sdw_peripheral; + struct regmap *sdw_bus_regmap; const char *fallback_fw_suffix; struct work_struct sdw_irq_work; bool sdw_irq_no_unmask; bool soft_resetting; bool sdw_attached; - bool sdw_in_clock_stop_1; struct completion init_completion; int speaker_id; @@ -65,6 +65,11 @@ static inline struct cs35l56_private *cs35l56_private_from_base(struct cs35l56_b extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; +void cs35l56_mask_soundwire_interrupts(struct sdw_slave *peripheral); +void cs35l56_unmask_soundwire_interrupts(struct sdw_slave *peripheral); +void cs35l56_disable_sdw_interrupts(struct cs35l56_private *cs35l56); +void cs35l56_enable_sdw_interrupts(struct cs35l56_private *cs35l56); + int cs35l56_system_suspend(struct device *dev); int cs35l56_system_suspend_late(struct device *dev); int cs35l56_system_suspend_no_irq(struct device *dev); diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 3f759c13d6d1..286d5ca29854 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -638,7 +638,7 @@ static const struct of_device_id cs4265_of_match[] = { MODULE_DEVICE_TABLE(of, cs4265_of_match); static const struct i2c_device_id cs4265_id[] = { - { "cs4265" }, + { .name = "cs4265" }, { } }; MODULE_DEVICE_TABLE(i2c, cs4265_id); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index a48980e746ff..47cb10eb21bb 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -732,8 +732,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client) * cs4270_id - I2C device IDs supported by this driver */ static const struct i2c_device_id cs4270_id[] = { - {"cs4270"}, - {} + { .name = "cs4270" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs4270_id); diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c index 1d210b969173..869a5317f677 100644 --- a/sound/soc/codecs/cs4271-i2c.c +++ b/sound/soc/codecs/cs4271-i2c.c @@ -23,7 +23,7 @@ static int cs4271_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id cs4271_i2c_id[] = { - { "cs4271" }, + { .name = "cs4271" }, { } }; MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c index 98b6718ccabf..c0942f28723b 100644 --- a/sound/soc/codecs/cs42l42-i2c.c +++ b/sound/soc/codecs/cs42l42-i2c.c @@ -78,8 +78,8 @@ static const struct acpi_device_id __maybe_unused cs42l42_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match); static const struct i2c_device_id cs42l42_id[] = { - {"cs42l42"}, - {} + { .name = "cs42l42" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs42l42_id); diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c index d5999ad9ff9b..b8256ce0b8fb 100644 --- a/sound/soc/codecs/cs42l42-sdw.c +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -433,19 +433,16 @@ static const struct reg_sequence cs42l42_soft_reboot_seq[] = { static int cs42l42_sdw_handle_unattach(struct cs42l42_private *cs42l42) { struct sdw_slave *peripheral = cs42l42->sdw_peripheral; + int ret; if (!peripheral->unattach_request) return 0; /* Cannot access registers until master re-attaches. */ dev_dbg(&peripheral->dev, "Wait for initialization_complete\n"); - if (!wait_for_completion_timeout(&peripheral->initialization_complete, - msecs_to_jiffies(5000))) { - dev_err(&peripheral->dev, "initialization_complete timed out\n"); - return -ETIMEDOUT; - } - - peripheral->unattach_request = 0; + ret = sdw_slave_wait_for_init(peripheral, 5000); + if (ret) + return ret; /* * After a bus reset there must be a reconfiguration reset to diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c index 3e04e6897b14..934666295ee3 100644 --- a/sound/soc/codecs/cs42l43-jack.c +++ b/sound/soc/codecs/cs42l43-jack.c @@ -805,7 +805,7 @@ irqreturn_t cs42l43_tip_sense(int irq, void *data) if (priv->suspend_jack_debounce) db_delay += priv->tip_fall_db_ms + priv->tip_rise_db_ms; - queue_delayed_work(system_long_wq, &priv->tip_sense_work, + queue_delayed_work(system_dfl_long_wq, &priv->tip_sense_work, msecs_to_jiffies(db_delay)); return IRQ_HANDLED; @@ -932,7 +932,8 @@ int cs42l43_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); if (!override) { - queue_delayed_work(system_long_wq, &priv->tip_sense_work, 0); + queue_delayed_work(system_dfl_long_wq, &priv->tip_sense_work, + 0); } else { override--; diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index ba7e237619f2..a20a1030c498 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -14,7 +14,7 @@ #include "cs42l51.h" static const struct i2c_device_id cs42l51_i2c_id[] = { - { "cs42l51" }, + { .name = "cs42l51" }, { } }; MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id); diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 662dc1a4835b..9d6bcfbbf0b2 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1226,7 +1226,7 @@ MODULE_DEVICE_TABLE(of, cs42l52_of_match); static const struct i2c_device_id cs42l52_id[] = { - { "cs42l52" }, + { .name = "cs42l52" }, { } }; MODULE_DEVICE_TABLE(i2c, cs42l52_id); diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index aabb74f1f43c..4d9a22a1029c 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1353,7 +1353,7 @@ MODULE_DEVICE_TABLE(of, cs42l56_of_match); static const struct i2c_device_id cs42l56_id[] = { - { "cs42l56" }, + { .name = "cs42l56" }, { } }; MODULE_DEVICE_TABLE(i2c, cs42l56_id); diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index bda8442c1d66..6ddc6549492a 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1369,8 +1369,8 @@ static const struct of_device_id cs42l73_of_match[] = { MODULE_DEVICE_TABLE(of, cs42l73_of_match); static const struct i2c_device_id cs42l73_id[] = { - {"cs42l73"}, - {} + { .name = "cs42l73" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs42l73_id); diff --git a/sound/soc/codecs/cs42l84.c b/sound/soc/codecs/cs42l84.c index e590a43559e4..f2a58163de0e 100644 --- a/sound/soc/codecs/cs42l84.c +++ b/sound/soc/codecs/cs42l84.c @@ -1101,8 +1101,8 @@ static const struct of_device_id cs42l84_of_match[] = { MODULE_DEVICE_TABLE(of, cs42l84_of_match); static const struct i2c_device_id cs42l84_id[] = { - { "cs42l84" }, - {} + { .name = "cs42l84" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs42l84_id); diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c index 0faca384073a..31debe2d8231 100644 --- a/sound/soc/codecs/cs42xx8-i2c.c +++ b/sound/soc/codecs/cs42xx8-i2c.c @@ -49,9 +49,9 @@ static const struct of_device_id cs42xx8_of_match[] = { MODULE_DEVICE_TABLE(of, cs42xx8_of_match); static const struct i2c_device_id cs42xx8_i2c_id[] = { - {"cs42448", (kernel_ulong_t)&cs42448_data}, - {"cs42888", (kernel_ulong_t)&cs42888_data}, - {} + { .name = "cs42448", .driver_data = (kernel_ulong_t)&cs42448_data }, + { .name = "cs42888", .driver_data = (kernel_ulong_t)&cs42888_data }, + { } }; MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id); diff --git a/sound/soc/codecs/cs42xx8-spi.c b/sound/soc/codecs/cs42xx8-spi.c new file mode 100644 index 000000000000..b86fe2fe771e --- /dev/null +++ b/sound/soc/codecs/cs42xx8-spi.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Cirrus Logic CS42448/CS42888 Audio CODEC DAI SPI driver + * + * Copyright 2026 NXP + * + */ + +#include +#include +#include +#include +#include +#include + +#include "cs42xx8.h" + +/* + * CS42448/CS42888 SPI register access (from datasheet Figure 23): + * + * The SPI frame is 3 bytes: + * Byte 0: chip address [7:1] = 1001111, bit[0] = R/W (0=write, 1=read) + * Write: 0x9E, Read: 0x9F + * Byte 1: MAP - Memory Address Pointer + * bit[7] = INCR (auto-increment for burst), bits[6:0] = address + * Byte 2: data byte + * + * We configure reg_bits=16 so that regmap treats the address field as 2 bytes + * (big-endian). The chip address byte (0x9E/0x9F) is placed in the high byte + * via write_flag_mask / read_flag_mask, and the MAP register address occupies + * the low byte. Currently INCR (MAP bit[7]) is not set and use_single_read/write + * are enabled. This produces the correct 3-byte on-wire frame without any + * custom bus implementation: + * + * write: [0x9E, MAP_addr, data] + * read: [0x9F, MAP_addr] -> [data] + */ + +static int cs42xx8_spi_probe(struct spi_device *spi) +{ + struct cs42xx8_driver_data *drvdata; + struct regmap_config config; + int ret; + + drvdata = (struct cs42xx8_driver_data *)spi_get_device_match_data(spi); + if (!drvdata) + return dev_err_probe(&spi->dev, -EINVAL, + "failed to find driver data\n"); + + config = cs42xx8_regmap_config; + /* + * reg_bits=16 makes regmap send a 2-byte address field (big-endian). + * write_flag_mask/read_flag_mask are OR'd into that address field: + */ + config.reg_bits = 16; + config.write_flag_mask = 0x9E; + config.read_flag_mask = 0x9F; + + ret = cs42xx8_probe(&spi->dev, + devm_regmap_init_spi(spi, &config), drvdata); + if (ret) + return ret; + + pm_runtime_enable(&spi->dev); + pm_request_idle(&spi->dev); + + return 0; +} + +static void cs42xx8_spi_remove(struct spi_device *spi) +{ + pm_runtime_disable(&spi->dev); +} + +static const struct of_device_id cs42xx8_of_match[] = { + { .compatible = "cirrus,cs42448", .data = &cs42448_data, }, + { .compatible = "cirrus,cs42888", .data = &cs42888_data, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, cs42xx8_of_match); + +static const struct spi_device_id cs42xx8_spi_id[] = { + { .name = "cs42448", .driver_data = (kernel_ulong_t)&cs42448_data }, + { .name = "cs42888", .driver_data = (kernel_ulong_t)&cs42888_data }, + { } +}; +MODULE_DEVICE_TABLE(spi, cs42xx8_spi_id); + +static struct spi_driver cs42xx8_spi_driver = { + .driver = { + .name = "cs42xx8", + .pm = pm_ptr(&cs42xx8_pm), + .of_match_table = cs42xx8_of_match, + }, + .probe = cs42xx8_spi_probe, + .remove = cs42xx8_spi_remove, + .id_table = cs42xx8_spi_id, +}; + +module_spi_driver(cs42xx8_spi_driver); + +MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec SPI Driver"); +MODULE_AUTHOR("Chancel Liu "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index 12fe9b3e2525..5b689549c74e 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -478,6 +478,9 @@ const struct regmap_config cs42xx8_regmap_config = { .volatile_reg = cs42xx8_volatile_register, .writeable_reg = cs42xx8_writeable_register, .cache_type = REGCACHE_MAPLE, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .use_single_read = true, + .use_single_write = true, }; EXPORT_SYMBOL_GPL(cs42xx8_regmap_config); diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index a3bdaac9c059..e7b06f962790 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -2753,11 +2753,11 @@ MODULE_DEVICE_TABLE(acpi, cs43130_acpi_match); static const struct i2c_device_id cs43130_i2c_id[] = { - {"cs43130"}, - {"cs4399"}, - {"cs43131"}, - {"cs43198"}, - {} + { .name = "cs43130" }, + { .name = "cs4399" }, + { .name = "cs43131" }, + { .name = "cs43198" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs43130_i2c_id); diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c index b726e22ef57d..a44e6b3c298e 100644 --- a/sound/soc/codecs/cs4341.c +++ b/sound/soc/codecs/cs4341.c @@ -248,7 +248,7 @@ static int cs4341_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id cs4341_i2c_id[] = { - { "cs4341" }, + { .name = "cs4341" }, { } }; MODULE_DEVICE_TABLE(i2c, cs4341_i2c_id); diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index d9a9c34fffe3..ced1270c4d68 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -358,8 +358,8 @@ static const struct of_device_id cs4349_of_match[] = { MODULE_DEVICE_TABLE(of, cs4349_of_match); static const struct i2c_device_id cs4349_i2c_id[] = { - {"cs4349"}, - {} + { .name = "cs4349" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs4349_i2c_id); diff --git a/sound/soc/codecs/cs530x-i2c.c b/sound/soc/codecs/cs530x-i2c.c index 52b02ceaa7e3..98cb61dd88c1 100644 --- a/sound/soc/codecs/cs530x-i2c.c +++ b/sound/soc/codecs/cs530x-i2c.c @@ -40,13 +40,13 @@ static const struct of_device_id cs530x_of_match[] = { MODULE_DEVICE_TABLE(of, cs530x_of_match); static const struct i2c_device_id cs530x_i2c_id[] = { - { "cs4282", CS4282 }, - { "cs4302", CS4302 }, - { "cs4304", CS4304 }, - { "cs4308", CS4308 }, - { "cs5302", CS5302 }, - { "cs5304", CS5304 }, - { "cs5308", CS5308 }, + { .name = "cs4282", .driver_data = CS4282 }, + { .name = "cs4302", .driver_data = CS4302 }, + { .name = "cs4304", .driver_data = CS4304 }, + { .name = "cs4308", .driver_data = CS4308 }, + { .name = "cs5302", .driver_data = CS5302 }, + { .name = "cs5304", .driver_data = CS5304 }, + { .name = "cs5308", .driver_data = CS5308 }, { } }; MODULE_DEVICE_TABLE(i2c, cs530x_i2c_id); diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 93ea2fb4dae9..511453b4c375 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -1083,8 +1083,8 @@ static const struct of_device_id cs53l30_of_match[] = { MODULE_DEVICE_TABLE(of, cs53l30_of_match); static const struct i2c_device_id cs53l30_id[] = { - { "cs53l30" }, - {} + { .name = "cs53l30" }, + { } }; MODULE_DEVICE_TABLE(i2c, cs53l30_id); diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index c0dc69ce4d0e..0dea84cd8ef2 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -236,7 +236,8 @@ static int v253_open(struct tty_struct *tty) /* Line discipline .close() */ static void v253_close(struct tty_struct *tty) { - struct snd_soc_component *component = tty->disc_data; + struct cx20442_codec *codec = tty->disc_data; + struct snd_soc_component *component = codec->component; struct cx20442_priv *cx20442; tty->disc_data = NULL; @@ -248,7 +249,7 @@ static void v253_close(struct tty_struct *tty) /* Prevent the codec driver from further accessing the modem */ cx20442->tty = NULL; - component->card->pop_time = 0; + codec->ready = false; } /* Line discipline .hangup() */ @@ -261,7 +262,8 @@ static void v253_hangup(struct tty_struct *tty) static void v253_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp, size_t count) { - struct snd_soc_component *component = tty->disc_data; + struct cx20442_codec *codec = tty->disc_data; + struct snd_soc_component *component = codec->component; struct cx20442_priv *cx20442; if (!component) @@ -274,7 +276,7 @@ static void v253_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp, /* Set up codec driver access to modem controls */ cx20442->tty = tty; - component->card->pop_time = 1; + codec->ready = true; } } @@ -375,7 +377,6 @@ static int cx20442_component_probe(struct snd_soc_component *component) cx20442->tty = NULL; snd_soc_component_set_drvdata(component, cx20442); - component->card->pop_time = 0; return 0; } diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h index bb897bcb2486..78ab1eab083e 100644 --- a/sound/soc/codecs/cx20442.h +++ b/sound/soc/codecs/cx20442.h @@ -8,6 +8,11 @@ #ifndef _CX20442_CODEC_H #define _CX20442_CODEC_H +struct cx20442_codec { + struct snd_soc_component *component; + bool ready; +}; + extern struct tty_ldisc_ops v253_ops; #endif diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index b0033bf9be3a..83c6cbd40804 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1681,9 +1681,9 @@ static void cx2072x_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id cx2072x_i2c_id[] = { - { "cx20721" }, - { "cx20723" }, - {} + { .name = "cx20721" }, + { .name = "cx20723" }, + { } }; MODULE_DEVICE_TABLE(i2c, cx2072x_i2c_id); diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 94e59546c2fe..4df1a25e318b 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1238,7 +1238,7 @@ static int da7210_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id da7210_i2c_id[] = { - { "da7210" }, + { .name = "da7210" }, { } }; MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 19f69a523f22..4bf91ab2553a 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1720,11 +1720,6 @@ static int da7213_set_component_pll(struct snd_soc_component *component, return _da7213_set_component_pll(component, pll_id, source, fref, fout); } -/* - * Select below from Sound Card, not Auto - * SND_SOC_DAIFMT_CBC_CFC - * SND_SOC_DAIFMT_CBP_CFP - */ static const u64 da7213_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_LEFT_J | @@ -2271,7 +2266,7 @@ static const struct dev_pm_ops da7213_pm = { }; static const struct i2c_device_id da7213_i2c_id[] = { - { "da7213" }, + { .name = "da7213" }, { } }; MODULE_DEVICE_TABLE(i2c, da7213_i2c_id); diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 5c80839704c7..93bd045ed870 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -3282,8 +3282,8 @@ static int da7218_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id da7218_i2c_id[] = { - { "da7217", DA7217_DEV_ID }, - { "da7218", DA7218_DEV_ID }, + { .name = "da7217", .driver_data = DA7217_DEV_ID }, + { .name = "da7218", .driver_data = DA7218_DEV_ID }, { } }; MODULE_DEVICE_TABLE(i2c, da7218_i2c_id); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index ec4059f381be..f0874d891e12 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -2712,7 +2712,7 @@ static int da7219_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id da7219_i2c_id[] = { - { "da7219", }, + { .name = "da7219" }, { } }; MODULE_DEVICE_TABLE(i2c, da7219_i2c_id); diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index 140e449d3ef4..12d1ac98461e 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1547,7 +1547,7 @@ static int da732x_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id da732x_i2c_id[] = { - { "da7320"}, + { .name = "da7320" }, { } }; MODULE_DEVICE_TABLE(i2c, da732x_i2c_id); diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index a52276e32f2f..a88c13533145 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1513,7 +1513,7 @@ static int da9055_i2c_probe(struct i2c_client *i2c) * and PMIC, which must be different to operate together. */ static const struct i2c_device_id da9055_i2c_id[] = { - { "da9055-codec" }, + { .name = "da9055-codec" }, { } }; MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); diff --git a/sound/soc/codecs/es8311.c b/sound/soc/codecs/es8311.c index 564af5c04dbb..6fe3ae41afbd 100644 --- a/sound/soc/codecs/es8311.c +++ b/sound/soc/codecs/es8311.c @@ -955,7 +955,7 @@ static int es8311_i2c_probe(struct i2c_client *i2c_client) } static const struct i2c_device_id es8311_id[] = { - { "es8311" }, + { .name = "es8311" }, { } }; MODULE_DEVICE_TABLE(i2c, es8311_id); diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 9245c33700de..6a428387e496 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -895,8 +895,8 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client) } static const struct i2c_device_id es8316_i2c_id[] = { - {"es8316" }, - {} + { .name = "es8316" }, + { } }; MODULE_DEVICE_TABLE(i2c, es8316_i2c_id); diff --git a/sound/soc/codecs/es8323.c b/sound/soc/codecs/es8323.c index 605375b154c8..d067f7bda03a 100644 --- a/sound/soc/codecs/es8323.c +++ b/sound/soc/codecs/es8323.c @@ -787,7 +787,7 @@ static int es8323_i2c_probe(struct i2c_client *i2c_client) } static const struct i2c_device_id es8323_i2c_id[] = { - { "es8323" }, + { .name = "es8323" }, { } }; MODULE_DEVICE_TABLE(i2c, es8323_i2c_id); diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index 55a65ef99208..a79b2da35099 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -1347,8 +1347,8 @@ static void es8326_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id es8326_i2c_id[] = { - {"es8326" }, - {} + { .name = "es8326" }, + { } }; MODULE_DEVICE_TABLE(i2c, es8326_i2c_id); diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c index 56bfbe9261ce..36a4987e1a59 100644 --- a/sound/soc/codecs/es8328-i2c.c +++ b/sound/soc/codecs/es8328-i2c.c @@ -16,8 +16,8 @@ #include "es8328.h" static const struct i2c_device_id es8328_id[] = { - { "es8328" }, - { "es8388" }, + { .name = "es8328" }, + { .name = "es8388" }, { } }; MODULE_DEVICE_TABLE(i2c, es8328_id); diff --git a/sound/soc/codecs/es8375.c b/sound/soc/codecs/es8375.c index 0b9406e93c0e..e8747bc24433 100644 --- a/sound/soc/codecs/es8375.c +++ b/sound/soc/codecs/es8375.c @@ -752,7 +752,7 @@ static void es8375_i2c_shutdown(struct i2c_client *i2c) } static const struct i2c_device_id es8375_id[] = { - {"es8375"}, + { .name = "es8375" }, { } }; MODULE_DEVICE_TABLE(i2c, es8375_id); diff --git a/sound/soc/codecs/es8389.c b/sound/soc/codecs/es8389.c index 449d9574b03a..3484c87853cb 100644 --- a/sound/soc/codecs/es8389.c +++ b/sound/soc/codecs/es8389.c @@ -1015,7 +1015,7 @@ MODULE_DEVICE_TABLE(of, es8389_if_dt_ids); #endif static const struct i2c_device_id es8389_i2c_id[] = { - {"es8389"}, + { .name = "es8389" }, { } }; MODULE_DEVICE_TABLE(i2c, es8389_i2c_id); diff --git a/sound/soc/codecs/es9356.c b/sound/soc/codecs/es9356.c new file mode 100644 index 000000000000..670e918b56a4 --- /dev/null +++ b/sound/soc/codecs/es9356.c @@ -0,0 +1,1142 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// es9356.c -- SoundWire codec driver +// +// Copyright(c) 2025 Everest Semiconductor Co., Ltd +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "es9356.h" + +struct es9356_sdw_priv { + struct sdw_slave *slave; + struct device *dev; + struct regmap *regmap; + struct snd_soc_component *component; + struct snd_soc_jack *hs_jack; + + /* lock for irq*/ + struct mutex disable_irq_lock; + + /* lock for pde*/ + struct mutex pde_lock; + + bool hw_init; + bool first_hw_init; + int jack_type; + bool disable_irq; + + struct delayed_work interrupt_handle_work; + struct delayed_work button_detect_work; + unsigned int sdca_status; +}; + +static int es9356_sdw_component_probe(struct snd_soc_component *component) +{ + struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component); + + es9356->component = component; + + return 0; +} + +static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -9600, 12, 0); +static const DECLARE_TLV_DB_SCALE(amic_gain_tlv, 0, 3, 0); +static const DECLARE_TLV_DB_SCALE(dmic_gain_tlv, 0, 6, 0); + +static const struct snd_kcontrol_new es9356_sdca_controls[] = { + SDCA_SINGLE_Q78_TLV("FU41 Left Playback Volume", + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_L), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU41 Right Playback Volume", + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_R), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU36 Left Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_L), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU36 Right Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_R), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU33 Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU33, ES9356_SDCA_CTL_FU_CH_GAIN, 0), + ES9356_GAIN_MIN, ES9356_AMIC_GAIN_MAX, ES9356_AMIC_GAIN_STEP, amic_gain_tlv), + SDCA_SINGLE_Q78_TLV("FU21 Left Playback Volume", + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_L), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU21 Right Playback Volume", + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_R), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU113 Left Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_L), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU113 Right Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_R), + ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv), + SDCA_SINGLE_Q78_TLV("FU11 Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU11, ES9356_SDCA_CTL_FU_CH_GAIN, 0), + ES9356_GAIN_MIN, ES9356_DMIC_GAIN_MAX, ES9356_DMIC_GAIN_STEP, dmic_gain_tlv), +}; + +static const char *const es9356_left_mux_txt[] = { + "Left", + "Right", +}; + +static const char *const es9356_right_mux_txt[] = { + "Right", + "Left", +}; + +static const struct soc_enum es9356_left_mux_enum = + SOC_ENUM_SINGLE(ES9356_DAC_SWAP, 1, + ARRAY_SIZE(es9356_left_mux_txt), es9356_left_mux_txt); +static const struct soc_enum es9356_right_mux_enum = + SOC_ENUM_SINGLE(ES9356_DAC_SWAP, 0, + ARRAY_SIZE(es9356_right_mux_txt), es9356_right_mux_txt); + +static const struct snd_kcontrol_new es9356_left_mux_controls = + SOC_DAPM_ENUM("Channel MUX", es9356_left_mux_enum); +static const struct snd_kcontrol_new es9356_right_mux_controls = + SOC_DAPM_ENUM("Channel MUX", es9356_right_mux_enum); + +static const struct snd_soc_dapm_widget es9356_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("HP"), + SND_SOC_DAPM_OUTPUT("SPK"), + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("PDM_DIN"), + + SND_SOC_DAPM_SUPPLY("DMIC Clock", ES9356_DMIC_GPIO, 1, 1, NULL, 0), + + SND_SOC_DAPM_AIF_IN("DP4RX", "DP4 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP1TX", "DP1 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_PGA("IF DP3RXL", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("IF DP3RXR", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_MUX("Left Channel MUX", SND_SOC_NOPM, 0, 0, &es9356_left_mux_controls), + SND_SOC_DAPM_MUX("Right Channel MUX", SND_SOC_NOPM, 0, 0, &es9356_right_mux_controls), + + SND_SOC_DAPM_DAC("FU 21 Left", NULL, + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1), + SND_SOC_DAPM_DAC("FU 21 Right", NULL, + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1), + SND_SOC_DAPM_DAC("FU 41 Left", NULL, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1), + SND_SOC_DAPM_DAC("FU 41 Right", NULL, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1), + SND_SOC_DAPM_DAC("FU 113 Left", NULL, + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1), + SND_SOC_DAPM_DAC("FU 113 Right", NULL, + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1), + SND_SOC_DAPM_DAC("FU 36 Left", NULL, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1), + SND_SOC_DAPM_DAC("FU 36 Right", NULL, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1), +}; + +static const struct snd_soc_dapm_route es9356_audio_map[] = { + {"FU 36 Left", NULL, "MIC1"}, + {"FU 36 Right", NULL, "MIC1"}, + {"DP2TX", NULL, "FU 36 Left"}, + {"DP2TX", NULL, "FU 36 Right"}, + + {"PDM_DIN", NULL, "DMIC Clock"}, + {"FU 113 Left", NULL, "PDM_DIN"}, + {"FU 113 Right", NULL, "PDM_DIN"}, + {"DP1TX", NULL, "FU 113 Left"}, + {"DP1TX", NULL, "FU 113 Right"}, + + {"FU 41 Left", NULL, "DP4RX"}, + {"FU 41 Right", NULL, "DP4RX"}, + + {"IF DP3RXL", NULL, "DP3RX"}, + {"IF DP3RXR", NULL, "DP3RX"}, + + {"Left Channel MUX", "Left", "IF DP3RXL"}, + {"Left Channel MUX", "Right", "IF DP3RXR"}, + {"Right Channel MUX", "Left", "IF DP3RXL"}, + {"Right Channel MUX", "Right", "IF DP3RXR"}, + + {"FU 21 Left", NULL, "Left Channel MUX"}, + {"FU 21 Right", NULL, "Right Channel MUX"}, + + {"SPK", NULL, "FU 21 Left"}, + {"SPK", NULL, "FU 21 Right"}, + + {"HP", NULL, "FU 41 Left"}, + {"HP", NULL, "FU 41 Right"}, +}; + +static int es9356_set_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *hs_jack, void *data) +{ + struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component); + int ret; + + es9356->hs_jack = hs_jack; + + /* we can only resume if the device was initialized at least once */ + if (!es9356->first_hw_init) + return 0; + + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret); + return ret; + } + /* pm_runtime not enabled yet */ + dev_info(component->dev, "%s: skipping jack init for now\n", __func__); + return 0; + } + + if (es9356->hs_jack) + sdw_write_no_pm(es9356->slave, SDW_SCP_SDCA_INTMASK1, + (SDW_SCP_SDCA_INTMASK_SDCA_7 | SDW_SCP_SDCA_INTMASK_SDCA_5 | SDW_SCP_SDCA_INTMASK_SDCA_1)); + + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + + return 0; +} +static const struct snd_soc_component_driver snd_soc_es9356_sdw_component = { + .probe = es9356_sdw_component_probe, + .controls = es9356_sdca_controls, + .num_controls = ARRAY_SIZE(es9356_sdca_controls), + .dapm_widgets = es9356_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(es9356_dapm_widgets), + .dapm_routes = es9356_audio_map, + .num_dapm_routes = ARRAY_SIZE(es9356_audio_map), + .set_jack = es9356_set_jack_detect, + .endianness = 1, +}; + +static int es9356_sdw_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static void es9356_sdw_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static int es9356_sdca_button(unsigned int *buffer) +{ + int cur_button = -1; + + if (*(buffer + 1) | *(buffer + 2)) + return -EINVAL; + switch (*buffer) { + case 0x00: + cur_button = 0; + break; + case 0x20: + cur_button = SND_JACK_BTN_4; + break; + case 0x10: + cur_button = SND_JACK_BTN_2; + break; + case 0x08: + cur_button = SND_JACK_BTN_1; + break; + case 0x02: + cur_button = SND_JACK_BTN_3; + break; + case 0x01: + cur_button = SND_JACK_BTN_0; + break; + default: + break; + } + + return cur_button; +} + +static int es9356_sdca_button_detect(struct es9356_sdw_priv *es9356) +{ + unsigned int btn_type = 0, offset, idx, val, owner; + unsigned int button[3]; + int ret; + + ret = regmap_read(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_HID, ES9356_SDCA_ENT_HID01, ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner); + if (ret < 0 || owner == 0x01) + return 0; + + ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID, &offset); + if (ret < 0) + goto button_det_end; + + for (idx = 0; idx < ARRAY_SIZE(button); idx++) { + ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID + offset + idx, &val); + if (ret < 0) + goto button_det_end; + button[idx] = val; + } + + btn_type = es9356_sdca_button(&button[0]); + +button_det_end: + if (owner == 0x00) + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_HID, ES9356_SDCA_ENT_HID01, ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01); + + return btn_type; +} + +static int es9356_sdca_headset_detect(struct es9356_sdw_priv *es9356) +{ + unsigned int reg; + int ret; + + ret = regmap_read(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_DETECTED_MODE, 0), ®); + + if (ret < 0) + goto io_error; + + switch (reg) { + case 0x00: + es9356->jack_type = 0; + break; + case 0x03: + es9356->jack_type = SND_JACK_HEADPHONE; + break; + case 0x04: + es9356->jack_type = SND_JACK_HEADSET; + break; + default: + es9356->jack_type = 0; + return -1; + } + + if (reg) { + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_SELECTED_MODE, 0), reg); + regmap_write(es9356->regmap, ES9356_HP_DETECTTIME, 0x75); + } else { + regmap_write(es9356->regmap, ES9356_HP_DETECTTIME, 0xa4); + } + + return 0; + +io_error: + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); + return ret; +} + +static void es9356_interrupt_handler(struct work_struct *work) +{ + struct es9356_sdw_priv *es9356 = + container_of(work, struct es9356_sdw_priv, interrupt_handle_work.work); + int ret, btn_type = 0; + + if (!es9356->hs_jack) + return; + + if (!es9356->component->card || !es9356->component->card->instantiated) + return; + + /* Handling different types of interrupts based on the mask bit */ + if (es9356->sdca_status & SDW_SCP_SDCA_INT_SDCA_7) { + btn_type = es9356_sdca_button_detect(es9356); + if (btn_type < 0) + return; + } else { + ret = es9356_sdca_headset_detect(es9356); + if (ret < 0) + return; + } + + if (es9356->jack_type != SND_JACK_HEADSET) + btn_type = 0; + + snd_soc_jack_report(es9356->hs_jack, es9356->jack_type | btn_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3 | + SND_JACK_BTN_4); + + if (btn_type) { + snd_soc_jack_report(es9356->hs_jack, es9356->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3 | + SND_JACK_BTN_4); + mod_delayed_work(system_power_efficient_wq, + &es9356->button_detect_work, msecs_to_jiffies(280)); + } +} + +static void es9356_button_detect_handler(struct work_struct *work) +{ + struct es9356_sdw_priv *es9356 = + container_of(work, struct es9356_sdw_priv, button_detect_work.work); + int ret, idx, btn_type = 0; + unsigned int reg, offset; + unsigned int button[3]; + + /* Check headset */ + ret = regmap_read(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_DETECTED_MODE, 0), ®); + + if (ret < 0) + goto io_error; + + if (reg == 0x04) { + ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID, &offset); + if (ret < 0) + goto io_error; + for (idx = 0; idx < ARRAY_SIZE(button); idx++) { + ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID + offset + idx, ®); + if (ret < 0) + goto io_error; + button[idx] = reg; + } + btn_type = es9356_sdca_button(&button[0]); + if (btn_type < 0) + return; + } + + snd_soc_jack_report(es9356->hs_jack, es9356->jack_type | btn_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3 | + SND_JACK_BTN_4); + + if (btn_type) { + snd_soc_jack_report(es9356->hs_jack, es9356->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3 | + SND_JACK_BTN_4); + mod_delayed_work(system_power_efficient_wq, + &es9356->button_detect_work, msecs_to_jiffies(280)); + } + + return; +io_error: + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); +} + +static int es9356_pde_transition_delay(struct es9356_sdw_priv *es9356, unsigned char func, + unsigned char entity, unsigned char ps) +{ + unsigned int retries = 10, val; + + /* waiting for Actual PDE becomes to PS0/PS3 */ + while (retries) { + regmap_read(es9356->regmap, + SDW_SDCA_CTL(func, entity, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val); + if (val == ps) + return 1; + + usleep_range(1000, 1500); + retries--; + } + if (!retries) { + dev_dbg(&es9356->slave->dev, "%s PDE is NOT %s", __func__, ps?"PS3":"PS0"); + } + return 0; +} + +static int es9356_power_state(struct snd_soc_dai *dai, unsigned char ps, unsigned int *rate) +{ + struct snd_soc_component *component = dai->component; + struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + unsigned char func, cs_entity, pde_entity; + int ret; + + switch (dai->id) { + case ES9356_DMIC: + func = FUNC_NUM_MIC; + cs_entity = ES9356_SDCA_ENT_CS113; + pde_entity = ES9356_SDCA_ENT_PDE11; + break; + case ES9356_AMP: + func = FUNC_NUM_AMP; + cs_entity = ES9356_SDCA_ENT_CS21; + pde_entity = ES9356_SDCA_ENT_PDE23; + break; + case ES9356_JACK_IN: + func = FUNC_NUM_UAJ; + cs_entity = ES9356_SDCA_ENT_CS36; + pde_entity = ES9356_SDCA_ENT_PDE34; + break; + case ES9356_JACK_OUT: + func = FUNC_NUM_UAJ; + cs_entity = ES9356_SDCA_ENT_CS41; + pde_entity = ES9356_SDCA_ENT_PDE47; + break; + default: + return -EINVAL; + } + + /* power state changes are not independent across functions */ + mutex_lock(&es9356->pde_lock); + ret = es9356_pde_transition_delay(es9356, func, pde_entity, ps?ps0:ps3); + if (ret) { + regmap_write(es9356->regmap, + SDW_SDCA_CTL(func, pde_entity, ES9356_SDCA_CTL_REQ_POWER_STATE, 0), ps?ps3:ps0); + es9356_pde_transition_delay(es9356, func, pde_entity, ps?ps3:ps0); + } else + dev_dbg(component->dev, "%s PDE is already %d\n", __func__, ps?ps0:ps3); + + mutex_unlock(&es9356->pde_lock); + + if (rate) + regmap_write(es9356->regmap, + SDW_SDCA_CTL(func, cs_entity, ES9356_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), *rate); + + return 0; +} + +static int es9356_sdw_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config = {0}; + struct sdw_port_config port_config = {0}; + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + unsigned char ps0 = 0x0; + unsigned int rate; + int ret; + + if (!sdw_stream) + return -EINVAL; + + if (!es9356->slave) + return -EINVAL; + + /* SoundWire specific configuration */ + snd_sdw_params_to_config(substream, params, &stream_config, &port_config); + + port_config.num = dai->id; + + ret = sdw_stream_add_slave(es9356->slave, &stream_config, + &port_config, 1, sdw_stream); + if (ret) { + dev_err(dai->dev, "Unable to configure port\n"); + return -EINVAL; + } + + switch (params_rate(params)) { + case 16000: + rate = ES9356_SDCA_RATE_16000HZ; + break; + case 44100: + rate = ES9356_SDCA_RATE_44100HZ; + break; + case 48000: + rate = ES9356_SDCA_RATE_48000HZ; + break; + case 96000: + rate = ES9356_SDCA_RATE_96000HZ; + break; + default: + dev_err(component->dev, "%s: Rate %d is not supported\n", + __func__, params_rate(params)); + return -EINVAL; + } + + ret = es9356_power_state(dai, ps0, &rate); + if (ret) { + dev_err(component->dev, "%s: Invalid dai id: %d\n", + __func__, dai->id); + return -EINVAL; + } + + return 0; +} + +static int es9356_sdw_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component); + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + unsigned char ps3 = 0x3; + int ret; + + if (!es9356->slave) + return -EINVAL; + + sdw_stream_remove_slave(es9356->slave, sdw_stream); + + ret = es9356_power_state(dai, ps3, NULL); + if (ret) { + dev_err(component->dev, "%s: Invalid dai id: %d\n", + __func__, dai->id); + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops es9356_sdw_ops = { + .hw_params = es9356_sdw_pcm_hw_params, + .hw_free = es9356_sdw_pcm_hw_free, + .set_stream = es9356_sdw_set_sdw_stream, + .shutdown = es9356_sdw_shutdown, +}; + +static struct snd_soc_dai_driver es9356_sdw_dai[] = { + { + .name = "es9356-sdp-aif4", + .id = ES9356_DMIC, + .capture = { + .stream_name = "DP1 Capture", + .channels_min = 1, + .channels_max = 2, + }, + .ops = &es9356_sdw_ops, + }, + { + .name = "es9356-sdp-aif2", + .id = ES9356_JACK_IN, + .capture = { + .stream_name = "DP2 Capture", + .channels_min = 1, + .channels_max = 2, + }, + .ops = &es9356_sdw_ops, + }, + { + .name = "es9356-sdp-aif3", + .id = ES9356_AMP, + .playback = { + .stream_name = "DP3 Playback", + .channels_min = 1, + .channels_max = 2, + }, + .ops = &es9356_sdw_ops, + }, + { + .name = "es9356-sdp-aif1", + .id = ES9356_JACK_OUT, + .playback = { + .stream_name = "DP4 Playback", + .channels_min = 1, + .channels_max = 2, + }, + .ops = &es9356_sdw_ops, + }, +}; + +static int es9356_sdca_mbq_size(struct device *dev, unsigned int reg) +{ + switch (reg) { + case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU33, ES9356_SDCA_CTL_FU_CH_GAIN, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU11, ES9356_SDCA_CTL_FU_CH_GAIN, 0): + return 2; + default: + return 1; + } +} + +static struct regmap_sdw_mbq_cfg es9356_mbq_config = { + .mbq_size = es9356_sdca_mbq_size, +}; + +static bool es9356_sdca_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ES9356_BUF_ADDR_HID: + case ES9356_HID_BYTE2: + case ES9356_HID_BYTE3: + case ES9356_HID_BYTE4: + case SDW_SDCA_CTL(FUNC_NUM_HID, ES9356_SDCA_ENT_HID01, ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER, 0): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_DETECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_SELECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_PDE23, ES9356_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_PDE23, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_PDE11, ES9356_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_PDE11, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE47, ES9356_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE47, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE34, ES9356_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE34, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0): + case ES9356_FLAGS_HP: + return true; + default: + return false; + } +} + +static const struct regmap_config es9356_sdca_regmap = { + .reg_bits = 32, + .val_bits = 16, + .volatile_reg = es9356_sdca_volatile_register, + .max_register = 0x45ffffff, + .cache_type = REGCACHE_MAPLE, + .use_single_read = true, + .use_single_write = true, +}; + +static void es9356_register_init(struct es9356_sdw_priv *es9356) +{ + regmap_write(es9356->regmap, ES9356_STATE, 0x02); + regmap_write(es9356->regmap, ES9356_ENDPOINT_MODE, 0x24); + regmap_write(es9356->regmap, ES9356_PRE_DIV_CTL, 0x00); + regmap_write(es9356->regmap, ES9356_ADC_OSR, 0x18); + regmap_write(es9356->regmap, ES9356_ADC_OSRGAIN, 0x13); + regmap_write(es9356->regmap, ES9356_DAC_OSR, 0x16); + regmap_write(es9356->regmap, ES9356_CLK_CTL, 0x0f); + regmap_write(es9356->regmap, ES9356_CSM_RESET, 0x01); + regmap_write(es9356->regmap, ES9356_CLK_SEL, 0x30); + + regmap_write(es9356->regmap, ES9356_DETCLK_CTL, 0x51); + regmap_write(es9356->regmap, ES9356_HP_TYPE, 0x10); + regmap_write(es9356->regmap, ES9356_MICBIAS_CTL, 0x10); + regmap_write(es9356->regmap, ES9356_HPDETECT_CTL, 0x07); + regmap_write(es9356->regmap, ES9356_ADC_ANA, 0x30); + regmap_write(es9356->regmap, ES9356_PGA_CTL, 0xa8); + regmap_write(es9356->regmap, ES9356_ADC_INT, 0xaa); + regmap_write(es9356->regmap, ES9356_ADC_LP, 0x19); + regmap_write(es9356->regmap, ES9356_VMID1SEL, 0xbc); + regmap_write(es9356->regmap, ES9356_VMID_TIME, 0x0b); + regmap_write(es9356->regmap, ES9356_STATE_TIME, 0xbb); + regmap_write(es9356->regmap, ES9356_HP_SPK_TIME, 0x77); + regmap_write(es9356->regmap, ES9356_HP_DETECTTIME, 0xa4); + regmap_write(es9356->regmap, ES9356_MICBIAS_SEL, 0x15); + regmap_write(es9356->regmap, ES9356_KEY_PRESS_TIME, 0xff); + regmap_write(es9356->regmap, ES9356_KEY_RELEASE_TIME, 0xff); + regmap_write(es9356->regmap, ES9356_KEY_HOLD_TIME, 0x0f); + regmap_write(es9356->regmap, ES9356_BTSEL_REF, 0x00); + regmap_write(es9356->regmap, ES9356_KEYD_DETECT, 0x18); + regmap_write(es9356->regmap, ES9356_MICBIAS_RES, 0x03); + regmap_write(es9356->regmap, ES9356_BUTTON_CHARGE, 0x00); + regmap_write(es9356->regmap, ES9356_CALIBRATION_TIME, 0x13); + regmap_write(es9356->regmap, ES9356_CALIBRATION_SETTING, 0xf4); + + regmap_write(es9356->regmap, ES9356_SPK_VOLUME, 0x33); + regmap_write(es9356->regmap, ES9356_DAC_VROI, 0x01); + regmap_write(es9356->regmap, ES9356_DAC_LP, 0x00); + regmap_write(es9356->regmap, ES9356_HP_IBIAS, 0x04); + regmap_write(es9356->regmap, ES9356_HP_LP, 0x03); + regmap_write(es9356->regmap, ES9356_SPKLDO_CTL, 0x65); + regmap_write(es9356->regmap, ES9356_SPKBIAS_COMP, 0x09); + regmap_write(es9356->regmap, ES9356_VMID1STL, 0x00); + regmap_write(es9356->regmap, ES9356_VMID2STL, 0x00); + regmap_write(es9356->regmap, ES9356_VSEL, 0xfc); + + regmap_write(es9356->regmap, ES9356_IBIASGEN, 0x10); + regmap_write(es9356->regmap, ES9356_ADC_AMIC_CTL, 0x0d); + regmap_write(es9356->regmap, ES9356_STATE, 0x0e); + regmap_write(es9356->regmap, ES9356_CSM_RESET, 0x00); + regmap_write(es9356->regmap, ES9356_HP_TYPE, 0x08); + + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME); + + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME); + + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME); + + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME); +} + +static int es9356_sdca_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev); + + if (es9356->hw_init) + return 0; + + es9356->disable_irq = false; + + regcache_cache_only(es9356->regmap, false); + + if (es9356->first_hw_init) { + regcache_cache_bypass(es9356->regmap, true); + } else { + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + es9356_register_init(es9356); + } + pm_runtime_get_noresume(&slave->dev); + + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_XU12, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT0, ES9356_SDCA_CTL_FUNC_STATUS, 0), 0x40); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_XU22, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT0, ES9356_SDCA_CTL_FUNC_STATUS, 0), 0x40); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_XU42, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_XU36, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01); + regmap_write(es9356->regmap, + SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT0, ES9356_SDCA_CTL_FUNC_STATUS, 0), 0x40); + + if (es9356->first_hw_init) { + regcache_cache_bypass(es9356->regmap, false); + regcache_mark_dirty(es9356->regmap); + } else + es9356->first_hw_init = true; + + es9356->hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + return 0; +} + +static int es9356_sdw_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev); + + if (status == SDW_SLAVE_UNATTACHED) { + es9356->hw_init = false; + cancel_delayed_work_sync(&es9356->interrupt_handle_work); + cancel_delayed_work_sync(&es9356->button_detect_work); + regcache_cache_only(es9356->regmap, true); + } + + if (status == SDW_SLAVE_ATTACHED) { + if (es9356->hs_jack) + sdw_write_no_pm(es9356->slave, SDW_SCP_SDCA_INTMASK1, + (SDW_SCP_SDCA_INTMASK_SDCA_7 | SDW_SCP_SDCA_INTMASK_SDCA_5 | SDW_SCP_SDCA_INTMASK_SDCA_1)); + } + + if (es9356->hw_init || status != SDW_SLAVE_ATTACHED) + return 0; + + return es9356_sdca_io_init(&slave->dev, slave); +} + +static int es9356_sdw_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval; + int i, j; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->paging_support = true; + + /* + * first we need to allocate memory for set bits in port lists + * the port allocation is completely arbitrary: + * DP0 is not supported + * DP3 and DP4 is sink + * DP1 and DP2 is source + */ + prop->source_ports = BIT(1) | BIT(2); + prop->sink_ports = BIT(3) | BIT(4); + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), + GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + j = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[j].num = bit; + dpn[j].type = SDW_DPN_FULL; + dpn[j].simple_ch_prep_sm = true; + j++; + } + + /* wake-up event */ + prop->wake_capable = 1; + + return 0; +} + +static int es9356_sdw_interrupt_callback(struct sdw_slave *slave, + struct sdw_slave_intr_status *status) +{ + struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev); + unsigned int sdca_cascade, scp_sdca_stat1 = 0; + int count = 0, retry = 3; + int ret, stat, reg; + + mutex_lock(&es9356->disable_irq_lock); + + ret = sdw_read_no_pm(es9356->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + es9356->sdca_status = ret; + + do { + reg = sdw_read_no_pm(es9356->slave, SDW_SCP_SDCA_INT1); + if (reg < 0) + goto io_error; + if (reg & SDW_SCP_SDCA_INTMASK_SDCA_1) { + ret = sdw_update_no_pm(es9356->slave, SDW_SCP_SDCA_INT1, + SDW_SCP_SDCA_INT_SDCA_1, SDW_SCP_SDCA_INT_SDCA_1); + if (ret < 0) + goto io_error; + } + + if (reg & SDW_SCP_SDCA_INTMASK_SDCA_5) { + ret = sdw_update_no_pm(es9356->slave, SDW_SCP_SDCA_INT1, + SDW_SCP_SDCA_INT_SDCA_5, SDW_SCP_SDCA_INT_SDCA_5); + if (ret < 0) + goto io_error; + } + + if (reg & SDW_SCP_SDCA_INTMASK_SDCA_7) { + ret = sdw_update_no_pm(es9356->slave, SDW_SCP_SDCA_INT1, + SDW_SCP_SDCA_INT_SDCA_7, SDW_SCP_SDCA_INT_SDCA_7); + if (ret < 0) + goto io_error; + } + + ret = sdw_read_no_pm(es9356->slave, SDW_DP0_INT); + if (ret < 0) + goto io_error; + sdca_cascade = ret & SDW_DP0_SDCA_CASCADE; + + ret = sdw_read_no_pm(es9356->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + scp_sdca_stat1 = ret & + (SDW_SCP_SDCA_INTMASK_SDCA_1 | SDW_SCP_SDCA_INTMASK_SDCA_5 | SDW_SCP_SDCA_INTMASK_SDCA_7); + + stat = scp_sdca_stat1 || sdca_cascade; + + count++; + } while (stat != 0 && count < retry); + + /* The 280 ms figure was determined through testing */ + if (status->sdca_cascade && !es9356->disable_irq) + mod_delayed_work(system_power_efficient_wq, + &es9356->interrupt_handle_work, msecs_to_jiffies(280)); + + mutex_unlock(&es9356->disable_irq_lock); + return 0; + +io_error: + mutex_unlock(&es9356->disable_irq_lock); + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); + return ret; +} + +static const struct sdw_slave_ops es9356_sdw_slave_ops = { + .read_prop = es9356_sdw_read_prop, + .interrupt_callback = es9356_sdw_interrupt_callback, + .update_status = es9356_sdw_update_status, +}; + +static int es9356_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave *slave) +{ + struct es9356_sdw_priv *es9356; + int ret; + + es9356 = devm_kzalloc(dev, sizeof(*es9356), GFP_KERNEL); + if (!es9356) + return -ENOMEM; + + dev_set_drvdata(dev, es9356); + + es9356->slave = slave; + es9356->regmap = regmap; + mutex_init(&es9356->disable_irq_lock); + mutex_init(&es9356->pde_lock); + + regcache_cache_only(es9356->regmap, true); + + es9356->hw_init = false; + es9356->first_hw_init = false; + + INIT_DELAYED_WORK(&es9356->interrupt_handle_work, + es9356_interrupt_handler); + INIT_DELAYED_WORK(&es9356->button_detect_work, + es9356_button_detect_handler); + + ret = devm_snd_soc_register_component(dev, + &snd_soc_es9356_sdw_component, + es9356_sdw_dai, + ARRAY_SIZE(es9356_sdw_dai)); + if (ret) { + dev_err_probe(dev, ret, "Failed to register component\n"); + return ret; + } + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(dev); + pm_runtime_enable(dev); + + return 0; +} + +static int es9356_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + + regmap = devm_regmap_init_sdw_mbq_cfg(&slave->dev, slave, &es9356_sdca_regmap, &es9356_mbq_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return es9356_sdca_init(&slave->dev, regmap, slave); +} + +static void es9356_sdw_remove(struct sdw_slave *slave) +{ + struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev); + + if (es9356->hw_init) { + cancel_delayed_work_sync(&es9356->interrupt_handle_work); + cancel_delayed_work_sync(&es9356->button_detect_work); + } + + if (es9356->first_hw_init) + pm_runtime_disable(&slave->dev); + + mutex_destroy(&es9356->disable_irq_lock); + mutex_destroy(&es9356->pde_lock); +} + +static const struct sdw_device_id es9356_sdw_id[] = { + SDW_SLAVE_ENTRY_EXT(0x04b3, 0x9356, 0x02, 0, 0), + SDW_SLAVE_ENTRY_EXT(0x04b3, 0x9356, 0x03, 0, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, es9356_sdw_id); + +static int es9356_sdca_dev_suspend(struct device *dev) +{ + struct es9356_sdw_priv *es9356 = dev_get_drvdata(dev); + + cancel_delayed_work_sync(&es9356->interrupt_handle_work); + cancel_delayed_work_sync(&es9356->button_detect_work); + + regcache_cache_only(es9356->regmap, true); + + return 0; +} + +static int es9356_sdca_dev_system_suspend(struct device *dev) +{ + struct es9356_sdw_priv *es9356 = dev_get_drvdata(dev); + + mutex_lock(&es9356->disable_irq_lock); + es9356->disable_irq = true; + mutex_unlock(&es9356->disable_irq_lock); + + return es9356_sdca_dev_suspend(dev); +} + +#define es9356_PROBE_TIMEOUT 2000 + +static int es9356_sdca_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct es9356_sdw_priv *es9356 = dev_get_drvdata(dev); + int ret; + + if (!slave->unattach_request) + es9356->disable_irq = false; + + ret = sdw_slave_wait_for_init(slave, es9356_PROBE_TIMEOUT); + if (ret) + return ret; + + regcache_cache_only(es9356->regmap, false); + regcache_sync(es9356->regmap); + return 0; +} + +static const struct dev_pm_ops es9356_sdca_pm = { + SYSTEM_SLEEP_PM_OPS(es9356_sdca_dev_system_suspend, es9356_sdca_dev_resume) + RUNTIME_PM_OPS(es9356_sdca_dev_suspend, es9356_sdca_dev_resume, NULL) +}; + +static struct sdw_driver es9356_sdw_driver = { + .driver = { + .name = "es9356", + .pm = pm_ptr(&es9356_sdca_pm), + }, + .probe = es9356_sdw_probe, + .remove = es9356_sdw_remove, + .ops = &es9356_sdw_slave_ops, + .id_table = es9356_sdw_id, +}; +module_sdw_driver(es9356_sdw_driver); + +MODULE_IMPORT_NS("SND_SOC_SDCA"); +MODULE_DESCRIPTION("ASoC ES9356 SDCA SDW codec driver"); +MODULE_AUTHOR("Michael Zhang "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/es9356.h b/sound/soc/codecs/es9356.h new file mode 100644 index 000000000000..2a676f36590f --- /dev/null +++ b/sound/soc/codecs/es9356.h @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ES9356_H__ +#define __ES9356_H__ + +/*ES9356 Implementation-define*/ +#define ES9356_FLAGS_HP 0x2003 +#define ES9356_CSM_RESET 0x2020 +#define ES9356_FUC_RESET 0x2021 +#define ES9356_STATE 0x2022 +#define ES9356_VMID_TIME 0x2023 +#define ES9356_STATE_TIME 0x2024 +#define ES9356_HP_SPK_TIME 0x2025 +#define ES9356_WP_ENABLE 0x2026 +#define ES9356_DMIC_GPIO 0x2027 +#define ES9356_ENDPOINT_MODE 0x2028 + +/*HP DETECT*/ +#define ES9356_HP_TYPE 0x2029 +#define ES9356_HP_DETECTTIME 0x202A +#define ES9356_MICBIAS_SEL 0x202B +#define ES9356_KEY_PRESS_TIME 0x202C +#define ES9356_KEY_RELEASE_TIME 0x202D +#define ES9356_KEY_HOLD_TIME 0x202E +#define ES9356_BTSEL_REF 0x202F +#define ES9356_BUTTON_CHARGE 0x2030 + +#define ES9356_KEYD_DETECT 0x2031 +#define ES9356_DPEN_TIME 0x2032 +#define ES9356_TIMER_CHECK 0x2033 +#define ES9356_IBIASGEN 0x2041 +#define ES9356_VMID1SEL 0x2042 +#define ES9356_VMID1STL 0x2043 +#define ES9356_VMID2SEL 0x2044 +#define ES9356_VMID2STL 0x2045 +#define ES9356_VSEL 0x2046 +#define ES9356_MICBIAS_CTL 0x2047 +#define ES9356_HPDETECT_CTL 0x2048 +#define ES9356_MICBIAS_RES 0x2049 + +/*CLK*/ +#define ES9356_CLK_SEL 0x2050 +#define ES9356_CLK_CTL 0x2051 +#define ES9356_DETCLK_CTL 0x2052 +#define ES9356_CPCLK_CTL 0x2053 +#define ES9356_SPKCLK_CTL 0x2054 +#define ES9356_PRE_DIV_CTL 0x2055 +#define ES9356_DLL_MODE 0x2056 +#define ES9356_ANACLK_SEL 0x2057 +#define ES9356_OSRCLK_SEL 0x2058 +#define ES9356_DSPCLK_SEL 0x2059 +#define ES9356_SPK9M_MODE 0x205a + +/*ADC DIG CTL*/ +#define ES9356_DMIC_POL 0x2061 +#define ES9356_ADC_SWAP 0x2062 +#define ES9356_ADC_OSR 0x2063 +#define ES9356_ADC_OSRGAIN 0x2064 +#define ES9356_ADC_CLEARRAM 0x2065 +#define ES9356_ADC_RAMP 0x2066 +#define ES9356_ADC_HPF1 0x2067 +#define ES9356_ADC_HPF2 0x2068 +#define ES9356_ADC_ALC 0x206C +#define ES9356_ALC_LEVEL 0x206D +#define ES9356_ALC_RAMP_WINSIZE 0x206E + +/*ADC ANA CTL*/ +#define ES9356_ADC_REF_EN 0x2080 +#define ES9356_ADC_AMIC_CTL 0x2081 +#define ES9356_ADC_ANA 0x2082 +#define ES9356_PGA_CTL 0x2083 +#define ES9356_ADC_INT 0x2084 +#define ES9356_ADC_VCM 0x2085 +#define ES9356_ADC_VRPBIAS 0x2086 +#define ES9356_ADC_LP 0x2087 + +/*DAC DIG CTL*/ +#define ES9356_DAC_FSMODE 0x2090 +#define ES9356_DAC_OSR 0x2091 +#define ES9356_DAC_INV 0x2092 +#define ES9356_DAC_RAMP 0x2093 +#define ES9356_DAC_VPPSCALE 0x2094 +#define ES9356_DAC_SWAP 0x2097 +#define ES9356_SPKCMP_VPPSC 0x20A0 +#define ES9356_CALIBRATION_TIME 0x20A1 +#define ES9356_CALIBRATION_SETTING 0x20A2 +#define ES9356_DAC_OFFSET_LH 0x20A3 +#define ES9356_DAC_OFFSET_LL 0x20A4 +#define ES9356_DAC_OFFSET_RH 0x20A5 +#define ES9356_DAC_OFFSET_RL 0x20A6 + +/*DAC ANA CTL*/ +#define ES9356_DAC_REF_EN 0x20B0 +#define ES9356_DAC_ENABLE 0x20B1 +#define ES9356_DAC_VROI 0x20B2 +#define ES9356_DAC_LP 0x20B3 + +/*HP CTL*/ +#define ES9356_CHARGEPUMP_CTL 0x20C0 +#define ES9356_CPLDO_CTL 0x20C1 +#define ES9356_HP_REF_CTL 0x20C2 +#define ES9356_HP_IBIAS 0x20C3 +#define ES9356_HP_EN 0x20C4 +#define ES9356_HP_VOLUME 0x20C5 +#define ES9356_HP_LP 0x20C6 + +/*SPK CTL*/ +#define ES9356_SPKLDO_CTL 0x20D0 +#define ES9356_CLASSD_CTL 0x20D1 +#define ES9356_SPK_HBDG 0x20D5 +#define ES9356_SPK_VOLUME 0x20D7 +#define ES9356_SPK_SCP 0x20D8 +#define ES9356_SPK_DT 0x20D9 +#define ES9356_SPK_OTP 0x20DA +#define ES9356_SPKBIAS_COMP 0x20DB + +/* ES9356 SDCA Control - function number */ +#define FUNC_NUM_UAJ 0x01 +#define FUNC_NUM_MIC 0x02 +#define FUNC_NUM_AMP 0x03 +#define FUNC_NUM_HID 0x04 + +/* ES9356 SDCA entity */ +#define ES9356_SDCA_ENT0 0x00 +#define ES9356_SDCA_ENT_PDE11 0x03 +#define ES9356_SDCA_ENT_FU11 0x04 +#define ES9356_SDCA_ENT_XU12 0x05 +#define ES9356_SDCA_ENT_FU113 0x07 +#define ES9356_SDCA_ENT_CS113 0x09 +#define ES9356_SDCA_ENT_PPU11 0x0C + +#define ES9356_SDCA_ENT_CS21 0x02 +#define ES9356_SDCA_ENT_PPU21 0x03 +#define ES9356_SDCA_ENT_FU21 0X04 +#define ES9356_SDCA_ENT_XU22 0x06 +#define ES9356_SDCA_ENT_SAPU29 0x03 +#define ES9356_SDCA_ENT_PDE23 0x0B +#define ES9356_SDCA_ENT_HID01 0x01 + +#define ES9356_SDCA_ENT_CS41 0x02 +#define ES9356_SDCA_ENT_FU35 0x04 +#define ES9356_SDCA_ENT_XU42 0x06 +#define ES9356_SDCA_ENT_FU41 0x07 +#define ES9356_SDCA_ENT_PDE47 0x0E +#define ES9356_SDCA_ENT_IT33 0x0F +#define ES9356_SDCA_ENT_PDE34 0x10 +#define ES9356_SDCA_ENT_FU33 0x11 +#define ES9356_SDCA_ENT_XU36 0x13 +#define ES9356_SDCA_ENT_FU36 0x15 +#define ES9356_SDCA_ENT_CS36 0x17 +#define ES9356_SDCA_ENT_GE35 0x18 + +/* ES9356 SDCA control */ +#define ES9356_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10 +#define ES9356_SDCA_CTL_FU_MUTE 0x01 +#define ES9356_SDCA_CTL_FU_VOLUME 0x02 +#define ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10 +#define ES9356_SDCA_CTL_SELECTED_MODE 0x01 +#define ES9356_SDCA_CTL_DETECTED_MODE 0x02 +#define ES9356_SDCA_CTL_REQ_POWER_STATE 0x01 +#define ES9356_SDCA_CTL_FU_CH_GAIN 0x0b +#define ES9356_SDCA_CTL_FUNC_STATUS 0x10 +#define ES9356_SDCA_CTL_ACTUAL_POWER_STATE 0x10 +#define ES9356_SDCA_CTL_POSTURE_NUMBER 0x00 + +/* ES9356 SDCA channel */ +#define CH_L 0x01 +#define CH_R 0x02 +#define MBQ 0x2000 + +/* ES9356 HID*/ +#define ES9356_BUF_ADDR_HID 0x44000000 +#define ES9356_HID_BYTE2 0x44000001 +#define ES9356_HID_BYTE3 0x44000002 +#define ES9356_HID_BYTE4 0x44000003 + +/* ES9356 Volume Setting*/ +#define ES9356_VU_BASE 768 +#define ES9356_OFFSET_HIGH 0x07F8 +#define ES9356_OFFSET_LOW 0x0007 +#define ES9356_DEFAULT_VOLUME 0x00 +#define ES9356_VOLUME_STEP 32 +#define ES9356_VOLUME_MIN -768 +#define ES9356_VOLUME_MAX 285 +#define ES9356_AMIC_GAIN_STEP 768 +#define ES9356_DMIC_GAIN_STEP 1536 +#define ES9356_GAIN_MIN 0 +#define ES9356_AMIC_GAIN_MAX 10 +#define ES9356_DMIC_GAIN_MAX 3 + +enum { + ES9356_DMIC = 1, /* For dmic */ + ES9356_JACK_IN, /* For headset mic */ + ES9356_AMP, /* For speaker */ + ES9356_JACK_OUT, /* For headphone */ +}; + +enum { + ES9356_SDCA_RATE_16000HZ, + ES9356_SDCA_RATE_24000HZ, + ES9356_SDCA_RATE_32000HZ, + ES9356_SDCA_RATE_44100HZ, + ES9356_SDCA_RATE_48000HZ, + ES9356_SDCA_RATE_88200HZ, + ES9356_SDCA_RATE_96000HZ, +}; + +#endif diff --git a/sound/soc/codecs/framer-codec.c b/sound/soc/codecs/framer-codec.c index 6f57a3aeecc8..a87a78390172 100644 --- a/sound/soc/codecs/framer-codec.c +++ b/sound/soc/codecs/framer-codec.c @@ -238,15 +238,13 @@ static int framer_dai_startup(struct snd_pcm_substream *substream, return 0; } -static const u64 framer_dai_formats[] = { - SND_SOC_POSSIBLE_DAIFMT_DSP_B, -}; +static const u64 framer_dai_formats = SND_SOC_POSSIBLE_DAIFMT_DSP_B; static const struct snd_soc_dai_ops framer_dai_ops = { .startup = framer_dai_startup, .set_tdm_slot = framer_dai_set_tdm_slot, - .auto_selectable_formats = framer_dai_formats, - .num_auto_selectable_formats = ARRAY_SIZE(framer_dai_formats), + .auto_selectable_formats = &framer_dai_formats, + .num_auto_selectable_formats = 1, }; static struct snd_soc_dai_driver framer_dai_driver = { diff --git a/sound/soc/codecs/fs210x.c b/sound/soc/codecs/fs210x.c index eda716f817b5..5f381fe063e8 100644 --- a/sound/soc/codecs/fs210x.c +++ b/sound/soc/codecs/fs210x.c @@ -1557,9 +1557,9 @@ static void fs210x_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id fs210x_i2c_id[] = { - { "fs2104" }, - { "fs2105s" }, - {} + { .name = "fs2104" }, + { .name = "fs2105s" }, + { } }; MODULE_DEVICE_TABLE(i2c, fs210x_i2c_id); diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 2652fcf2a3a3..3220f9226e0b 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -911,12 +911,14 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); struct hdac_hdmi_pcm *pcm; - const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]]; + const char *cvt_name; ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); if (ret < 0) return ret; + cvt_name = e->texts[ucontrol->value.enumerated.item[0]]; + if (port == NULL) return -EINVAL; diff --git a/sound/soc/codecs/idt821034.c b/sound/soc/codecs/idt821034.c index 39bafefa6a18..084090ccef77 100644 --- a/sound/soc/codecs/idt821034.c +++ b/sound/soc/codecs/idt821034.c @@ -860,18 +860,17 @@ static int idt821034_dai_startup(struct snd_pcm_substream *substream, return 0; } -static const u64 idt821034_dai_formats[] = { +static const u64 idt821034_dai_formats = SND_SOC_POSSIBLE_DAIFMT_DSP_A | - SND_SOC_POSSIBLE_DAIFMT_DSP_B, -}; + SND_SOC_POSSIBLE_DAIFMT_DSP_B; static const struct snd_soc_dai_ops idt821034_dai_ops = { .startup = idt821034_dai_startup, .hw_params = idt821034_dai_hw_params, .set_tdm_slot = idt821034_dai_set_tdm_slot, .set_fmt = idt821034_dai_set_fmt, - .auto_selectable_formats = idt821034_dai_formats, - .num_auto_selectable_formats = ARRAY_SIZE(idt821034_dai_formats), + .auto_selectable_formats = &idt821034_dai_formats, + .num_auto_selectable_formats = 1, }; static struct snd_soc_dai_driver idt821034_dai_driver = { diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index b7a94631d77d..fa1c23dda4eb 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -1133,7 +1133,7 @@ static int isabelle_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id isabelle_i2c_id[] = { - { "isabelle" }, + { .name = "isabelle" }, { } }; MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id); diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 26cdb750cbca..06add7fb6737 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -128,7 +128,7 @@ static int lm4857_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id lm4857_i2c_id[] = { - { "lm4857" }, + { .name = "lm4857" }, { } }; MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id); diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 043030509795..6e2e292d143b 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1443,7 +1443,7 @@ static int lm49453_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id lm49453_i2c_id[] = { - { "lm49453" }, + { .name = "lm49453" }, { } }; MODULE_DEVICE_TABLE(i2c, lm49453_i2c_id); diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index 7ad7a9fb7255..8621d9bdb9fd 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c @@ -213,7 +213,7 @@ static int max9768_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id max9768_i2c_id[] = { - { "max9768" }, + { .name = "max9768" }, { } }; MODULE_DEVICE_TABLE(i2c, max9768_i2c_id); diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 9f40ca4b60d5..df438baf05dc 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1722,8 +1722,8 @@ static const struct snd_soc_component_driver soc_component_dev_max98088 = { }; static const struct i2c_device_id max98088_i2c_id[] = { - { "max98088", MAX98088 }, - { "max98089", MAX98089 }, + { .name = "max98088", .driver_data = MAX98088 }, + { .name = "max98089", .driver_data = MAX98089 }, { } }; MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 13a15459040f..da416329b038 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2337,7 +2337,7 @@ static irqreturn_t max98090_interrupt(int irq, void *data) } /** - * max98090_mic_detect - Enable microphone detection via the MAX98090 IRQ + * max98090_set_jack - Enable microphone detection via the MAX98090 IRQ * * @component: MAX98090 component * @jack: jack to report detection events on @@ -2349,12 +2349,12 @@ static irqreturn_t max98090_interrupt(int irq, void *data) * * If no jack is supplied detection will be disabled. */ -int max98090_mic_detect(struct snd_soc_component *component, - struct snd_soc_jack *jack) +static int max98090_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) { struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); - dev_dbg(component->dev, "max98090_mic_detect\n"); + dev_dbg(component->dev, "%s\n", __func__); max98090->jack = jack; if (jack) { @@ -2377,7 +2377,6 @@ int max98090_mic_detect(struct snd_soc_component *component, return 0; } -EXPORT_SYMBOL_GPL(max98090_mic_detect); #define MAX98090_RATES SNDRV_PCM_RATE_8000_96000 #define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) @@ -2554,6 +2553,7 @@ static const struct snd_soc_component_driver soc_component_dev_max98090 = { .remove = max98090_remove, .seq_notifier = max98090_seq_notifier, .set_bias_level = max98090_set_bias_level, + .set_jack = max98090_set_jack, .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, @@ -2572,8 +2572,8 @@ static const struct regmap_config max98090_regmap = { }; static const struct i2c_device_id max98090_i2c_id[] = { - { "max98090", MAX98090 }, - { "max98091", MAX98091 }, + { .name = "max98090", .driver_data = MAX98090 }, + { .name = "max98091", .driver_data = MAX98091 }, { } }; MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h index 6ce8dd176e48..048af4a1376f 100644 --- a/sound/soc/codecs/max98090.h +++ b/sound/soc/codecs/max98090.h @@ -1543,7 +1543,4 @@ struct max98090_priv { bool shdn_pending; }; -int max98090_mic_detect(struct snd_soc_component *component, - struct snd_soc_jack *jack); - #endif diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index aae6423156e1..ced9bd4d94da 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -2109,7 +2109,7 @@ static const struct snd_soc_component_driver soc_component_dev_max98095 = { }; static const struct i2c_device_id max98095_i2c_id[] = { - { "max98095", MAX98095 }, + { .name = "max98095", .driver_data = MAX98095 }, { } }; MODULE_DEVICE_TABLE(i2c, max98095_i2c_id); diff --git a/sound/soc/codecs/max98363.c b/sound/soc/codecs/max98363.c index 25af78ab30d5..099dc5bf6195 100644 --- a/sound/soc/codecs/max98363.c +++ b/sound/soc/codecs/max98363.c @@ -90,24 +90,15 @@ static int max98363_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct max98363_priv *max98363 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!max98363->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, MAX98363_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(MAX98363_PROBE_TIMEOUT)); - if (!time) { - dev_err(dev, "Initialization not complete, timed out\n"); - return -ETIMEDOUT; - } - -regmap_sync: - - slave->unattach_request = 0; regcache_cache_only(max98363->regmap, false); regcache_sync(max98363->regmap); diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c index 852db211ba1e..c8d4c68af562 100644 --- a/sound/soc/codecs/max98371.c +++ b/sound/soc/codecs/max98371.c @@ -400,7 +400,7 @@ static int max98371_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98371_i2c_id[] = { - { "max98371" }, + { .name = "max98371" }, { } }; diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c index f58b8c8625a7..20de379d08de 100644 --- a/sound/soc/codecs/max98373-i2c.c +++ b/sound/soc/codecs/max98373-i2c.c @@ -576,8 +576,8 @@ static int max98373_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98373_i2c_id[] = { - { "max98373"}, - { }, + { .name = "max98373" }, + { } }; MODULE_DEVICE_TABLE(i2c, max98373_i2c_id); diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 16673440218c..6829fa07c9ec 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -266,25 +266,15 @@ static int max98373_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct max98373_priv *max98373 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!max98373->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, MAX98373_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(MAX98373_PROBE_TIMEOUT)); - if (!time) { - dev_err(dev, "Initialization not complete, timed out\n"); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(max98373->regmap, false); regcache_sync(max98373->regmap); diff --git a/sound/soc/codecs/max98388.c b/sound/soc/codecs/max98388.c index 076f15a9867e..2576841b7de2 100644 --- a/sound/soc/codecs/max98388.c +++ b/sound/soc/codecs/max98388.c @@ -977,8 +977,8 @@ static int max98388_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98388_i2c_id[] = { - { "max98388"}, - { }, + { .name = "max98388" }, + { } }; MODULE_DEVICE_TABLE(i2c, max98388_i2c_id); diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index 65f095c47191..2bbedf84ee5d 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -1096,8 +1096,8 @@ static int max98390_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98390_i2c_id[] = { - { "max98390"}, - {}, + { .name = "max98390" }, + { } }; MODULE_DEVICE_TABLE(i2c, max98390_i2c_id); diff --git a/sound/soc/codecs/max98396.c b/sound/soc/codecs/max98396.c index 18fd90227187..9c1d7213410c 100644 --- a/sound/soc/codecs/max98396.c +++ b/sound/soc/codecs/max98396.c @@ -1871,9 +1871,9 @@ static int max98396_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98396_i2c_id[] = { - { "max98396", CODEC_TYPE_MAX98396}, - { "max98397", CODEC_TYPE_MAX98397}, - { }, + { .name = "max98396", .driver_data = CODEC_TYPE_MAX98396 }, + { .name = "max98397", .driver_data = CODEC_TYPE_MAX98397 }, + { } }; MODULE_DEVICE_TABLE(i2c, max98396_i2c_id); diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 1fcbc64a2771..9bd6a61212c1 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -321,7 +321,7 @@ static int max9850_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max9850_i2c_id[] = { - { "max9850" }, + { .name = "max9850" }, { } }; MODULE_DEVICE_TABLE(i2c, max9850_i2c_id); diff --git a/sound/soc/codecs/max98504.c b/sound/soc/codecs/max98504.c index c94142768c81..8b2620eaf9b0 100644 --- a/sound/soc/codecs/max98504.c +++ b/sound/soc/codecs/max98504.c @@ -363,7 +363,7 @@ MODULE_DEVICE_TABLE(of, max98504_of_match); #endif static const struct i2c_device_id max98504_i2c_id[] = { - { "max98504" }, + { .name = "max98504" }, { } }; MODULE_DEVICE_TABLE(i2c, max98504_i2c_id); diff --git a/sound/soc/codecs/max98520.c b/sound/soc/codecs/max98520.c index 5bc3d95ade5a..4fb98505db1a 100644 --- a/sound/soc/codecs/max98520.c +++ b/sound/soc/codecs/max98520.c @@ -734,8 +734,8 @@ static int max98520_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98520_i2c_id[] = { - { "max98520"}, - { }, + { .name = "max98520" }, + { } }; MODULE_DEVICE_TABLE(i2c, max98520_i2c_id); diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 716d16daf7d7..0d7ac37850bb 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -709,7 +709,7 @@ static void max9860_remove(struct i2c_client *i2c) } static const struct i2c_device_id max9860_i2c_id[] = { - { "max9860", }, + { .name = "max9860" }, { } }; MODULE_DEVICE_TABLE(i2c, max9860_i2c_id); diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 9cad9b698cf2..07a53ec2a18a 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -689,7 +689,7 @@ static int max9867_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max9867_i2c_id[] = { - { "max9867" }, + { .name = "max9867" }, { } }; MODULE_DEVICE_TABLE(i2c, max9867_i2c_id); diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 1bd0d4761ca6..7cd07b6f9dd6 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c @@ -151,7 +151,7 @@ static int max9877_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id max9877_i2c_id[] = { - { "max9877" }, + { .name = "max9877" }, { } }; MODULE_DEVICE_TABLE(i2c, max9877_i2c_id); diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c index 124af6408d96..4302ab16a642 100644 --- a/sound/soc/codecs/max98925.c +++ b/sound/soc/codecs/max98925.c @@ -617,7 +617,7 @@ static int max98925_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98925_i2c_id[] = { - { "max98925" }, + { .name = "max98925" }, { } }; MODULE_DEVICE_TABLE(i2c, max98925_i2c_id); diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index ae962bda163e..5305e1f9d97f 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c @@ -565,7 +565,7 @@ static int max98926_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98926_i2c_id[] = { - { "max98926" }, + { .name = "max98926" }, { } }; MODULE_DEVICE_TABLE(i2c, max98926_i2c_id); diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 0e9b8970997c..65e6fdb30eec 100644 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -873,8 +873,8 @@ static void max98927_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id max98927_i2c_id[] = { - { "max98927"}, - { }, + { .name = "max98927" }, + { } }; MODULE_DEVICE_TABLE(i2c, max98927_i2c_id); diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index fad0cc902346..8a14626d43ff 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -573,7 +573,7 @@ static int ml26124_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ml26124_i2c_id[] = { - { "ml26124" }, + { .name = "ml26124" }, { } }; MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id); diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index ef63fd113cb7..21741afc80ef 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -557,8 +557,8 @@ static const struct of_device_id __maybe_unused mt6660_of_id[] = { MODULE_DEVICE_TABLE(of, mt6660_of_id); static const struct i2c_device_id mt6660_i2c_id[] = { - {"mt6660" }, - {}, + { .name = "mt6660" }, + { } }; MODULE_DEVICE_TABLE(i2c, mt6660_i2c_id); diff --git a/sound/soc/codecs/nau8325.c b/sound/soc/codecs/nau8325.c index 58ef5c493835..236d94c29c24 100644 --- a/sound/soc/codecs/nau8325.c +++ b/sound/soc/codecs/nau8325.c @@ -877,7 +877,7 @@ static int nau8325_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8325_i2c_ids[] = { - { "nau8325" }, + { .name = "nau8325" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8325_i2c_ids); diff --git a/sound/soc/codecs/nau8540.c b/sound/soc/codecs/nau8540.c index caf2edb23088..fefbd5722c00 100644 --- a/sound/soc/codecs/nau8540.c +++ b/sound/soc/codecs/nau8540.c @@ -965,7 +965,7 @@ static int nau8540_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8540_i2c_ids[] = { - { "nau8540" }, + { .name = "nau8540" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8540_i2c_ids); diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index 9870e62d372e..a050387dd485 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -896,9 +896,9 @@ static int nau8810_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8810_i2c_id[] = { - { "nau8810" }, - { "nau8812" }, - { "nau8814" }, + { .name = "nau8810" }, + { .name = "nau8812" }, + { .name = "nau8814" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8810_i2c_id); diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index ffb526de0021..c45c5b864ea4 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -1968,7 +1968,7 @@ static int nau8821_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8821_i2c_ids[] = { - { "nau8821" }, + { .name = "nau8821" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8821_i2c_ids); diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index a11759f85eac..830164e991a7 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,10 @@ static const struct reg_default nau8822_reg_defaults[] = { { NAU8822_REG_OUTPUT_TIEOFF, 0x0000 }, }; +static const char * const nau8822_supply_names[NAU8822_NUM_SUPPLIES] = { + "vdda", "vddb", "vddc", "vddspk", +}; + static bool nau8822_readable_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -1056,6 +1061,7 @@ static int nau8822_suspend(struct snd_soc_component *component) struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); snd_soc_dapm_force_bias_level(dapm, SND_SOC_BIAS_OFF); + regulator_bulk_disable(NAU8822_NUM_SUPPLIES, nau8822->supplies); regcache_mark_dirty(nau8822->regmap); @@ -1066,6 +1072,15 @@ static int nau8822_resume(struct snd_soc_component *component) { struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + int ret = regulator_bulk_enable(NAU8822_NUM_SUPPLIES, nau8822->supplies); + + if (ret) { + dev_err(component->dev, + "Failed to enable regulators: %d\n", ret); + return ret; + } + + fsleep(100); regcache_sync(nau8822->regmap); @@ -1153,7 +1168,7 @@ static int nau8822_i2c_probe(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct nau8822 *nau8822 = dev_get_platdata(dev); - int ret; + int ret, i; if (!nau8822) { nau8822 = devm_kzalloc(dev, sizeof(*nau8822), GFP_KERNEL); @@ -1167,6 +1182,13 @@ static int nau8822_i2c_probe(struct i2c_client *i2c) return dev_err_probe(&i2c->dev, PTR_ERR(nau8822->mclk), "Error getting mclk\n"); + for (i = 0; i < NAU8822_NUM_SUPPLIES; i++) + nau8822->supplies[i].supply = nau8822_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, NAU8822_NUM_SUPPLIES, nau8822->supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to get regulators\n"); + nau8822->regmap = devm_regmap_init_i2c(i2c, &nau8822_regmap_config); if (IS_ERR(nau8822->regmap)) { ret = PTR_ERR(nau8822->regmap); @@ -1175,25 +1197,42 @@ static int nau8822_i2c_probe(struct i2c_client *i2c) } nau8822->dev = dev; + ret = regulator_bulk_enable(NAU8822_NUM_SUPPLIES, nau8822->supplies); + if (ret) + return dev_err_probe(dev, ret, "Failed to enable regulators\n"); + + fsleep(100); + /* Reset the codec */ ret = regmap_write(nau8822->regmap, NAU8822_REG_RESET, 0x00); if (ret != 0) { dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); - return ret; + goto err_reg; } ret = devm_snd_soc_register_component(dev, &soc_component_dev_nau8822, &nau8822_dai, 1); if (ret != 0) { dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); - return ret; + goto err_reg; } return 0; + +err_reg: + regulator_bulk_disable(NAU8822_NUM_SUPPLIES, nau8822->supplies); + return ret; +} + +static void nau8822_i2c_remove(struct i2c_client *i2c) +{ + struct nau8822 *nau8822 = i2c_get_clientdata(i2c); + + regulator_bulk_disable(NAU8822_NUM_SUPPLIES, nau8822->supplies); } static const struct i2c_device_id nau8822_i2c_id[] = { - { "nau8822" }, + { .name = "nau8822" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8822_i2c_id); @@ -1212,6 +1251,7 @@ static struct i2c_driver nau8822_i2c_driver = { .of_match_table = of_match_ptr(nau8822_of_match), }, .probe = nau8822_i2c_probe, + .remove = nau8822_i2c_remove, .id_table = nau8822_i2c_id, }; module_i2c_driver(nau8822_i2c_driver); diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h index 13fe0a091e9e..24799c7b5931 100644 --- a/sound/soc/codecs/nau8822.h +++ b/sound/soc/codecs/nau8822.h @@ -211,6 +211,8 @@ struct nau8822_pll { int freq_out; }; +#define NAU8822_NUM_SUPPLIES 4 + /* Codec Private Data */ struct nau8822 { struct device *dev; @@ -219,6 +221,7 @@ struct nau8822 { struct nau8822_pll pll; int sysclk; int div_id; + struct regulator_bulk_data supplies[NAU8822_NUM_SUPPLIES]; }; #endif /* __NAU8822_H__ */ diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c index 6ce763762443..426a488ff2a3 100644 --- a/sound/soc/codecs/nau8824.c +++ b/sound/soc/codecs/nau8824.c @@ -2020,7 +2020,7 @@ static int nau8824_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8824_i2c_ids[] = { - { "nau8824" }, + { .name = "nau8824" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8824_i2c_ids); diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index dd3528537ae4..ae83b778bf93 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -712,8 +712,8 @@ static void nau8825_xtalk_measure(struct nau8825 *nau8825) /* In left headphone IMM state, read out left headphone * impedance measure result, and delay some time to wait * detection sine wave output finish. Then, we can calculate - * the cross talk suppresstion side tone according to the L/R - * headphone imedance. + * the cross talk suppression side tone according to the L/R + * headphone impedance. */ regmap_read(nau8825->regmap, NAU8825_REG_IMM_RMS_L, &nau8825->imp_rms[NAU8825_XTALK_HPL_R2L]); @@ -2237,7 +2237,7 @@ static void nau8825_component_remove(struct snd_soc_component *component) { struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component); - /* Cancel and reset cross tak suppresstion detection funciton */ + /* Cancel and reset cross talk suppression detection function */ nau8825_xtalk_cancel(nau8825); } @@ -2651,7 +2651,7 @@ static int nau8825_set_bias_level(struct snd_soc_component *component, /* ground HPL/HPR, MICGRND1/2 */ regmap_update_bits(nau8825->regmap, NAU8825_REG_HSD_CTRL, 0xf, 0xf); - /* Cancel and reset cross talk detection funciton */ + /* Cancel and reset cross talk detection function */ nau8825_xtalk_cancel(nau8825); /* Turn off all interruptions before system shutdown. Keep the * interruption quiet before resume setup completes. @@ -2930,11 +2930,8 @@ static int nau8825_i2c_probe(struct i2c_client *i2c) &nau8825_dai, 1); } -static void nau8825_i2c_remove(struct i2c_client *client) -{} - static const struct i2c_device_id nau8825_i2c_ids[] = { - { "nau8825" }, + { .name = "nau8825" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8825_i2c_ids); @@ -2962,7 +2959,6 @@ static struct i2c_driver nau8825_driver = { .acpi_match_table = ACPI_PTR(nau8825_acpi_match), }, .probe = nau8825_i2c_probe, - .remove = nau8825_i2c_remove, .id_table = nau8825_i2c_ids, }; module_i2c_driver(nau8825_driver); diff --git a/sound/soc/codecs/ntp8835.c b/sound/soc/codecs/ntp8835.c index 2b93bea11752..5837b9379fee 100644 --- a/sound/soc/codecs/ntp8835.c +++ b/sound/soc/codecs/ntp8835.c @@ -454,8 +454,8 @@ static int ntp8835_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ntp8835_i2c_id[] = { - { "ntp8835" }, - {} + { .name = "ntp8835" }, + { } }; MODULE_DEVICE_TABLE(i2c, ntp8835_i2c_id); diff --git a/sound/soc/codecs/ntp8918.c b/sound/soc/codecs/ntp8918.c index 5593d48ef696..a18d79aa80aa 100644 --- a/sound/soc/codecs/ntp8918.c +++ b/sound/soc/codecs/ntp8918.c @@ -370,8 +370,8 @@ static int ntp8918_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ntp8918_i2c_id[] = { - { "ntp8918" }, - {} + { .name = "ntp8918" }, + { } }; MODULE_DEVICE_TABLE(i2c, ntp8918_i2c_id); diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index f4e5f3133f2b..cb923cecb47f 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -290,8 +290,8 @@ static const struct snd_soc_component_driver soc_component_dev_pcm1681 = { }; static const struct i2c_device_id pcm1681_i2c_id[] = { - {"pcm1681"}, - {} + { .name = "pcm1681" }, + { } }; MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id); diff --git a/sound/soc/codecs/pcm1789-i2c.c b/sound/soc/codecs/pcm1789-i2c.c index abadf4f8ed5e..4f1bb13fd4c3 100644 --- a/sound/soc/codecs/pcm1789-i2c.c +++ b/sound/soc/codecs/pcm1789-i2c.c @@ -41,7 +41,7 @@ MODULE_DEVICE_TABLE(of, pcm1789_of_match); #endif static const struct i2c_device_id pcm1789_i2c_ids[] = { - { "pcm1789" }, + { .name = "pcm1789" }, { } }; MODULE_DEVICE_TABLE(i2c, pcm1789_i2c_ids); diff --git a/sound/soc/codecs/pcm179x-i2c.c b/sound/soc/codecs/pcm179x-i2c.c index effc1dd6df22..5337bcc7c62c 100644 --- a/sound/soc/codecs/pcm179x-i2c.c +++ b/sound/soc/codecs/pcm179x-i2c.c @@ -38,7 +38,7 @@ MODULE_DEVICE_TABLE(of, pcm179x_of_match); #endif static const struct i2c_device_id pcm179x_i2c_ids[] = { - { "pcm179x" }, + { .name = "pcm179x" }, { } }; MODULE_DEVICE_TABLE(i2c, pcm179x_i2c_ids); diff --git a/sound/soc/codecs/pcm186x-i2c.c b/sound/soc/codecs/pcm186x-i2c.c index a50f9f6e39c1..3bd9d557e3c2 100644 --- a/sound/soc/codecs/pcm186x-i2c.c +++ b/sound/soc/codecs/pcm186x-i2c.c @@ -23,10 +23,10 @@ static const struct of_device_id pcm186x_of_match[] = { MODULE_DEVICE_TABLE(of, pcm186x_of_match); static const struct i2c_device_id pcm186x_i2c_id[] = { - { "pcm1862", PCM1862 }, - { "pcm1863", PCM1863 }, - { "pcm1864", PCM1864 }, - { "pcm1865", PCM1865 }, + { .name = "pcm1862", .driver_data = PCM1862 }, + { .name = "pcm1863", .driver_data = PCM1863 }, + { .name = "pcm1864", .driver_data = PCM1864 }, + { .name = "pcm1865", .driver_data = PCM1865 }, { } }; MODULE_DEVICE_TABLE(i2c, pcm186x_i2c_id); diff --git a/sound/soc/codecs/pcm3168a-i2c.c b/sound/soc/codecs/pcm3168a-i2c.c index ff18c74b616c..334f344761aa 100644 --- a/sound/soc/codecs/pcm3168a-i2c.c +++ b/sound/soc/codecs/pcm3168a-i2c.c @@ -33,7 +33,7 @@ static void pcm3168a_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id pcm3168a_i2c_id[] = { - { "pcm3168a", }, + { .name = "pcm3168a" }, { } }; MODULE_DEVICE_TABLE(i2c, pcm3168a_i2c_id); diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index c8617a488b11..cb6a6f08f2f8 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -563,12 +563,6 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, } static const u64 pcm3168a_dai_formats[] = { - /* - * Select below from Sound Card, not here - * SND_SOC_DAIFMT_CBC_CFC - * SND_SOC_DAIFMT_CBP_CFP - */ - /* * First Priority */ @@ -581,6 +575,8 @@ static const u64 pcm3168a_dai_formats[] = { * see * pcm3168a_hw_params() */ + SND_SOC_POSSIBLE_DAIFMT_I2S | + SND_SOC_POSSIBLE_DAIFMT_LEFT_J | SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | SND_SOC_POSSIBLE_DAIFMT_DSP_A | SND_SOC_POSSIBLE_DAIFMT_DSP_B, @@ -799,7 +795,6 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap) pm_runtime_set_active(dev); pm_runtime_enable(dev); - pm_runtime_idle(dev); memcpy(pcm3168a->dai_drv, pcm3168a_dais, sizeof(pcm3168a->dai_drv)); ret = devm_snd_soc_register_component(dev, &pcm3168a_driver, @@ -822,15 +817,6 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap) } EXPORT_SYMBOL_GPL(pcm3168a_probe); -static void pcm3168a_disable(struct device *dev) -{ - struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); - - regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), - pcm3168a->supplies); - clk_disable_unprepare(pcm3168a->scki); -} - void pcm3168a_remove(struct device *dev) { struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev); @@ -842,10 +828,12 @@ void pcm3168a_remove(struct device *dev) * The asserted level of GPIO_ACTIVE_LOW is LOW. */ gpiod_set_value_cansleep(pcm3168a->gpio_rst, 1); + pm_runtime_disable(dev); -#ifndef CONFIG_PM - pcm3168a_disable(dev); -#endif + if (!pm_runtime_status_suspended(dev)) { + regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies); + clk_disable_unprepare(pcm3168a->scki); + } } EXPORT_SYMBOL_GPL(pcm3168a_remove); @@ -900,13 +888,15 @@ static int pcm3168a_rt_suspend(struct device *dev) regcache_cache_only(pcm3168a->regmap, true); - pcm3168a_disable(dev); + regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies); + clk_disable_unprepare(pcm3168a->scki); return 0; } EXPORT_GPL_DEV_PM_OPS(pcm3168a_pm_ops) = { RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; MODULE_DESCRIPTION("PCM3168A codec driver"); diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c index a1d849b0c50f..836865d11d22 100644 --- a/sound/soc/codecs/pcm512x-i2c.c +++ b/sound/soc/codecs/pcm512x-i2c.c @@ -35,13 +35,13 @@ static void pcm512x_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id pcm512x_i2c_id[] = { - { "pcm5121", }, - { "pcm5122", }, - { "pcm5141", }, - { "pcm5142", }, - { "pcm5242", }, - { "tas5754", }, - { "tas5756", }, + { .name = "pcm5121" }, + { .name = "pcm5122" }, + { .name = "pcm5141" }, + { .name = "pcm5142" }, + { .name = "pcm5242" }, + { .name = "tas5754" }, + { .name = "tas5756" }, { } }; MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id); diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c index 78b21fbfad50..4ac4448ac3c8 100644 --- a/sound/soc/codecs/pcm6240.c +++ b/sound/soc/codecs/pcm6240.c @@ -27,28 +27,28 @@ #include "pcm6240.h" static const struct i2c_device_id pcmdevice_i2c_id[] = { - { "adc3120", ADC3120 }, - { "adc5120", ADC5120 }, - { "adc6120", ADC6120 }, - { "dix4192", DIX4192 }, - { "pcm1690", PCM1690 }, - { "pcm3120", PCM3120 }, - { "pcm3140", PCM3140 }, - { "pcm5120", PCM5120 }, - { "pcm5140", PCM5140 }, - { "pcm6120", PCM6120 }, - { "pcm6140", PCM6140 }, - { "pcm6240", PCM6240 }, - { "pcm6260", PCM6260 }, - { "pcm9211", PCM9211 }, - { "pcmd3140", PCMD3140 }, - { "pcmd3180", PCMD3180 }, - { "pcmd512x", PCMD512X }, - { "taa5212", TAA5212 }, - { "taa5412", TAA5412 }, - { "tad5212", TAD5212 }, - { "tad5412", TAD5412 }, - {} + { .name = "adc3120", .driver_data = ADC3120 }, + { .name = "adc5120", .driver_data = ADC5120 }, + { .name = "adc6120", .driver_data = ADC6120 }, + { .name = "dix4192", .driver_data = DIX4192 }, + { .name = "pcm1690", .driver_data = PCM1690 }, + { .name = "pcm3120", .driver_data = PCM3120 }, + { .name = "pcm3140", .driver_data = PCM3140 }, + { .name = "pcm5120", .driver_data = PCM5120 }, + { .name = "pcm5140", .driver_data = PCM5140 }, + { .name = "pcm6120", .driver_data = PCM6120 }, + { .name = "pcm6140", .driver_data = PCM6140 }, + { .name = "pcm6240", .driver_data = PCM6240 }, + { .name = "pcm6260", .driver_data = PCM6260 }, + { .name = "pcm9211", .driver_data = PCM9211 }, + { .name = "pcmd3140", .driver_data = PCMD3140 }, + { .name = "pcmd3180", .driver_data = PCMD3180 }, + { .name = "pcmd512x", .driver_data = PCMD512X }, + { .name = "taa5212", .driver_data = TAA5212 }, + { .name = "taa5412", .driver_data = TAA5412 }, + { .name = "tad5212", .driver_data = TAD5212 }, + { .name = "tad5412", .driver_data = TAD5412 }, + { } }; MODULE_DEVICE_TABLE(i2c, pcmdevice_i2c_id); @@ -1230,15 +1230,11 @@ static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt, int *status) { struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt; - struct pcmdevice_config_info *cfg_info; + struct pcmdevice_config_info *cfg_info = NULL; struct pcmdevice_block_data **bk_da; + char cfg_name[64] = {}; unsigned int config_offset = 0, i; - - cfg_info = kzalloc_obj(struct pcmdevice_config_info); - if (!cfg_info) { - *status = -ENOMEM; - goto out; - } + unsigned int nblocks; if (pcm_dev->regbin.fw_hdr.binary_version_num >= 0x105) { if (config_offset + 64 > (int)config_size) { @@ -1247,7 +1243,7 @@ static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt, "%s: cfg_name out of boundary\n", __func__); goto out; } - memcpy(cfg_info->cfg_name, &config_data[config_offset], 64); + memcpy(cfg_name, &config_data[config_offset], 64); config_offset += 64; } @@ -1257,16 +1253,17 @@ static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt, __func__); goto out; } - cfg_info->nblocks = - get_unaligned_be32(&config_data[config_offset]); + nblocks = get_unaligned_be32(&config_data[config_offset]); config_offset += 4; - bk_da = cfg_info->blk_data = kzalloc_objs(struct pcmdevice_block_data *, - cfg_info->nblocks); - if (!bk_da) { + cfg_info = kzalloc_flex(*cfg_info, blk_data, nblocks); + if (!cfg_info) { *status = -ENOMEM; goto out; } + cfg_info->nblocks = nblocks; + memcpy(cfg_info->cfg_name, cfg_name, sizeof(cfg_info->cfg_name)); + bk_da = cfg_info->blk_data; cfg_info->real_nblocks = 0; for (i = 0; i < cfg_info->nblocks; i++) { if (config_offset + 12 > config_size) { @@ -1449,14 +1446,11 @@ static void pcmdevice_config_info_remove(void *ctxt) for (i = 0; i < regbin->ncfgs; i++) { if (!cfg_info[i]) continue; - if (cfg_info[i]->blk_data) { - for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) { - if (!cfg_info[i]->blk_data[j]) - continue; - kfree(cfg_info[i]->blk_data[j]->regdata); - kfree(cfg_info[i]->blk_data[j]); - } - kfree(cfg_info[i]->blk_data); + for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) { + if (!cfg_info[i]->blk_data[j]) + continue; + kfree(cfg_info[i]->blk_data[j]->regdata); + kfree(cfg_info[i]->blk_data[j]); } kfree(cfg_info[i]); } diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h index 2d8f9e798139..e27afd33910c 100644 --- a/sound/soc/codecs/pcm6240.h +++ b/sound/soc/codecs/pcm6240.h @@ -199,7 +199,7 @@ struct pcmdevice_config_info { unsigned int nblocks; unsigned int real_nblocks; unsigned char active_dev; - struct pcmdevice_block_data **blk_data; + struct pcmdevice_block_data *blk_data[] __counted_by(nblocks); }; struct pcmdevice_regbin { diff --git a/sound/soc/codecs/peb2466.c b/sound/soc/codecs/peb2466.c index 2d5163c15d0d..2d71d204d8fa 100644 --- a/sound/soc/codecs/peb2466.c +++ b/sound/soc/codecs/peb2466.c @@ -817,18 +817,17 @@ static int peb2466_dai_startup(struct snd_pcm_substream *substream, &peb2466_sample_bits_constr); } -static const u64 peb2466_dai_formats[] = { +static const u64 peb2466_dai_formats = SND_SOC_POSSIBLE_DAIFMT_DSP_A | - SND_SOC_POSSIBLE_DAIFMT_DSP_B, -}; + SND_SOC_POSSIBLE_DAIFMT_DSP_B; static const struct snd_soc_dai_ops peb2466_dai_ops = { .startup = peb2466_dai_startup, .hw_params = peb2466_dai_hw_params, .set_tdm_slot = peb2466_dai_set_tdm_slot, .set_fmt = peb2466_dai_set_fmt, - .auto_selectable_formats = peb2466_dai_formats, - .num_auto_selectable_formats = ARRAY_SIZE(peb2466_dai_formats), + .auto_selectable_formats = &peb2466_dai_formats, + .num_auto_selectable_formats = 1, }; static struct snd_soc_dai_driver peb2466_dai_driver = { diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c index 1f0a3f5389f1..29655175ea28 100644 --- a/sound/soc/codecs/pm4125.c +++ b/sound/soc/codecs/pm4125.c @@ -1309,17 +1309,12 @@ static int pm4125_irq_init(struct pm4125_priv *pm4125, struct device *dev) static int pm4125_soc_codec_probe(struct snd_soc_component *component) { struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component); - struct sdw_slave *tx_sdw_dev = pm4125->tx_sdw_dev; struct device *dev = component->dev; - unsigned long time_left; int i, ret; - time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, - msecs_to_jiffies(5000)); - if (!time_left) { - dev_err(dev, "soundwire device init timeout\n"); - return -ETIMEDOUT; - } + ret = sdw_slave_wait_for_init(pm4125->tx_sdw_dev, 5000); + if (ret) + return ret; snd_soc_component_init_regmap(component, pm4125->regmap); ret = pm_runtime_resume_and_get(dev); diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 9697aefc6e03..5871b5a81975 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c @@ -425,7 +425,6 @@ static int rk3328_platform_probe(struct platform_device *pdev) struct rk3328_codec_priv *rk3328; struct regmap *grf; void __iomem *base; - int ret = 0; rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL); if (!rk3328) @@ -441,14 +440,13 @@ static int rk3328_platform_probe(struct platform_device *pdev) regmap_write(grf, RK3328_GRF_SOC_CON2, (BIT(14) << 16 | BIT(14))); - ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms", - &rk3328->spk_depop_time); - if (ret < 0) { + if (of_property_read_u32(rk3328_np, "spk-depop-time-ms", + &rk3328->spk_depop_time)) { dev_info(&pdev->dev, "spk_depop_time use default value.\n"); rk3328->spk_depop_time = 200; } - rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH); + rk3328->mute = devm_gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH); if (IS_ERR(rk3328->mute)) return PTR_ERR(rk3328->mute); /* @@ -461,57 +459,31 @@ static int rk3328_platform_probe(struct platform_device *pdev) regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1)); } - rk3328->mclk = devm_clk_get(&pdev->dev, "mclk"); + rk3328->mclk = devm_clk_get_enabled(&pdev->dev, "mclk"); if (IS_ERR(rk3328->mclk)) return PTR_ERR(rk3328->mclk); - ret = clk_prepare_enable(rk3328->mclk); - if (ret) - return ret; clk_set_rate(rk3328->mclk, INITIAL_FREQ); - rk3328->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(rk3328->pclk)) { - dev_err(&pdev->dev, "can't get acodec pclk\n"); - ret = PTR_ERR(rk3328->pclk); - goto err_unprepare_mclk; - } - - ret = clk_prepare_enable(rk3328->pclk); - if (ret < 0) { - dev_err(&pdev->dev, "failed to enable acodec pclk\n"); - goto err_unprepare_mclk; - } + rk3328->pclk = devm_clk_get_enabled(&pdev->dev, "pclk"); + if (IS_ERR(rk3328->pclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(rk3328->pclk), + "failed to get or enable acodec pclk\n"); base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - goto err_unprepare_pclk; - } + if (IS_ERR(base)) + return PTR_ERR(base); rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base, &rk3328_codec_regmap_config); - if (IS_ERR(rk3328->regmap)) { - ret = PTR_ERR(rk3328->regmap); - goto err_unprepare_pclk; - } + if (IS_ERR(rk3328->regmap)) + return PTR_ERR(rk3328->regmap); platform_set_drvdata(pdev, rk3328); - ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328, + return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328, rk3328_dai, ARRAY_SIZE(rk3328_dai)); - if (ret) - goto err_unprepare_pclk; - - return 0; - -err_unprepare_pclk: - clk_disable_unprepare(rk3328->pclk); - -err_unprepare_mclk: - clk_disable_unprepare(rk3328->mclk); - return ret; } static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = { diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 03f31d9d916e..15488a059283 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -2201,7 +2201,7 @@ MODULE_DEVICE_TABLE(acpi, rt1011_acpi_match); #endif static const struct i2c_device_id rt1011_i2c_id[] = { - { "rt1011" }, + { .name = "rt1011" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1011_i2c_id); diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index ca1ed9d5a24e..ff0c08ff610e 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -1094,7 +1094,7 @@ static const struct regmap_config rt1015_regmap = { }; static const struct i2c_device_id rt1015_i2c_id[] = { - { "rt1015" }, + { .name = "rt1015" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1015_i2c_id); diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c index 9f86f071fca8..11c8c45574a1 100644 --- a/sound/soc/codecs/rt1016.c +++ b/sound/soc/codecs/rt1016.c @@ -608,7 +608,7 @@ static const struct regmap_config rt1016_regmap = { }; static const struct i2c_device_id rt1016_i2c_id[] = { - { "rt1016" }, + { .name = "rt1016" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1016_i2c_id); diff --git a/sound/soc/codecs/rt1017-sdca-sdw.c b/sound/soc/codecs/rt1017-sdca-sdw.c index 148b36173a25..d62e8a253676 100644 --- a/sound/soc/codecs/rt1017-sdca-sdw.c +++ b/sound/soc/codecs/rt1017-sdca-sdw.c @@ -773,25 +773,15 @@ static int rt1017_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1017_sdca_priv *rt1017 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt1017->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT1017_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT1017_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "Initialization not complete, timed out\n"); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt1017->regmap, false); regcache_sync(rt1017->regmap); diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index 86539c6f6cc1..370521149ac8 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -540,7 +540,7 @@ static const struct regmap_config rt1019_regmap = { }; static const struct i2c_device_id rt1019_i2c_id[] = { - { "rt1019" }, + { .name = "rt1019" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1019_i2c_id); diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index 26b7382f97ef..2d5fad76cf52 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -981,8 +981,8 @@ MODULE_DEVICE_TABLE(acpi, rt1305_acpi_match); #endif static const struct i2c_device_id rt1305_i2c_id[] = { - { "rt1305" }, - { "rt1306" }, + { .name = "rt1305" }, + { .name = "rt1306" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1305_i2c_id); diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index e077d096bc23..39e06a3a7560 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -768,25 +768,15 @@ static int rt1308_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt1308->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT1308_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT1308_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "Initialization not complete, timed out\n"); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt1308->regmap, false); regcache_sync_region(rt1308->regmap, 0xc000, 0xcfff); diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index df50b38c24b9..630946cd7cdf 100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -795,7 +795,7 @@ MODULE_DEVICE_TABLE(acpi, rt1308_acpi_match); #endif static const struct i2c_device_id rt1308_i2c_id[] = { - { "rt1308" }, + { .name = "rt1308" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1308_i2c_id); diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 20fc1579eb9c..1828fd9d5af6 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -745,25 +745,15 @@ static int rt1316_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt1316->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT1316_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT1316_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt1316->regmap, false); regcache_sync(rt1316->regmap); diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c index d28f1afe68f1..51bd11b92a55 100644 --- a/sound/soc/codecs/rt1318-sdw.c +++ b/sound/soc/codecs/rt1318-sdw.c @@ -821,23 +821,15 @@ static int rt1318_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt1318->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT1318_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT1318_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt1318->regmap, false); regcache_sync(rt1318->regmap); diff --git a/sound/soc/codecs/rt1318.c b/sound/soc/codecs/rt1318.c index a80643099644..d13fd0e14125 100644 --- a/sound/soc/codecs/rt1318.c +++ b/sound/soc/codecs/rt1318.c @@ -1139,7 +1139,7 @@ static const struct regmap_config rt1318_regmap = { }; static const struct i2c_device_id rt1318_i2c_id[] = { - { "rt1318" }, + { .name = "rt1318" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1318_i2c_id); diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index 192faa431b5e..13493b85f3c9 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -3053,23 +3053,15 @@ static int rt1320_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt1320->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT1320_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT1320_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt1320->regmap, false); regcache_sync(rt1320->regmap); regcache_cache_only(rt1320->mbq_regmap, false); diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index bba714020c70..63b5fc439773 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -1098,8 +1098,8 @@ MODULE_DEVICE_TABLE(of, rt274_of_match); #endif static const struct i2c_device_id rt274_i2c_id[] = { - {"rt274"}, - {} + { .name = "rt274" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt274_i2c_id); diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 195658f626cc..ded0ea332480 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1077,9 +1077,9 @@ static const struct regmap_config rt286_regmap = { }; static const struct i2c_device_id rt286_i2c_id[] = { - {"rt286"}, - {"rt288"}, - {} + { .name = "rt286" }, + { .name = "rt288" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 7d532a5a5f73..5414a1712b57 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1138,8 +1138,8 @@ static const struct regmap_config rt298_regmap = { }; static const struct i2c_device_id rt298_i2c_id[] = { - {"rt298"}, - {} + { .name = "rt298" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt298_i2c_id); diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index 649b44b790b0..00a4a208d2fa 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -1200,7 +1200,7 @@ static const struct regmap_config rt5514_regmap = { }; static const struct i2c_device_id rt5514_i2c_id[] = { - { "rt5514" }, + { .name = "rt5514" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); diff --git a/sound/soc/codecs/rt5575.c b/sound/soc/codecs/rt5575.c index 24e41af29689..5c3e60eaa6a4 100644 --- a/sound/soc/codecs/rt5575.c +++ b/sound/soc/codecs/rt5575.c @@ -325,7 +325,7 @@ static int rt5575_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id rt5575_i2c_id[] = { - { "rt5575" }, + { .name = "rt5575" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5575_i2c_id); diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index fb9cf127e3ff..46ee412dc81d 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1321,7 +1321,7 @@ static const struct regmap_config rt5616_regmap = { }; static const struct i2c_device_id rt5616_i2c_id[] = { - { "rt5616" }, + { .name = "rt5616" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5616_i2c_id); @@ -1386,9 +1386,6 @@ static int rt5616_i2c_probe(struct i2c_client *i2c) rt5616_dai, ARRAY_SIZE(rt5616_dai)); } -static void rt5616_i2c_remove(struct i2c_client *i2c) -{} - static void rt5616_i2c_shutdown(struct i2c_client *client) { struct rt5616_priv *rt5616 = i2c_get_clientdata(client); @@ -1403,7 +1400,6 @@ static struct i2c_driver rt5616_i2c_driver = { .of_match_table = of_match_ptr(rt5616_of_match), }, .probe = rt5616_i2c_probe, - .remove = rt5616_i2c_remove, .shutdown = rt5616_i2c_shutdown, .id_table = rt5616_i2c_id, }; diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 19c6d8f760d9..ed1233973eb8 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1671,8 +1671,8 @@ static const struct snd_soc_component_driver soc_component_dev_rt5631 = { }; static const struct i2c_device_id rt5631_i2c_id[] = { - { "rt5631" }, - { "alc5631" }, + { .name = "rt5631" }, + { .name = "alc5631" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); @@ -1722,16 +1722,12 @@ static int rt5631_i2c_probe(struct i2c_client *i2c) return ret; } -static void rt5631_i2c_remove(struct i2c_client *client) -{} - static struct i2c_driver rt5631_i2c_driver = { .driver = { .name = "rt5631", .of_match_table = of_match_ptr(rt5631_i2c_dt_ids), }, - .probe = rt5631_i2c_probe, - .remove = rt5631_i2c_remove, + .probe = rt5631_i2c_probe, .id_table = rt5631_i2c_id, }; diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index f6c6294e1588..74fd05176eff 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2397,7 +2397,7 @@ static void rt5640_jack_work(struct work_struct *work) * disabled the OVCD IRQ, the IRQ pin will stay high and as * we react to edges, we miss the unplug event -> recheck. */ - queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); + queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0); } } @@ -2410,7 +2410,8 @@ static irqreturn_t rt5640_irq(int irq, void *data) delay = 100; if (rt5640->jack) - mod_delayed_work(system_long_wq, &rt5640->jack_work, delay); + mod_delayed_work(system_dfl_long_wq, &rt5640->jack_work, + delay); return IRQ_HANDLED; } @@ -2419,7 +2420,7 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data) { struct rt5640_priv *rt5640 = data; - queue_delayed_work(system_long_wq, &rt5640->jack_work, + queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, msecs_to_jiffies(JACK_SETTLE_TIME)); return IRQ_HANDLED; @@ -2553,10 +2554,12 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, rt5640->jd_gpio = jack_data->jd_gpio; rt5640->jd_gpio_irq = gpiod_to_irq(rt5640->jd_gpio); - ret = request_irq(rt5640->jd_gpio_irq, rt5640_jd_gpio_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "rt5640-jd-gpio", rt5640); - if (ret) { + ret = request_any_context_irq(rt5640->jd_gpio_irq, + rt5640_jd_gpio_irq, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "rt5640-jd-gpio", rt5640); + if (ret < 0) { dev_warn(component->dev, "Failed to request jd GPIO IRQ %d: %d\n", rt5640->jd_gpio_irq, ret); rt5640_disable_jack_detect(component); @@ -2568,10 +2571,10 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, if (jack_data && jack_data->use_platform_clock) rt5640->use_platform_clock = jack_data->use_platform_clock; - ret = request_irq(rt5640->irq, rt5640_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "rt5640", rt5640); - if (ret) { + ret = request_any_context_irq(rt5640->irq, rt5640_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "rt5640", rt5640); + if (ret < 0) { dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret); rt5640_disable_jack_detect(component); return; @@ -2579,7 +2582,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, rt5640->irq_requested = true; /* sync initial jack state */ - queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); + queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0); } static const struct snd_soc_dapm_route rt5640_hda_jack_dapm_routes[] = { @@ -2622,9 +2625,9 @@ static void rt5640_enable_hda_jack_detect( rt5640->jack = jack; - ret = request_irq(rt5640->irq, rt5640_irq, - IRQF_TRIGGER_RISING, "rt5640", rt5640); - if (ret) { + ret = request_any_context_irq(rt5640->irq, rt5640_irq, + IRQF_TRIGGER_RISING, "rt5640", rt5640); + if (ret < 0) { dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret); rt5640->jack = NULL; return; @@ -2632,7 +2635,7 @@ static void rt5640_enable_hda_jack_detect( rt5640->irq_requested = true; /* sync initial jack state */ - queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); + queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0); snd_soc_dapm_add_routes(dapm, rt5640_hda_jack_dapm_routes, ARRAY_SIZE(rt5640_hda_jack_dapm_routes)); @@ -2860,7 +2863,7 @@ static int rt5640_resume(struct snd_soc_component *component) } enable_irq(rt5640->irq); - queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); + queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0); } return 0; @@ -2958,9 +2961,9 @@ static const struct regmap_config rt5640_regmap = { }; static const struct i2c_device_id rt5640_i2c_id[] = { - { "rt5640" }, - { "rt5639" }, - { "rt5642" }, + { .name = "rt5640" }, + { .name = "rt5639" }, + { .name = "rt5642" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index f7701b8d0d3c..8a9af260e5f7 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3646,8 +3646,8 @@ static const struct regmap_config temp_regmap = { }; static const struct i2c_device_id rt5645_i2c_id[] = { - { "rt5645" }, - { "rt5650" }, + { .name = "rt5645" }, + { .name = "rt5650" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 23c4bf3da298..5c729135f71b 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -2202,7 +2202,7 @@ MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match); #endif static const struct i2c_device_id rt5651_i2c_id[] = { - { "rt5651" }, + { .name = "rt5651" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id); diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 3590ebd41c27..3097ee6d4e89 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -3814,8 +3814,8 @@ static const struct regmap_config rt5659_regmap = { }; static const struct i2c_device_id rt5659_i2c_id[] = { - { "rt5658" }, - { "rt5659" }, + { .name = "rt5658" }, + { .name = "rt5659" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5659_i2c_id); diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index 84cdfb810c66..edf2e3e346e4 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -1225,7 +1225,7 @@ static const struct regmap_config rt5660_regmap = { }; static const struct i2c_device_id rt5660_i2c_id[] = { - { "rt5660" }, + { .name = "rt5660" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5660_i2c_id); diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index eee1c98cc4aa..262d3bba1f3d 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -3307,8 +3307,8 @@ static const struct regmap_config temp_regmap = { }; static const struct i2c_device_id rt5663_i2c_id[] = { - { "rt5663" }, - {} + { .name = "rt5663" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt5663_i2c_id); diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 38fb3a277e26..48f57cd0920d 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4534,8 +4534,8 @@ static const struct regmap_config rt5665_regmap = { }; static const struct i2c_device_id rt5665_i2c_id[] = { - {"rt5665"}, - {} + { .name = "rt5665" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt5665_i2c_id); diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index c551696ae11a..fed6de40b8c8 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -2334,8 +2334,8 @@ static const struct regmap_config rt5668_regmap = { }; static const struct i2c_device_id rt5668_i2c_id[] = { - {"rt5668b"}, - {} + { .name = "rt5668b" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt5668_i2c_id); diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index cb5d03bf4c7f..1d120b5dc2be 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2876,9 +2876,9 @@ static const struct regmap_config rt5670_regmap = { }; static const struct i2c_device_id rt5670_i2c_id[] = { - { "rt5670" }, - { "rt5671" }, - { "rt5672" }, + { .name = "rt5670" }, + { .name = "rt5671" }, + { .name = "rt5672" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 60a93c3fe2e7..ac084ca008f3 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5210,7 +5210,7 @@ static const struct acpi_device_id rt5677_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match); static const struct i2c_device_id rt5677_i2c_id[] = { - { "rt5677", RT5677 }, + { .name = "rt5677", .driver_data = RT5677 }, { } }; MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id); diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index e556a365adc8..286cf0d17968 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -324,8 +324,8 @@ static const struct acpi_device_id rt5682_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match); static const struct i2c_device_id rt5682_i2c_id[] = { - {"rt5682"}, - {} + { .name = "rt5682" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index fc464538ceff..ec2a35a0cacd 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -754,7 +754,7 @@ static int rt5682_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt5682_priv *rt5682 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt5682->first_hw_init) return 0; @@ -766,20 +766,12 @@ static int rt5682_dev_resume(struct device *dev) rt5682->disable_irq = false; } mutex_unlock(&rt5682->disable_irq_lock); - goto regmap_sync; } - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT5682_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - sdw_show_ping_status(slave->bus, true); + ret = sdw_slave_wait_for_init(slave, RT5682_PROBE_TIMEOUT); + if (ret) + return ret; - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt5682->sdw_regmap, false); regcache_cache_only(rt5682->regmap, false); regcache_sync(rt5682->regmap); diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index d39f8e4f3474..4b82e07d3b2c 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2929,20 +2929,14 @@ static int rt5682_probe(struct snd_soc_component *component) { struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); - struct sdw_slave *slave; - unsigned long time; + int ret; rt5682->component = component; if (rt5682->is_sdw) { - slave = rt5682->slave; - time = wait_for_completion_timeout( - &slave->initialization_complete, - msecs_to_jiffies(RT5682_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "Initialization not complete, timed out\n"); - return -ETIMEDOUT; - } + ret = sdw_slave_wait_for_init(rt5682->slave, RT5682_PROBE_TIMEOUT); + if (ret) + return ret; } snd_soc_dapm_disable_pin(dapm, "MICBIAS"); diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index 98de94a79260..3624067950c0 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -3325,8 +3325,8 @@ static const struct acpi_device_id rt5682s_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rt5682s_acpi_match); static const struct i2c_device_id rt5682s_i2c_id[] = { - {"rt5682s"}, - {} + { .name = "rt5682s" }, + { } }; MODULE_DEVICE_TABLE(i2c, rt5682s_i2c_id); diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 9ce36a66fae1..30fcca210f05 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -522,25 +522,15 @@ static int rt700_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt700_priv *rt700 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt700->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT700_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT700_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "Initialization not complete, timed out\n"); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt700->regmap, false); regcache_sync_region(rt700->regmap, 0x3000, 0x8fff); regcache_sync_region(rt700->regmap, 0x752010, 0x75206b); diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index 49dacceddf81..a8164fc3979a 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -438,7 +438,7 @@ static int rt711_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt711->first_hw_init) return 0; @@ -451,20 +451,12 @@ static int rt711_sdca_dev_resume(struct device *dev) rt711->disable_irq = false; } mutex_unlock(&rt711->disable_irq_lock); - goto regmap_sync; } - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT711_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - sdw_show_ping_status(slave->bus, true); + ret = sdw_slave_wait_for_init(slave, RT711_PROBE_TIMEOUT); + if (ret) + return ret; - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt711->regmap, false); regcache_sync(rt711->regmap); regcache_cache_only(rt711->mbq_regmap, false); diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 72ddf4cebdf3..df3c43f2ab6b 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -530,7 +530,7 @@ static int rt711_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt711_priv *rt711 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt711->first_hw_init) return 0; @@ -542,18 +542,12 @@ static int rt711_dev_resume(struct device *dev) rt711->disable_irq = false; } mutex_unlock(&rt711->disable_irq_lock); - goto regmap_sync; } - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT711_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - return -ETIMEDOUT; - } + ret = sdw_slave_wait_for_init(slave, RT711_PROBE_TIMEOUT); + if (ret) + return ret; -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt711->regmap, false); regcache_sync_region(rt711->regmap, 0x3000, 0x8fff); regcache_sync_region(rt711->regmap, 0x752009, 0x752091); diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c index 4d83544ef204..4c5c2f5ba5ed 100644 --- a/sound/soc/codecs/rt712-sdca-dmic.c +++ b/sound/soc/codecs/rt712-sdca-dmic.c @@ -905,26 +905,15 @@ static int rt712_sdca_dmic_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt712->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT712_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT712_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", - __func__); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt712->regmap, false); regcache_sync(rt712->regmap); regcache_cache_only(rt712->mbq_regmap, false); diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c index 8c82887174db..581732180473 100644 --- a/sound/soc/codecs/rt712-sdca-sdw.c +++ b/sound/soc/codecs/rt712-sdca-sdw.c @@ -450,7 +450,7 @@ static int rt712_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt712->first_hw_init) return 0; @@ -464,20 +464,12 @@ static int rt712_sdca_dev_resume(struct device *dev) rt712->disable_irq = false; } mutex_unlock(&rt712->disable_irq_lock); - goto regmap_sync; } - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT712_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - sdw_show_ping_status(slave->bus, true); + ret = sdw_slave_wait_for_init(slave, RT712_PROBE_TIMEOUT); + if (ret) + return ret; - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt712->regmap, false); regcache_sync(rt712->regmap); regcache_cache_only(rt712->mbq_regmap, false); diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index 968bc183b8d8..4b9815b5628d 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -224,25 +224,15 @@ static int rt715_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt715->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT715_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT715_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt715->regmap, false); regcache_sync_region(rt715->regmap, SDW_SDCA_CTL(FUN_JACK_CODEC, RT715_SDCA_ST_EN, RT715_SDCA_ST_CTRL, diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 49c91d015be4..7f83a8f1a06e 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -501,25 +501,15 @@ static int rt715_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt715_priv *rt715 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt715->first_hw_init) return 0; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, RT715_PROBE_TIMEOUT); + if (ret) + return ret; - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT715_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); - sdw_show_ping_status(slave->bus, true); - - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt715->regmap, false); regcache_sync_region(rt715->regmap, 0x3000, 0x8fff); regcache_sync_region(rt715->regmap, 0x752039, 0x752039); diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c index 6eb8512975b8..58606209316a 100644 --- a/sound/soc/codecs/rt721-sdca-sdw.c +++ b/sound/soc/codecs/rt721-sdca-sdw.c @@ -489,7 +489,7 @@ static int rt721_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt721->first_hw_init) return 0; @@ -502,20 +502,12 @@ static int rt721_sdca_dev_resume(struct device *dev) rt721->disable_irq = false; } mutex_unlock(&rt721->disable_irq_lock); - goto regmap_sync; } - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT721_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "Initialization not complete, timed out\n"); - sdw_show_ping_status(slave->bus, true); + ret = sdw_slave_wait_for_init(slave, RT721_PROBE_TIMEOUT); + if (ret) + return ret; - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt721->regmap, false); regcache_sync(rt721->regmap); regcache_cache_only(rt721->mbq_regmap, false); diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index 0a5b3ffa90da..0f76492ff915 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -19,7 +19,9 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg) { switch (reg) { - case 0x2f01 ... 0x2f0a: + case 0x22f0 ... 0x22f1: + case 0x2f01 ... 0x2f0c: + case 0x2f21 ... 0x2f24: case 0x2f35 ... 0x2f36: case 0x2f50 ... 0x2f52: case 0x2f54: @@ -84,6 +86,21 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg) case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31, RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: + case 0x44011000 ... 0x440115ff: + case 0x44012000: + case 0x44012021: + case 0x44012022: + case 0x44012025: + case 0x44021000 ... 0x440211ff: + case 0x44022000: + case 0x44022019: + case 0x4402201a: + case 0x4402201d: + case 0x44041000 ... 0x440415ff: + case 0x44042000: + case 0x44042019: + case 0x4404201a: + case 0x4404201d: return 1; case 0x2000000 ... 0x2000024: case 0x2000029 ... 0x200004a: @@ -95,8 +112,10 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg) case 0x200007f: case 0x2000082 ... 0x200008e: case 0x2000090 ... 0x2000094: + case 0x20000b1: + case 0x20000b4: case 0x3110000: - case 0x5300000 ... 0x5300002: + case 0x5300000 ... 0x5300300: case 0x5400002: case 0x5600000 ... 0x5600007: case 0x5700000 ... 0x5700004: @@ -175,6 +194,7 @@ static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg) case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, RT722_SDCA_CTL_ACTUAL_POWER_STATE, 0): case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2: case 0x2000000: + case 0x2000007: case 0x200000d: case 0x2000019: case 0x2000020: @@ -186,6 +206,21 @@ static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg) case 0x3110000: case 0x5800003: case 0x5810000: + case 0x44011000 ... 0x440115ff: + case 0x44012000: + case 0x44012021: + case 0x44012022: + case 0x44012025: + case 0x44021000 ... 0x440211ff: + case 0x44022000: + case 0x44022019: + case 0x4402201a: + case 0x4402201d: + case 0x44041000 ... 0x440415ff: + case 0x44042000: + case 0x44042019: + case 0x4404201a: + case 0x4404201d: return true; default: return false; @@ -501,7 +536,7 @@ static int rt722_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct rt722_sdca_priv *rt722 = dev_get_drvdata(dev); - unsigned long time; + int ret; if (!rt722->first_hw_init) return 0; @@ -514,20 +549,12 @@ static int rt722_sdca_dev_resume(struct device *dev) rt722->disable_irq = false; } mutex_unlock(&rt722->disable_irq_lock); - goto regmap_sync; } - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(RT722_PROBE_TIMEOUT)); - if (!time) { - dev_err(&slave->dev, "Initialization not complete, timed out\n"); - sdw_show_ping_status(slave->bus, true); + ret = sdw_slave_wait_for_init(slave, RT722_PROBE_TIMEOUT); + if (ret) + return ret; - return -ETIMEDOUT; - } - -regmap_sync: - slave->unattach_request = 0; regcache_cache_only(rt722->regmap, false); regcache_sync(rt722->regmap); return 0; diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c index 79b8b7e70a33..1b6729f363fc 100644 --- a/sound/soc/codecs/rt722-sdca.c +++ b/sound/soc/codecs/rt722-sdca.c @@ -7,19 +7,21 @@ // #include -#include #include +#include +#include #include -#include -#include #include #include #include -#include #include -#include -#include #include +#include +#include +#include +#include +#include +#include #include #include @@ -344,6 +346,280 @@ static int rt722_sdca_set_jack_detect(struct snd_soc_component *component, return 0; } +static int rt722_cae_load(struct rt722_sdca_priv *rt722) +{ + struct device *dev = &rt722->slave->dev; + static const char func_tag[] = "FUNC"; + static const char xu_tag[] = "XU"; + const char *dmi_vendor, *dmi_product, *dmi_sku; + char *cae_filename; + const struct firmware *cae_fw = NULL; + unsigned int cae_st_spk, cae_st_hp, cae_st_mic; + unsigned int func, value; + unsigned int combined_val; + unsigned int addr, size; + unsigned int fw_offset; + unsigned char mbq_high_val = 0; + unsigned char *param_data; + unsigned char *fw_data; + char tag[5]; + char *space; + int v_len, p_len, s_len; + int ret = 0, i; + int retry = 50; + + dmi_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + dmi_product = dmi_get_system_info(DMI_PRODUCT_NAME); + dmi_sku = dmi_get_system_info(DMI_PRODUCT_SKU); + + if (!dmi_vendor || !dmi_product || !dmi_sku) { + dev_warn(dev, "%s: Incomplete DMI info\n", __func__); + return -EINVAL; + } + space = strchr(dmi_vendor, ' '); + v_len = space ? space - dmi_vendor : strlen(dmi_vendor); + + space = strchr(dmi_product, ' '); + p_len = space ? space - dmi_product : strlen(dmi_product); + + space = strchr(dmi_sku, ' '); + s_len = space ? space - dmi_sku : strlen(dmi_sku); + + cae_filename = kasprintf(GFP_KERNEL, + "realtek/rt722/rt722_RAE_%.*s_%.*s_%.*s.dat", + v_len, dmi_vendor, + p_len, dmi_product, + s_len, dmi_sku); + if (!cae_filename) + return -ENOMEM; + dev_dbg(dev, "%s: try to load CAE file %s\n", __func__, cae_filename); + + regmap_write(rt722->regmap, RT722_SPK_CAE_PARAM1, 0x5f); + regmap_write(rt722->regmap, RT722_HP_CAE_PARAM39, 0x5f); + regmap_write(rt722->regmap, RT722_MIC_CAE_PARAM39, 0x5f); + usleep_range(50000, 60000); + + request_firmware(&cae_fw, cae_filename, dev); + kfree(cae_filename); + if (!cae_fw) { + dev_err(dev, "%s: Failed to load CAE firmware\n", __func__); + return -ENOENT; + } + + regmap_read(rt722->regmap, RT722_SPK_CAE_PARAM38, &cae_st_spk); + regmap_read(rt722->regmap, RT722_HP_CAE_PARAM68, &cae_st_hp); + regmap_read(rt722->regmap, RT722_MIC_CAE_PARAM99, &cae_st_mic); + cae_st_spk &= 0x80; + cae_st_hp &= 0x80; + cae_st_mic &= 0x80; + + dev_dbg(dev, "%s(%d) spk_crc:%x, hp_crc:%x, mic_crc:%x\n", + __func__, __LINE__, cae_st_spk, cae_st_hp, cae_st_mic); + + if (cae_st_spk) + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_EQ_CAE, + RT722_EQ_CTRL_SPK, 0x0008, 0x0008); + else if (cae_st_hp) + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_EQ_CAE, + RT722_EQ_CTRL_HP, 0x0008, 0x0008); + else if (cae_st_mic) + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_EQ_CAE, + RT722_EQ_CTRL_DMIC, 0x0008, 0x0008); + + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG, + RT722_MISC_CTRL1, 0x8000, 0x8000); + + regmap_update_bits(rt722->regmap, RT722_SPK_CAE_PARAM34, 0x1, 0x0); + regmap_update_bits(rt722->regmap, RT722_HP_CAE_PARAM64, 0x1, 0x0); + regmap_update_bits(rt722->regmap, RT722_MIC_CAE_PARAM95, 0x1, 0x0); + + while (--retry) { + regmap_read(rt722->regmap, RT722_SPK_CAE_PARAM35, &cae_st_spk); + regmap_read(rt722->regmap, RT722_HP_CAE_PARAM65, &cae_st_hp); + regmap_read(rt722->regmap, RT722_MIC_CAE_PARAM96, &cae_st_mic); + dev_dbg(dev, "%s(%d) cae_st_spk:%x, cae_st_hp:%x, cae_st_mic:%x\n", + __func__, __LINE__, cae_st_spk, cae_st_hp, cae_st_mic); + if ((cae_st_spk & 0x40) && (cae_st_hp & 0x40) && (cae_st_mic & 0x40)) + break; + usleep_range(1000, 1100); + } + + if (!retry && !((cae_st_spk & 0x40) && (cae_st_hp & 0x40) + && (cae_st_mic & 0x40))) { + dev_err(dev, "%s: CAE is not ready to be loaded.\n", __func__); + ret = -ETIMEDOUT; + goto out_release; + } + + dev_dbg(dev, "%s, cae_fw size=0x%zx, start\n", __func__, cae_fw->size); + + rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE, + RT722_EQ_CTRL_AMIC, 0x8000); + rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE, + RT722_EQ_CTRL_DMIC, 0x8004); + rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE, + RT722_EQ_CTRL_HP, 0x8074); + rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE, + RT722_EQ_CTRL_SPK, 0xa074); + + regcache_cache_bypass(rt722->regmap, true); + for (fw_offset = 0; fw_offset < cae_fw->size;) { + + if (fw_offset + 12 > cae_fw->size) { + dev_err(dev, "%s: Unexpected end of firmware\n", __func__); + ret = -EINVAL; + goto verify_abort; + } + + fw_data = (unsigned char *)&cae_fw->data[fw_offset]; + memcpy(tag, fw_data, 4); + tag[4] = '\0'; + + if (strcmp(tag, xu_tag) == 0) { + dev_dbg(dev, "%s: This is a XU tag", __func__); + memcpy(&addr, (fw_data + 4), 4); + memcpy(&size, (fw_data + 8), 4); + + if (size == 0 || size > cae_fw->size - fw_offset - 12) { + dev_err(dev, "%s: Invalid payload size: %u\n", __func__, size); + ret = -EINVAL; + goto verify_abort; + } + + param_data = (unsigned char *)(fw_data + 12); + + dev_dbg(dev, "%s: addr=0x%x, size=0x%x\n", __func__, addr, size); + + if ((addr <= 0x05302300 && addr >= 0x05300000) || + (addr <= 0x020020b4 && addr >= 0x020000b1)) { + if (addr & BIT(13)) { + mbq_high_val = param_data[0]; + dev_dbg(dev, "MBQ: High Byte 0x%02x\n", mbq_high_val); + fw_offset += (size + 12); + + continue; + } else { + regcache_cache_bypass(rt722->regmap, false); + combined_val = (mbq_high_val << 8) | param_data[0]; + if (addr == 0x20000b1 || addr == 0x20000b4) + combined_val |= (0x2 << 8); + ret = regmap_write(rt722->regmap, addr, combined_val); + if (ret) { + dev_err(dev, + "MBQ fail: addr=0x%x ret=%d\n", addr, ret); + regcache_cache_bypass(rt722->regmap, true); + goto verify_abort; + } + + dev_dbg(dev, "MBQ-reg=0x%x, value=0x%x\n", + addr, combined_val); + + fw_offset += (size + 12); + regcache_cache_bypass(rt722->regmap, true); + continue; + } + } + + for (i = 0; i < size; i++) { + ret = regmap_write(rt722->regmap, addr + i, param_data[i]); + if (ret) { + dev_err(dev, + "CAE write fail: addr=0x%x ret=%d\n", + addr + i, ret); + goto verify_abort; + } + } + fw_offset += (size + 12); + } else if (strcmp(tag, func_tag) == 0) { + dev_dbg(dev, "%s: This is a FUNC tag", __func__); + + memcpy(&func, (fw_data + 4), 4); + memcpy(&value, (fw_data + 8), 4); + dev_dbg(dev, "%s: func=0x%x, value=0x%x\n", + __func__, func, value); + + if (func == 1) + msleep(value); + + fw_offset += 12; + } else { + dev_err(dev, "%s: No XU/FUNC tag at fw_offset=0x%x\n", + __func__, fw_offset); + ret = -EINVAL; + goto verify_abort; + } + } + + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG, + RT722_MISC_CTRL1, 0x8000, 0x0000); + regcache_cache_bypass(rt722->regmap, false); + rt722->cae_update_done = 1; + dev_dbg(dev, "%s: CAE FW update done.\n", __func__); + release_firmware(cae_fw); + return 0; + +verify_abort: + regcache_cache_bypass(rt722->regmap, false); + if (!ret) + ret = -EIO; +out_release: + rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG, + RT722_MISC_CTRL1, 0x8000, 0x0000); + release_firmware(cae_fw); + dev_err(dev, "%s: CAE FW update aborted (ret=%d).\n", __func__, ret); + return ret; +} + +static int rt722_cae_update_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + int ret, changed = 0; + + if (!rt722->hw_init) + return 0; + + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0 && ret != -EACCES) + return ret; + + if (ucontrol->value.integer.value[0]) { + if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) { + ret = rt722_cae_load(rt722); + if (ret) { + dev_err(component->dev, "CAE load failed: %d\n", ret); + goto out; + } else + changed = 1; + } + } else { + if (rt722->cae_update_done) { + rt722->cae_update_done = 0; + changed = 1; + } + } + +out: + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + + return ret < 0 ? ret : changed; +} + +static int rt722_cae_update_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rt722->cae_update_done; + + return 0; +} + + /* For SDCA control DAC/ADC Gain */ static int rt722_sdca_set_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -517,6 +793,61 @@ static int rt722_sdca_fu1e_capture_put(struct snd_kcontrol *kcontrol, return changed; } +static int rt722_sdca_set_fu06_playback_ctl(struct rt722_sdca_priv *rt722) +{ + int err; + unsigned int ch_l, ch_r; + + ch_l = (rt722->fu06_dapm_mute || rt722->fu06_mixer_l_mute) ? 0x01 : 0x00; + ch_r = (rt722->fu06_dapm_mute || rt722->fu06_mixer_r_mute) ? 0x01 : 0x00; + + err = regmap_write(rt722->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, + RT722_SDCA_CTL_FU_MUTE, CH_L), ch_l); + if (err < 0) + return err; + + err = regmap_write(rt722->regmap, + SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, + RT722_SDCA_CTL_FU_MUTE, CH_R), ch_r); + if (err < 0) + return err; + + return 0; +} + +static int rt722_sdca_fu06_playback_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = !rt722->fu06_mixer_l_mute; + ucontrol->value.integer.value[1] = !rt722->fu06_mixer_r_mute; + return 0; +} + +static int rt722_sdca_fu06_playback_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); + int err, changed = 0; + + if (rt722->fu06_mixer_l_mute != !ucontrol->value.integer.value[0] || + rt722->fu06_mixer_r_mute != !ucontrol->value.integer.value[1]) + changed = 1; + + rt722->fu06_mixer_l_mute = !ucontrol->value.integer.value[0]; + rt722->fu06_mixer_r_mute = !ucontrol->value.integer.value[1]; + + err = rt722_sdca_set_fu06_playback_ctl(rt722); + if (err < 0) + return err; + + return changed; +} + static int rt722_sdca_set_fu0f_capture_ctl(struct rt722_sdca_priv *rt722) { int err; @@ -718,6 +1049,8 @@ static const struct snd_kcontrol_new rt722_sdca_controls[] = { RT722_SDCA_CTL_FU_CH_GAIN, CH_R), 8, 3, 0, rt722_sdca_set_gain_get, rt722_sdca_set_gain_put, boost_vol_tlv), /* AMP playback settings */ + SOC_DOUBLE_EXT("FU06 Playback Switch", SND_SOC_NOPM, 0, 1, 1, 0, + rt722_sdca_fu06_playback_get, rt722_sdca_fu06_playback_put), SOC_DOUBLE_R_EXT_TLV("FU06 Playback Volume", SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, RT722_SDCA_CTL_FU_VOLUME, CH_L), @@ -738,6 +1071,9 @@ static const struct snd_kcontrol_new rt722_sdca_controls[] = { RT722_SDCA_CTL_FU_CH_GAIN, CH_01), rt722_sdca_dmic_set_gain_get, rt722_sdca_dmic_set_gain_put, 4, 3, boost_vol_tlv), + /* CAE firmware update */ + SOC_SINGLE_EXT("CAE Update", SND_SOC_NOPM, 0, 1, 0, + rt722_cae_update_get, rt722_cae_update_put), }; static const char * const adc22_mux_text[] = { @@ -807,27 +1143,17 @@ static int rt722_sdca_fu21_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component); - unsigned char unmute = 0x0, mute = 0x1; switch (event) { case SND_SOC_DAPM_POST_PMU: - regmap_write(rt722->regmap, - SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, - RT722_SDCA_CTL_FU_MUTE, CH_L), unmute); - regmap_write(rt722->regmap, - SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, - RT722_SDCA_CTL_FU_MUTE, CH_R), unmute); + rt722->fu06_dapm_mute = false; break; case SND_SOC_DAPM_PRE_PMD: - regmap_write(rt722->regmap, - SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, - RT722_SDCA_CTL_FU_MUTE, CH_L), mute); - regmap_write(rt722->regmap, - SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06, - RT722_SDCA_CTL_FU_MUTE, CH_R), mute); + rt722->fu06_dapm_mute = true; break; } - return 0; + + return rt722_sdca_set_fu06_playback_ctl(rt722); } static int rt722_sdca_fu113_event(struct snd_soc_dapm_widget *w, @@ -1324,9 +1650,12 @@ int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave rt722->first_hw_init = false; rt722->fu1e_dapm_mute = true; rt722->fu0f_dapm_mute = true; + rt722->fu06_dapm_mute = true; + rt722->fu06_mixer_l_mute = rt722->fu06_mixer_r_mute = false; rt722->fu0f_mixer_l_mute = rt722->fu0f_mixer_r_mute = true; rt722->fu1e_mixer_mute[0] = rt722->fu1e_mixer_mute[1] = rt722->fu1e_mixer_mute[2] = rt722->fu1e_mixer_mute[3] = true; + rt722->cae_update_done = 0; return devm_snd_soc_register_component(dev, &soc_sdca_dev_rt722, rt722_sdca_dai, ARRAY_SIZE(rt722_sdca_dai)); diff --git a/sound/soc/codecs/rt722-sdca.h b/sound/soc/codecs/rt722-sdca.h index 823abee9ab76..b654b14334d4 100644 --- a/sound/soc/codecs/rt722-sdca.h +++ b/sound/soc/codecs/rt722-sdca.h @@ -36,10 +36,15 @@ struct rt722_sdca_priv { bool fu0f_dapm_mute; bool fu0f_mixer_l_mute; bool fu0f_mixer_r_mute; + /* For AMP */ + bool fu06_dapm_mute; + bool fu06_mixer_l_mute; + bool fu06_mixer_r_mute; /* For DMIC */ bool fu1e_dapm_mute; bool fu1e_mixer_mute[4]; int hw_vid; + int cae_update_done; }; struct rt722_sdca_dmic_kctrl_priv { @@ -51,6 +56,7 @@ struct rt722_sdca_dmic_kctrl_priv { /* NID */ #define RT722_VENDOR_REG 0x20 +#define RT722_VENDOR_EQ_CAE 0x53 #define RT722_VENDOR_CALI 0x58 #define RT722_VENDOR_SPK_EFUSE 0x5c #define RT722_VENDOR_IMS_DRE 0x5b @@ -60,6 +66,7 @@ struct rt722_sdca_dmic_kctrl_priv { /* Index (NID:20h) */ #define RT722_JD_PRODUCT_NUM 0x00 #define RT722_ANALOG_BIAS_CTL3 0x04 +#define RT722_MISC_CTRL1 0x07 #define RT722_JD_CTRL1 0x09 #define RT722_LDO2_3_CTL1 0x0e #define RT722_LDO1_CTL 0x1a @@ -75,6 +82,12 @@ struct rt722_sdca_dmic_kctrl_priv { #define RT722_SW_CONFIG1 0x8a #define RT722_SW_CONFIG2 0x8b +/* Index (NID:53h) */ +#define RT722_EQ_CTRL_SPK 0x00 +#define RT722_EQ_CTRL_HP 0x100 +#define RT722_EQ_CTRL_DMIC 0x200 +#define RT722_EQ_CTRL_AMIC 0x300 + /* Index (NID:58h) */ #define RT722_DAC_DC_CALI_CTL0 0x00 #define RT722_DAC_DC_CALI_CTL1 0x01 @@ -152,6 +165,20 @@ struct rt722_sdca_dmic_kctrl_priv { #define RT722_BUF_ADDR_HID1 0x44030000 #define RT722_BUF_ADDR_HID2 0x44030020 +/* RT722 CAE parameter settings */ +#define RT722_SPK_CAE_PARAM1 0x44012000 +#define RT722_SPK_CAE_PARAM34 0x44012021 +#define RT722_SPK_CAE_PARAM35 0x44012022 +#define RT722_SPK_CAE_PARAM38 0x44012025 +#define RT722_HP_CAE_PARAM39 0x44022000 +#define RT722_HP_CAE_PARAM64 0x44022019 +#define RT722_HP_CAE_PARAM65 0x4402201a +#define RT722_HP_CAE_PARAM68 0x4402201d +#define RT722_MIC_CAE_PARAM39 0x44042000 +#define RT722_MIC_CAE_PARAM95 0x44042019 +#define RT722_MIC_CAE_PARAM96 0x4404201a +#define RT722_MIC_CAE_PARAM99 0x4404201d + /* RT722 SDCA Control - function number */ #define FUNC_NUM_JACK_CODEC 0x01 #define FUNC_NUM_MIC_ARRAY 0x02 diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 320312f8db92..59642673b4cb 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1809,8 +1809,8 @@ static void sgtl5000_i2c_shutdown(struct i2c_client *client) } static const struct i2c_device_id sgtl5000_id[] = { - {"sgtl5000"}, - {}, + { .name = "sgtl5000" }, + { } }; MODULE_DEVICE_TABLE(i2c, sgtl5000_id); diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index 3343dbb63d2b..2e08fde3989c 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c @@ -35,7 +35,7 @@ struct sigmadsp_control { struct snd_kcontrol *kcontrol; bool is_readback; bool cached; - uint8_t cache[]; + u8 cache[] __counted_by(num_bytes); }; struct sigmadsp_data { @@ -223,7 +223,7 @@ static int sigma_fw_load_control(struct sigmadsp *sigmadsp, return -EINVAL; num_bytes = le16_to_cpu(ctrl_chunk->num_bytes); - ctrl = kzalloc(sizeof(*ctrl) + num_bytes, GFP_KERNEL); + ctrl = kzalloc_flex(*ctrl, cache, num_bytes); if (!ctrl) return -ENOMEM; diff --git a/sound/soc/codecs/simple-amplifier.c b/sound/soc/codecs/simple-amplifier.c index d306c585b52b..ca0e6ce8cc37 100644 --- a/sound/soc/codecs/simple-amplifier.c +++ b/sound/soc/codecs/simple-amplifier.c @@ -1,25 +1,101 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017 BayLibre, SAS. - * Author: Jerome Brunet + * Support for gpio amplifier + * Copyright 2026 CS GROUP France + * Author: Herve Codina + * + * Basic simple amplifier driver + * Copyright (c) 2017 BayLibre, SAS. + * Author: Jerome Brunet */ +#include +#include #include +#include +#include +#include #include +#include #include +#include #include +#include +#include -#define DRV_NAME "simple-amplifier" - -struct simple_amp { - struct gpio_desc *gpiod_enable; +struct simple_amp_single { + struct gpio_desc *gpio; + bool is_inverted; + int kctrl_val; + const char *control_name; }; -static int drv_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *control, int event) +struct simple_amp_point { + u32 gpio_val; + int gain_db; +}; + +struct simple_amp_range { + unsigned int nb_points; + struct simple_amp_point min; + struct simple_amp_point max; +}; + +struct simple_amp_ranges { + unsigned int nb_ranges; + struct simple_amp_range *tab_ranges; +}; + +struct simple_amp_labels { + unsigned int nb_labels; + const char **tab_labels; +}; + +enum simple_amp_mode { + SIMPLE_AMP_MODE_NONE, + SIMPLE_AMP_MODE_RANGES, + SIMPLE_AMP_MODE_LABELS, +}; + +struct simple_amp_multi { + struct gpio_descs *gpios; + u32 kctrl_val; + u32 kctrl_max; + const char *control_name; + unsigned int *tlv_array; + enum simple_amp_mode mode; + union { + struct simple_amp_ranges ranges; + struct simple_amp_labels labels; + }; +}; + +struct simple_amp_data { + unsigned int supports; +#define SIMPLE_AUDIO_SUPPORT_PGA BIT(0) +#define SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES BIT(1) +#define SIMPLE_AUDIO_SUPPORT_MUTE BIT(2) +#define SIMPLE_AUDIO_SUPPORT_BYPASS BIT(3) + + const struct snd_soc_dapm_widget *dapm_widgets; + unsigned int num_dapm_widgets; + const struct snd_soc_dapm_route *dapm_routes; + unsigned int num_dapm_routes; +}; + +struct simple_amp { + const struct simple_amp_data *data; + struct gpio_desc *gpiod_enable; + struct simple_amp_single mute; + struct simple_amp_single bypass; + struct simple_amp_multi gain; +}; + +static int simple_amp_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *control, int event) { struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); - struct simple_amp *priv = snd_soc_component_get_drvdata(c); + struct simple_amp *simple_amp = snd_soc_component_get_drvdata(c); int val; switch (event) { @@ -34,7 +110,7 @@ static int drv_event(struct snd_soc_dapm_widget *w, return -EINVAL; } - gpiod_set_value_cansleep(priv->gpiod_enable, val); + gpiod_set_value_cansleep(simple_amp->gpiod_enable, val); return 0; } @@ -42,7 +118,7 @@ static int drv_event(struct snd_soc_dapm_widget *w, static const struct snd_soc_dapm_widget simple_amp_dapm_widgets[] = { SND_SOC_DAPM_INPUT("INL"), SND_SOC_DAPM_INPUT("INR"), - SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, drv_event, + SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event, (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)), SND_SOC_DAPM_OUTPUT("OUTL"), SND_SOC_DAPM_OUTPUT("OUTR"), @@ -58,47 +134,836 @@ static const struct snd_soc_dapm_route simple_amp_dapm_routes[] = { { "OUTR", NULL, "DRV" }, }; -static const struct snd_soc_component_driver simple_amp_component_driver = { - .dapm_widgets = simple_amp_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(simple_amp_dapm_widgets), - .dapm_routes = simple_amp_dapm_routes, - .num_dapm_routes = ARRAY_SIZE(simple_amp_dapm_routes), +static const struct snd_soc_dapm_widget simple_amp_mono_pga_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("IN"), + SND_SOC_DAPM_OUTPUT("OUT"), + SND_SOC_DAPM_PGA_E("PGA", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event, + (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)), + SND_SOC_DAPM_REGULATOR_SUPPLY("vdd", 0, 0), }; +static const struct snd_soc_dapm_route simple_amp_mono_pga_dapm_routes[] = { + { "PGA", NULL, "IN" }, + { "PGA", NULL, "vdd" }, + { "OUT", NULL, "PGA" }, +}; + +static const struct snd_soc_dapm_widget simple_amp_stereo_pga_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("INL"), + SND_SOC_DAPM_INPUT("INR"), + SND_SOC_DAPM_OUTPUT("OUTL"), + SND_SOC_DAPM_OUTPUT("OUTR"), + SND_SOC_DAPM_PGA_E("PGA", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event, + (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)), + SND_SOC_DAPM_REGULATOR_SUPPLY("vdd", 0, 0), +}; + +static const struct snd_soc_dapm_route simple_amp_stereo_pga_dapm_routes[] = { + { "PGA", NULL, "INL" }, + { "PGA", NULL, "INR" }, + { "PGA", NULL, "vdd" }, + { "OUTL", NULL, "PGA" }, + { "OUTR", NULL, "PGA" }, +}; + +static int simple_amp_single_kctrl_write_gpio(struct simple_amp_single *single, + int kctrl_val) +{ + int gpio_val; + + gpio_val = single->is_inverted ? !kctrl_val : kctrl_val; + + return gpiod_set_value_cansleep(single->gpio, gpio_val); +} + +static int simple_amp_single_kctrl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + return 0; +} + +static int simple_amp_single_kctrl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct simple_amp_single *single = (struct simple_amp_single *)kcontrol->private_value; + + ucontrol->value.integer.value[0] = single->kctrl_val; + + return 0; +} + +static int simple_amp_single_kctrl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct simple_amp_single *single = (struct simple_amp_single *)kcontrol->private_value; + int kctrl_val; + int err; + + kctrl_val = ucontrol->value.integer.value[0] ? 1 : 0; + + if (kctrl_val == single->kctrl_val) + return 0; + + err = simple_amp_single_kctrl_write_gpio(single, kctrl_val); + if (err) + return err; + + single->kctrl_val = kctrl_val; + + return 1; /* The value changed */ +} + +static int simple_amp_single_add_kcontrol(struct snd_soc_component *component, + struct simple_amp_single *single) +{ + struct snd_kcontrol_new control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = single->control_name, + .info = simple_amp_single_kctrl_info, + .get = simple_amp_single_kctrl_get, + .put = simple_amp_single_kctrl_put, + .private_value = (unsigned long)single, + }; + int ret; + + /* Be consistent between single->kctrl_val value and the GPIO value */ + ret = simple_amp_single_kctrl_write_gpio(single, single->kctrl_val); + if (ret) + return ret; + + return snd_soc_add_component_controls(component, &control, 1); +} + +static u32 simple_amp_multi_ranges_kctrl_to_gpio(u32 kctrl_val, + struct simple_amp_ranges *ranges) +{ + struct simple_amp_range *range; + u32 index = kctrl_val; + unsigned int i; + + for (i = 0; i < ranges->nb_ranges; i++) { + range = &ranges->tab_ranges[i]; + + if (index < range->nb_points) + return (range->max.gpio_val >= range->min.gpio_val) ? + range->min.gpio_val + index : + range->min.gpio_val - index; + + index -= range->nb_points; + } + + /* + * Given index out of possible ranges. This is shouldn't happen. + * Signal the issue and return the maximum value + */ + WARN(1, "kctrl_val %u out of ranges\n", kctrl_val); + return ranges->tab_ranges[ranges->nb_ranges - 1].max.gpio_val; +} + +static int simple_amp_multi_kctrl_write_gpios(struct simple_amp_multi *multi, + u32 kctrl_val) +{ + DECLARE_BITMAP(bm, 32); + u32 gpio_val; + + if (kctrl_val > multi->kctrl_max) + return -EINVAL; + + if (multi->mode == SIMPLE_AMP_MODE_RANGES) + gpio_val = simple_amp_multi_ranges_kctrl_to_gpio(kctrl_val, + &multi->ranges); + else + gpio_val = kctrl_val; + + bitmap_from_arr32(bm, &gpio_val, multi->gpios->ndescs); + + return gpiod_multi_set_value_cansleep(multi->gpios, bm); +} + +static int simple_amp_multi_kctrl_int_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value; + + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = multi->kctrl_max; + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + return 0; +} + +static int simple_amp_multi_kctrl_int_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value; + + ucontrol->value.integer.value[0] = multi->kctrl_val; + return 0; +} + +static int simple_amp_multi_kctrl_int_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value; + u32 kctrl_val; + int ret; + + kctrl_val = ucontrol->value.integer.value[0]; + + if (kctrl_val == multi->kctrl_val) + return 0; + + ret = simple_amp_multi_kctrl_write_gpios(multi, kctrl_val); + if (ret) + return ret; + + multi->kctrl_val = kctrl_val; + + return 1; /* The value changed */ +} + +static int simple_amp_multi_kctrl_enum_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value; + + return snd_ctl_enum_info(uinfo, 1, multi->labels.nb_labels, + multi->labels.tab_labels); +} + +static int simple_amp_multi_kctrl_enum_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value; + + ucontrol->value.enumerated.item[0] = multi->kctrl_val; + return 0; +} + +static int simple_amp_multi_kctrl_enum_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value; + u32 kctrl_val; + int ret; + + kctrl_val = ucontrol->value.enumerated.item[0]; + + if (kctrl_val == multi->kctrl_val) + return 0; + + ret = simple_amp_multi_kctrl_write_gpios(multi, kctrl_val); + if (ret) + return ret; + + multi->kctrl_val = kctrl_val; + + return 1; /* The value changed */ +} + +static unsigned int *simple_amp_alloc_tlv_ranges(const struct simple_amp_ranges *ranges) +{ + unsigned int index; + unsigned int *tlv; + unsigned int *t; + unsigned int i; + + tlv = kzalloc_objs(*tlv, 2 + ranges->nb_ranges * 6, GFP_KERNEL); + if (!tlv) + return NULL; + + t = tlv; + + /* Fill first TLV */ + *t++ = SNDRV_CTL_TLVT_DB_RANGE; /* Tag */ + *t++ = ranges->nb_ranges * 6 * sizeof(*tlv); /* Len */ + /* Ranges are sorted from lower to higher value */ + index = 0; + for (i = 0; i < ranges->nb_ranges; i++) { + /* Fill range item i */ + *t++ = index; /* min */ + index += ranges->tab_ranges[i].nb_points; + *t++ = index - 1; /* max */ + *t++ = SNDRV_CTL_TLVT_DB_MINMAX; /* Tag */ + *t++ = 2 * sizeof(*tlv); /* Len */ + *t++ = ranges->tab_ranges[i].min.gain_db; /* min_dB */ + *t++ = ranges->tab_ranges[i].max.gain_db; /* max_dB */ + } + + return tlv; +} + +static int simple_amp_multi_add_kcontrol(struct snd_soc_component *component, + struct simple_amp_multi *multi) +{ + struct snd_kcontrol_new control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = multi->control_name, + .info = simple_amp_multi_kctrl_int_info, + .get = simple_amp_multi_kctrl_int_get, + .put = simple_amp_multi_kctrl_int_put, + .private_value = (unsigned long)multi, + }; + int ret; + + switch (multi->mode) { + case SIMPLE_AMP_MODE_RANGES: + multi->tlv_array = simple_amp_alloc_tlv_ranges(&multi->ranges); + if (!multi->tlv_array) + return -ENOMEM; + + control.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | + SNDRV_CTL_ELEM_ACCESS_READWRITE; + control.tlv.p = multi->tlv_array; + break; + + case SIMPLE_AMP_MODE_LABELS: + /* Use enumerated values */ + control.info = simple_amp_multi_kctrl_enum_info; + control.get = simple_amp_multi_kctrl_enum_get; + control.put = simple_amp_multi_kctrl_enum_put; + break; + + case SIMPLE_AMP_MODE_NONE: + /* Already set control configuration is enough */ + break; + + default: + return -EINVAL; + } + + /* Be consistent between multi->kctrl_val value and the GPIOs value */ + ret = simple_amp_multi_kctrl_write_gpios(multi, multi->kctrl_val); + if (ret) + goto err_free_tlv_array; + + ret = snd_soc_add_component_controls(component, &control, 1); + if (ret) + goto err_free_tlv_array; + + return 0; + +err_free_tlv_array: + kfree(multi->tlv_array); + return ret; +} + +static int simple_amp_add_basic_dapm(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component); + struct device *dev = component->dev; + int ret; + + /* Add basic dapm widgets and routes */ + ret = snd_soc_dapm_new_controls(dapm, simple_amp->data->dapm_widgets, + simple_amp->data->num_dapm_widgets); + if (ret) { + dev_err(dev, "Failed to add basic dapm widgets (%d)\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(dapm, simple_amp->data->dapm_routes, + simple_amp->data->num_dapm_routes); + if (ret) { + dev_err(dev, "Failed to add basic dapm routes (%d)\n", ret); + return ret; + } + + return 0; +} + +struct simple_amp_supply { + const char *prop_name; + const struct snd_soc_dapm_widget dapm_widget; + const struct snd_soc_dapm_route dapm_route; +}; + +static const struct simple_amp_supply simple_amp_supplies[] = { + { + .prop_name = "vddio-supply", + .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vddio", 0, 0), + .dapm_route = { "PGA", NULL, "vddio" }, + }, { + .prop_name = "vdda1-supply", + .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda1", 0, 0), + .dapm_route = { "PGA", NULL, "vdda1" }, + }, { + .prop_name = "vdda2-supply", + .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda2", 0, 0), + .dapm_route = { "PGA", NULL, "vdda2" }, + }, + { /* End of list */} +}; + +static int simple_amp_add_power_supplies(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component); + const struct simple_amp_supply *supply; + struct device *dev = component->dev; + int ret; + + /* + * Those additional power supplies are attached to the PGA. + * If PGA is not supported, simply skipped them. + */ + if (!(simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_PGA)) { + dev_err(dev, "Extra power supplied need PGA\n"); + return -EINVAL; + } + + supply = simple_amp_supplies; + do { + if (!of_property_present(dev->of_node, supply->prop_name)) + continue; + + ret = snd_soc_dapm_new_controls(dapm, &supply->dapm_widget, 1); + if (ret) { + dev_err(dev, "Failed to add control for '%s' (%d)\n", + supply->prop_name, ret); + return ret; + } + ret = snd_soc_dapm_add_routes(dapm, &supply->dapm_route, 1); + if (ret) { + dev_err(dev, "Failed to add route for '%s' (%d)\n", + supply->prop_name, ret); + return ret; + } + } while ((++supply)->prop_name); + + return 0; +} + +static int simple_amp_component_probe(struct snd_soc_component *component) +{ + struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component); + int ret; + + /* Add basic dapm widgets and routes */ + ret = simple_amp_add_basic_dapm(component); + if (ret) + return ret; + + /* Add additional power supplies */ + if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES) { + ret = simple_amp_add_power_supplies(component); + if (ret) + return ret; + } + + if (simple_amp->mute.gpio) { + /* + * The name of the GPIO used is mute. According to this name, 1 + * means muted and 0 means un-muted. + * + * An inversion is expected by ALSA. Indeed from ALSA point of + * view, 1 means 'on' (un-muted) and 0 means 'off' (muted). + */ + simple_amp->mute.is_inverted = true; + simple_amp->mute.kctrl_val = 1; /* Un-muted */ + ret = simple_amp_single_add_kcontrol(component, &simple_amp->mute); + if (ret) + return ret; + } + + if (simple_amp->bypass.gpio) { + ret = simple_amp_single_add_kcontrol(component, &simple_amp->bypass); + if (ret) + return ret; + } + + if (simple_amp->gain.gpios) { + ret = simple_amp_multi_add_kcontrol(component, &simple_amp->gain); + if (ret) + return ret; + } + + return 0; +} + +static void simple_amp_component_remove(struct snd_soc_component *component) +{ + struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component); + + kfree(simple_amp->gain.tlv_array); + simple_amp->gain.tlv_array = NULL; +} + +static const struct snd_soc_component_driver simple_amp_component_driver = { + .probe = simple_amp_component_probe, + .remove = simple_amp_component_remove, +}; + +static int simple_amp_parse_single_gpio(struct device *dev, + struct simple_amp_single *single, + const char *gpio_property) +{ + /* Start with the inactive value */ + single->is_inverted = false; + single->kctrl_val = 0; + single->gpio = devm_gpiod_get_optional(dev, gpio_property, GPIOD_OUT_LOW); + if (IS_ERR(single->gpio)) + return dev_err_probe(dev, PTR_ERR(single->gpio), + "Failed to get '%s' gpio\n", + gpio_property); + return 0; +} + +static int simple_amp_cmp_ranges(const void *a, const void *b) +{ + const struct simple_amp_range *a_range = a; + const struct simple_amp_range *b_range = b; + + /* Ranges a and b don't overlap. This has been already checked */ + + return a_range->min.gain_db - b_range->max.gain_db; +} + +static int simple_amp_check_new_range(const struct simple_amp_range *new_range, + const struct simple_amp_range *tab_ranges, + unsigned int nb_ranges) +{ + unsigned int i; + + for (i = 0; i < nb_ranges; i++) { + /* Check for range overlaps */ + if (new_range->min.gain_db >= tab_ranges[i].min.gain_db && + new_range->min.gain_db <= tab_ranges[i].max.gain_db) + return -EINVAL; + + if (new_range->max.gain_db >= tab_ranges[i].min.gain_db && + new_range->max.gain_db <= tab_ranges[i].max.gain_db) + return -EINVAL; + + if (new_range->min.gain_db <= tab_ranges[i].min.gain_db && + new_range->max.gain_db >= tab_ranges[i].max.gain_db) + return -EINVAL; + } + return 0; +} + +static int simple_amp_parse_ranges(struct device *dev, + struct simple_amp_multi *multi, + const char *ranges_property) +{ + struct simple_amp_ranges *ranges = &multi->ranges; + struct simple_amp_range *range; + struct device_node *np = dev->of_node; + struct simple_amp_point first_point; + unsigned int max_gpio_val; + unsigned int i; + int ret; + u32 u; + s32 s; + + max_gpio_val = (1 << multi->gpios->ndescs) - 1; + + ret = of_property_count_u32_elems(np, ranges_property); + if (ret < 0) + return ret; + + /* The ranges array cannot be empty */ + if (ret == 0) + return -EINVAL; + /* + * One range item is composed of 2 points and each point is composed of + * 2 values. + */ + if (ret % 4) + return -EINVAL; + + ranges->nb_ranges = ret / 4; + + /* The worst case is one range per possible gpio value */ + if (ranges->nb_ranges > max_gpio_val + 1) + return -EINVAL; + + ranges->tab_ranges = devm_kcalloc(dev, ranges->nb_ranges, + sizeof(*ranges->tab_ranges), + GFP_KERNEL); + if (!ranges->tab_ranges) + return -ENOMEM; + + multi->kctrl_max = 0; + for (i = 0; i < ranges->nb_ranges; i++) { + range = &ranges->tab_ranges[i]; + + /* First gpios value */ + ret = of_property_read_u32_index(np, ranges_property, i * 4, &u); + if (ret) + return ret; + if (u > max_gpio_val) + return -EINVAL; + + range->min.gpio_val = u; + + /* First Gain value */ + ret = of_property_read_s32_index(np, ranges_property, i * 4 + 1, &s); + if (ret) + return ret; + + range->min.gain_db = s; + + /* Second gpios value */ + ret = of_property_read_u32_index(np, ranges_property, i * 4 + 2, &u); + if (ret) + return ret; + if (u > max_gpio_val) + return -EINVAL; + + range->max.gpio_val = u; + + /* Second Gain value */ + ret = of_property_read_s32_index(np, ranges_property, i * 4 + 3, &s); + if (ret) + return ret; + + range->max.gain_db = s; + + /* Save the first point for later usage */ + if (i == 0) + first_point = range->min; + + /* Fix min and max if needed */ + if (range->min.gain_db > range->max.gain_db) + swap(range->min, range->max); + + ret = simple_amp_check_new_range(range, ranges->tab_ranges, i); + if (ret) + return ret; + + range->nb_points = abs_diff(range->min.gpio_val, + range->max.gpio_val) + 1; + + multi->kctrl_max += range->nb_points; + } + + multi->kctrl_max -= 1; + + /* Sort the tab_range array by gain_db value */ + sort(ranges->tab_ranges, ranges->nb_ranges, sizeof(*ranges->tab_ranges), + simple_amp_cmp_ranges, NULL); + + /* + * multi->kctrl_val is the index in tab_ranges. + * + * Choose to have the initial amplification value set to the first point + * available in the first range available in the tab_ranges array before + * sorting. + * + * This first point has been identified before sorting. Search for it in + * the sorted array in order to set the multi->kctrl_val initial value. + */ + multi->kctrl_val = 0; + for (i = 0; i < ranges->nb_ranges; i++) { + range = &ranges->tab_ranges[i]; + + if (range->min.gpio_val == first_point.gpio_val && + range->min.gain_db == first_point.gain_db) + break; + + multi->kctrl_val += range->nb_points; + + if (range->max.gpio_val == first_point.gpio_val && + range->max.gain_db == first_point.gain_db) { + multi->kctrl_val--; + break; + } + } + + return 0; +} + +static int simple_amp_parse_labels(struct device *dev, + struct simple_amp_multi *multi, + const char *labels_property) +{ + struct simple_amp_labels *labels = &multi->labels; + struct device_node *np = dev->of_node; + int ret; + + ret = of_property_count_strings(np, labels_property); + if (ret < 0) + return ret; + + /* The labels array cannot be empty */ + if (ret == 0) + return -EINVAL; + + labels->nb_labels = ret; + if (labels->nb_labels > (1 << multi->gpios->ndescs)) + return -EINVAL; + + labels->tab_labels = devm_kcalloc(dev, labels->nb_labels, + sizeof(*labels->tab_labels), + GFP_KERNEL); + if (!labels->tab_labels) + return -ENOMEM; + + multi->kctrl_max = labels->nb_labels - 1; + multi->kctrl_val = 0; + + return of_property_read_string_array(np, labels_property, labels->tab_labels, + labels->nb_labels); +} + +static int simple_amp_parse_multi_gpio(struct device *dev, + struct simple_amp_multi *multi, + const char *gpios_property, + const char *ranges_property, + const char *labels_property) +{ + struct device_node *np = dev->of_node; + int ret; + + /* Start with the value 0 (GPIO inactive). Can be changed later */ + multi->kctrl_val = 0; + multi->gpios = devm_gpiod_get_array_optional(dev, gpios_property, GPIOD_OUT_LOW); + if (IS_ERR(multi->gpios)) + return dev_err_probe(dev, PTR_ERR(multi->gpios), + "Failed to get '%s' gpios\n", + gpios_property); + if (!multi->gpios) + return 0; + + if (multi->gpios->ndescs > 16) + return dev_err_probe(dev, -EINVAL, + "Number of '%s' gpios limited to 16\n", + gpios_property); + + /* Set default value for the kctrl_max. Can be changed later */ + multi->kctrl_max = (1 << multi->gpios->ndescs) - 1; + + multi->mode = SIMPLE_AMP_MODE_NONE; + if (of_property_present(np, ranges_property)) { + ret = simple_amp_parse_ranges(dev, multi, ranges_property); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to parse '%s'\n", + ranges_property); + multi->mode = SIMPLE_AMP_MODE_RANGES; + } else if (of_property_present(np, labels_property)) { + ret = simple_amp_parse_labels(dev, multi, labels_property); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to parse '%s'\n", + labels_property); + + multi->mode = SIMPLE_AMP_MODE_LABELS; + } + + return 0; +} + static int simple_amp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct simple_amp *priv; + struct simple_amp *simple_amp; + int ret; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (priv == NULL) + simple_amp = devm_kzalloc(dev, sizeof(*simple_amp), GFP_KERNEL); + if (!simple_amp) return -ENOMEM; - platform_set_drvdata(pdev, priv); + platform_set_drvdata(pdev, simple_amp); - priv->gpiod_enable = devm_gpiod_get_optional(dev, "enable", - GPIOD_OUT_LOW); - if (IS_ERR(priv->gpiod_enable)) - return dev_err_probe(dev, PTR_ERR(priv->gpiod_enable), + simple_amp->data = of_device_get_match_data(dev); + if (!simple_amp->data) + return -EINVAL; + + simple_amp->gpiod_enable = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_LOW); + if (IS_ERR(simple_amp->gpiod_enable)) + return dev_err_probe(dev, PTR_ERR(simple_amp->gpiod_enable), "Failed to get 'enable' gpio"); + if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_MUTE) { + ret = simple_amp_parse_single_gpio(dev, &simple_amp->mute, "mute"); + if (ret) + return ret; + } + + if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_BYPASS) { + ret = simple_amp_parse_single_gpio(dev, &simple_amp->bypass, "bypass"); + if (ret) + return ret; + } + + if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_PGA) { + ret = simple_amp_parse_multi_gpio(dev, &simple_amp->gain, "gain", + "gain-ranges", "gain-labels"); + if (ret) + return ret; + } + + /* Set controls name */ + simple_amp->gain.control_name = "Volume"; + simple_amp->mute.control_name = "Switch"; + simple_amp->bypass.control_name = "Bypass Switch"; + + if (simple_amp->gain.mode == SIMPLE_AMP_MODE_LABELS) { + /* + * The gain widget control will use enumerated values. + * + * Having just "Voltage" and "Switch" widget names with + * enumerated values and boolean value can confuse ALSA in terms + * of possible values (strings). + * + * Make things clear and avoid the just "Switch" name in that + * case. + */ + simple_amp->mute.control_name = "Out Switch"; + } + return devm_snd_soc_register_component(dev, &simple_amp_component_driver, NULL, 0); } -#ifdef CONFIG_OF +static const struct simple_amp_data simple_audio_amplifier_data = { + .dapm_widgets = simple_amp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(simple_amp_dapm_widgets), + .dapm_routes = simple_amp_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(simple_amp_dapm_routes), +}; + +static const struct simple_amp_data simple_audio_mono_pga_data = { + .supports = SIMPLE_AUDIO_SUPPORT_PGA | + SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES | + SIMPLE_AUDIO_SUPPORT_MUTE | + SIMPLE_AUDIO_SUPPORT_BYPASS, + .dapm_widgets = simple_amp_mono_pga_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(simple_amp_mono_pga_dapm_widgets), + .dapm_routes = simple_amp_mono_pga_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(simple_amp_mono_pga_dapm_routes), +}; + +static const struct simple_amp_data simple_audio_stereo_pga_data = { + .supports = SIMPLE_AUDIO_SUPPORT_PGA | + SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES | + SIMPLE_AUDIO_SUPPORT_MUTE | + SIMPLE_AUDIO_SUPPORT_BYPASS, + .dapm_widgets = simple_amp_stereo_pga_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(simple_amp_stereo_pga_dapm_widgets), + .dapm_routes = simple_amp_stereo_pga_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(simple_amp_stereo_pga_dapm_routes), +}; + static const struct of_device_id simple_amp_ids[] = { - { .compatible = "dioo,dio2125", }, - { .compatible = "simple-audio-amplifier", }, + { .compatible = "dioo,dio2125", .data = &simple_audio_amplifier_data}, + { .compatible = "simple-audio-amplifier", .data = &simple_audio_amplifier_data}, + { .compatible = "gpio-audio-amp-mono", .data = &simple_audio_mono_pga_data}, + { .compatible = "gpio-audio-amp-stereo", .data = &simple_audio_stereo_pga_data}, { } }; MODULE_DEVICE_TABLE(of, simple_amp_ids); -#endif static struct platform_driver simple_amp_driver = { .driver = { - .name = DRV_NAME, - .of_match_table = of_match_ptr(simple_amp_ids), + .name = "simple-amplifier", + .of_match_table = simple_amp_ids, }, .probe = simple_amp_probe, }; @@ -107,4 +972,5 @@ module_platform_driver(simple_amp_driver); MODULE_DESCRIPTION("ASoC Simple Audio Amplifier driver"); MODULE_AUTHOR("Jerome Brunet "); +MODULE_AUTHOR("Herve Codina "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c index 06de2b4fce5e..c7aaf98ef71e 100644 --- a/sound/soc/codecs/sma1303.c +++ b/sound/soc/codecs/sma1303.c @@ -1782,8 +1782,8 @@ static void sma1303_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id sma1303_i2c_id[] = { - {"sma1303"}, - {} + { .name = "sma1303" }, + { } }; MODULE_DEVICE_TABLE(i2c, sma1303_i2c_id); diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c index 5850bf6e71ca..c52fe95b30c6 100644 --- a/sound/soc/codecs/sma1307.c +++ b/sound/soc/codecs/sma1307.c @@ -1592,6 +1592,7 @@ static void sma1307_check_fault_worker(struct work_struct *work) struct sma1307_priv *sma1307 = container_of(work, struct sma1307_priv, check_fault_work.work); unsigned int status1_val, status2_val; + char volume[sizeof("VOLUME=0x12345678")]; char *envp[3] = { NULL, NULL, NULL }; if (sma1307->tsdw_cnt) @@ -1607,7 +1608,7 @@ static void sma1307_check_fault_worker(struct work_struct *work) if (~status1_val & SMA1307_OT1_OK_STATUS) { dev_crit(sma1307->dev, "%s: OT1(Over Temperature Level 1)\n", __func__); - envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1"); + envp[0] = "STATUS=OT1"; if (sma1307->sw_ot1_prot) { /* Volume control (Current Volume -3dB) */ if ((sma1307->cur_vol + 6) <= 0xFA) { @@ -1615,8 +1616,9 @@ static void sma1307_check_fault_worker(struct work_struct *work) regmap_write(sma1307->regmap, SMA1307_0A_SPK_VOL, sma1307->cur_vol); - envp[1] = kasprintf(GFP_KERNEL, - "VOLUME=0x%02X", sma1307->cur_vol); + snprintf(volume, sizeof(volume), + "VOLUME=0x%02X", sma1307->cur_vol); + envp[1] = volume; } } sma1307->tsdw_cnt++; @@ -1625,48 +1627,53 @@ static void sma1307_check_fault_worker(struct work_struct *work) SMA1307_0A_SPK_VOL, sma1307->init_vol); sma1307->tsdw_cnt = 0; sma1307->cur_vol = sma1307->init_vol; - envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1_CLEAR"); - envp[1] = kasprintf(GFP_KERNEL, - "VOLUME=0x%02X", sma1307->cur_vol); + envp[0] = "STATUS=OT1_CLEAR"; + snprintf(volume, sizeof(volume), "VOLUME=0x%02X", + sma1307->cur_vol); + envp[1] = volume; } if (~status1_val & SMA1307_OT2_OK_STATUS) { dev_crit(sma1307->dev, "%s: OT2(Over Temperature Level 2)\n", __func__); - envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT2"); + envp[0] = "STATUS=OT2"; + envp[1] = NULL; } if (status1_val & SMA1307_UVLO_STATUS) { dev_crit(sma1307->dev, "%s: UVLO(Under Voltage Lock Out)\n", __func__); - envp[0] = kasprintf(GFP_KERNEL, "STATUS=UVLO"); + envp[0] = "STATUS=UVLO"; + envp[1] = NULL; } if (status1_val & SMA1307_OVP_BST_STATUS) { dev_crit(sma1307->dev, "%s: OVP_BST(Over Voltage Protection)\n", __func__); - envp[0] = kasprintf(GFP_KERNEL, "STATUS=OVP_BST"); + envp[0] = "STATUS=OVP_BST"; + envp[1] = NULL; } if (status2_val & SMA1307_OCP_SPK_STATUS) { dev_crit(sma1307->dev, "%s: OCP_SPK(Over Current Protect SPK)\n", __func__); - envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_SPK"); + envp[0] = "STATUS=OCP_SPK"; + envp[1] = NULL; } if (status2_val & SMA1307_OCP_BST_STATUS) { dev_crit(sma1307->dev, "%s: OCP_BST(Over Current Protect Boost)\n", __func__); - envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_BST"); + envp[0] = "STATUS=OCP_BST"; + envp[1] = NULL; } if (status2_val & SMA1307_CLK_MON_STATUS) { dev_crit(sma1307->dev, "%s: CLK_FAULT(No clock input)\n", __func__); - envp[0] = kasprintf(GFP_KERNEL, "STATUS=CLK_FAULT"); + envp[0] = "STATUS=CLK_FAULT"; + envp[1] = NULL; } if (envp[0] != NULL) { if (kobject_uevent_env(sma1307->kobj, KOBJ_CHANGE, envp)) dev_err(sma1307->dev, "%s: Error sending uevent\n", __func__); - kfree(envp[0]); - kfree(envp[1]); } if (sma1307->check_fault_status) { @@ -2008,8 +2015,8 @@ static void sma1307_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id sma1307_i2c_id[] = { - { "sma1307a" }, - { "sma1307aq" }, + { .name = "sma1307a" }, + { .name = "sma1307aq" }, { } }; diff --git a/sound/soc/codecs/src4xxx-i2c.c b/sound/soc/codecs/src4xxx-i2c.c index 55f00ce7c718..34b3abdb9a70 100644 --- a/sound/soc/codecs/src4xxx-i2c.c +++ b/sound/soc/codecs/src4xxx-i2c.c @@ -19,7 +19,7 @@ static int src4xxx_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id src4xxx_i2c_ids[] = { - { "src4392" }, + { .name = "src4392" }, { } }; MODULE_DEVICE_TABLE(i2c, src4xxx_i2c_ids); diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index 9008e5416004..5192569ba6a8 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -794,7 +794,7 @@ MODULE_DEVICE_TABLE(of, ssm2518_dt_ids); #endif static const struct i2c_device_id ssm2518_i2c_ids[] = { - { "ssm2518" }, + { .name = "ssm2518" }, { } }; MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids); diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c index 49c74cba17c7..23570d0a2f53 100644 --- a/sound/soc/codecs/ssm2602-i2c.c +++ b/sound/soc/codecs/ssm2602-i2c.c @@ -26,9 +26,9 @@ static int ssm2602_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ssm2602_i2c_id[] = { - { "ssm2602", SSM2602 }, - { "ssm2603", SSM2602 }, - { "ssm2604", SSM2604 }, + { .name = "ssm2602", .driver_data = SSM2602 }, + { .name = "ssm2603", .driver_data = SSM2602 }, + { .name = "ssm2604", .driver_data = SSM2604 }, { } }; MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index 15f88624faeb..8415dd163edd 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -472,7 +472,7 @@ static int ssm4567_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ssm4567_i2c_ids[] = { - { "ssm4567" }, + { .name = "ssm4567" }, { } }; MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index b9f9784f5164..652c6e3a9e63 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -1154,9 +1154,9 @@ static int sta32x_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id sta32x_i2c_id[] = { - { "sta326" }, - { "sta328" }, - { "sta329" }, + { .name = "sta326" }, + { .name = "sta328" }, + { .name = "sta329" }, { } }; MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id); diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 71af82b099c0..99c7f7ac807b 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1236,11 +1236,8 @@ static int sta350_i2c_probe(struct i2c_client *i2c) return ret; } -static void sta350_i2c_remove(struct i2c_client *client) -{} - static const struct i2c_device_id sta350_i2c_id[] = { - { "sta350" }, + { .name = "sta350" }, { } }; MODULE_DEVICE_TABLE(i2c, sta350_i2c_id); @@ -1250,8 +1247,7 @@ static struct i2c_driver sta350_i2c_driver = { .name = "sta350", .of_match_table = of_match_ptr(st350_dt_ids), }, - .probe = sta350_i2c_probe, - .remove = sta350_i2c_remove, + .probe = sta350_i2c_probe, .id_table = sta350_i2c_id, }; diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 946aa6a4e57c..7d57999f9cb1 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -361,7 +361,7 @@ static int sta529_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id sta529_i2c_id[] = { - { "sta529" }, + { .name = "sta529" }, { } }; MODULE_DEVICE_TABLE(i2c, sta529_i2c_id); diff --git a/sound/soc/codecs/tac5xx2-sdw.c b/sound/soc/codecs/tac5xx2-sdw.c new file mode 100644 index 000000000000..bb12cfb6da12 --- /dev/null +++ b/sound/soc/codecs/tac5xx2-sdw.c @@ -0,0 +1,2037 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC Texas Instruments TAC5XX2 Audio Smart Amplifier +// +// Copyright (C) 2025 Texas Instruments Incorporated +// https://www.ti.com +// +// Author: Niranjan H Y + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tac5xx2.h" + +#define TAC5XX2_PROBE_TIMEOUT_MS 3000 +#define TAC5XX2_FW_CACHE_TIMEOUT_MS 300 + +#define TAC5XX2_DEVICE_RATES (SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | \ + SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_88200) +#define TAC5XX2_DEVICE_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) +/* Define channel constants */ +#define TAC_CHANNEL_LEFT 1 +#define TAC_CHANNEL_RIGHT 2 +#define TAC_JACK_MONO_CS 2 + +#define TAC_MUTE_REG(func, fu, ch) \ + SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##fu, \ + TAC_SDCA_CHANNEL_MUTE, TAC_CHANNEL_##ch) +#define TAC_USAGE_REG(func, ent) \ + SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##ent, \ + TAC_SDCA_CTL_USAGE, 0) +#define TAC_XU_BYPASS_REG(func, xu) \ + SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##xu, \ + TAC_SDCA_CTL_XU_BYPASS, 0) + +/* mute registers */ +#define FU21_L_MUTE_REG TAC_MUTE_REG(SA, FU21, LEFT) +#define FU21_R_MUTE_REG TAC_MUTE_REG(SA, FU21, RIGHT) +#define FU23_L_MUTE_REG TAC_MUTE_REG(SA, FU23, LEFT) +#define FU23_R_MUTE_REG TAC_MUTE_REG(SA, FU23, RIGHT) +#define FU26_MUTE_REG TAC_MUTE_REG(SA, FU26, LEFT) +#define FU11_L_MUTE_REG TAC_MUTE_REG(SM, FU11, LEFT) +#define FU11_R_MUTE_REG TAC_MUTE_REG(SM, FU11, RIGHT) +#define FU113_L_MUTE_REG TAC_MUTE_REG(SM, FU113, LEFT) +#define FU113_R_MUTE_REG TAC_MUTE_REG(SM, FU113, RIGHT) +#define FU41_L_MUTE_REG TAC_MUTE_REG(UAJ, FU41, LEFT) +#define FU41_R_MUTE_REG TAC_MUTE_REG(UAJ, FU41, RIGHT) +#define FU36_MUTE_REG TAC_MUTE_REG(UAJ, FU36, RIGHT) + +/* it/ot usage */ +#define IT11_USAGE_REG TAC_USAGE_REG(SM, IT11) +#define IT41_USAGE_REG TAC_USAGE_REG(UAJ, IT41) +#define IT33_USAGE_REG TAC_USAGE_REG(UAJ, IT33) +#define OT113_USAGE_REG TAC_USAGE_REG(SM, OT113) +#define OT45_USAGE_REG TAC_USAGE_REG(UAJ, OT45) +#define OT36_USAGE_REG TAC_USAGE_REG(UAJ, OT36) + +/* xu bypass */ +#define XU12_BYPASS_REG TAC_XU_BYPASS_REG(SM, XU12) +#define XU42_BYPASS_REG TAC_XU_BYPASS_REG(UAJ, XU42) + +#define TAC_DSP_ALGO_STATUS TAC_REG_SDW(0, 3, 12) +#define TAC_DSP_ALGO_STATUS_RUNNING 0x20 +#define TAC_FW_HDR_SIZE 88 +#define TAC_FW_FILE_HDR 20 +#define TAC_MAX_FW_CHUNKS 512 + +struct tac_fw_hdr { + u32 size; + u32 version_offset; + u32 plt_id; + u32 ppc3_ver; + u64 timestamp; + u8 ddc_name[64]; +}; + +/* Firmware file/chunk structure */ +struct tac_fw_file { + u32 vendor_id; + u32 file_id; + u32 version; + u32 length; + u32 dest_addr; + u8 *fw_data; +}; + +/* TLV for volume control */ +static const DECLARE_TLV_DB_SCALE(tac5xx2_amp_tlv, 0, 50, 0); +static const DECLARE_TLV_DB_SCALE(tac5xx2_dvc_tlv, -7200, 50, 0); + +/* Q7.8 volume control parameters: range -72dB to +6dB, step 0.5dB */ +#define TAC_DVC_STEP 128 /* 0.5 dB in Q7.8 format */ +#define TAC_DVC_MIN (-144) /* -72 dB / 0.5 dB step */ +#define TAC_DVC_MAX 12 /* +6 dB / 0.5 dB step */ + +/* TAC-specific stereo volume control macro using SDW_SDCA_CTL (single control for L/R) */ +#define TAC_DOUBLE_Q78_TLV(name, func_id, ent_id) \ + SDCA_DOUBLE_Q78_TLV(name, \ + SDW_SDCA_CTL(TAC_FUNCTION_ID_##func_id, TAC_SDCA_ENT_##ent_id, \ + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), \ + SDW_SDCA_CTL(TAC_FUNCTION_ID_##func_id, TAC_SDCA_ENT_##ent_id, \ + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), \ + TAC_DVC_MIN, TAC_DVC_MAX, TAC_DVC_STEP, tac5xx2_dvc_tlv) + +struct tac5xx2_prv { + struct snd_soc_component *component; + struct sdw_slave *sdw_peripheral; + struct sdca_function_data *sa_func_data; + struct sdca_function_data *sm_func_data; + struct sdca_function_data *uaj_func_data; + struct sdca_function_data *hid_func_data; + enum sdw_slave_status status; + struct regmap *regmap; + struct device *dev; + bool hw_init; + bool first_hw_init_done; + u32 part_id; + struct snd_soc_jack *hs_jack; + int jack_type; + /* Custom fw binary. UMP File Download is not used. */ + unsigned int fw_file_cnt; + struct tac_fw_file *fw_files; + struct completion fw_caching_complete; + bool fw_dl_success; + u8 fw_binaryname[64]; +}; + +static const struct reg_default tac_reg_default[] = { + {TAC_SW_RESET, 0x0}, + {TAC_SLEEP_MODEZ, 0x0}, + {TAC_FEATURE_PDZ, 0x0}, + {TAC_TX_CH_EN, 0xf0}, + {TAC_REG_SDW(0, 0, 0x5), 0xcf}, + {TAC_REG_SDW(0, 0, 0x6), 0xa}, + {TAC_REG_SDW(0, 0, 0x7), 0x0}, + {TAC_REG_SDW(0, 0, 0x8), 0xfe}, + {TAC_REG_SDW(0, 0, 0x9), 0x9}, + {TAC_REG_SDW(0, 0, 0xa), 0x28}, + {TAC_REG_SDW(0, 0, 0xb), 0x1}, + {TAC_REG_SDW(0, 0, 0xc), 0x11}, + {TAC_REG_SDW(0, 0, 0xd), 0x11}, + {TAC_REG_SDW(0, 0, 0xe), 0x61}, + {TAC_REG_SDW(0, 0, 0xf), 0x0}, + {TAC_REG_SDW(0, 0, 0x10), 0x50}, + {TAC_REG_SDW(0, 0, 0x11), 0x70}, + {TAC_REG_SDW(0, 0, 0x12), 0x60}, + {TAC_REG_SDW(0, 0, 0x13), 0x28}, + {TAC_REG_SDW(0, 0, 0x14), 0x0}, + {TAC_REG_SDW(0, 0, 0x15), 0x18}, + {TAC_REG_SDW(0, 0, 0x16), 0x20}, + {TAC_REG_SDW(0, 0, 0x17), 0x0}, + {TAC_REG_SDW(0, 0, 0x18), 0x18}, + {TAC_REG_SDW(0, 0, 0x19), 0x54}, + {TAC_REG_SDW(0, 0, 0x1a), 0x8}, + {TAC_REG_SDW(0, 0, 0x1b), 0x0}, + {TAC_REG_SDW(0, 0, 0x1c), 0x30}, + {TAC_REG_SDW(0, 0, 0x1d), 0x0}, + {TAC_REG_SDW(0, 0, 0x1e), 0x0}, + {TAC_REG_SDW(0, 0, 0x1f), 0x0}, + {TAC_REG_SDW(0, 0, 0x20), 0x0}, + {TAC_REG_SDW(0, 0, 0x21), 0x20}, + {TAC_REG_SDW(0, 0, 0x22), 0x21}, + {TAC_REG_SDW(0, 0, 0x23), 0x22}, + {TAC_REG_SDW(0, 0, 0x24), 0x23}, + {TAC_REG_SDW(0, 0, 0x25), 0x4}, + {TAC_REG_SDW(0, 0, 0x26), 0x5}, + {TAC_REG_SDW(0, 0, 0x27), 0x6}, + {TAC_REG_SDW(0, 0, 0x28), 0x7}, + {TAC_REG_SDW(0, 0, 0x29), 0x0}, + {TAC_REG_SDW(0, 0, 0x2a), 0x0}, + {TAC_REG_SDW(0, 0, 0x2b), 0x0}, + {TAC_REG_SDW(0, 0, 0x2c), 0x20}, + {TAC_REG_SDW(0, 0, 0x2d), 0x21}, + {TAC_REG_SDW(0, 0, 0x2e), 0x2}, + {TAC_REG_SDW(0, 0, 0x2f), 0x3}, + {TAC_REG_SDW(0, 0, 0x30), 0x4}, + {TAC_REG_SDW(0, 0, 0x31), 0x5}, + {TAC_REG_SDW(0, 0, 0x32), 0x6}, + {TAC_REG_SDW(0, 0, 0x33), 0x7}, + {TAC_REG_SDW(0, 0, 0x34), 0x0}, + {TAC_REG_SDW(0, 0, 0x35), 0x90}, + {TAC_REG_SDW(0, 0, 0x36), 0x80}, + {TAC_REG_SDW(0, 0, 0x37), 0x0}, + {TAC_REG_SDW(0, 0, 0x39), 0x0}, + {TAC_REG_SDW(0, 0, 0x3a), 0x90}, + {TAC_REG_SDW(0, 0, 0x3b), 0x80}, + {TAC_REG_SDW(0, 0, 0x3c), 0x0}, + {TAC_REG_SDW(0, 0, 0x3e), 0x0}, + {TAC_REG_SDW(0, 0, 0x3f), 0x90}, + {TAC_REG_SDW(0, 0, 0x40), 0x80}, + {TAC_REG_SDW(0, 0, 0x41), 0x0}, + {TAC_REG_SDW(0, 0, 0x43), 0x90}, + {TAC_REG_SDW(0, 0, 0x44), 0x80}, + {TAC_REG_SDW(0, 0, 0x45), 0x0}, + {TAC_REG_SDW(0, 0, 0x47), 0x90}, + {TAC_REG_SDW(0, 0, 0x48), 0x80}, + {TAC_REG_SDW(0, 0, 0x49), 0x0}, + {TAC_REG_SDW(0, 0, 0x4b), 0x90}, + {TAC_REG_SDW(0, 0, 0x4c), 0x80}, + {TAC_REG_SDW(0, 0, 0x4d), 0x0}, + {TAC_REG_SDW(0, 0, 0x4f), 0x31}, + {TAC_REG_SDW(0, 0, 0x50), 0x0}, + {TAC_REG_SDW(0, 0, 0x51), 0x0}, + {TAC_REG_SDW(0, 0, 0x52), 0x90}, + {TAC_REG_SDW(0, 0, 0x53), 0x80}, + {TAC_REG_SDW(0, 0, 0x55), 0x90}, + {TAC_REG_SDW(0, 0, 0x56), 0x80}, + {TAC_REG_SDW(0, 0, 0x58), 0x90}, + {TAC_REG_SDW(0, 0, 0x59), 0x80}, + {TAC_REG_SDW(0, 0, 0x5b), 0x90}, + {TAC_REG_SDW(0, 0, 0x5c), 0x80}, + {TAC_REG_SDW(0, 0, 0x5e), 0x8}, + {TAC_REG_SDW(0, 0, 0x5f), 0x8}, + {TAC_REG_SDW(0, 0, 0x60), 0x0}, + {TAC_REG_SDW(0, 0, 0x61), 0x0}, + {TAC_REG_SDW(0, 0, 0x62), 0xff}, + {TAC_REG_SDW(0, 0, 0x63), 0xc0}, + {TAC_REG_SDW(0, 0, 0x64), 0x5}, + {TAC_REG_SDW(0, 0, 0x65), 0x3}, + {TAC_REG_SDW(0, 0, 0x66), 0x0}, + {TAC_REG_SDW(0, 0, 0x67), 0x0}, + {TAC_REG_SDW(0, 0, 0x68), 0x0}, + {TAC_REG_SDW(0, 0, 0x69), 0x8}, + {TAC_REG_SDW(0, 0, 0x6a), 0x0}, + {TAC_REG_SDW(0, 0, 0x6b), 0xa0}, + {TAC_REG_SDW(0, 0, 0x6c), 0x18}, + {TAC_REG_SDW(0, 0, 0x6d), 0x18}, + {TAC_REG_SDW(0, 0, 0x6e), 0x18}, + {TAC_REG_SDW(0, 0, 0x6f), 0x18}, + {TAC_REG_SDW(0, 0, 0x70), 0x88}, + {TAC_REG_SDW(0, 0, 0x71), 0xff}, + {TAC_REG_SDW(0, 0, 0x72), 0x0}, + {TAC_REG_SDW(0, 0, 0x73), 0x31}, + {TAC_REG_SDW(0, 0, 0x74), 0xc0}, + {TAC_REG_SDW(0, 0, 0x75), 0x0}, + {TAC_REG_SDW(0, 0, 0x76), 0x0}, + {TAC_REG_SDW(0, 0, 0x77), 0x0}, + {TAC_REG_SDW(0, 0, 0x78), 0x0}, + {TAC_REG_SDW(0, 0, 0x7b), 0x0}, + {TAC_REG_SDW(0, 0, 0x7c), 0xd0}, + {TAC_REG_SDW(0, 0, 0x7d), 0x0}, + {TAC_REG_SDW(0, 0, 0x7e), 0x0}, + {TAC_REG_SDW(0, 1, 0x1), 0x0}, + {TAC_REG_SDW(0, 1, 0x2), 0x0}, + {TAC_REG_SDW(0, 1, 0x3), 0x0}, + {TAC_REG_SDW(0, 1, 0x4), 0x4}, + {TAC_REG_SDW(0, 1, 0x5), 0x0}, + {TAC_REG_SDW(0, 1, 0x6), 0x0}, + {TAC_REG_SDW(0, 1, 0x7), 0x0}, + {TAC_REG_SDW(0, 1, 0x8), 0x0}, + {TAC_REG_SDW(0, 1, 0x9), 0x0}, + {TAC_REG_SDW(0, 1, 0xa), 0x0}, + {TAC_REG_SDW(0, 1, 0xb), 0x1}, + {TAC_REG_SDW(0, 1, 0xc), 0x0}, + {TAC_REG_SDW(0, 1, 0xd), 0x0}, + {TAC_REG_SDW(0, 1, 0xe), 0x0}, + {TAC_REG_SDW(0, 1, 0xf), 0x8}, + {TAC_REG_SDW(0, 1, 0x10), 0x0}, + {TAC_REG_SDW(0, 1, 0x11), 0x0}, + {TAC_REG_SDW(0, 1, 0x12), 0x1}, + {TAC_REG_SDW(0, 1, 0x13), 0x0}, + {TAC_REG_SDW(0, 1, 0x14), 0x0}, + {TAC_REG_SDW(0, 1, 0x15), 0x0}, + {TAC_REG_SDW(0, 1, 0x16), 0x0}, + {TAC_REG_SDW(0, 1, 0x17), 0x0}, + {TAC_REG_SDW(0, 1, 0x18), 0x0}, + {TAC_REG_SDW(0, 1, 0x19), 0x0}, + {TAC_REG_SDW(0, 1, 0x1a), 0x0}, + {TAC_REG_SDW(0, 1, 0x1b), 0x0}, + {TAC_REG_SDW(0, 1, 0x1c), 0x0}, + {TAC_REG_SDW(0, 1, 0x1d), 0x0}, + {TAC_REG_SDW(0, 1, 0x1e), 0x2}, + {TAC_REG_SDW(0, 1, 0x1f), 0x8}, + {TAC_REG_SDW(0, 1, 0x20), 0x9}, + {TAC_REG_SDW(0, 1, 0x21), 0xa}, + {TAC_REG_SDW(0, 1, 0x22), 0xb}, + {TAC_REG_SDW(0, 1, 0x23), 0xc}, + {TAC_REG_SDW(0, 1, 0x24), 0xd}, + {TAC_REG_SDW(0, 1, 0x25), 0xe}, + {TAC_REG_SDW(0, 1, 0x26), 0xf}, + {TAC_REG_SDW(0, 1, 0x27), 0x8}, + {TAC_REG_SDW(0, 1, 0x28), 0x9}, + {TAC_REG_SDW(0, 1, 0x29), 0xa}, + {TAC_REG_SDW(0, 1, 0x2a), 0xb}, + {TAC_REG_SDW(0, 1, 0x2b), 0xc}, + {TAC_REG_SDW(0, 1, 0x2c), 0xd}, + {TAC_REG_SDW(0, 1, 0x2d), 0xe}, + {TAC_REG_SDW(0, 1, 0x2e), 0xf}, + {TAC_REG_SDW(0, 1, 0x2f), 0x0}, + {TAC_REG_SDW(0, 1, 0x30), 0x0}, + {TAC_REG_SDW(0, 1, 0x31), 0x0}, + {TAC_REG_SDW(0, 1, 0x32), 0x0}, + {TAC_REG_SDW(0, 1, 0x33), 0x0}, + {TAC_REG_SDW(0, 1, 0x34), 0x0}, + {TAC_REG_SDW(0, 1, 0x35), 0x0}, + {TAC_REG_SDW(0, 1, 0x36), 0x0}, + {TAC_REG_SDW(0, 1, 0x37), 0x0}, + {TAC_REG_SDW(0, 1, 0x38), 0x98}, + {TAC_REG_SDW(0, 1, 0x39), 0x0}, + {TAC_REG_SDW(0, 1, 0x3a), 0x0}, + {TAC_REG_SDW(0, 1, 0x3b), 0x0}, + {TAC_REG_SDW(0, 1, 0x3c), 0x1}, + {TAC_REG_SDW(0, 1, 0x3d), 0x2}, + {TAC_REG_SDW(0, 1, 0x3e), 0x3}, + {TAC_REG_SDW(0, 1, 0x3f), 0x4}, + {TAC_REG_SDW(0, 1, 0x40), 0x5}, + {TAC_REG_SDW(0, 1, 0x41), 0x6}, + {TAC_REG_SDW(0, 1, 0x42), 0x7}, + {TAC_REG_SDW(0, 1, 0x43), 0x0}, + {TAC_REG_SDW(0, 1, 0x44), 0x0}, + {TAC_REG_SDW(0, 1, 0x45), 0x1}, + {TAC_REG_SDW(0, 1, 0x46), 0x2}, + {TAC_REG_SDW(0, 1, 0x47), 0x3}, + {TAC_REG_SDW(0, 1, 0x48), 0x4}, + {TAC_REG_SDW(0, 1, 0x49), 0x5}, + {TAC_REG_SDW(0, 1, 0x4a), 0x6}, + {TAC_REG_SDW(0, 1, 0x4b), 0x7}, + {TAC_REG_SDW(0, 1, 0x4c), 0x98}, + {TAC_REG_SDW(0, 1, 0x4d), 0x0}, + {TAC_REG_SDW(0, 1, 0x4e), 0x0}, + {TAC_REG_SDW(0, 1, 0x4f), 0x0}, + {TAC_REG_SDW(0, 1, 0x50), 0x1}, + {TAC_REG_SDW(0, 1, 0x51), 0x2}, + {TAC_REG_SDW(0, 1, 0x52), 0x3}, + {TAC_REG_SDW(0, 1, 0x53), 0x4}, + {TAC_REG_SDW(0, 1, 0x54), 0x5}, + {TAC_REG_SDW(0, 1, 0x55), 0x6}, + {TAC_REG_SDW(0, 1, 0x56), 0x7}, + {TAC_REG_SDW(0, 1, 0x57), 0x0}, + {TAC_REG_SDW(0, 1, 0x58), 0x0}, + {TAC_REG_SDW(0, 1, 0x59), 0x1}, + {TAC_REG_SDW(0, 1, 0x5a), 0x2}, + {TAC_REG_SDW(0, 1, 0x5b), 0x3}, + {TAC_REG_SDW(0, 1, 0x5c), 0x4}, + {TAC_REG_SDW(0, 1, 0x5d), 0x5}, + {TAC_REG_SDW(0, 1, 0x5e), 0x6}, + {TAC_REG_SDW(0, 1, 0x5f), 0x7}, + {TAC_REG_SDW(0, 1, 0x60), 0x98}, + {TAC_REG_SDW(0, 1, 0x61), 0x0}, + {TAC_REG_SDW(0, 1, 0x62), 0x0}, + {TAC_REG_SDW(0, 1, 0x63), 0x0}, + {TAC_REG_SDW(0, 1, 0x64), 0x1}, + {TAC_REG_SDW(0, 1, 0x65), 0x2}, + {TAC_REG_SDW(0, 1, 0x66), 0x3}, + {TAC_REG_SDW(0, 1, 0x67), 0x4}, + {TAC_REG_SDW(0, 1, 0x68), 0x5}, + {TAC_REG_SDW(0, 1, 0x69), 0x6}, + {TAC_REG_SDW(0, 1, 0x6a), 0x7}, + {TAC_REG_SDW(0, 1, 0x6b), 0x0}, + {TAC_REG_SDW(0, 1, 0x6c), 0x0}, + {TAC_REG_SDW(0, 1, 0x6d), 0x1}, + {TAC_REG_SDW(0, 1, 0x6e), 0x2}, + {TAC_REG_SDW(0, 1, 0x6f), 0x3}, + {TAC_REG_SDW(0, 1, 0x70), 0x4}, + {TAC_REG_SDW(0, 1, 0x71), 0x5}, + {TAC_REG_SDW(0, 1, 0x72), 0x6}, + {TAC_REG_SDW(0, 1, 0x73), 0x7}, +}; + +static const struct reg_sequence tac_spk_seq[] = { + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0), +}; + +static const struct reg_sequence tac_sm_seq[] = { + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0), +}; + +static const struct reg_sequence tac_uaj_seq[] = { + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0), + REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36, + TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS), 0), +}; + +static bool tac_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TAC_REG_SDW(0, 0, 1) ... TAC_REG_SDW(0, 0, 5): + case TAC_REG_SDW(0, 2, 1) ... TAC_REG_SDW(0, 2, 6): + case TAC_REG_SDW(0, 2, 24) ... TAC_REG_SDW(0, 2, 55): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1, + TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1, + TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35, + TAC_SDCA_CTL_DET_MODE, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_PDE23, + TAC_SDCA_REQUESTED_PS, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_PDE11, + TAC_SDCA_REQUESTED_PS, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE47, + TAC_SDCA_REQUESTED_PS, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE34, + TAC_SDCA_REQUESTED_PS, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_PDE23, + TAC_SDCA_ACTUAL_PS, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_PDE11, + TAC_SDCA_ACTUAL_PS, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE47, + TAC_SDCA_ACTUAL_PS, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE34, + TAC_SDCA_ACTUAL_PS, 0): + case SDW_SCP_SDCA_INT1: + case SDW_SCP_SDCA_INT2: + case SDW_SCP_SDCA_INT3: + case SDW_SCP_SDCA_INT4: + case SDW_SDCA_CTL(1, 0, 0x10, 0): + case SDW_SDCA_CTL(2, 0, 0x10, 0): + case SDW_SDCA_CTL(3, 0, 0x10, 0): + case SDW_SDCA_CTL(4, 0, 0x1, 0): + case 0x44007F80 ... 0x44007F87: + case TAC_DSP_ALGO_STATUS: /* DSP algo status - always read from HW */ + return true; + default: + break; + } + + return false; +} + +static int tac_sdca_mbq_size(struct device *dev, unsigned int reg) +{ + switch (reg) { + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21, + TAC_SDCA_CHANNEL_VOLUME, TAC_CHANNEL_LEFT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21, + TAC_SDCA_CHANNEL_VOLUME, TAC_CHANNEL_RIGHT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23, + TAC_SDCA_MASTER_GAIN, 0): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41, + TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT): + case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36, + TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS): + return 2; + + default: + return 1; + } +} + +static const struct regmap_sdw_mbq_cfg tac_mbq_cfg = { + .mbq_size = tac_sdca_mbq_size, +}; + +static const struct regmap_config tac_regmap = { + .reg_bits = 32, + .val_bits = 16, /* mbq support */ + .reg_defaults = tac_reg_default, + .num_reg_defaults = ARRAY_SIZE(tac_reg_default), + .max_register = 0x47FFFFFF, + .cache_type = REGCACHE_MAPLE, + .volatile_reg = tac_volatile_reg, + .use_single_read = true, + .use_single_write = true, +}; + +/* Check if device has DSP algo that needs status monitoring */ +static bool tac_has_dsp_algo(struct tac5xx2_prv *tac_dev) +{ + switch (tac_dev->part_id) { + case 0x5682: + case 0x2883: + return true; + default: + return false; + } +} + +/* Check if device has UAJ (Universal Audio Jack) support */ +static bool tac_has_uaj_support(struct tac5xx2_prv *tac_dev) +{ + return tac_dev->uaj_func_data; +} + +/* Forward declaration for headset detection */ +static int tac5xx2_sdca_headset_detect(struct tac5xx2_prv *tac_dev); + +/* Volume controls for mic, hp and mic cap */ +static const struct snd_kcontrol_new tac5xx2_snd_controls[] = { + SOC_DOUBLE_R_RANGE_TLV("Amp Volume", TAC_AMP_LVL_CFG0, TAC_AMP_LVL_CFG1, + 2, 0, 44, 1, tac5xx2_amp_tlv), + TAC_DOUBLE_Q78_TLV("DMIC Capture Volume", SM, FU113), + TAC_DOUBLE_Q78_TLV("Speaker Volume", SA, FU21), +}; + +static const struct snd_kcontrol_new tac_uaj_controls[] = { + TAC_DOUBLE_Q78_TLV("UAJ Playback Volume", UAJ, FU41), + SDCA_SINGLE_Q78_TLV("UAJ Capture Volume", + SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36, + TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS), + TAC_DVC_MIN, TAC_DVC_MAX, TAC_DVC_STEP, tac5xx2_dvc_tlv), +}; + +static const struct snd_soc_dapm_widget tac5xx2_common_widgets[] = { + /* Port 1: Speaker Playback Path */ + SND_SOC_DAPM_AIF_IN("AIF1 Playback", "DP1 Speaker Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA("FU21_L", FU21_L_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("FU21_R", FU21_R_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("FU23_L", FU23_L_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("FU23_R", FU23_R_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_OUTPUT("SPK_L"), + SND_SOC_DAPM_OUTPUT("SPK_R"), + + /* Port 3: Smart Mic (DMIC) Capture Path */ + SND_SOC_DAPM_AIF_OUT("AIF3 Capture", "DP3 Mic Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_INPUT("DMIC_L"), + SND_SOC_DAPM_INPUT("DMIC_R"), + SND_SOC_DAPM_PGA("IT11", IT11_USAGE_REG, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CS113", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("FU11_L", FU11_L_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("FU11_R", FU11_R_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("PPU11", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("XU12", XU12_BYPASS_REG, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("FU113_L", FU113_L_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("FU113_R", FU113_R_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("OT113", OT113_USAGE_REG, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget tac_uaj_widgets[] = { + /* Port 4: UAJ (Headphone) Playback Path */ + SND_SOC_DAPM_AIF_IN("AIF4 Playback", "DP4 UAJ Speaker Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_PGA("IT41", IT41_USAGE_REG, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("FU41_L", FU41_L_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("FU41_R", FU41_R_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_PGA("XU42", XU42_BYPASS_REG, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("CS41", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_DAC("OT45", "DP4 UAJ Speaker Playback", OT45_USAGE_REG, 0, 0), + SND_SOC_DAPM_OUTPUT("HP_L"), + SND_SOC_DAPM_OUTPUT("HP_R"), + + /* Port 7: UAJ (Headset Mic) Capture Path */ + SND_SOC_DAPM_AIF_OUT("AIF7 Capture", "DP7 UAJ Mic Capture", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_INPUT("UAJ_MIC"), + SND_SOC_DAPM_ADC("IT33", "DP7 UAJ Mic Capture", IT33_USAGE_REG, 0, 0), + SND_SOC_DAPM_PGA("FU36", FU36_MUTE_REG, 0, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("CS36", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("OT36", OT36_USAGE_REG, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route tac5xx2_common_routes[] = { + /* Speaker Playback Path */ + {"FU21_L", NULL, "AIF1 Playback"}, + {"FU21_R", NULL, "AIF1 Playback"}, + + {"FU23_L", NULL, "FU21_L"}, + {"FU23_R", NULL, "FU21_R"}, + + {"SPK_L", NULL, "FU23_L"}, + {"SPK_R", NULL, "FU23_R"}, + + /* Smart Mic DAPM Routes */ + {"IT11", NULL, "DMIC_L"}, + {"IT11", NULL, "DMIC_R"}, + {"FU11_L", NULL, "IT11"}, + {"FU11_R", NULL, "IT11"}, + {"PPU11", NULL, "FU11_L"}, + {"PPU11", NULL, "FU11_R"}, + {"XU12", NULL, "PPU11"}, + {"FU113_L", NULL, "XU12"}, + {"FU113_R", NULL, "XU12"}, + {"FU113_L", NULL, "CS113"}, + {"FU113_R", NULL, "CS113"}, + {"OT113", NULL, "FU113_L"}, + {"OT113", NULL, "FU113_R"}, + {"OT113", NULL, "CS113"}, + {"AIF3 Capture", NULL, "OT113"}, +}; + +static const struct snd_soc_dapm_route tac_uaj_routes[] = { + /* UAJ Playback routes */ + {"IT41", NULL, "AIF4 Playback"}, + {"IT41", NULL, "CS41"}, + {"FU41_L", NULL, "IT41"}, + {"FU41_R", NULL, "IT41"}, + {"XU42", NULL, "FU41_L"}, + {"XU42", NULL, "FU41_R"}, + {"OT45", NULL, "XU42"}, + {"OT45", NULL, "CS41"}, + {"HP_L", NULL, "OT45"}, + {"HP_R", NULL, "OT45"}, + + /* UAJ Capture routes */ + {"IT33", NULL, "UAJ_MIC"}, + {"IT33", NULL, "CS36"}, + {"FU36", NULL, "IT33"}, + {"OT36", NULL, "FU36"}, + {"OT36", NULL, "CS36"}, + {"AIF7 Capture", NULL, "OT36"}, +}; + +static s32 tac_set_sdw_stream(struct snd_soc_dai *dai, + void *sdw_stream, s32 direction) +{ + if (sdw_stream) + snd_soc_dai_dma_data_set(dai, direction, sdw_stream); + + return 0; +} + +static void tac_sdw_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + snd_soc_dai_set_dma_data(dai, substream, NULL); +} + +static int tac_clear_latch(struct tac5xx2_prv *priv) +{ + /* CLR_REG is a self-clearing bit */ + return regmap_update_bits(priv->regmap, TAC_INT_CFG, + TAC_INT_CFG_CLR_REG, TAC_INT_CFG_CLR_REG); +} + +static int tac_sdw_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component); + struct sdw_slave *sdw_peripheral = tac_dev->sdw_peripheral; + struct sdw_stream_runtime *sdw_stream; + struct sdw_stream_config stream_config = {0}; + struct sdw_port_config port_config = {0}; + u8 sample_rate_idx = 0; + int function_id; + int pde_entity; + int port_num; + int ret; + + if (!tac_dev->hw_init) { + dev_err(tac_dev->dev, + "error: operation without hw initialization"); + return -EINVAL; + } + + sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + if (!sdw_stream) { + dev_err(tac_dev->dev, "failed to get dma data"); + return -EINVAL; + } + + ret = tac_clear_latch(tac_dev); + if (ret) + dev_warn(tac_dev->dev, "clear latch failed, err=%d", ret); + + switch (dai->id) { + case TAC5XX2_DMIC: + function_id = TAC_FUNCTION_ID_SM; + pde_entity = TAC_SDCA_ENT_PDE11; + port_num = TAC_SDW_PORT_NUM_DMIC; + break; + case TAC5XX2_UAJ: + function_id = TAC_FUNCTION_ID_UAJ; + pde_entity = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + TAC_SDCA_ENT_PDE47 : TAC_SDCA_ENT_PDE34; + port_num = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + TAC_SDW_PORT_NUM_UAJ_PLAYBACK : + TAC_SDW_PORT_NUM_UAJ_CAPTURE; + break; + case TAC5XX2_SPK: + function_id = TAC_FUNCTION_ID_SA; + pde_entity = TAC_SDCA_ENT_PDE23; + port_num = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + TAC_SDW_PORT_NUM_SPK_PLAYBACK : + TAC_SDW_PORT_NUM_SPK_CAPTURE; + break; + default: + dev_err(tac_dev->dev, "Invalid dai id: %d for power up\n", dai->id); + return -EINVAL; + } + + snd_sdw_params_to_config(substream, params, &stream_config, &port_config); + port_config.num = port_num; + ret = sdw_stream_add_slave(sdw_peripheral, &stream_config, + &port_config, 1, sdw_stream); + if (ret) { + dev_err(dai->dev, + "Unable to configure port %d: %d\n", port_num, ret); + return ret; + } + + switch (params_rate(params)) { + case 48000: + sample_rate_idx = 0x01; + break; + case 44100: + sample_rate_idx = 0x02; + break; + case 96000: + sample_rate_idx = 0x03; + break; + case 88200: + sample_rate_idx = 0x04; + break; + default: + dev_dbg(tac_dev->dev, "Unsupported sample rate: %d Hz", + params_rate(params)); + return -EINVAL; + } + + switch (function_id) { + case TAC_FUNCTION_ID_SM: + ret = regmap_write(tac_dev->regmap, + SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS113, + TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0), + sample_rate_idx); + if (ret) { + dev_err(tac_dev->dev, "Failed to set CS113 sample rate: %d", ret); + return ret; + } + + break; + case TAC_FUNCTION_ID_UAJ: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = regmap_write(tac_dev->regmap, + SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS41, + TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0), + sample_rate_idx); + if (ret) { + dev_err(tac_dev->dev, "Failed to set CS41 sample rate: %d", ret); + return ret; + } + } else { + ret = regmap_write(tac_dev->regmap, + SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS36, + TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0), + sample_rate_idx); + if (ret) { + dev_err(tac_dev->dev, "Failed to set CS36 sample rate: %d", ret); + return ret; + } + } + break; + case TAC_FUNCTION_ID_SA: + /* SmartAmp: no additional sample rate configuration needed */ + break; + } + + ret = regmap_write(tac_dev->regmap, SDW_SDCA_CTL(function_id, pde_entity, + TAC_SDCA_REQUESTED_PS, 0), 0); + if (ret) { + dev_err(tac_dev->dev, + "failed to set func %d, entity %d's requested PS to 0: %d\n", + function_id, pde_entity, ret); + return ret; + } + + ret = sdca_asoc_pde_poll_actual_ps(tac_dev->dev, tac_dev->regmap, function_id, pde_entity, + SDCA_PDE_PS3, SDCA_PDE_PS0, NULL, 0); + if (ret) + dev_err(tac_dev->dev, "failed to transition func %d, pde %d from PS3 -> PS0, err=%d\n", + function_id, pde_entity, ret); + return ret; +} + +static int tac_sdw_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); + struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(dai->component); + int pde_entity, function_id; + int ret; + + sdw_stream_remove_slave(tac_dev->sdw_peripheral, sdw_stream); + + switch (dai->id) { + case TAC5XX2_DMIC: + pde_entity = TAC_SDCA_ENT_PDE11; + function_id = TAC_FUNCTION_ID_SM; + break; + case TAC5XX2_UAJ: + function_id = TAC_FUNCTION_ID_UAJ; + pde_entity = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + TAC_SDCA_ENT_PDE47 : TAC_SDCA_ENT_PDE34; + break; + case TAC5XX2_SPK: + function_id = TAC_FUNCTION_ID_SA; + pde_entity = TAC_SDCA_ENT_PDE23; + break; + default: + dev_err(tac_dev->dev, "unhandled dai %d for power down\n", dai->id); + return -EINVAL; + } + + ret = regmap_write(tac_dev->regmap, SDW_SDCA_CTL(function_id, pde_entity, + TAC_SDCA_REQUESTED_PS, 0), + SDCA_PDE_PS3); + if (ret) { + dev_err(tac_dev->dev, + "failed to set func %d, entity %d's requested PS to 3: %d\n", + function_id, pde_entity, ret); + return ret; + } + + ret = sdca_asoc_pde_poll_actual_ps(tac_dev->dev, tac_dev->regmap, function_id, + pde_entity, SDCA_PDE_PS0, SDCA_PDE_PS3, + NULL, 0); + if (ret) + dev_err(tac_dev->dev, + "failed to transition func %d, pde %d from PS0 -> PS3, err=%d\n", + function_id, pde_entity, ret); + + return ret; +} + +static const struct snd_soc_dai_ops tac_dai_ops = { + .hw_params = tac_sdw_hw_params, + .hw_free = tac_sdw_pcm_hw_free, + .set_stream = tac_set_sdw_stream, + .shutdown = tac_sdw_shutdown, +}; + +static int tac5xx2_sdca_btn_type(unsigned char *buffer, struct tac5xx2_prv *tac_dev) +{ + switch (*buffer) { + case 1: /* play pause */ + return SND_JACK_BTN_0; + case 10: /* vol down */ + return SND_JACK_BTN_3; + case 8: /* vol up */ + return SND_JACK_BTN_2; + case 4: /* long press */ + return SND_JACK_BTN_1; + case 2: /* next song */ + case 32: /* next song */ + return SND_JACK_BTN_4; + default: + return 0; + } +} + +static int tac5xx2_sdca_button_detect(struct tac5xx2_prv *tac_dev) +{ + unsigned int btn_type, offset, idx; + int ret, value, owner; + u8 buf[2]; + + ret = regmap_read(tac_dev->regmap, + SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1, + TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner); + if (ret) { + dev_err(tac_dev->dev, + "Failed to read current UMP message owner 0x%x", ret); + return ret; + } + + if (owner == SDCA_UMP_OWNER_DEVICE) { + dev_dbg(tac_dev->dev, "skip button detect as current owner is not host\n"); + return 0; + } + + ret = regmap_read(tac_dev->regmap, + SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1, + TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset); + if (ret) { + dev_err(tac_dev->dev, + "Failed to read current UMP message offset: %d", ret); + goto end_btn_det; + } + + dev_dbg(tac_dev->dev, "button detect: message offset = %x", offset); + + for (idx = 0; idx < sizeof(buf); idx++) { + ret = regmap_read(tac_dev->regmap, + TAC_BUF_ADDR_HID1 + offset + idx, &value); + if (ret) { + dev_err(tac_dev->dev, + "Failed to read HID buffer: %d", ret); + goto end_btn_det; + } + buf[idx] = value & 0xff; + } + + if (buf[0] == 0x1) { + btn_type = tac5xx2_sdca_btn_type(&buf[1], tac_dev); + ret = btn_type; + } + +end_btn_det: + regmap_write(tac_dev->regmap, + SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1, + TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01); + + return ret; +} + +static int tac5xx2_sdca_headset_detect(struct tac5xx2_prv *tac_dev) +{ + int val, ret; + + ret = regmap_read(tac_dev->regmap, + SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35, + TAC_SDCA_CTL_DET_MODE, 0), &val); + if (ret) { + dev_err(tac_dev->dev, "Failed to read the detect mode"); + return ret; + } + + switch (val) { + case 4: + tac_dev->jack_type = SND_JACK_MICROPHONE; + break; + case 5: + tac_dev->jack_type = SND_JACK_HEADPHONE; + break; + case 6: + tac_dev->jack_type = SND_JACK_HEADSET; + break; + case 0: + default: + tac_dev->jack_type = 0; + break; + } + + ret = regmap_write(tac_dev->regmap, + SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35, + TAC_SDCA_CTL_SEL_MODE, 0), val); + if (ret) + dev_err(tac_dev->dev, "Failed to update the jack type to device"); + + return 0; +} + +static int tac5xx2_jack_init(struct tac5xx2_prv *tac_dev) +{ + int ret = 0; + + if (!tac_dev->hs_jack) + goto disable_interrupts; + + ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK2, + SDW_SCP_SDCA_INTMASK_SDCA_11); + if (ret) { + dev_err(tac_dev->dev, + "Failed to register jack detection interrupt: %d\n", ret); + goto disable_interrupts; + } + + ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK3, + SDW_SCP_SDCA_INTMASK_SDCA_16); + if (ret) { + dev_err(tac_dev->dev, + "Failed to register for button detect interrupt: %d\n", ret); + goto disable_interrupts; + } + + return 0; + +disable_interrupts: + /* ignore errors while disabling interrupts */ + regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK2, 0); + regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK3, 0); + + return ret; +} + +static int tac5xx2_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *hs_jack, void *data) +{ + struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component); + int ret; + + tac_dev->hs_jack = hs_jack; + + /* resume can happen only after first hw_init */ + if (!tac_dev->first_hw_init_done) + return 0; + + ret = pm_runtime_resume_and_get(component->dev); + if (ret < 0) { + if (ret != -EACCES) { + dev_err(component->dev, + "%s: failed to resume %d\n", __func__, ret); + return ret; + } + + /* pm_runtime not enabled yet */ + dev_dbg(component->dev, + "%s: skipping jack init for now\n", __func__); + return 0; + } + + ret = tac5xx2_jack_init(tac_dev); + if (ret) + dev_err(tac_dev->dev, "jack init failed, err=%d\n", ret); + + pm_runtime_mark_last_busy(component->dev); + pm_runtime_put_autosuspend(component->dev); + + return ret; +} + +static int tac_interrupt_callback(struct sdw_slave *slave, + struct sdw_slave_intr_status *status) +{ + unsigned int sdca_int2, sdca_int3, jack_report_mask = 0; + struct tac5xx2_prv *tac_dev = dev_get_drvdata(&slave->dev); + struct device *dev = &slave->dev; + int btn_type = 0; + int ret = 0; + + if (status->control_port) { + if (status->control_port & SDW_SCP_INT1_PARITY) + dev_warn(dev, "SCP: Parity error interrupt"); + if (status->control_port & SDW_SCP_INT1_BUS_CLASH) + dev_warn(dev, "SCP: Bus clash interrupt"); + } + + if (!tac_has_uaj_support(tac_dev)) + return 0; + + ret = regmap_read(tac_dev->regmap, SDW_SCP_SDCA_INT2, &sdca_int2); + if (ret) { + dev_err(dev, "Failed to read UAJ Interrupt, reg:%#x err=%d\n", + SDW_SCP_SDCA_INT2, ret); + return ret; + } + + ret = regmap_read(tac_dev->regmap, SDW_SCP_SDCA_INT3, &sdca_int3); + if (ret) { + dev_err(dev, "Failed to read HID interrupt reg=%#x: err=%d", + SDW_SCP_SDCA_INT3, ret); + return ret; + } + + dev_dbg(dev, "SDCA_INT2: 0x%02x, SDCA_INT3: 0x%02x\n", + sdca_int2, sdca_int3); + + if (sdca_int2 & SDW_SCP_SDCA_INT_SDCA_11) { + ret = tac5xx2_sdca_headset_detect(tac_dev); + if (ret < 0) + goto clear; + jack_report_mask |= SND_JACK_HEADSET; + } + + if (sdca_int3 & SDW_SCP_SDCA_INT_SDCA_16) { + btn_type = tac5xx2_sdca_button_detect(tac_dev); + if (btn_type < 0) + btn_type = 0; + jack_report_mask |= SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4; + } + + if (tac_dev->jack_type == 0) + btn_type = 0; + + dev_dbg(tac_dev->dev, "in %s, jack_type=%d\n", __func__, tac_dev->jack_type); + dev_dbg(tac_dev->dev, "in %s, btn_type=0x%x\n", __func__, btn_type); + + if (!tac_dev->hs_jack) + goto clear; + + snd_soc_jack_report(tac_dev->hs_jack, tac_dev->jack_type | btn_type, + jack_report_mask); + +clear: + if (sdca_int2) { + ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INT2, sdca_int2); + if (ret) + dev_dbg(tac_dev->dev, "Failed to clear jack interrupt\n"); + } + + if (sdca_int3) { + ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INT3, sdca_int3); + if (ret) + dev_dbg(tac_dev->dev, "failed to clear hid interrupt\n"); + } + + return 0; +} + +static struct snd_soc_dai_driver tac5572_dai_driver[] = { + { + .name = "tac5xx2-aif1", + .id = TAC5XX2_SPK, + .playback = { + .stream_name = "DP1 Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, + { + .name = "tac5xx2-aif2", + .id = TAC5XX2_DMIC, + .capture = { + .stream_name = "DP3 Mic Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, + { + .name = "tac5xx2-aif3", + .id = TAC5XX2_UAJ, + .playback = { + .stream_name = "DP4 UAJ Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .capture = { + .stream_name = "DP7 UAJ Mic Capture", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, +}; + +static struct snd_soc_dai_driver tac5672_dai_driver[] = { + { + .name = "tac5xx2-aif1", + .id = TAC5XX2_SPK, + .playback = { + .stream_name = "DP1 Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .capture = { + .stream_name = "DP8 IV Sense Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + .symmetric_rate = 1, + }, + { + .name = "tac5xx2-aif2", + .id = TAC5XX2_DMIC, + .capture = { + .stream_name = "DP3 Mic Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, + { + .name = "tac5xx2-aif3", + .id = TAC5XX2_UAJ, + .playback = { + .stream_name = "DP4 UAJ Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .capture = { + .stream_name = "DP7 UAJ Mic Capture", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, +}; + +static struct snd_soc_dai_driver tac5682_dai_driver[] = { + { + .name = "tac5xx2-aif1", + .id = TAC5XX2_SPK, + .playback = { + .stream_name = "DP1 Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .capture = { + .stream_name = "DP2 Echo Reference Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + .symmetric_rate = 1, + }, + { + .name = "tac5xx2-aif2", + .id = TAC5XX2_DMIC, + .capture = { + .stream_name = "DP3 Mic Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, + { + .name = "tac5xx2-aif3", + .id = TAC5XX2_UAJ, + .playback = { + .stream_name = "DP4 UAJ Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .capture = { + .stream_name = "DP7 UAJ Mic Capture", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, +}; + +static struct snd_soc_dai_driver tas2883_dai_driver[] = { + { + .name = "tac5xx2-aif1", + .id = TAC5XX2_SPK, + .playback = { + .stream_name = "DP1 Speaker Playback", + .channels_min = 1, + .channels_max = 2, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + .symmetric_rate = 1, + }, + { + .name = "tac5xx2-aif2", + .id = TAC5XX2_DMIC, + .capture = { + .stream_name = "DP3 Mic Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5XX2_DEVICE_RATES, + .formats = TAC5XX2_DEVICE_FORMATS, + }, + .ops = &tac_dai_ops, + }, +}; + +static s32 tac_component_probe(struct snd_soc_component *component) +{ + struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component); + int ret; + + ret = pm_runtime_resume(component->dev); + if (ret < 0 && ret != -EACCES) + return ret; + + if (!tac_has_uaj_support(tac_dev)) + goto done_comp_probe; + + ret = snd_soc_dapm_new_controls(snd_soc_component_to_dapm(component), + tac_uaj_widgets, + ARRAY_SIZE(tac_uaj_widgets)); + if (ret) { + dev_err(component->dev, "Failed to add UAJ widgets: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(snd_soc_component_to_dapm(component), + tac_uaj_routes, ARRAY_SIZE(tac_uaj_routes)); + if (ret) { + dev_err(component->dev, "Failed to add UAJ routes: %d\n", ret); + return ret; + } + + ret = snd_soc_add_component_controls(component, tac_uaj_controls, + ARRAY_SIZE(tac_uaj_controls)); + if (ret) { + dev_err(component->dev, "Failed to add UAJ controls: %d\n", ret); + return ret; + } + +done_comp_probe: + tac_dev->component = component; + return 0; +} + +static void tac_component_remove(struct snd_soc_component *codec) +{ + struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(codec); + + tac_dev->component = NULL; +} + +static const struct snd_soc_component_driver soc_codec_driver_tacdevice = { + .probe = tac_component_probe, + .remove = tac_component_remove, + .controls = tac5xx2_snd_controls, + .num_controls = ARRAY_SIZE(tac5xx2_snd_controls), + .dapm_widgets = tac5xx2_common_widgets, + .num_dapm_widgets = ARRAY_SIZE(tac5xx2_common_widgets), + .dapm_routes = tac5xx2_common_routes, + .num_dapm_routes = ARRAY_SIZE(tac5xx2_common_routes), + .idle_bias_on = 0, + .endianness = 1, +}; + +static s32 tac_init(struct tac5xx2_prv *tac_dev) +{ + struct snd_soc_component_driver *component_driver; + struct snd_soc_dai_driver *dai_drv; + int num_dais; + s32 ret; + + dev_set_drvdata(tac_dev->dev, tac_dev); + + switch (tac_dev->part_id) { + case 0x5572: + dai_drv = tac5572_dai_driver; + num_dais = ARRAY_SIZE(tac5572_dai_driver); + break; + case 0x5672: + dai_drv = tac5672_dai_driver; + num_dais = ARRAY_SIZE(tac5672_dai_driver); + break; + case 0x5682: + dai_drv = tac5682_dai_driver; + num_dais = ARRAY_SIZE(tac5682_dai_driver); + break; + case 0x2883: + dai_drv = tas2883_dai_driver; + num_dais = ARRAY_SIZE(tas2883_dai_driver); + break; + default: + dev_err(tac_dev->dev, "Unsupported device: 0x%x\n", + tac_dev->part_id); + return -EINVAL; + } + + component_driver = devm_kzalloc(tac_dev->dev, sizeof(*component_driver), + GFP_KERNEL); + if (!component_driver) + return -ENOMEM; + + memcpy(component_driver, &soc_codec_driver_tacdevice, sizeof(*component_driver)); + if (tac_has_uaj_support(tac_dev)) + component_driver->set_jack = tac5xx2_set_jack; + + ret = devm_snd_soc_register_component(tac_dev->dev, component_driver, + dai_drv, num_dais); + if (ret) { + dev_err(tac_dev->dev, "%s: codec register error:%d.\n", + __func__, ret); + return ret; + } + + return 0; +} + +static s32 tac5xx2_sdca_dev_suspend(struct device *dev) +{ + struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev); + + if (!tac_dev->hw_init) + return 0; + + regcache_cache_only(tac_dev->regmap, true); + return 0; +} + +static s32 tac5xx2_sdca_dev_system_suspend(struct device *dev) +{ + return tac5xx2_sdca_dev_suspend(dev); +} + +static s32 tac5xx2_sdca_dev_resume(struct device *dev) +{ + struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev); + struct sdw_slave *slave = dev_to_sdw_dev(dev); + int ret; + + if (!tac_dev->first_hw_init_done) { + dev_dbg(dev, "Device not initialized yet, skipping resume sync\n"); + return 0; + } + + ret = sdw_slave_wait_for_init(slave, TAC5XX2_PROBE_TIMEOUT_MS); + if (ret) + return ret; + + regcache_cache_only(tac_dev->regmap, false); + regcache_mark_dirty(tac_dev->regmap); + ret = regcache_sync(tac_dev->regmap); + if (ret < 0) + dev_warn(dev, "Failed to sync regcache: %d\n", ret); + + /* Detect and set jack type for UAJ path before playback. + * This is required as jack detection does not trigger interrupt + * when device is in runtime_pm suspend with bus in clock stop mode. + */ + if (tac_has_uaj_support(tac_dev)) + tac5xx2_sdca_headset_detect(tac_dev); + + return 0; +} + +static const struct dev_pm_ops tac5xx2_sdca_pm = { + SYSTEM_SLEEP_PM_OPS(tac5xx2_sdca_dev_system_suspend, tac5xx2_sdca_dev_resume) + RUNTIME_PM_OPS(tac5xx2_sdca_dev_suspend, tac5xx2_sdca_dev_resume, NULL) +}; + +static s32 tac_fw_read_hdr(const u8 *data, struct tac_fw_hdr *hdr) +{ + hdr->size = get_unaligned_le32(data); + hdr->version_offset = get_unaligned_le32(data + 4); + hdr->plt_id = get_unaligned_le32(data + 8); + hdr->ppc3_ver = get_unaligned_le32(data + 12); + memcpy(hdr->ddc_name, data + 16, 64); + hdr->ddc_name[63] = 0; + hdr->timestamp = get_unaligned_le64(data + 80); + + return TAC_FW_HDR_SIZE; +} + +static s32 tac_fw_get_next_file(const u8 *data, size_t data_size, struct tac_fw_file *file) +{ + u32 file_length; + + /* Validate file header size */ + if (data_size < TAC_FW_FILE_HDR) + return -EINVAL; + + file->vendor_id = get_unaligned_le32(&data[0]); + file->file_id = get_unaligned_le32(&data[4]); + file->version = get_unaligned_le32(&data[8]); + file->length = get_unaligned_le32(&data[12]); + file->dest_addr = get_unaligned_le32(&data[16]); + file_length = file->length; + + /* Validate file payload exists */ + if (data_size < TAC_FW_FILE_HDR + file_length) + return -EINVAL; + + file->fw_data = (u8 *)&data[20]; + + return file_length + sizeof(u32) * 5; +} + +static void tac5xx2_fw_ready(const struct firmware *fmw, void *context) +{ + struct tac5xx2_prv *tac_dev = context; + struct tac_fw_file *files; + u32 fw_hdr_size; + u32 num_files = 0; + struct tac_fw_hdr hdr; + struct tm tm_time; + size_t img_sz; + u32 offset; + s32 ret = 0; + u8 *buf; + + if (!fmw || !fmw->data || fmw->size == 0 || fmw->size < TAC_FW_HDR_SIZE + TAC_FW_FILE_HDR) { + dev_err(tac_dev->dev, "fw file: %s is empty or invalid\n", + tac_dev->fw_binaryname); + goto out; + } + + /* Verify firmware size from header */ + fw_hdr_size = get_unaligned_le32(fmw->data); + if (fw_hdr_size != fmw->size) { + dev_err(tac_dev->dev, "firmware size mismatch: hdr=%u, actual=%zu\n", + fw_hdr_size, fmw->size); + goto out; + } + + files = devm_kzalloc(tac_dev->dev, sizeof(*files) * TAC_MAX_FW_CHUNKS, GFP_KERNEL); + buf = devm_kmemdup(tac_dev->dev, fmw->data, fmw->size, GFP_KERNEL); + if (!files || !buf) + goto out; + + /* validate the cache the firmware */ + img_sz = fmw->size; + offset = tac_fw_read_hdr(buf, &hdr); + while (offset < img_sz && num_files < TAC_MAX_FW_CHUNKS) { + u32 file_length; + + if (offset + TAC_FW_FILE_HDR > img_sz) { + dev_warn(tac_dev->dev, "Incomplete block header at offset %d\n", + offset); + goto out; + } + /* Validate that the file payload doesn't exceed buffer */ + file_length = get_unaligned_le32(&buf[offset + 12]); + /* Check for integer overflow and buffer bounds */ + if (file_length > img_sz || offset > img_sz - TAC_FW_FILE_HDR || + file_length > img_sz - offset - TAC_FW_FILE_HDR) { + dev_warn(tac_dev->dev, "File at offset %d exceeds buffer: length=%u, available=%zu\n", + offset, file_length, img_sz - offset - TAC_FW_FILE_HDR); + goto out; + } + ret = tac_fw_get_next_file(&buf[offset], img_sz - offset, &files[num_files]); + if (ret < 0) { + dev_err(tac_dev->dev, "Failed to parse file at offset %d\n", offset); + goto out; + } + offset += ret; + num_files++; + } + + if (num_files == 0) { + dev_err(tac_dev->dev, "firmware with no files\n"); + goto out; + } + + /* cache ready to use validated firmware */ + tac_dev->fw_file_cnt = num_files; + tac_dev->fw_files = files; + + time64_to_tm(hdr.timestamp, 0, &tm_time); + dev_dbg(tac_dev->dev, "fw file: %s, num_files=%u, ts:%04ld-%02d-%02d %02d:%02d\n", + tac_dev->fw_binaryname, tac_dev->fw_file_cnt, + tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday, + tm_time.tm_hour, tm_time.tm_min); + dev_dbg(tac_dev->dev, "fw file: DDC Name: %s\n", hdr.ddc_name); + dev_dbg(tac_dev->dev, "fw file: PPC3 Version: 3.%ld.%ld.%ld\n", + FIELD_GET(GENMASK(31, 24), hdr.ppc3_ver), + FIELD_GET(GENMASK(23, 16), hdr.ppc3_ver), + FIELD_GET(GENMASK(15, 8), hdr.ppc3_ver) & 0x3f); + +out: + complete_all(&tac_dev->fw_caching_complete); + if (fmw) + release_firmware(fmw); +} + +static int tac_load_and_cache_firmware_async(struct tac5xx2_prv *tac_dev) +{ + tac_dev->fw_file_cnt = 0; + tac_dev->fw_files = NULL; /* ready to download files */ + + return request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, + tac_dev->fw_binaryname, tac_dev->dev, + GFP_KERNEL, tac_dev, tac5xx2_fw_ready); +} + +static int tac_download(struct tac5xx2_prv *tac_dev) +{ + struct tac_fw_file *files = tac_dev->fw_files; + u32 num_files = tac_dev->fw_file_cnt; + u32 i; + int ret = 0; + + for (i = 0; i < num_files; i++) { + ret = sdw_nwrite_no_pm(tac_dev->sdw_peripheral, files[i].dest_addr, + files[i].length, files[i].fw_data); + if (ret < 0) { + dev_dbg(tac_dev->dev, + "FW write failed at addr 0x%x: %d\n", + files[i].dest_addr, ret); + return ret; + } + } + + return 0; +} + +/* + * tac5xx2 uses custom firmware binary fw. + * This is not using UMP File Download. + */ +static s32 tac_download_fw_to_hw(struct tac5xx2_prv *tac_dev) +{ + int ret; + + ret = tac_download(tac_dev); + if (ret < 0) { + dev_err(tac_dev->dev, "Firmware download failed: %d\n", ret); + return ret; + } + + dev_dbg(tac_dev->dev, "Firmware download complete: %d chunks\n", + tac_dev->fw_file_cnt); + tac_dev->fw_dl_success = true; + + return 0; +} + +static struct pci_dev *tac_get_pci_dev(struct sdw_slave *peripheral) +{ + struct device *dev = &peripheral->dev; + + for (; dev; dev = dev->parent) { + if (dev_is_pci(dev)) + return to_pci_dev(dev); + } + + return NULL; +} + +static void tac_generate_fw_name(struct sdw_slave *slave, char *name, size_t size) +{ + struct sdw_bus *bus = slave->bus; + u16 part_id = slave->id.part_id; + u8 unique_id = slave->id.unique_id; + struct pci_dev *pci = tac_get_pci_dev(slave); + + if (pci) + scnprintf(name, size, "%04X-%04X-%1X-%1X.bin", part_id, + pci->subsystem_device, bus->link_id, unique_id); + else + /* Default firmware name based on part ID */ + scnprintf(name, size, "%s%04x-%1X-%1X.bin", + part_id == 0x2883 ? "tas" : "tac", + part_id, bus->link_id, unique_id); +} + +static int tac_io_init(struct device *dev, struct sdw_slave *slave, bool first) +{ + struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev); + u64 time; + int ret; + + if (tac_dev->hw_init) { + dev_dbg(dev, "early return hw_init already done.."); + return 0; + } + + time = wait_for_completion_timeout(&tac_dev->fw_caching_complete, + msecs_to_jiffies(TAC5XX2_FW_CACHE_TIMEOUT_MS)); + if (!time) { + ret = -ETIMEDOUT; + dev_warn(tac_dev->dev, "%s: fw caching timeout\n", __func__); + goto io_init_err; + } + + if (tac_dev->fw_files && tac_dev->fw_file_cnt > 0) { + ret = tac_download_fw_to_hw(tac_dev); + if (ret) { + dev_err(tac_dev->dev, "FW download failed, fw: %d\n", ret); + goto io_init_err; + } + } + + if (tac_dev->sa_func_data) { + ret = sdca_regmap_write_init(dev, tac_dev->regmap, + tac_dev->sa_func_data); + if (ret) { + dev_err(dev, "smartamp init table update failed\n"); + goto io_init_err; + } + dev_dbg(dev, "smartamp init done\n"); + + if (first) { + ret = regmap_multi_reg_write(tac_dev->regmap, tac_spk_seq, + ARRAY_SIZE(tac_spk_seq)); + if (ret) { + dev_err(dev, "init writes failed, err=%d", ret); + goto io_init_err; + } + } + } + + if (tac_dev->sm_func_data) { + ret = sdca_regmap_write_init(dev, tac_dev->regmap, + tac_dev->sm_func_data); + if (ret) { + dev_err(dev, "smartmic init table update failed\n"); + goto io_init_err; + } + dev_dbg(dev, "smartmic init done\n"); + + if (first) { + ret = regmap_multi_reg_write(tac_dev->regmap, tac_sm_seq, + ARRAY_SIZE(tac_sm_seq)); + if (ret) { + dev_err(tac_dev->dev, + "init writes failed, err=%d", ret); + goto io_init_err; + } + } + } + + if (tac_dev->uaj_func_data) { + ret = sdca_regmap_write_init(dev, tac_dev->regmap, + tac_dev->uaj_func_data); + if (ret) { + dev_err(dev, "uaj init table update failed\n"); + goto io_init_err; + } + dev_dbg(dev, "uaj init done\n"); + + if (first) { + ret = regmap_multi_reg_write(tac_dev->regmap, tac_uaj_seq, + ARRAY_SIZE(tac_uaj_seq)); + if (ret) { + dev_err(tac_dev->dev, + "init writes failed, err=%d", ret); + goto io_init_err; + } + + if (tac_dev->hs_jack) { + ret = tac5xx2_jack_init(tac_dev); + if (ret) { + dev_err(tac_dev->dev, "jack init failed"); + goto io_init_err; + } + } + } + } + + if (tac_dev->hid_func_data) { + ret = sdca_regmap_write_init(dev, tac_dev->regmap, + tac_dev->hid_func_data); + if (ret) { + dev_err(dev, "hid init table update failed\n"); + goto io_init_err; + } + dev_dbg(dev, "hid init done\n"); + } + + tac_dev->hw_init = true; + + return 0; + +io_init_err: + dev_err(dev, "init writes failed, err=%d", ret); + return ret; +} + +static int tac_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct tac5xx2_prv *tac_dev = dev_get_drvdata(&slave->dev); + struct device *dev = &slave->dev; + bool first = false; + int ret; + + tac_dev->status = status; + if (status == SDW_SLAVE_UNATTACHED) { + tac_dev->hw_init = false; + tac_dev->fw_dl_success = false; + } + + if (tac_dev->hw_init || tac_dev->status != SDW_SLAVE_ATTACHED) { + dev_dbg(dev, "%s: early return, hw_init=%d, status=%d", + __func__, tac_dev->hw_init, tac_dev->status); + return 0; + } + + if (!tac_dev->first_hw_init_done) { + pm_runtime_set_active(tac_dev->dev); + tac_dev->first_hw_init_done = true; + first = true; + } + + pm_runtime_get_noresume(tac_dev->dev); + + regcache_mark_dirty(tac_dev->regmap); + regcache_cache_only(tac_dev->regmap, false); + ret = tac_io_init(&slave->dev, slave, first); + if (ret) { + dev_err(dev, "Device initialization failed: %d\n", ret); + goto err_out; + } + + ret = regcache_sync(tac_dev->regmap); + if (ret) + dev_warn(dev, "Failed to sync regcache after init: %d\n", ret); + +err_out: + pm_runtime_mark_last_busy(tac_dev->dev); + pm_runtime_put_autosuspend(tac_dev->dev); + + return ret; +} + +static int tac5xx2_sdw_read_prop(struct sdw_slave *peripheral) +{ + struct device *dev = &peripheral->dev; + int ret; + + ret = sdw_slave_read_prop(peripheral); + if (ret) { + dev_err(dev, "sdw_slave_read_prop failed: %d", ret); + return ret; + } + + return 0; +} + +static int tac_port_prep(struct sdw_slave *slave, struct sdw_prepare_ch *prep_ch, + enum sdw_port_prep_ops pre_ops) +{ + struct device *dev = &slave->dev; + struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev); + unsigned int val; + int ret; + + if (pre_ops != SDW_OPS_PORT_POST_PREP) + return 0; + + if (!tac_dev->fw_dl_success) + return 0; + + ret = regmap_read(tac_dev->regmap, TAC_DSP_ALGO_STATUS, &val); + if (ret) { + dev_err(dev, "Failed to read algo status: %d\n", ret); + return ret; + } + + if (val != TAC_DSP_ALGO_STATUS_RUNNING) { + dev_dbg(dev, "Algo not running (0x%02x), re-enabling\n", val); + ret = regmap_write(tac_dev->regmap, TAC_DSP_ALGO_STATUS, + TAC_DSP_ALGO_STATUS_RUNNING); + if (ret) { + dev_err(dev, "Failed to re-enable algo: %d\n", ret); + return ret; + } + } + + return 0; +} + +static const struct sdw_slave_ops tac_sdw_ops = { + .read_prop = tac5xx2_sdw_read_prop, + .update_status = tac_update_status, + .interrupt_callback = tac_interrupt_callback, + .port_prep = tac_port_prep, +}; + +static s32 tac_sdw_probe(struct sdw_slave *peripheral, + const struct sdw_device_id *id) +{ + struct sdca_function_data *function_data = NULL; + struct device *dev = &peripheral->dev; + struct tac5xx2_prv *tac_dev; + struct regmap *regmap; + int ret, i; + + tac_dev = devm_kzalloc(dev, sizeof(*tac_dev), GFP_KERNEL); + if (!tac_dev) + return dev_err_probe(dev, -ENOMEM, + "Failed devm_kzalloc"); + + if (peripheral->sdca_data.num_functions > 0) { + dev_dbg(dev, "SDCA functions found: %d", + peripheral->sdca_data.num_functions); + + for (i = 0; i < peripheral->sdca_data.num_functions; i++) { + struct sdca_function_data **func_ptr; + const char *func_name; + + switch (peripheral->sdca_data.function[i].type) { + case SDCA_FUNCTION_TYPE_SMART_AMP: + func_ptr = &tac_dev->sa_func_data; + func_name = "smartamp"; + break; + case SDCA_FUNCTION_TYPE_SMART_MIC: + func_ptr = &tac_dev->sm_func_data; + func_name = "smartmic"; + break; + case SDCA_FUNCTION_TYPE_UAJ: + func_ptr = &tac_dev->uaj_func_data; + func_name = "uaj"; + break; + case SDCA_FUNCTION_TYPE_HID: + func_ptr = &tac_dev->hid_func_data; + func_name = "hid"; + break; + default: + continue; + } + + function_data = devm_kzalloc(dev, sizeof(*function_data), + GFP_KERNEL); + if (!function_data) + return dev_err_probe(dev, -ENOMEM, + "failed to allocate %s function data", + func_name); + function_data->desc = &peripheral->sdca_data.function[i]; + ret = sdca_parse_function(dev, peripheral, function_data); + if (!ret) + *func_ptr = function_data; + else + devm_kfree(dev, function_data); + } + } + + dev_dbg(dev, "SDCA functions enabled: SA=%s SM=%s UAJ=%s HID=%s", + tac_dev->sa_func_data ? "yes" : "no", + tac_dev->sm_func_data ? "yes" : "no", + tac_dev->uaj_func_data ? "yes" : "no", + tac_dev->hid_func_data ? "yes" : "no"); + + tac_dev->dev = dev; + tac_dev->sdw_peripheral = peripheral; + tac_dev->hw_init = false; + tac_dev->first_hw_init_done = false; + tac_dev->part_id = id->part_id; + dev_set_drvdata(dev, tac_dev); + + regmap = devm_regmap_init_sdw_mbq_cfg(&peripheral->dev, peripheral, + &tac_regmap, &tac_mbq_cfg); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed devm_regmap_init_sdw\n"); + + regcache_cache_only(regmap, true); + tac_dev->regmap = regmap; + tac_dev->jack_type = 0; + init_completion(&tac_dev->fw_caching_complete); + + if (tac_has_dsp_algo(tac_dev)) { + tac_generate_fw_name(peripheral, tac_dev->fw_binaryname, + sizeof(tac_dev->fw_binaryname)); + + ret = tac_load_and_cache_firmware_async(tac_dev); + if (ret) { + complete_all(&tac_dev->fw_caching_complete); + dev_dbg(dev, "failed to load fw: %d, use rom mode\n", ret); + } + } else { + complete_all(&tac_dev->fw_caching_complete); + } + + ret = tac_init(tac_dev); + if (ret) + return dev_err_probe(dev, ret, + "failed to initialize tac device\n"); + + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(dev); + + pm_runtime_enable(dev); + /* the device is still not in active */ + + return 0; +} + +static void tac_sdw_remove(struct sdw_slave *peripheral) +{ + struct tac5xx2_prv *tac_dev = dev_get_drvdata(&peripheral->dev); + + pm_runtime_disable(tac_dev->dev); + + dev_set_drvdata(&peripheral->dev, NULL); +} + +static const struct sdw_device_id tac_sdw_id[] = { + SDW_SLAVE_ENTRY(0x0102, 0x5572, 0), + SDW_SLAVE_ENTRY(0x0102, 0x5672, 0), + SDW_SLAVE_ENTRY(0x0102, 0x5682, 0), + SDW_SLAVE_ENTRY(0x0102, 0x2883, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, tac_sdw_id); + +static struct sdw_driver tac_sdw_driver = { + .driver = { + .name = "slave-tac5xx2", + .pm = pm_ptr(&tac5xx2_sdca_pm), + }, + .probe = tac_sdw_probe, + .remove = tac_sdw_remove, + .ops = &tac_sdw_ops, + .id_table = tac_sdw_id, +}; +module_sdw_driver(tac_sdw_driver); + +MODULE_IMPORT_NS("SND_SOC_SDCA"); +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("ASoC TAC5XX2 SoundWire Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tac5xx2.h b/sound/soc/codecs/tac5xx2.h new file mode 100644 index 000000000000..eed8e6cf3498 --- /dev/null +++ b/sound/soc/codecs/tac5xx2.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * ALSA SoC Texas Instruments TAC5XX2 Audio Smart Amplifier + * + * Copyright (C) 2025 Texas Instruments Incorporated + * https://www.ti.com + * + * This the header file for TAC5XX2 family of devices + * which includes TAC5572, TAC5672, TAC5682 and TAS2883 + * + * Author: Niranjan H Y + */ +#ifndef __RGL_TAC5XX2_H__ +#define __RGL_TAC5XX2_H__ + +/* for soundwire */ +#define TAC_REG_SDW(book, page, reg) (((book) * 256 * 128) + \ + 0x3000000 + ((page) * 128) + (reg)) + +/* page 0 registers */ +#define TAC_SW_RESET TAC_REG_SDW(0, 0, 1) +#define TAC_SLEEP_MODEZ TAC_REG_SDW(0, 0, 2) +#define TAC_FEATURE_PDZ TAC_REG_SDW(0, 0, 3) +#define TAC_TX_CH_EN TAC_REG_SDW(0, 0, 4) +#define TAC_RX_CH_PD TAC_REG_SDW(0, 0, 5) +#define TAC_SHDNZ_CFG TAC_REG_SDW(0, 0, 6) +#define TAC_MISC_CFG0 TAC_REG_SDW(0, 0, 7) +#define TAC_MISC_CFG1 TAC_REG_SDW(0, 0, 8) +#define TAC_GPIO1_CFG0 TAC_REG_SDW(0, 0, 9) +#define TAC_GPIO2_CFG0 TAC_REG_SDW(0, 0, 10) +#define TAC_GPIO3_CFG0 TAC_REG_SDW(0, 0, 11) +#define TAC_GPIO4_CFG0 TAC_REG_SDW(0, 0, 12) +#define TAC_GPIO5_CFG0 TAC_REG_SDW(0, 0, 13) +#define TAC_GPIO6_CFG0 TAC_REG_SDW(0, 0, 14) +#define TAC_INTF_CFG1 TAC_REG_SDW(0, 0, 15) +#define TAC_INTF_CFG5 TAC_REG_SDW(0, 0, 16) +#define TAC_PASI_BCLK_CFG0 TAC_REG_SDW(0, 0, 17) +#define TAC_PASI_FSYNC_CFG0 TAC_REG_SDW(0, 0, 18) +#define TAC_PASI_DIN1_CFG0 TAC_REG_SDW(0, 0, 19) +#define TAC_PASI_DIN2_CFG0 TAC_REG_SDW(0, 0, 20) +#define TAC_PDM_DIN1_CFG0 TAC_REG_SDW(0, 0, 21) +#define TAC_PDM_DIN2_CFG0 TAC_REG_SDW(0, 0, 22) +#define TAC_MCLK_SEL TAC_REG_SDW(0, 0, 23) +#define TAC_I2C2_CFG0 TAC_REG_SDW(0, 0, 24) +#define TAC_SDW_IO_CFG0 TAC_REG_SDW(0, 0, 25) +#define TAC_SDW_CLK_CFG0 TAC_REG_SDW(0, 0, 26) +#define TAC_PASI_CFG0 TAC_REG_SDW(0, 0, 27) +#define TAC_PASI_CFG1 TAC_REG_SDW(0, 0, 28) +#define TAC_PASI_TX_CFG0 TAC_REG_SDW(0, 0, 29) +#define TAC_PASI_TX_CFG1 TAC_REG_SDW(0, 0, 30) +#define TAC_PASI_TX_CFG2 TAC_REG_SDW(0, 0, 31) +#define TAC_PASI_TX_CFG3 TAC_REG_SDW(0, 0, 32) +#define TAC_PASI_TX_CH1_CFG0 TAC_REG_SDW(0, 0, 33) +#define TAC_PASI_TX_CH2_CFG0 TAC_REG_SDW(0, 0, 34) +#define TAC_PASI_TX_CH3_CFG0 TAC_REG_SDW(0, 0, 35) +#define TAC_PASI_TX_CH4_CFG0 TAC_REG_SDW(0, 0, 36) +#define TAC_PASI_TX_CH5_CFG0 TAC_REG_SDW(0, 0, 37) +#define TAC_PASI_TX_CH6_CFG0 TAC_REG_SDW(0, 0, 38) +#define TAC_PASI_TX_CH7_CFG0 TAC_REG_SDW(0, 0, 39) +#define TAC_PASI_TX_CH8_CFG0 TAC_REG_SDW(0, 0, 40) +#define TAC_PASI_RX_CFG0 TAC_REG_SDW(0, 0, 41) +#define TAC_PASI_RX_CFG1 TAC_REG_SDW(0, 0, 42) +#define TAC_PASI_RX_CFG2 TAC_REG_SDW(0, 0, 43) +#define TAC_PASI_RX_CH1_CFG0 TAC_REG_SDW(0, 0, 44) +#define TAC_PASI_RX_CH2_CFG0 TAC_REG_SDW(0, 0, 45) +#define TAC_PASI_RX_CH3_CFG0 TAC_REG_SDW(0, 0, 46) +#define TAC_PASI_RX_CH4_CFG0 TAC_REG_SDW(0, 0, 47) +#define TAC_PASI_RX_CH5_CFG0 TAC_REG_SDW(0, 0, 48) +#define TAC_PASI_RX_CH6_CFG0 TAC_REG_SDW(0, 0, 49) +#define TAC_PASI_RX_CH7_CFG0 TAC_REG_SDW(0, 0, 50) +#define TAC_PASI_RX_CH8_CFG0 TAC_REG_SDW(0, 0, 51) +#define TAC_ADC_CH1_CFG0 TAC_REG_SDW(0, 0, 52) +#define TAC_ADC_DVOL_CFG0 TAC_REG_SDW(0, 0, 53) +#define TAC_ADC_CH1_FGAIN TAC_REG_SDW(0, 0, 54) +#define TAC_ADC_CH1_CFG1 TAC_REG_SDW(0, 0, 55) +#define TAC_ADC_CH2_CFG0 TAC_REG_SDW(0, 0, 57) +#define TAC_ADC_DVOL_CFG1 TAC_REG_SDW(0, 0, 58) +#define TAC_ADC_CH2_FGAIN TAC_REG_SDW(0, 0, 59) +#define TAC_ADC_CH2_CFG1 TAC_REG_SDW(0, 0, 60) +#define TAC_ADC_CFG1 TAC_REG_SDW(0, 0, 62) +#define TAC_PDM_CH1_DVOL TAC_REG_SDW(0, 0, 63) +#define TAC_PDM_CH1_FGAIN TAC_REG_SDW(0, 0, 64) +#define TAC_PDM_CH1_CFG0 TAC_REG_SDW(0, 0, 65) +#define TAC_PDM_CH2_DVOL TAC_REG_SDW(0, 0, 67) +#define TAC_PDM_CH2_FGAIN TAC_REG_SDW(0, 0, 68) +#define TAC_PDM_CH2_CFG2 TAC_REG_SDW(0, 0, 69) +#define TAC_PDM_CH3_DVOL TAC_REG_SDW(0, 0, 71) +#define TAC_PDM_CH3_FGAIN TAC_REG_SDW(0, 0, 72) +#define TAC_PDM_CH3_CFG0 TAC_REG_SDW(0, 0, 73) +#define TAC_PDM_CH4_DVOL TAC_REG_SDW(0, 0, 75) +#define TAC_PDM_CH4_FGAIN TAC_REG_SDW(0, 0, 76) +#define TAC_PDM_CH4_CFG0 TAC_REG_SDW(0, 0, 77) +#define TAC_MICBIAS_CFG0 TAC_REG_SDW(0, 0, 79) +#define TAC_MICPREAMP_CFG TAC_REG_SDW(0, 0, 80) +#define TAC_MICBIAS_CFG1 TAC_REG_SDW(0, 0, 81) +#define TAC_CLASSD_CH1_DVOL TAC_REG_SDW(0, 0, 82) +#define TAC_CLASSD_CH1_FGAIN TAC_REG_SDW(0, 0, 83) +#define TAC_CLASSD_CH2_DVOL TAC_REG_SDW(0, 0, 85) +#define TAC_CLASSD_CH2_FGAIN TAC_REG_SDW(0, 0, 86) +#define TAC_GCHP_CH1_DVOL TAC_REG_SDW(0, 0, 88) +#define TAC_GCHP_CH1_FGAIN TAC_REG_SDW(0, 0, 89) +#define TAC_GCHP_CH2_DVOL TAC_REG_SDW(0, 0, 91) +#define TAC_GCHP_CH2_FGAIN TAC_REG_SDW(0, 0, 92) +#define TAC_AMP_LVL_CFG0 TAC_REG_SDW(0, 0, 94) +#define TAC_AMP_LVL_CFG1 TAC_REG_SDW(0, 0, 95) +#define TAC_AMP_LVL_CFG2 TAC_REG_SDW(0, 0, 96) +#define TAC_AMP_LVL_CFG3 TAC_REG_SDW(0, 0, 97) +#define TAC_EFF_MODE_CFG0 TAC_REG_SDW(0, 0, 98) +#define TAC_EFF_MODE_CFG1 TAC_REG_SDW(0, 0, 99) +#define TAC_CLASSD_CFG0 TAC_REG_SDW(0, 0, 100) +#define TAC_CLASSD_CFG1 TAC_REG_SDW(0, 0, 101) +#define TAC_CLASSD_CFG3 TAC_REG_SDW(0, 0, 102) +#define TAC_CLASSD_CFG4 TAC_REG_SDW(0, 0, 103) +#define TAC_CLASSD_CFG5 TAC_REG_SDW(0, 0, 104) +#define TAC_CLASSD_CFG6 TAC_REG_SDW(0, 0, 105) +#define TAC_CLASSD_CFG8 TAC_REG_SDW(0, 0, 106) +#define TAC_ISNS_CFG TAC_REG_SDW(0, 0, 107) +#define TAC_DSP_CFG0 TAC_REG_SDW(0, 0, 108) +#define TAC_DSP_CFG1 TAC_REG_SDW(0, 0, 109) +#define TAC_DSP_CFG2 TAC_REG_SDW(0, 0, 110) +#define TAC_DSP_CFG3 TAC_REG_SDW(0, 0, 111) +#define TAC_JACK_DET_CFG1 TAC_REG_SDW(0, 0, 112) +#define TAC_JACK_DET_CFG2 TAC_REG_SDW(0, 0, 113) +#define TAC_JACK_DET_CFG3 TAC_REG_SDW(0, 0, 114) +#define TAC_JACK_DET_CFG4 TAC_REG_SDW(0, 0, 115) +#define TAC_JACK_DET_CFG7 TAC_REG_SDW(0, 0, 116) +#define TAC_UJ_IMPEDANCE_L TAC_REG_SDW(0, 0, 117) +#define TAC_UJ_IMPEDANCE_R TAC_REG_SDW(0, 0, 118) +#define UJ_IMPEDANCE_L TAC_REG_SDW(0, 0, 119) +#define UJ_IMPEDANCE_R TAC_REG_SDW(0, 0, 120) +#define TAC_GP_ANA_STS TAC_REG_SDW(0, 0, 123) +#define TAC_DEV_ID TAC_REG_SDW(0, 0, 124) +#define TAC_REV_ID TAC_REG_SDW(0, 0, 125) +#define TAC_I2C_CKSUM TAC_REG_SDW(0, 0, 126) +#define TAC_BOOK TAC_REG_SDW(0, 0, 127) + +#define TAC_INT_CFG TAC_REG_SDW(0, 2, 1) +#define TAC_INT_CFG_CLR_REG BIT(3) + +/* smartamp function */ +#define TAC_FUNCTION_ID_SA 0x1 + +#define TAC_SDCA_ENT_ENT0 0x0 +#define TAC_SDCA_ENT_PPU21 0x1 +#define TAC_SDCA_ENT_FU21 0x2 +#define TAC_SDCA_ENT_FU26 0x3 +#define TAC_SDCA_ENT_XU22 0x4 +#define TAC_SDCA_ENT_CS24 0x5 +#define TAC_SDCA_ENT_CS21 0x6 +#define TAC_SDCA_ENT_CS25 0x7 +#define TAC_SDCA_ENT_CS26 0x8 +#define TAC_SDCA_ENT_CS28 0x9 +#define TAC_SDCA_ENT_PPU26 0xa +#define TAC_SDCA_ENT_FU23 0xb +#define TAC_SDCA_ENT_PDE23 0xc +#define TAC_SDCA_ENT_TG23 0x12 +#define TAC_SDCA_ENT_IT21 0x13 +#define TAC_SDCA_ENT_IT29 0x14 +#define TAC_SDCA_ENT_IT26 0x15 +#define TAC_SDCA_ENT_IT28 0x16 +#define TAC_SDCA_ENT_OT24 0x17 +#define TAC_SDCA_ENT_OT23 0x18 +#define TAC_SDCA_ENT_OT25 0x19 +#define TAC_SDCA_ENT_OT28 0x1a +#define TAC_SDCA_ENT_OT27 0x1c +#define TAC_SDCA_ENT_SPE199 0x21 +#define TAC_SDCA_ENT_OT20 0x24 +#define TAC_SDCA_ENT_FU27 0x26 +#define TAC_SDCA_ENT_FU20 0x27 +#define TAC_SDCA_ENT_PDE24 0x2e +#define TAC_SDCA_ENT_PDE27 0x2f +#define TAC_SDCA_ENT_PDE28 0x30 +#define TAC_SDCA_ENT_PDE20 0x31 +#define TAC_SDCA_ENT_SAPU29 0x35 + +/* Control selector definitions */ +#define TAC_SDCA_MASTER_GAIN 0x0B +#define TAC_SDCA_MASTER_MUTE 0x01 +#define TAC_SDCA_CHANNEL_MUTE 0x01 +#define TAC_SDCA_CHANNEL_GAIN 0x02 +#define TAC_SDCA_POSTURENUMBER 0x10 +#define TAC_SDCA_REQUESTED_PS 0x01 +#define TAC_SDCA_ACTUAL_PS 0x10 +#define TAC_SDCA_CHANNEL_VOLUME 0x02 + +/* 2. smart mic function */ +#define TAC_FUNCTION_ID_SM 0x2 + +#define TAC_SDCA_ENT_IT11 0x1 +#define TAC_SDCA_ENT_OT113 0x2 +#define TAC_SDCA_ENT_CS11 0x3 +#define TAC_SDCA_ENT_CS18 0x4 +#define TAC_SDCA_ENT_FU113 0x5 +#define TAC_SDCA_ENT_FU13 0x6 +#define TAC_SDCA_ENT_FU11 0x8 +#define TAC_SDCA_ENT_XU12 0xa +#define TAC_SDCA_ENT_CS113 0xc +#define TAC_SDCA_ENT_CX11 0xf +#define TAC_SDCA_ENT_PDE11 0x12 +#define TAC_SDCA_ENT_PPU11 0x9 + +/* controls */ +#define TAC_SDCA_CTL_USAGE 0x04 +#define TAC_SDCA_CTL_IT_CLUSTER 0x10 +#define TAC_SDCA_CTL_OT_DP_SEL 0x11 +#define TAC_SDCA_CTL_XU_BYPASS 0x01 +/* cx */ +#define TAC_SDCA_CTL_CX_CLK_SEL 0x01 +/* cs */ +#define TAC_SDCA_CTL_CS_CLKVLD 0x02 +#define TAC_SDCA_CTL_CS_SAMP_RATE_IDX 0x10 +/* cs113 end */ +/* ppu */ +#define TAC_SDCA_CTL_PPU_POSTURE_NUM 0x10 + +/* 3. UAJ function */ +#define TAC_FUNCTION_ID_UAJ 0x3 +#define TAC_SDCA_ENT_PDE47 0x35 +#define TAC_SDCA_ENT_PDE34 0x32 +#define TAC_SDCA_ENT_FU41 0x26 /* user */ +#define TAC_SDCA_ENT_IT41 0x07 +#define TAC_SDCA_ENT_XU42 0x2C +#define TAC_SDCA_ENT_CS41 0x30 +#define TAC_SDCA_ENT_OT45 0x0E +#define TAC_SDCA_ENT_IT33 0x03 +#define TAC_SDCA_ENT_OT36 0x0A +#define TAC_SDCA_ENT_FU36 0x28 +#define TAC_SDCA_ENT_CS36 0x2E +#define TAC_SDCA_ENT_GE35 0x3B /* 59 */ + +#define TAC_SDCA_CTL_SEL_MODE 0x1 +#define TAC_SDCA_CTL_DET_MODE 0x2 + +/* 4. HID function */ +#define TAC_FUNCTION_ID_HID 0x4 +#define TAC_SDCA_ENT_HID1 0x1 +/* HID Control Selectors */ +#define TAC_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10 +#define TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12 +#define TAC_SDCA_CTL_HIDTX_MESSAGE_LENGTH 0x13 +#define TAC_SDCA_CTL_DETECTED_MODE 0x10 +#define TAC_SDCA_CTL_SELECTED_MODE 0x11 + +#define TAC_BUF_ADDR_HID1 0x44007F80 + +/* DAI interfaces */ +#define TAC5XX2_SPK 0 +#define TAC5XX2_DMIC 2 +#define TAC5XX2_UAJ 3 + +/* Port numbers for DAIs */ +#define TAC_SDW_PORT_NUM_SPK_PLAYBACK 1 +#define TAC_SDW_PORT_NUM_SPK_CAPTURE 2 +#define TAC_SDW_PORT_NUM_DMIC 3 +#define TAC_SDW_PORT_NUM_UAJ_PLAYBACK 4 +#define TAC_SDW_PORT_NUM_UAJ_CAPTURE 7 +#define TAC_SDW_PORT_NUM_IV_SENSE 8 + +#endif diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 80206c2e0946..1a7650b9b2a7 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -745,7 +745,7 @@ static void tas2552_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id tas2552_id[] = { - { "tas2552" }, + { .name = "tas2552" }, { } }; MODULE_DEVICE_TABLE(i2c, tas2552_id); diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index ceb367ae05ba..2f7cfc2be970 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -711,9 +711,9 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562) } static const struct i2c_device_id tas2562_id[] = { - { "tas2562", TAS2562 }, - { "tas2564", TAS2564 }, - { "tas2110", TAS2110 }, + { .name = "tas2562", .driver_data = TAS2562 }, + { .name = "tas2564", .driver_data = TAS2564 }, + { .name = "tas2110", .driver_data = TAS2110 }, { } }; MODULE_DEVICE_TABLE(i2c, tas2562_id); diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 55211266927d..b11b998aa32a 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -1036,7 +1036,7 @@ static int tas2764_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tas2764_i2c_id[] = { - { "tas2764"}, + { .name = "tas2764" }, { } }; MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id); diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index dbda9f327535..e79754edac5c 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -958,7 +958,7 @@ static int tas2770_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tas2770_i2c_id[] = { - { "tas2770"}, + { .name = "tas2770" }, { } }; MODULE_DEVICE_TABLE(i2c, tas2770_i2c_id); diff --git a/sound/soc/codecs/tas2780.c b/sound/soc/codecs/tas2780.c index cf3f6abd7e7b..1ec1c076204f 100644 --- a/sound/soc/codecs/tas2780.c +++ b/sound/soc/codecs/tas2780.c @@ -621,7 +621,7 @@ static int tas2780_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tas2780_i2c_id[] = { - { "tas2780"}, + { .name = "tas2780" }, { } }; MODULE_DEVICE_TABLE(i2c, tas2780_i2c_id); diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index 885e0b6fed00..bd16d5326a23 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -921,7 +921,8 @@ static int tasdevice_process_block(void *context, unsigned char *data, data[subblk_offset + 1], data[subblk_offset + 2]), data[subblk_offset + 3]); - if (rc < 0) { + if (rc < 0 && + !(tas_priv->isspi && rc == -EXDEV)) { is_err = true; dev_err(tas_priv->dev, "process_block: single write error\n"); @@ -953,7 +954,7 @@ static int tasdevice_process_block(void *context, unsigned char *data, data[subblk_offset + 1], data[subblk_offset + 2]), &(data[subblk_offset + 4]), len); - if (rc < 0) { + if (rc < 0 && !(tas_priv->isspi && rc == -EXDEV)) { is_err = true; dev_err(tas_priv->dev, "%s: bulk_write error = %d\n", @@ -991,7 +992,7 @@ static int tasdevice_process_block(void *context, unsigned char *data, data[subblk_offset + 4]), data[subblk_offset + 1], data[subblk_offset + 5]); - if (rc < 0) { + if (rc < 0 && !(tas_priv->isspi && rc == -EXDEV)) { is_err = true; dev_err(tas_priv->dev, "%s: update_bits error = %d\n", diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index a78a8f9b9833..9e6f0ad5f05d 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -100,27 +100,28 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = { }; static const struct i2c_device_id tasdevice_id[] = { - { "tas2020", TAS2020 }, - { "tas2118", TAS2118 }, - { "tas2120", TAS2120 }, - { "tas2320", TAS2320 }, - { "tas2563", TAS2563 }, - { "tas2568", TAS2568 }, - { "tas2570", TAS2570 }, - { "tas2572", TAS2572 }, - { "tas2574", TAS2574 }, - { "tas2781", TAS2781 }, - { "tas5802", TAS5802 }, - { "tas5806m", TAS5806M }, - { "tas5806md", TAS5806MD }, - { "tas5815", TAS5815 }, - { "tas5822", TAS5822 }, - { "tas5825", TAS5825 }, - { "tas5827", TAS5827 }, - { "tas5828", TAS5828 }, - { "tas5830", TAS5830 }, - { "tas5832", TAS5832 }, - {} + { .name = "tas2020", .driver_data = TAS2020 }, + { .name = "tas2118", .driver_data = TAS2118 }, + { .name = "tas2120", .driver_data = TAS2120 }, + { .name = "tas2320", .driver_data = TAS2320 }, + { .name = "tas2563", .driver_data = TAS2563 }, + { .name = "tas2568", .driver_data = TAS2568 }, + { .name = "tas2570", .driver_data = TAS2570 }, + { .name = "tas2572", .driver_data = TAS2572 }, + { .name = "tas2573", .driver_data = TAS2573 }, + { .name = "tas2574", .driver_data = TAS2574 }, + { .name = "tas2781", .driver_data = TAS2781 }, + { .name = "tas5802", .driver_data = TAS5802 }, + { .name = "tas5806m", .driver_data = TAS5806M }, + { .name = "tas5806md", .driver_data = TAS5806MD }, + { .name = "tas5815", .driver_data = TAS5815 }, + { .name = "tas5822", .driver_data = TAS5822 }, + { .name = "tas5825", .driver_data = TAS5825 }, + { .name = "tas5827", .driver_data = TAS5827 }, + { .name = "tas5828", .driver_data = TAS5828 }, + { .name = "tas5830", .driver_data = TAS5830 }, + { .name = "tas5832", .driver_data = TAS5832 }, + { } }; static const struct of_device_id tasdevice_of_match[] = { @@ -132,6 +133,7 @@ static const struct of_device_id tasdevice_of_match[] = { { .compatible = "ti,tas2568", .data = &tasdevice_id[TAS2568] }, { .compatible = "ti,tas2570", .data = &tasdevice_id[TAS2570] }, { .compatible = "ti,tas2572", .data = &tasdevice_id[TAS2572] }, + { .compatible = "ti,tas2573", .data = &tasdevice_id[TAS2573] }, { .compatible = "ti,tas2574", .data = &tasdevice_id[TAS2574] }, { .compatible = "ti,tas2781", .data = &tasdevice_id[TAS2781] }, { .compatible = "ti,tas5802", .data = &tasdevice_id[TAS5802] }, @@ -1683,7 +1685,7 @@ static void tasdevice_fw_ready(const struct firmware *fmw, tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; /* There is no calibration required for TAS58XX. */ - if (tas_priv->chip_id < TAS5802) { + if (tas_priv->chip_id == TAS2563 || tas_priv->chip_id == TAS2781) { ret = tasdevice_create_cali_ctrls(tas_priv); if (ret) { dev_err(tas_priv->dev, "cali controls error\n"); @@ -1736,6 +1738,7 @@ static void tasdevice_fw_ready(const struct firmware *fmw, if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) { switch (tas_priv->chip_id) { case TAS2563: + case TAS2573: case TAS2781: case TAS5802: case TAS5806M: @@ -1900,6 +1903,7 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) case TAS2568: case TAS2570: case TAS2572: + case TAS2573: case TAS2574: p = (struct snd_kcontrol_new *)tas2x20_snd_controls; size = ARRAY_SIZE(tas2x20_snd_controls); @@ -2094,6 +2098,7 @@ static const struct acpi_device_id tasdevice_acpi_match[] = { { "TXNW2568", (kernel_ulong_t)&tasdevice_id[TAS2568] }, { "TXNW2570", (kernel_ulong_t)&tasdevice_id[TAS2570] }, { "TXNW2572", (kernel_ulong_t)&tasdevice_id[TAS2572] }, + { "TXNW2573", (kernel_ulong_t)&tasdevice_id[TAS2573] }, { "TXNW2574", (kernel_ulong_t)&tasdevice_id[TAS2574] }, { "TXNW2781", (kernel_ulong_t)&tasdevice_id[TAS2781] }, { "TXNW5802", (kernel_ulong_t)&tasdevice_id[TAS5802] }, diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c index 90008d2d06e2..7d70e7e3f24f 100644 --- a/sound/soc/codecs/tas2783-sdw.c +++ b/sound/soc/codecs/tas2783-sdw.c @@ -1011,7 +1011,6 @@ static s32 tas_component_probe(struct snd_soc_component *component) snd_soc_component_get_drvdata(component); tas_dev->component = component; - tas25xx_register_misc(tas_dev->sdw_peripheral); return 0; } @@ -1020,7 +1019,6 @@ static void tas_component_remove(struct snd_soc_component *codec) { struct tas2783_prv *tas_dev = snd_soc_component_get_drvdata(codec); - tas25xx_deregister_misc(); tas_dev->component = NULL; } @@ -1082,22 +1080,12 @@ static s32 tas2783_sdca_dev_resume(struct device *dev) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct tas2783_prv *tas_dev = dev_get_drvdata(dev); - unsigned long t; + int ret; - if (!slave->unattach_request) - goto regmap_sync; + ret = sdw_slave_wait_for_init(slave, TAS2783_PROBE_TIMEOUT); + if (ret) + return ret; - t = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(TAS2783_PROBE_TIMEOUT)); - if (!t) { - dev_err(&slave->dev, "resume: initialization timed out\n"); - sdw_show_ping_status(slave->bus, true); - return -ETIMEDOUT; - } - - slave->unattach_request = 0; - -regmap_sync: regcache_cache_only(tas_dev->regmap, false); regcache_sync(tas_dev->regmap); return 0; @@ -1310,10 +1298,10 @@ static s32 tas_sdw_probe(struct sdw_slave *peripheral, return dev_err_probe(dev, -ENOMEM, "failed to parse sdca functions"); + function_data->desc = &peripheral->sdca_data.function[i]; + /* Parse the function */ - ret = sdca_parse_function(dev, peripheral, - &peripheral->sdca_data.function[i], - function_data); + ret = sdca_parse_function(dev, peripheral, function_data); if (!ret) tas_dev->sa_func_data = function_data; else diff --git a/sound/soc/codecs/tas2783.h b/sound/soc/codecs/tas2783.h index bf34319c9a9f..d5996c73526c 100644 --- a/sound/soc/codecs/tas2783.h +++ b/sound/soc/codecs/tas2783.h @@ -100,12 +100,4 @@ #define TAS2783_CALIB_DATA_SZ ((TAS2783_CALIB_HDR_SZ) + TAS2783_CALIB_CRC_SZ + \ ((TAS2783_CALIB_PARAMS) * 4 * (TAS2783_CALIB_MAX_SPK_COUNT))) -#if IS_ENABLED(CONFIG_SND_SOC_TAS2783_UTIL) -int32_t tas25xx_register_misc(struct sdw_slave *peripheral); -int32_t tas25xx_deregister_misc(void); -#else -static void tas25xx_register_misc(struct sdw_slave *peripheral) {} -static void tas25xx_deregister_misc(void) {} -#endif - #endif /*__TAS2783_H__ */ diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index 12bf6a89dbd8..4d1c122c8f04 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -891,7 +891,7 @@ static const struct snd_soc_component_driver soc_component_dev_tas5086 = { }; static const struct i2c_device_id tas5086_i2c_id[] = { - { "tas5086" }, + { .name = "tas5086" }, { } }; MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id); @@ -975,17 +975,13 @@ static int tas5086_i2c_probe(struct i2c_client *i2c) return ret; } -static void tas5086_i2c_remove(struct i2c_client *i2c) -{} - static struct i2c_driver tas5086_i2c_driver = { .driver = { - .name = "tas5086", + .name = "tas5086", .of_match_table = of_match_ptr(tas5086_dt_ids), }, - .id_table = tas5086_i2c_id, - .probe = tas5086_i2c_probe, - .remove = tas5086_i2c_remove, + .id_table = tas5086_i2c_id, + .probe = tas5086_i2c_probe, }; module_i2c_driver(tas5086_i2c_driver); diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 19ccf8641e16..8b5f9accf120 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -1064,13 +1064,13 @@ static const struct of_device_id tas571x_of_match[] __maybe_unused = { MODULE_DEVICE_TABLE(of, tas571x_of_match); static const struct i2c_device_id tas571x_i2c_id[] = { - { "tas5707", (kernel_ulong_t) &tas5707_chip }, - { "tas5711", (kernel_ulong_t) &tas5711_chip }, - { "tas5717", (kernel_ulong_t) &tas5717_chip }, - { "tas5719", (kernel_ulong_t) &tas5717_chip }, - { "tas5721", (kernel_ulong_t) &tas5721_chip }, - { "tas5733", (kernel_ulong_t) &tas5733_chip }, - { "tas5753", (kernel_ulong_t) &tas5753_chip }, + { .name = "tas5707", .driver_data = (kernel_ulong_t)&tas5707_chip }, + { .name = "tas5711", .driver_data = (kernel_ulong_t)&tas5711_chip }, + { .name = "tas5717", .driver_data = (kernel_ulong_t)&tas5717_chip }, + { .name = "tas5719", .driver_data = (kernel_ulong_t)&tas5717_chip }, + { .name = "tas5721", .driver_data = (kernel_ulong_t)&tas5721_chip }, + { .name = "tas5733", .driver_data = (kernel_ulong_t)&tas5733_chip }, + { .name = "tas5753", .driver_data = (kernel_ulong_t)&tas5753_chip }, { } }; MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id); diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c index 2dcdd0a4bf80..0bbcfaadf3f2 100644 --- a/sound/soc/codecs/tas5720.c +++ b/sound/soc/codecs/tas5720.c @@ -716,9 +716,9 @@ static struct snd_soc_dai_driver tas5720_dai[] = { }; static const struct i2c_device_id tas5720_id[] = { - { "tas5720", TAS5720 }, - { "tas5720a-q1", TAS5720A_Q1 }, - { "tas5722", TAS5722 }, + { .name = "tas5720", .driver_data = TAS5720 }, + { .name = "tas5720a-q1", .driver_data = TAS5720A_Q1 }, + { .name = "tas5722", .driver_data = TAS5722 }, { } }; MODULE_DEVICE_TABLE(i2c, tas5720_id); diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c index 867046b7aaa0..bcc8cab8d667 100644 --- a/sound/soc/codecs/tas5805m.c +++ b/sound/soc/codecs/tas5805m.c @@ -580,7 +580,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id tas5805m_i2c_id[] = { - { "tas5805m", }, + { .name = "tas5805m" }, { } }; MODULE_DEVICE_TABLE(i2c, tas5805m_i2c_id); diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index 85ecc246896f..f5d50f8a1cfb 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -794,7 +794,7 @@ static void tas6424_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id tas6424_i2c_ids[] = { - { "tas6424" }, + { .name = "tas6424" }, { } }; MODULE_DEVICE_TABLE(i2c, tas6424_i2c_ids); diff --git a/sound/soc/codecs/tas675x.c b/sound/soc/codecs/tas675x.c new file mode 100644 index 000000000000..6f89a422f3c6 --- /dev/null +++ b/sound/soc/codecs/tas675x.c @@ -0,0 +1,2194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ALSA SoC Texas Instruments TAS67524 Quad-Channel Audio Amplifier + * + * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/ + * Author: Sen Wang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas675x.h" + +#define TAS675X_FAULT_CHECK_INTERVAL_MS 200 + +enum tas675x_type { + TAS67524, +}; + +struct tas675x_reg_param { + u8 page; + u8 reg; + u32 val; +}; + +struct tas675x_priv { + struct device *dev; + struct regmap *regmap; + enum tas675x_type dev_type; + /* Custom regmap lock; protects writes across books */ + struct mutex io_lock; + + struct gpio_desc *pd_gpio; + struct gpio_desc *stby_gpio; + struct regulator_bulk_data supplies[2]; + struct regulator *vbat; + bool fast_boot; + + int audio_slot; + int llp_slot; + int vpredict_slot; + int isense_slot; + int bclk_offset; + int slot_width; + unsigned int tx_mask; + + int gpio1_func; + int gpio2_func; + + unsigned long active_playback_dais; + unsigned long active_capture_dais; + unsigned int rate; + unsigned int saved_rtldg_en; +#define TAS675X_DSP_PARAM_NUM 2 + struct tas675x_reg_param dsp_params[TAS675X_DSP_PARAM_NUM]; + + /* Fault monitor, disabled when Fault IRQ is used */ + struct delayed_work fault_check_work; +#define TAS675X_FAULT_REGS_NUM 9 + unsigned int last_status[TAS675X_FAULT_REGS_NUM]; +}; + +static const char * const tas675x_supply_names[] = { + "dvdd", /* Digital power supply */ + "pvdd", /* Output powerstage supply */ +}; + +/* Page 1 setup initialization defaults */ +static const struct reg_sequence tas675x_page1_init[] = { + REG_SEQ0(TAS675X_PAGE_REG(1, 0xC8), 0x20), /* Charge pump clock */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0x2F), 0x90), /* VBAT idle */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0x29), 0x40), /* OC/CBC threshold */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0x2E), 0x0C), /* OC/CBC config */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0xC5), 0x02), /* OC/CBC config */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0xC6), 0x10), /* OC/CBC config */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0x1F), 0x20), /* OC/CBC config */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0x16), 0x01), /* OC/CBC config */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0x1E), 0x04), /* OC/CBC config */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0xC1), 0x00), /* CH1 DC fault */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0xC2), 0x04), /* CH2 DC fault */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0xC3), 0x00), /* CH3 DC fault */ + REG_SEQ0(TAS675X_PAGE_REG(1, 0xC4), 0x00), /* CH4 DC fault */ +}; + +static inline const char *tas675x_state_name(unsigned int state) +{ + switch (state & 0x0F) { + case TAS675X_STATE_DEEPSLEEP: return "DEEPSLEEP"; + case TAS675X_STATE_LOAD_DIAG: return "LOAD_DIAG"; + case TAS675X_STATE_SLEEP: return "SLEEP"; + case TAS675X_STATE_HIZ: return "HIZ"; + case TAS675X_STATE_PLAY: return "PLAY"; + case TAS675X_STATE_FAULT: return "FAULT"; + case TAS675X_STATE_AUTOREC: return "AUTOREC"; + default: return "UNKNOWN"; + } +} + +static inline int tas675x_set_state_all(struct tas675x_priv *tas, u8 state) +{ + const struct reg_sequence seq[] = { + REG_SEQ0(TAS675X_STATE_CTRL_CH1_CH2_REG, state), + REG_SEQ0(TAS675X_STATE_CTRL_CH3_CH4_REG, state), + }; + + return regmap_multi_reg_write(tas->regmap, seq, ARRAY_SIZE(seq)); +} + +static inline int tas675x_select_book(struct regmap *regmap, u8 book) +{ + int ret; + + /* Reset page to 0 before switching books */ + ret = regmap_write(regmap, TAS675X_PAGE_CTRL_REG, 0x00); + if (!ret) + ret = regmap_write(regmap, TAS675X_BOOK_CTRL_REG, book); + + return ret; +} + +/* Raw I2C version of tas675x_select_book, must be called with io_lock held */ +static inline int __tas675x_select_book(struct tas675x_priv *tas, u8 book) +{ + struct i2c_client *client = to_i2c_client(tas->dev); + int ret; + + /* Reset page to 0 before switching books */ + ret = i2c_smbus_write_byte_data(client, TAS675X_PAGE_CTRL_REG, 0x00); + if (ret) + return ret; + + return i2c_smbus_write_byte_data(client, TAS675X_BOOK_CTRL_REG, book); +} + +static int tas675x_dsp_mem_write(struct tas675x_priv *tas, u8 page, u8 reg, u32 val) +{ + struct i2c_client *client = to_i2c_client(tas->dev); + u8 buf[4]; + int ret; + + /* DSP registers are 32 bit big-endian */ + buf[0] = (val >> 24) & 0xFF; + buf[1] = (val >> 16) & 0xFF; + buf[2] = (val >> 8) & 0xFF; + buf[3] = val & 0xFF; + + /* + * DSP regs in a different book, therefore block + * regmap access before completion. + */ + mutex_lock(&tas->io_lock); + + ret = __tas675x_select_book(tas, TAS675X_BOOK_DSP); + if (ret) + goto out; + + ret = i2c_smbus_write_byte_data(client, TAS675X_PAGE_CTRL_REG, page); + if (ret) + goto out; + + ret = i2c_smbus_write_i2c_block_data(client, reg, sizeof(buf), buf); + +out: + __tas675x_select_book(tas, TAS675X_BOOK_DEFAULT); + mutex_unlock(&tas->io_lock); + + return ret; +} + +static int tas675x_dsp_mem_read(struct tas675x_priv *tas, u8 page, u8 reg, u32 *val) +{ + struct i2c_client *client = to_i2c_client(tas->dev); + u8 buf[4]; + int ret; + + /* + * DSP regs in a different book, therefore block + * regmap access before completion. + */ + mutex_lock(&tas->io_lock); + + ret = __tas675x_select_book(tas, TAS675X_BOOK_DSP); + if (ret) + goto out; + + ret = i2c_smbus_write_byte_data(client, TAS675X_PAGE_CTRL_REG, page); + if (ret) + goto out; + + ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf); + if (ret == sizeof(buf)) { + *val = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + ret = 0; + } else if (ret >= 0) { + ret = -EIO; + } + +out: + __tas675x_select_book(tas, TAS675X_BOOK_DEFAULT); + mutex_unlock(&tas->io_lock); + + return ret; +} + +static const struct { + const char *name; + int val; +} tas675x_gpio_func_map[] = { + /* Output functions */ + { "low", TAS675X_GPIO_SEL_LOW }, + { "auto-mute", TAS675X_GPIO_SEL_AUTO_MUTE_ALL }, + { "auto-mute-ch4", TAS675X_GPIO_SEL_AUTO_MUTE_CH4 }, + { "auto-mute-ch3", TAS675X_GPIO_SEL_AUTO_MUTE_CH3 }, + { "auto-mute-ch2", TAS675X_GPIO_SEL_AUTO_MUTE_CH2 }, + { "auto-mute-ch1", TAS675X_GPIO_SEL_AUTO_MUTE_CH1 }, + { "sdout2", TAS675X_GPIO_SEL_SDOUT2 }, + { "sdout1", TAS675X_GPIO_SEL_SDOUT1 }, + { "warn", TAS675X_GPIO_SEL_WARN }, + { "fault", TAS675X_GPIO_SEL_FAULT }, + { "clock-sync", TAS675X_GPIO_SEL_CLOCK_SYNC }, + { "invalid-clock", TAS675X_GPIO_SEL_INVALID_CLK }, + { "high", TAS675X_GPIO_SEL_HIGH }, + /* Input functions */ + { "mute", TAS675X_GPIO_IN_MUTE }, + { "phase-sync", TAS675X_GPIO_IN_PHASE_SYNC }, + { "sdin2", TAS675X_GPIO_IN_SDIN2 }, + { "deep-sleep", TAS675X_GPIO_IN_DEEP_SLEEP }, + { "hiz", TAS675X_GPIO_IN_HIZ }, + { "play", TAS675X_GPIO_IN_PLAY }, + { "sleep", TAS675X_GPIO_IN_SLEEP }, +}; + +static int tas675x_gpio_func_parse(struct device *dev, const char *propname) +{ + const char *str; + int i, ret; + + ret = device_property_read_string(dev, propname, &str); + if (ret) + return -1; + + for (i = 0; i < ARRAY_SIZE(tas675x_gpio_func_map); i++) { + if (!strcmp(str, tas675x_gpio_func_map[i].name)) + return tas675x_gpio_func_map[i].val; + } + + dev_warn(dev, "Invalid %s value '%s'\n", propname, str); + return -1; +} + +static const struct { + unsigned int reg; + unsigned int mask; +} tas675x_gpio_input_table[TAS675X_GPIO_IN_NUM] = { + [TAS675X_GPIO_IN_ID_MUTE] = { + TAS675X_GPIO_INPUT_MUTE_REG, TAS675X_GPIO_IN_MUTE_MASK }, + [TAS675X_GPIO_IN_ID_PHASE_SYNC] = { + TAS675X_GPIO_INPUT_SYNC_REG, TAS675X_GPIO_IN_SYNC_MASK }, + [TAS675X_GPIO_IN_ID_SDIN2] = { + TAS675X_GPIO_INPUT_SDIN2_REG, TAS675X_GPIO_IN_SDIN2_MASK }, + [TAS675X_GPIO_IN_ID_DEEP_SLEEP] = { + TAS675X_GPIO_INPUT_SLEEP_HIZ_REG, TAS675X_GPIO_IN_DEEP_SLEEP_MASK }, + [TAS675X_GPIO_IN_ID_HIZ] = { + TAS675X_GPIO_INPUT_SLEEP_HIZ_REG, TAS675X_GPIO_IN_HIZ_MASK }, + [TAS675X_GPIO_IN_ID_PLAY] = { + TAS675X_GPIO_INPUT_PLAY_SLEEP_REG, TAS675X_GPIO_IN_PLAY_MASK }, + [TAS675X_GPIO_IN_ID_SLEEP] = { + TAS675X_GPIO_INPUT_PLAY_SLEEP_REG, TAS675X_GPIO_IN_SLEEP_MASK }, +}; + +static void tas675x_config_gpio_pin(struct regmap *regmap, int func_id, + unsigned int out_sel_reg, + unsigned int pin_idx, + unsigned int *gpio_ctrl) +{ + int id; + + if (func_id < 0) + return; + + if (func_id & TAS675X_GPIO_FUNC_INPUT) { + /* 3-bit mux: 0 = disabled, 0b1 = GPIO1, 0b10 = GPIO2 */ + id = func_id & ~TAS675X_GPIO_FUNC_INPUT; + regmap_update_bits(regmap, + tas675x_gpio_input_table[id].reg, + tas675x_gpio_input_table[id].mask, + (pin_idx + 1) << __ffs(tas675x_gpio_input_table[id].mask)); + } else { + /* Output GPIO, update selection register and enable bit */ + regmap_write(regmap, out_sel_reg, func_id); + *gpio_ctrl |= pin_idx ? TAS675X_GPIO2_OUTPUT_EN : TAS675X_GPIO1_OUTPUT_EN; + } +} + +static int tas675x_rtldg_thresh_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + /* threshold reg ranges up to 24bit */ + uinfo->value.integer.max = 0x00FFFFFF; + return 0; +} + +static int tas675x_set_rtldg_thresh(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp); + const struct tas675x_reg_param *t = + (const struct tas675x_reg_param *)kcontrol->private_value; + u32 val = ucontrol->value.integer.value[0]; + int ret; + + ret = tas675x_dsp_mem_write(tas, t->page, t->reg, val); + + /* Cache the value */ + if (!ret) { + int i; + + for (i = 0; i < ARRAY_SIZE(tas->dsp_params); i++) { + if (tas->dsp_params[i].page == t->page && + tas->dsp_params[i].reg == t->reg) { + tas->dsp_params[i].val = val; + break; + } + } + } + + /* Return 1 to notify change, or propagate error */ + return ret ? ret : 1; +} + +static int tas675x_get_rtldg_thresh(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp); + const struct tas675x_reg_param *t = + (const struct tas675x_reg_param *)kcontrol->private_value; + u32 val = 0; + int ret; + + ret = tas675x_dsp_mem_read(tas, t->page, t->reg, &val); + if (!ret) + ucontrol->value.integer.value[0] = val; + + return ret; +} + +static const struct tas675x_reg_param tas675x_dsp_defaults[] = { + [TAS675X_DSP_PARAM_ID_OL_THRESH] = { + TAS675X_DSP_PAGE_RTLDG, TAS675X_DSP_RTLDG_OL_THRESH_REG }, + [TAS675X_DSP_PARAM_ID_SL_THRESH] = { + TAS675X_DSP_PAGE_RTLDG, TAS675X_DSP_RTLDG_SL_THRESH_REG }, +}; + +static_assert(ARRAY_SIZE(tas675x_dsp_defaults) == TAS675X_DSP_PARAM_NUM); + +static int tas675x_set_dcldg_trigger(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp); + unsigned int state, state34; + int ret; + + if (!ucontrol->value.integer.value[0]) + return 0; + + if (snd_soc_component_active(comp)) + return -EBUSY; + + ret = pm_runtime_resume_and_get(tas->dev); + if (ret < 0) + return ret; + + /* + * Abort automatic DC LDG retry loops (startup or init-after-fault) + * and clear faults before manual diagnostics. + */ + regmap_update_bits(tas->regmap, TAS675X_DC_LDG_CTRL_REG, + TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT, + TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT); + regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR); + + /* Wait for LOAD_DIAG to exit */ + ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG, + state, (state & 0x0F) != TAS675X_STATE_LOAD_DIAG && + (state >> 4) != TAS675X_STATE_LOAD_DIAG, + TAS675X_POLL_INTERVAL_US, + TAS675X_STATE_TRANSITION_TIMEOUT_US); + ret |= regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG, + state34, (state34 & 0x0F) != TAS675X_STATE_LOAD_DIAG && + (state34 >> 4) != TAS675X_STATE_LOAD_DIAG, + TAS675X_POLL_INTERVAL_US, + TAS675X_STATE_TRANSITION_TIMEOUT_US); + if (ret) { + dev_err(tas->dev, + "DC LDG: abort timeout (CH1/2=0x%02x [%s/%s], CH3/4=0x%02x [%s/%s])\n", + state, tas675x_state_name(state), tas675x_state_name(state >> 4), + state34, tas675x_state_name(state34), tas675x_state_name(state34 >> 4)); + goto out_restore_ldg_ctrl; + } + + /* Transition to HIZ state */ + ret = tas675x_set_state_all(tas, TAS675X_STATE_HIZ_BOTH); + if (ret) + goto out_restore_ldg_ctrl; + + /* Set LOAD_DIAG state for manual DC LDG */ + ret = tas675x_set_state_all(tas, TAS675X_STATE_LOAD_DIAG_BOTH); + if (ret) + goto out_restore_ldg_ctrl; + + /* Wait for device to transition to LOAD_DIAG state */ + ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG, + state, state == TAS675X_STATE_LOAD_DIAG_BOTH, + TAS675X_POLL_INTERVAL_US, + TAS675X_STATE_TRANSITION_TIMEOUT_US); + ret |= regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG, + state34, state34 == TAS675X_STATE_LOAD_DIAG_BOTH, + TAS675X_POLL_INTERVAL_US, + TAS675X_STATE_TRANSITION_TIMEOUT_US); + if (ret) { + dev_err(tas->dev, + "DC LDG: LOAD_DIAG timeout (CH1/2=0x%02x [%s/%s], CH3/4=0x%02x [%s/%s])\n", + state, tas675x_state_name(state), tas675x_state_name(state >> 4), + state34, tas675x_state_name(state34), tas675x_state_name(state34 >> 4)); + goto out_restore_hiz; + } + + /* Clear ABORT and BYPASS bits to enable manual DC LDG */ + ret = regmap_update_bits(tas->regmap, TAS675X_DC_LDG_CTRL_REG, + TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT, + 0); + if (ret) + goto out_restore_hiz; + + dev_dbg(tas->dev, "DC LDG: Started\n"); + + /* Poll all channels for SLEEP state */ + ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG, + state, state == TAS675X_STATE_SLEEP_BOTH, + TAS675X_POLL_INTERVAL_US, + TAS675X_DC_LDG_TIMEOUT_US); + ret |= regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG, + state34, state34 == TAS675X_STATE_SLEEP_BOTH, + TAS675X_POLL_INTERVAL_US, + TAS675X_DC_LDG_TIMEOUT_US); + if (ret) { + dev_err(tas->dev, + "DC LDG: SLEEP timeout (CH1/2=0x%02x [%s/%s], CH3/4=0x%02x [%s/%s])\n", + state, tas675x_state_name(state), tas675x_state_name(state >> 4), + state34, tas675x_state_name(state34), tas675x_state_name(state34 >> 4)); + goto out_restore_hiz; + } + + dev_dbg(tas->dev, "DC LDG: Completed successfully (CH1/2=0x%02x, CH3/4=0x%02x)\n", + state, state34); + +out_restore_hiz: + tas675x_set_state_all(tas, TAS675X_STATE_HIZ_BOTH); + +out_restore_ldg_ctrl: + regmap_update_bits(tas->regmap, TAS675X_DC_LDG_CTRL_REG, + TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT, + 0); + + pm_runtime_mark_last_busy(tas->dev); + pm_runtime_put_autosuspend(tas->dev); + + return ret; +} + +static int tas675x_set_acldg_trigger(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp); + unsigned int state, state34; + int ret; + + if (!ucontrol->value.integer.value[0]) + return 0; + + if (snd_soc_component_active(comp)) + return -EBUSY; + + ret = pm_runtime_resume_and_get(tas->dev); + if (ret < 0) + return ret; + + /* AC Load Diagnostics requires SLEEP state */ + ret = tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH); + if (ret) { + dev_err(tas->dev, "AC LDG: Failed to set SLEEP state: %d\n", ret); + goto out; + } + + /* Start AC LDG on all 4 channels (0x0F) */ + ret = regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x0F); + if (ret) { + dev_err(tas->dev, "AC LDG: Failed to start: %d\n", ret); + goto out; + } + + dev_dbg(tas->dev, "AC LDG: Started\n"); + + /* Poll all channels for SLEEP state */ + ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG, + state, (state == TAS675X_STATE_SLEEP_BOTH), + TAS675X_POLL_INTERVAL_US, + TAS675X_AC_LDG_TIMEOUT_US); + if (ret) { + dev_err(tas->dev, + "AC LDG: CH1/CH2 timeout: %d (state=0x%02x [%s/%s])\n", + ret, state, tas675x_state_name(state), + tas675x_state_name(state >> 4)); + regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x00); + goto out; + } + + ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG, + state34, (state34 == TAS675X_STATE_SLEEP_BOTH), + TAS675X_POLL_INTERVAL_US, + TAS675X_AC_LDG_TIMEOUT_US); + if (ret) { + dev_err(tas->dev, + "AC LDG: CH3/CH4 timeout: %d (state=0x%02x [%s/%s])\n", + ret, state34, tas675x_state_name(state34), + tas675x_state_name(state34 >> 4)); + regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x00); + goto out; + } + + dev_dbg(tas->dev, "AC LDG: Completed successfully (CH1/2=0x%02x, CH3/4=0x%02x)\n", + state, state34); + regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x00); + +out: + pm_runtime_mark_last_busy(tas->dev); + pm_runtime_put_autosuspend(tas->dev); + + return ret; +} + +static int tas675x_rtldg_impedance_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xFFFF; + return 0; +} + +static int tas675x_get_rtldg_impedance(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp); + unsigned int msb_reg = (unsigned int)kcontrol->private_value; + u8 buf[2]; + int ret; + + ret = regmap_bulk_read(tas->regmap, msb_reg, buf, 2); + if (ret) + return ret; + + ucontrol->value.integer.value[0] = (buf[0] << 8) | buf[1]; + return 0; +} + +static int tas675x_dc_resistance_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + /* 10-bit: 2-bit MSB + 8-bit LSB, 0.1 ohm/code, 0-102.3 ohm */ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1023; + return 0; +} + +static int tas675x_get_dc_resistance(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp); + unsigned int lsb_reg = (unsigned int)kcontrol->private_value; + unsigned int msb, lsb, shift; + int ret; + + ret = regmap_read(tas->regmap, TAS675X_DC_LDG_DCR_MSB_REG, &msb); + if (ret) + return ret; + + ret = regmap_read(tas->regmap, lsb_reg, &lsb); + if (ret) + return ret; + + /* 2-bit MSB: CH1=[7:6], CH2=[5:4], CH3=[3:2], CH4=[1:0] */ + shift = 6 - (lsb_reg - TAS675X_CH1_DC_LDG_DCR_LSB_REG) * 2; + msb = (msb >> shift) & 0x3; + + ucontrol->value.integer.value[0] = (msb << 8) | lsb; + return 0; +} + +/* Counterparts with read-only access */ +#define SOC_SINGLE_RO(xname, xreg, xshift, xmax) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, \ + .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, 0, 0) } +#define SOC_DC_RESIST_RO(xname, xlsb_reg) \ +{ .name = xname, \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = tas675x_dc_resistance_info, \ + .get = tas675x_get_dc_resistance, \ + .private_value = (xlsb_reg) } +#define SOC_RTLDG_IMP_RO(xname, xreg) \ +{ .name = xname, \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = tas675x_rtldg_impedance_info, \ + .get = tas675x_get_rtldg_impedance, \ + .private_value = (xreg) } + +#define SOC_DSP_THRESH_EXT(xname, xthresh) \ +{ .name = xname, \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .info = tas675x_rtldg_thresh_info, \ + .get = tas675x_get_rtldg_thresh, \ + .put = tas675x_set_rtldg_thresh, \ + .private_value = (unsigned long)&(xthresh) } + +/* + * DAC digital volumes. From -103 to 0 dB in 0.5 dB steps, -103.5 dB means mute. + * DAC analog gain. From -15.5 to 0 dB in 0.5 dB steps, no mute. + */ +static const DECLARE_TLV_DB_SCALE(tas675x_dig_vol_tlv, -10350, 50, 1); +static const DECLARE_TLV_DB_SCALE(tas675x_ana_gain_tlv, -1550, 50, 0); + +static const char * const tas675x_ss_texts[] = { + "Disabled", "Triangle", "Random", "Triangle and Random" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ss_enum, TAS675X_SS_CTRL_REG, 0, tas675x_ss_texts); + +static const char * const tas675x_ss_tri_range_texts[] = { + "6.5%", "13.5%", "5%", "10%" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ss_tri_range_enum, + TAS675X_SS_RANGE_CTRL_REG, 0, + tas675x_ss_tri_range_texts); + +static const char * const tas675x_ss_rdm_range_texts[] = { + "0.83%", "2.50%", "5.83%", "12.50%", "25.83%" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ss_rdm_range_enum, + TAS675X_SS_RANGE_CTRL_REG, 4, + tas675x_ss_rdm_range_texts); + +static const char * const tas675x_ss_rdm_dwell_texts[] = { + "1/FSS to 2/FSS", "1/FSS to 4/FSS", "1/FSS to 8/FSS", "1/FSS to 15/FSS" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ss_rdm_dwell_enum, + TAS675X_SS_RANGE_CTRL_REG, 2, + tas675x_ss_rdm_dwell_texts); + +static const char * const tas675x_oc_limit_texts[] = { + "Level 4", "Level 3", "Level 2", "Level 1" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_oc_limit_enum, TAS675X_CURRENT_LIMIT_CTRL_REG, + 0, tas675x_oc_limit_texts); + +static const char * const tas675x_otw_texts[] = { + "Disabled", ">95C", ">110C", ">125C", ">135C", ">145C", ">155C", ">165C" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ch1_otw_enum, + TAS675X_OTW_CTRL_CH1_CH2_REG, 4, + tas675x_otw_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch2_otw_enum, + TAS675X_OTW_CTRL_CH1_CH2_REG, 0, + tas675x_otw_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch3_otw_enum, + TAS675X_OTW_CTRL_CH3_CH4_REG, 4, + tas675x_otw_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch4_otw_enum, + TAS675X_OTW_CTRL_CH3_CH4_REG, 0, + tas675x_otw_texts); + +static const char * const tas675x_dc_ldg_sl_texts[] = { + "0.5 Ohm", "1 Ohm", "1.5 Ohm", "2 Ohm", "2.5 Ohm", + "3 Ohm", "3.5 Ohm", "4 Ohm", "4.5 Ohm", "5 Ohm" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ch1_dc_ldg_sl_enum, + TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG, 4, + tas675x_dc_ldg_sl_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch2_dc_ldg_sl_enum, + TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG, 0, + tas675x_dc_ldg_sl_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch3_dc_ldg_sl_enum, + TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG, 4, + tas675x_dc_ldg_sl_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch4_dc_ldg_sl_enum, + TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG, 0, + tas675x_dc_ldg_sl_texts); + +static const char * const tas675x_dc_slol_ramp_texts[] = { + "15 ms", "30 ms", "10 ms", "20 ms" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_dc_slol_ramp_enum, + TAS675X_DC_LDG_TIME_CTRL_REG, 6, + tas675x_dc_slol_ramp_texts); + +static const char * const tas675x_dc_slol_settling_texts[] = { + "10 ms", "5 ms", "20 ms", "15 ms" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_dc_slol_settling_enum, + TAS675X_DC_LDG_TIME_CTRL_REG, 4, + tas675x_dc_slol_settling_texts); + +static const char * const tas675x_dc_s2pg_ramp_texts[] = { + "5 ms", "2.5 ms", "10 ms", "15 ms" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_dc_s2pg_ramp_enum, + TAS675X_DC_LDG_TIME_CTRL_REG, 2, + tas675x_dc_s2pg_ramp_texts); + +static const char * const tas675x_dc_s2pg_settling_texts[] = { + "10 ms", "5 ms", "20 ms", "30 ms" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_dc_s2pg_settling_enum, + TAS675X_DC_LDG_TIME_CTRL_REG, 0, + tas675x_dc_s2pg_settling_texts); + +static const char * const tas675x_dsp_mode_texts[] = { + "Normal", "LLP", "FFLP" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_dsp_mode_enum, + TAS675X_LL_EN_REG, 0, + tas675x_dsp_mode_texts); + +static const char * const tas675x_ana_ramp_texts[] = { + "15us", "60us", "200us", "400us" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ana_ramp_enum, + TAS675X_ANALOG_GAIN_RAMP_CTRL_REG, 2, + tas675x_ana_ramp_texts); + +static const char * const tas675x_ramp_rate_texts[] = { + "4 FS", "16 FS", "32 FS", "Instant" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ramp_down_rate_enum, + TAS675X_DIG_VOL_RAMP_CTRL_REG, 6, + tas675x_ramp_rate_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ramp_up_rate_enum, + TAS675X_DIG_VOL_RAMP_CTRL_REG, 2, + tas675x_ramp_rate_texts); + +static const char * const tas675x_ramp_step_texts[] = { + "4dB", "2dB", "1dB", "0.5dB" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ramp_down_step_enum, + TAS675X_DIG_VOL_RAMP_CTRL_REG, 4, + tas675x_ramp_step_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ramp_up_step_enum, + TAS675X_DIG_VOL_RAMP_CTRL_REG, 0, + tas675x_ramp_step_texts); + +static const char * const tas675x_vol_combine_ch12_texts[] = { + "Independent", "CH2 follows CH1", "CH1 follows CH2" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_vol_combine_ch12_enum, + TAS675X_DIG_VOL_COMBINE_CTRL_REG, 0, + tas675x_vol_combine_ch12_texts); + +static const char * const tas675x_vol_combine_ch34_texts[] = { + "Independent", "CH4 follows CH3", "CH3 follows CH4" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_vol_combine_ch34_enum, + TAS675X_DIG_VOL_COMBINE_CTRL_REG, 2, + tas675x_vol_combine_ch34_texts); + +static const char * const tas675x_auto_mute_time_texts[] = { + "11.5ms", "53ms", "106.5ms", "266.5ms", + "535ms", "1065ms", "2665ms", "5330ms" +}; + +static SOC_ENUM_SINGLE_DECL(tas675x_ch1_mute_time_enum, + TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG, 4, + tas675x_auto_mute_time_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch2_mute_time_enum, + TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG, 0, + tas675x_auto_mute_time_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch3_mute_time_enum, + TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG, 4, + tas675x_auto_mute_time_texts); +static SOC_ENUM_SINGLE_DECL(tas675x_ch4_mute_time_enum, + TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG, 0, + tas675x_auto_mute_time_texts); + +/* + * ALSA Mixer Controls + * + * For detailed documentation of each control see: + * Documentation/sound/codecs/tas675x.rst + */ +static const struct snd_kcontrol_new tas675x_snd_controls[] = { + /* Volume & Gain Control */ + SOC_DOUBLE_R_TLV("Analog Playback Volume", TAS675X_ANALOG_GAIN_CH1_CH2_REG, + TAS675X_ANALOG_GAIN_CH3_CH4_REG, 1, 0x1F, 1, tas675x_ana_gain_tlv), + SOC_ENUM("Analog Gain Ramp Step", tas675x_ana_ramp_enum), + SOC_SINGLE_RANGE_TLV("CH1 Digital Playback Volume", + TAS675X_DIG_VOL_CH1_REG, 0, 0x30, 0xFF, 1, + tas675x_dig_vol_tlv), + SOC_SINGLE_RANGE_TLV("CH2 Digital Playback Volume", + TAS675X_DIG_VOL_CH2_REG, 0, 0x30, 0xFF, 1, + tas675x_dig_vol_tlv), + SOC_SINGLE_RANGE_TLV("CH3 Digital Playback Volume", + TAS675X_DIG_VOL_CH3_REG, 0, 0x30, 0xFF, 1, + tas675x_dig_vol_tlv), + SOC_SINGLE_RANGE_TLV("CH4 Digital Playback Volume", + TAS675X_DIG_VOL_CH4_REG, 0, 0x30, 0xFF, 1, + tas675x_dig_vol_tlv), + SOC_ENUM("Volume Ramp Down Rate", tas675x_ramp_down_rate_enum), + SOC_ENUM("Volume Ramp Down Step", tas675x_ramp_down_step_enum), + SOC_ENUM("Volume Ramp Up Rate", tas675x_ramp_up_rate_enum), + SOC_ENUM("Volume Ramp Up Step", tas675x_ramp_up_step_enum), + SOC_ENUM("CH1/2 Volume Combine", tas675x_vol_combine_ch12_enum), + SOC_ENUM("CH3/4 Volume Combine", tas675x_vol_combine_ch34_enum), + + /* Auto Mute & Silence Detection */ + SOC_SINGLE("CH1 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 0, 1, 0), + SOC_SINGLE("CH2 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 1, 1, 0), + SOC_SINGLE("CH3 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 2, 1, 0), + SOC_SINGLE("CH4 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 3, 1, 0), + SOC_SINGLE("Auto Mute Combine Switch", TAS675X_AUTO_MUTE_EN_REG, 4, 1, 0), + SOC_ENUM("CH1 Auto Mute Time", tas675x_ch1_mute_time_enum), + SOC_ENUM("CH2 Auto Mute Time", tas675x_ch2_mute_time_enum), + SOC_ENUM("CH3 Auto Mute Time", tas675x_ch3_mute_time_enum), + SOC_ENUM("CH4 Auto Mute Time", tas675x_ch4_mute_time_enum), + + /* Clock & EMI Management */ + SOC_ENUM("Spread Spectrum Mode", tas675x_ss_enum), + SOC_ENUM("SS Triangle Range", tas675x_ss_tri_range_enum), + SOC_ENUM("SS Random Range", tas675x_ss_rdm_range_enum), + SOC_ENUM("SS Random Dwell Range", tas675x_ss_rdm_dwell_enum), + SOC_SINGLE("SS Triangle Dwell Min", TAS675X_SS_DWELL_CTRL_REG, 4, 15, 0), + SOC_SINGLE("SS Triangle Dwell Max", TAS675X_SS_DWELL_CTRL_REG, 0, 15, 0), + + /* Hardware Protection */ + SOC_SINGLE("OTSD Auto Recovery Switch", TAS675X_OTSD_RECOVERY_EN_REG, 1, 1, 0), + SOC_ENUM("Overcurrent Limit Level", tas675x_oc_limit_enum), + SOC_ENUM("CH1 OTW Threshold", tas675x_ch1_otw_enum), + SOC_ENUM("CH2 OTW Threshold", tas675x_ch2_otw_enum), + SOC_ENUM("CH3 OTW Threshold", tas675x_ch3_otw_enum), + SOC_ENUM("CH4 OTW Threshold", tas675x_ch4_otw_enum), + + /* DSP Signal Path & Mode */ + SOC_ENUM("DSP Signal Path Mode", tas675x_dsp_mode_enum), + + /* DC Load Diagnostics */ + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DC LDG Trigger", + .access = SNDRV_CTL_ELEM_ACCESS_WRITE, + .info = snd_ctl_boolean_mono_info, + .put = tas675x_set_dcldg_trigger, + }, + SOC_SINGLE("DC LDG Auto Diagnostics Switch", TAS675X_DC_LDG_CTRL_REG, 0, 1, 1), + SOC_SINGLE("CH1 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 3, 1, 0), + SOC_SINGLE("CH2 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 2, 1, 0), + SOC_SINGLE("CH3 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 1, 1, 0), + SOC_SINGLE("CH4 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 0, 1, 0), + SOC_ENUM("DC LDG SLOL Ramp Time", tas675x_dc_slol_ramp_enum), + SOC_ENUM("DC LDG SLOL Settling Time", tas675x_dc_slol_settling_enum), + SOC_ENUM("DC LDG S2PG Ramp Time", tas675x_dc_s2pg_ramp_enum), + SOC_ENUM("DC LDG S2PG Settling Time", tas675x_dc_s2pg_settling_enum), + SOC_ENUM("CH1 DC LDG SL Threshold", tas675x_ch1_dc_ldg_sl_enum), + SOC_ENUM("CH2 DC LDG SL Threshold", tas675x_ch2_dc_ldg_sl_enum), + SOC_ENUM("CH3 DC LDG SL Threshold", tas675x_ch3_dc_ldg_sl_enum), + SOC_ENUM("CH4 DC LDG SL Threshold", tas675x_ch4_dc_ldg_sl_enum), + SOC_SINGLE_RO("DC LDG Result", TAS675X_DC_LDG_RESULT_REG, 0, 0xFF), + SOC_SINGLE_RO("CH1 DC LDG Report", TAS675X_DC_LDG_REPORT_CH1_CH2_REG, 4, 0x0F), + SOC_SINGLE_RO("CH2 DC LDG Report", TAS675X_DC_LDG_REPORT_CH1_CH2_REG, 0, 0x0F), + SOC_SINGLE_RO("CH3 DC LDG Report", TAS675X_DC_LDG_REPORT_CH3_CH4_REG, 4, 0x0F), + SOC_SINGLE_RO("CH4 DC LDG Report", TAS675X_DC_LDG_REPORT_CH3_CH4_REG, 0, 0x0F), + SOC_SINGLE_RO("CH1 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 7, 1), + SOC_SINGLE_RO("CH2 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 6, 1), + SOC_SINGLE_RO("CH3 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 5, 1), + SOC_SINGLE_RO("CH4 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 4, 1), + SOC_DC_RESIST_RO("CH1 DC Resistance", TAS675X_CH1_DC_LDG_DCR_LSB_REG), + SOC_DC_RESIST_RO("CH2 DC Resistance", TAS675X_CH2_DC_LDG_DCR_LSB_REG), + SOC_DC_RESIST_RO("CH3 DC Resistance", TAS675X_CH3_DC_LDG_DCR_LSB_REG), + SOC_DC_RESIST_RO("CH4 DC Resistance", TAS675X_CH4_DC_LDG_DCR_LSB_REG), + + /* AC Load Diagnostics */ + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "AC LDG Trigger", + .access = SNDRV_CTL_ELEM_ACCESS_WRITE, + .info = snd_ctl_boolean_mono_info, + .put = tas675x_set_acldg_trigger, + }, + SOC_SINGLE("AC LDG Gain", TAS675X_AC_LDG_CTRL_REG, 4, 1, 0), + SOC_SINGLE("AC LDG Test Frequency", TAS675X_AC_LDG_FREQ_CTRL_REG, 0, 0xFF, 0), + SOC_SINGLE_RO("CH1 AC LDG Real", TAS675X_AC_LDG_REPORT_CH1_R_REG, 0, 0xFF), + SOC_SINGLE_RO("CH1 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH1_I_REG, 0, 0xFF), + SOC_SINGLE_RO("CH2 AC LDG Real", TAS675X_AC_LDG_REPORT_CH2_R_REG, 0, 0xFF), + SOC_SINGLE_RO("CH2 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH2_I_REG, 0, 0xFF), + SOC_SINGLE_RO("CH3 AC LDG Real", TAS675X_AC_LDG_REPORT_CH3_R_REG, 0, 0xFF), + SOC_SINGLE_RO("CH3 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH3_I_REG, 0, 0xFF), + SOC_SINGLE_RO("CH4 AC LDG Real", TAS675X_AC_LDG_REPORT_CH4_R_REG, 0, 0xFF), + SOC_SINGLE_RO("CH4 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH4_I_REG, 0, 0xFF), + + /* Temperature and Voltage Monitoring */ + SOC_SINGLE_RO("PVDD Sense", TAS675X_PVDD_SENSE_REG, 0, 0xFF), + SOC_SINGLE_RO("Global Temperature", TAS675X_TEMP_GLOBAL_REG, 0, 0xFF), + SOC_SINGLE_RO("CH1 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 6, 3), + SOC_SINGLE_RO("CH2 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 4, 3), + SOC_SINGLE_RO("CH3 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 2, 3), + SOC_SINGLE_RO("CH4 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 0, 3), + + /* Speaker Protection & Detection */ + SOC_SINGLE("Tweeter Detection Switch", TAS675X_TWEETER_DETECT_CTRL_REG, 0, 1, 1), + SOC_SINGLE("Tweeter Detect Threshold", TAS675X_TWEETER_DETECT_THRESH_REG, 0, 0xFF, 0), + SOC_SINGLE_RO("CH1 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 3, 1), + SOC_SINGLE_RO("CH2 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 2, 1), + SOC_SINGLE_RO("CH3 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 1, 1), + SOC_SINGLE_RO("CH4 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 0, 1), + + /* + * Unavailable in LLP, available in Normal & FFLP + */ + SOC_SINGLE("Thermal Foldback Switch", TAS675X_DSP_CTRL_REG, 0, 1, 0), + SOC_SINGLE("PVDD Foldback Switch", TAS675X_DSP_CTRL_REG, 4, 1, 0), + SOC_SINGLE("DC Blocker Bypass Switch", TAS675X_DC_BLOCK_BYP_REG, 0, 1, 0), + SOC_SINGLE("Clip Detect Switch", TAS675X_CLIP_DETECT_CTRL_REG, 6, 1, 0), + SOC_SINGLE("Audio SDOUT Switch", TAS675X_DSP_CTRL_REG, 5, 1, 0), + + /* + * Unavailable in both FFLP and LLP, Normal mode only + */ + /* Real-Time Load Diagnostics */ + SOC_SINGLE("CH1 RTLDG Switch", TAS675X_RTLDG_EN_REG, 3, 1, 0), + SOC_SINGLE("CH2 RTLDG Switch", TAS675X_RTLDG_EN_REG, 2, 1, 0), + SOC_SINGLE("CH3 RTLDG Switch", TAS675X_RTLDG_EN_REG, 1, 1, 0), + SOC_SINGLE("CH4 RTLDG Switch", TAS675X_RTLDG_EN_REG, 0, 1, 0), + SOC_SINGLE("RTLDG Clip Mask Switch", TAS675X_RTLDG_EN_REG, 4, 1, 0), + SOC_SINGLE("ISENSE Calibration Switch", TAS675X_ISENSE_CAL_REG, 3, 1, 0), + SOC_DSP_THRESH_EXT("RTLDG Open Load Threshold", + tas675x_dsp_defaults[TAS675X_DSP_PARAM_ID_OL_THRESH]), + SOC_DSP_THRESH_EXT("RTLDG Short Load Threshold", + tas675x_dsp_defaults[TAS675X_DSP_PARAM_ID_SL_THRESH]), + SOC_RTLDG_IMP_RO("CH1 RTLDG Impedance", TAS675X_CH1_RTLDG_IMP_MSB_REG), + SOC_RTLDG_IMP_RO("CH2 RTLDG Impedance", TAS675X_CH2_RTLDG_IMP_MSB_REG), + SOC_RTLDG_IMP_RO("CH3 RTLDG Impedance", TAS675X_CH3_RTLDG_IMP_MSB_REG), + SOC_RTLDG_IMP_RO("CH4 RTLDG Impedance", TAS675X_CH4_RTLDG_IMP_MSB_REG), +}; + +static const struct snd_kcontrol_new tas675x_audio_path_switch = + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1); + +static const struct snd_kcontrol_new tas675x_anc_path_switch = + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1); + +static const struct snd_soc_dapm_widget tas675x_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Analog Core", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("SDOUT Vpredict", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("SDOUT Isense", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_DAC("Audio DAC", "Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("ANC DAC", "ANC Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_ADC("Feedback ADC", "Feedback Capture", SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_SWITCH("Audio Path", SND_SOC_NOPM, 0, 0, + &tas675x_audio_path_switch), + SND_SOC_DAPM_SWITCH("ANC Path", SND_SOC_NOPM, 0, 0, + &tas675x_anc_path_switch), + + /* + * Even though all channels are coupled in terms of power control, + * use logical outputs for each channel to allow independent routing + * and DAPM controls if needed. + */ + SND_SOC_DAPM_OUTPUT("OUT_CH1"), + SND_SOC_DAPM_OUTPUT("OUT_CH2"), + SND_SOC_DAPM_OUTPUT("OUT_CH3"), + SND_SOC_DAPM_OUTPUT("OUT_CH4"), + SND_SOC_DAPM_INPUT("SPEAKER_LOAD"), +}; + +static const struct snd_soc_dapm_route tas675x_dapm_routes[] = { + { "Audio DAC", NULL, "Analog Core" }, + { "Audio Path", "Switch", "Audio DAC" }, + { "OUT_CH1", NULL, "Audio Path" }, + { "OUT_CH2", NULL, "Audio Path" }, + { "OUT_CH3", NULL, "Audio Path" }, + { "OUT_CH4", NULL, "Audio Path" }, + + { "ANC DAC", NULL, "Analog Core" }, + { "ANC Path", "Switch", "ANC DAC" }, + { "OUT_CH1", NULL, "ANC Path" }, + { "OUT_CH2", NULL, "ANC Path" }, + { "OUT_CH3", NULL, "ANC Path" }, + { "OUT_CH4", NULL, "ANC Path" }, + + { "Feedback ADC", NULL, "Analog Core" }, + { "Feedback ADC", NULL, "SDOUT Vpredict" }, + { "Feedback ADC", NULL, "SDOUT Isense" }, + { "Feedback ADC", NULL, "SPEAKER_LOAD" }, +}; + +static void tas675x_program_slot_offsets(struct tas675x_priv *tas, + int dai_id, int slot_width) +{ + int offset = 0; + + switch (dai_id) { + case 0: + /* Standard Audio on SDIN */ + if (tas->audio_slot >= 0) + offset = tas->audio_slot * slot_width; + else if (tas->tx_mask) + offset = __ffs(tas->tx_mask) * slot_width; + else + return; + offset += tas->bclk_offset; + regmap_update_bits(tas->regmap, TAS675X_SDIN_OFFSET_MSB_REG, + TAS675X_SDIN_AUDIO_OFF_MSB_MASK, + FIELD_PREP(TAS675X_SDIN_AUDIO_OFF_MSB_MASK, offset >> 8)); + regmap_write(tas->regmap, TAS675X_SDIN_AUDIO_OFFSET_REG, + offset & 0xFF); + break; + case 1: + /* + * Low-Latency Playback on SDIN, **only** enabled in LLP mode + * and to be mixed with main audio before output amplification + * to achieve ANC/RNC. + */ + if (tas->llp_slot >= 0) + offset = tas->llp_slot * slot_width; + else if (tas->tx_mask) + offset = __ffs(tas->tx_mask) * slot_width; + else + return; + offset += tas->bclk_offset; + regmap_update_bits(tas->regmap, TAS675X_SDIN_OFFSET_MSB_REG, + TAS675X_SDIN_LL_OFF_MSB_MASK, + FIELD_PREP(TAS675X_SDIN_LL_OFF_MSB_MASK, offset >> 8)); + regmap_write(tas->regmap, TAS675X_SDIN_LL_OFFSET_REG, + offset & 0xFF); + break; + case 2: + /* SDOUT Data Output (Vpredict + Isense feedback) */ + if (!tas->slot_width) + break; + if (tas->vpredict_slot >= 0) { + offset = tas->vpredict_slot * slot_width; + offset += tas->bclk_offset; + regmap_update_bits(tas->regmap, TAS675X_SDOUT_OFFSET_MSB_REG, + TAS675X_SDOUT_VP_OFF_MSB_MASK, + FIELD_PREP(TAS675X_SDOUT_VP_OFF_MSB_MASK, offset >> 8)); + regmap_write(tas->regmap, TAS675X_VPREDICT_OFFSET_REG, + offset & 0xFF); + } + if (tas->isense_slot >= 0) { + offset = tas->isense_slot * slot_width; + offset += tas->bclk_offset; + regmap_update_bits(tas->regmap, TAS675X_SDOUT_OFFSET_MSB_REG, + TAS675X_SDOUT_IS_OFF_MSB_MASK, + FIELD_PREP(TAS675X_SDOUT_IS_OFF_MSB_MASK, offset >> 8)); + regmap_write(tas->regmap, TAS675X_ISENSE_OFFSET_REG, + offset & 0xFF); + } + break; + } + + if (offset > 511) + dev_warn(tas->dev, + "DAI %d slot offset %d exceeds 511 SCLK limit\n", + dai_id, offset); +} + +static int tas675x_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct tas675x_priv *tas = snd_soc_component_get_drvdata(component); + unsigned int rate = params_rate(params); + u8 word_length; + + /* + * Single clock domain: SDIN and SDOUT share one SCLK/FSYNC pair, + * so all active DAIs must use the same sample rate. + */ + if ((tas->active_playback_dais || tas->active_capture_dais) && + tas->rate && tas->rate != rate) { + dev_err(component->dev, + "Rate %u conflicts with active rate %u\n", + rate, tas->rate); + return -EINVAL; + } + + switch (params_width(params)) { + case 16: + word_length = TAS675X_WL_16BIT; + break; + case 20: + word_length = TAS675X_WL_20BIT; + break; + case 24: + word_length = TAS675X_WL_24BIT; + break; + case 32: + word_length = TAS675X_WL_32BIT; + break; + default: + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* + * RTLDG is not supported above 96kHz. Auto-disable to + * prevent DSP overload and restore when rate drops back. + */ + if (rate > 96000) { + unsigned int val; + + regmap_read(component->regmap, TAS675X_RTLDG_EN_REG, + &val); + if (val & TAS675X_RTLDG_CH_EN_MASK) { + tas->saved_rtldg_en = val; + dev_dbg(component->dev, + "Sample rate %dHz > 96kHz: Auto-disabling RTLDG\n", + rate); + regmap_update_bits(component->regmap, + TAS675X_RTLDG_EN_REG, + TAS675X_RTLDG_CH_EN_MASK, + 0x00); + } + } else if (tas->saved_rtldg_en) { + unsigned int cur; + + /* + * Respect overrides and only restore if RTLDG is still auto-disabled + */ + regmap_read(component->regmap, TAS675X_RTLDG_EN_REG, + &cur); + if (!(cur & TAS675X_RTLDG_CH_EN_MASK)) { + dev_dbg(component->dev, + "Restoring RTLDG config after high-rate stream\n"); + regmap_update_bits(component->regmap, + TAS675X_RTLDG_EN_REG, + TAS675X_RTLDG_CH_EN_MASK, + TAS675X_RTLDG_CH_EN_MASK & + tas->saved_rtldg_en); + } + tas->saved_rtldg_en = 0; + } + + /* Set SDIN word length (audio path + low-latency path) */ + regmap_update_bits(component->regmap, TAS675X_SDIN_CTRL_REG, + TAS675X_SDIN_WL_MASK, + FIELD_PREP(TAS675X_SDIN_AUDIO_WL_MASK, word_length) | + FIELD_PREP(TAS675X_SDIN_LL_WL_MASK, word_length)); + } else { + /* Set SDOUT word length (VPREDICT + ISENSE) for capture */ + regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG, + TAS675X_SDOUT_WL_MASK, + FIELD_PREP(TAS675X_SDOUT_VP_WL_MASK, word_length) | + FIELD_PREP(TAS675X_SDOUT_IS_WL_MASK, word_length)); + } + + tas675x_program_slot_offsets(tas, dai->id, + tas->slot_width ?: params_width(params)); + + tas->rate = rate; + + return 0; +} + +static int tas675x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct tas675x_priv *tas = snd_soc_component_get_drvdata(component); + bool tdm_mode = false, i2s_mode = false; + + /* Enforce Clocking Direction (Codec is strictly a consumer) */ + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_BC_FC: + break; + default: + dev_err(component->dev, "Unsupported clock provider format\n"); + return -EINVAL; + } + + /* SCLK polarity: NB_NF or IB_NF only (no FSYNC inversion support) */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + regmap_update_bits(component->regmap, TAS675X_SCLK_INV_CTRL_REG, + TAS675X_SCLK_INV_MASK, 0x00); + break; + case SND_SOC_DAIFMT_IB_NF: + regmap_update_bits(component->regmap, TAS675X_SCLK_INV_CTRL_REG, + TAS675X_SCLK_INV_MASK, TAS675X_SCLK_INV_MASK); + break; + default: + dev_err(component->dev, "Unsupported clock inversion\n"); + return -EINVAL; + } + + /* Configure Audio Format and TDM Enable */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + i2s_mode = true; + tas->bclk_offset = 0; + regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG, + TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK | + TAS675X_FS_PULSE_MASK, + TAS675X_SAP_FMT_I2S); + regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG, + TAS675X_SDOUT_SELECT_MASK, + TAS675X_SDOUT_SELECT_NON_TDM); + break; + case SND_SOC_DAIFMT_RIGHT_J: + tas->bclk_offset = 0; + regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG, + TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK | + TAS675X_FS_PULSE_MASK, + TAS675X_SAP_FMT_RIGHT_J); + regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG, + TAS675X_SDOUT_SELECT_MASK, + TAS675X_SDOUT_SELECT_NON_TDM); + break; + case SND_SOC_DAIFMT_LEFT_J: + tas->bclk_offset = 0; + regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG, + TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK | + TAS675X_FS_PULSE_MASK, + TAS675X_SAP_FMT_LEFT_J); + regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG, + TAS675X_SDOUT_SELECT_MASK, + TAS675X_SDOUT_SELECT_NON_TDM); + break; + case SND_SOC_DAIFMT_DSP_A: + tdm_mode = true; + tas->bclk_offset = 1; + regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG, + TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK | + TAS675X_FS_PULSE_MASK, + TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_TDM | + TAS675X_FS_PULSE_SHORT); + regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG, + TAS675X_SDOUT_SELECT_MASK, + TAS675X_SDOUT_SELECT_TDM_SDOUT1); + break; + case SND_SOC_DAIFMT_DSP_B: + tdm_mode = true; + tas->bclk_offset = 0; + regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG, + TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK | + TAS675X_FS_PULSE_MASK, + TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_TDM | + TAS675X_FS_PULSE_SHORT); + regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG, + TAS675X_SDOUT_SELECT_MASK, + TAS675X_SDOUT_SELECT_TDM_SDOUT1); + break; + default: + dev_err(component->dev, "Unsupported DAI format\n"); + return -EINVAL; + } + + /* Setup Vpredict and Isense outputs */ + if (dai->id == 2) { + unsigned int sdout_en = 0; + + if (tdm_mode) { + /* TDM: Vpredict and Isense may coexist on separate slots */ + if (tas->vpredict_slot >= 0) + sdout_en |= TAS675X_SDOUT_EN_VPREDICT; + if (tas->isense_slot >= 0) + sdout_en |= TAS675X_SDOUT_EN_ISENSE; + regmap_update_bits(component->regmap, + TAS675X_SDOUT_EN_REG, + TAS675X_SDOUT_EN_VPREDICT | + TAS675X_SDOUT_EN_ISENSE, + sdout_en); + if (tas->vpredict_slot >= 0 && tas->isense_slot >= 0 && + abs(tas->vpredict_slot - tas->isense_slot) < 4) + dev_warn(component->dev, + "ti,vpredict-slot-no and ti,isense-slot-no overlaps (each occupies 4 consecutive slots)\n"); + } else if (i2s_mode) { + /* I2S: only one source at a time; Vpredict takes priority */ + if (tas->vpredict_slot >= 0) + sdout_en = TAS675X_SDOUT_NON_TDM_SEL_VPREDICT | + TAS675X_SDOUT_EN_NON_TDM_ALL; + else if (tas->isense_slot >= 0) + sdout_en = TAS675X_SDOUT_NON_TDM_SEL_ISENSE | + TAS675X_SDOUT_EN_NON_TDM_ALL; + regmap_update_bits(component->regmap, + TAS675X_SDOUT_EN_REG, + TAS675X_SDOUT_NON_TDM_SEL_MASK | + TAS675X_SDOUT_EN_NON_TDM_ALL, + sdout_en); + if (sdout_en && + tas->gpio1_func != TAS675X_GPIO_SEL_SDOUT2 && + tas->gpio2_func != TAS675X_GPIO_SEL_SDOUT2) + dev_warn(component->dev, + "sdout enabled in I2S mode but no GPIO configured as SDOUT2; Ch3/Ch4 will be absent\n"); + } + } + + return 0; +} + +static int tas675x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct tas675x_priv *tas = snd_soc_component_get_drvdata(dai->component); + + if (slots == 0) { + tas->slot_width = 0; + tas->tx_mask = 0; + return 0; + } + + /* No rx_mask as hardware does not support channel muxing for capture */ + tas->slot_width = slot_width; + tas->tx_mask = tx_mask; + return 0; +} + +static int tas675x_mute_stream(struct snd_soc_dai *dai, int mute, int direction) +{ + struct snd_soc_component *component = dai->component; + struct tas675x_priv *tas = snd_soc_component_get_drvdata(component); + unsigned int discard; + int ret; + + if (direction == SNDRV_PCM_STREAM_CAPTURE) { + if (mute) + clear_bit(dai->id, &tas->active_capture_dais); + else + set_bit(dai->id, &tas->active_capture_dais); + return 0; + } + + /* + * Track which playback DAIs are active. + * The TAS675x has two playback DAIs (main audio and LLP). + * Only transition to SLEEP when ALL are muted. + */ + if (mute) + clear_bit(dai->id, &tas->active_playback_dais); + else + set_bit(dai->id, &tas->active_playback_dais); + + /* Last playback stream */ + if (mute && !tas->active_playback_dais) { + ret = tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH); + regmap_read(tas->regmap, TAS675X_CLK_FAULT_LATCHED_REG, &discard); + return ret; + } + + return tas675x_set_state_all(tas, + tas->active_playback_dais ? + TAS675X_STATE_PLAY_BOTH : + TAS675X_STATE_SLEEP_BOTH); +} + +static const struct snd_soc_dai_ops tas675x_dai_ops = { + .hw_params = tas675x_hw_params, + .set_fmt = tas675x_set_fmt, + .set_tdm_slot = tas675x_set_tdm_slot, + .mute_stream = tas675x_mute_stream, +}; + +static struct snd_soc_dai_driver tas675x_dais[] = { + { + .name = "tas675x-audio", + .id = 0, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 4, + .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tas675x_dai_ops, + }, + /* Only available when Low Latency Path (LLP) is enabled */ + { + .name = "tas675x-anc", + .id = 1, + .playback = { + .stream_name = "ANC Playback", + .channels_min = 2, + .channels_max = 4, + .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tas675x_dai_ops, + }, + { + .name = "tas675x-feedback", + .id = 2, + .capture = { + .stream_name = "Feedback Capture", + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_LE | + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &tas675x_dai_ops, + } +}; + +/* + * Enable regulators and release hardware reset GPIOs. + * The device is not I2C-accessible until this returns. + */ +static int tas675x_hw_enable(struct tas675x_priv *tas) +{ + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(tas->supplies), tas->supplies); + if (ret) { + dev_err(tas->dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + + if (!IS_ERR(tas->vbat)) { + ret = regulator_enable(tas->vbat); + if (ret) { + dev_err(tas->dev, "Failed to enable vbat: %d\n", ret); + regulator_bulk_disable(ARRAY_SIZE(tas->supplies), tas->supplies); + return ret; + } + } + + if (tas->pd_gpio && tas->stby_gpio) { + /* + * Independent Pin Control + * Deassert PD first to boot digital, then STBY for analog. + */ + /* Min 4ms digital boot wait */ + gpiod_set_value_cansleep(tas->pd_gpio, 0); + usleep_range(4000, 5000); + + /* ~2ms analog stabilization */ + gpiod_set_value_cansleep(tas->stby_gpio, 0); + usleep_range(2000, 3000); + } else if (tas->pd_gpio) { + /* + * Simultaneous Pin Release + * STBY tied to PD or hardwired HIGH. + */ + /* 6ms wait for simultaneous release transition */ + gpiod_set_value_cansleep(tas->pd_gpio, 0); + usleep_range(6000, 7000); + } else { + /* + * PD hardwired, device in DEEP_SLEEP. + * Digital core already booted, I2C active. Deassert STBY + * to bring up the analog output stage. + */ + /* ~2ms analog stabilization */ + gpiod_set_value_cansleep(tas->stby_gpio, 0); + usleep_range(2000, 3000); + } + + return 0; +} + +static void tas675x_hw_disable(struct tas675x_priv *tas) +{ + if (tas->stby_gpio) + gpiod_set_value_cansleep(tas->stby_gpio, 1); + + if (tas->pd_gpio) + gpiod_set_value_cansleep(tas->pd_gpio, 1); + + /* + * Hold PD/STBY asserted for at least 10ms + * before removing PVDD, VBAT or DVDD. + */ + usleep_range(10000, 11000); + + if (!IS_ERR(tas->vbat)) + regulator_disable(tas->vbat); + + regulator_bulk_disable(ARRAY_SIZE(tas->supplies), tas->supplies); +} + +/* + * Write device start-up defaults. + * Must be called after tas675x_hw_enable() and after regcache is enabled. + */ +static int tas675x_init_device(struct tas675x_priv *tas) +{ + struct regmap *regmap = tas->regmap; + unsigned int val; + int ret, i; + + /* Clear POR fault flag to prevent IRQ storm */ + regmap_read(regmap, TAS675X_POWER_FAULT_LATCHED_REG, &val); + + /* Bypass DC Load Diagnostics for fast boot */ + if (tas->fast_boot) + regmap_update_bits(regmap, TAS675X_DC_LDG_CTRL_REG, + TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT, + TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT); + + tas675x_select_book(regmap, TAS675X_BOOK_DEFAULT); + + /* Enter setup mode */ + ret = regmap_write(regmap, TAS675X_SETUP_REG1, TAS675X_SETUP_ENTER_VAL1); + if (ret) + goto err; + ret = regmap_write(regmap, TAS675X_SETUP_REG2, TAS675X_SETUP_ENTER_VAL2); + if (ret) + goto err; + + /* Set all channels to Sleep (required before Page 1 config) */ + tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH); + + /* Set DAC clock per TRM startup script */ + regmap_write(regmap, TAS675X_DAC_CLK_REG, 0x00); + + /* + * Switch to Page 1 for safety-critical OC/CBC configuration, + * while bypassing regcache. (Page 1 not accessible post setup) + */ + regcache_cache_bypass(regmap, true); + ret = regmap_multi_reg_write(regmap, tas675x_page1_init, + ARRAY_SIZE(tas675x_page1_init)); + regcache_cache_bypass(regmap, false); + if (ret) + goto err_setup; + + /* Resync regmap's cached page selector */ + regmap_write(regmap, TAS675X_PAGE_CTRL_REG, 0x00); + + /* Exit setup mode */ + regmap_write(regmap, TAS675X_SETUP_REG1, TAS675X_SETUP_EXIT_VAL); + regmap_write(regmap, TAS675X_SETUP_REG2, TAS675X_SETUP_EXIT_VAL); + + /* Write DSP parameters if cached */ + for (i = 0; i < ARRAY_SIZE(tas->dsp_params); i++) { + if (tas->dsp_params[i].val) + tas675x_dsp_mem_write(tas, + tas->dsp_params[i].page, + tas->dsp_params[i].reg, + tas->dsp_params[i].val); + } + + /* + * Configure fault and warning event routing: + * + * ROUTING_1: CP fault/UVLO latch, OUTM soft short latch + * ROUTING_2: CBC latch, OTSD latch, OTSD, power fault + * ROUTING_3: CBC latch, OTSD latch, power latch, DC LDG, + * OTSD, power warnings + * ROUTING_4: OC latch, DC latch, protection shutdown + * OTW latch, OTW, clip latch + * ROUTING_5: clock latch+non-latch, RTLDG latch + * CBC warning, clip warning + */ + regmap_write(regmap, TAS675X_REPORT_ROUTING_1_REG, 0x70); + regmap_write(regmap, TAS675X_REPORT_ROUTING_2_REG, 0xA3); + regmap_write(regmap, TAS675X_REPORT_ROUTING_3_REG, 0xBB); + regmap_write(regmap, TAS675X_REPORT_ROUTING_4_REG, 0x7E); + regmap_write(regmap, TAS675X_REPORT_ROUTING_5_REG, 0xF3); + + /* Configure GPIO pins if specified in DT */ + if (tas->gpio1_func >= 0 || tas->gpio2_func >= 0) { + unsigned int gpio_ctrl = TAS675X_GPIO_CTRL_RSTVAL; + + tas675x_config_gpio_pin(regmap, tas->gpio1_func, + TAS675X_GPIO1_OUTPUT_SEL_REG, + 0, &gpio_ctrl); + tas675x_config_gpio_pin(regmap, tas->gpio2_func, + TAS675X_GPIO2_OUTPUT_SEL_REG, + 1, &gpio_ctrl); + regmap_write(regmap, TAS675X_GPIO_CTRL_REG, gpio_ctrl); + } + + /* Clear fast boot bits */ + if (tas->fast_boot) + regmap_update_bits(regmap, TAS675X_DC_LDG_CTRL_REG, + TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT, + 0); + + /* Clear any stale faults from the boot sequence */ + regmap_read(regmap, TAS675X_POWER_FAULT_STATUS_1_REG, &val); + regmap_read(regmap, TAS675X_POWER_FAULT_LATCHED_REG, &val); + regmap_read(regmap, TAS675X_CLK_FAULT_LATCHED_REG, &val); + regmap_write(regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR); + + return 0; + +err_setup: + regmap_write(regmap, TAS675X_SETUP_REG1, TAS675X_SETUP_EXIT_VAL); + regmap_write(regmap, TAS675X_SETUP_REG2, TAS675X_SETUP_EXIT_VAL); +err: + dev_err(tas->dev, "Init device failed: %d\n", ret); + return ret; +} + +static void tas675x_power_off(struct tas675x_priv *tas) +{ + regcache_cache_only(tas->regmap, true); + regcache_mark_dirty(tas->regmap); + tas675x_hw_disable(tas); +} + +static int tas675x_power_on(struct tas675x_priv *tas) +{ + int ret; + + ret = tas675x_hw_enable(tas); + if (ret) + return ret; + + regcache_cache_only(tas->regmap, false); + regcache_mark_dirty(tas->regmap); + + ret = tas675x_init_device(tas); + if (ret) + goto err_disable; + + ret = regcache_sync(tas->regmap); + if (ret) { + dev_err(tas->dev, "Failed to sync regcache: %d\n", ret); + goto err_disable; + } + + /* Reset fault tracking */ + memset(tas->last_status, 0, sizeof(tas->last_status)); + + return 0; + +err_disable: + tas675x_power_off(tas); + return ret; +} + +static int tas675x_runtime_suspend(struct device *dev) +{ + struct tas675x_priv *tas = dev_get_drvdata(dev); + + disable_delayed_work_sync(&tas->fault_check_work); + tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH); + + return 0; +} + +static int tas675x_runtime_resume(struct device *dev) +{ + struct tas675x_priv *tas = dev_get_drvdata(dev); + + tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH); + + if (!to_i2c_client(dev)->irq) { + enable_delayed_work(&tas->fault_check_work); + schedule_delayed_work(&tas->fault_check_work, + msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS)); + } + + return 0; +} + +static int tas675x_system_suspend(struct device *dev) +{ + struct tas675x_priv *tas = dev_get_drvdata(dev); + int ret; + + ret = tas675x_runtime_suspend(dev); + if (ret) + return ret; + + if (to_i2c_client(dev)->irq) + disable_irq(to_i2c_client(dev)->irq); + + tas675x_power_off(tas); + return 0; +} + +static int tas675x_system_resume(struct device *dev) +{ + struct tas675x_priv *tas = dev_get_drvdata(dev); + int ret; + + ret = tas675x_power_on(tas); + if (ret) + return ret; + + if (to_i2c_client(dev)->irq) + enable_irq(to_i2c_client(dev)->irq); + + return tas675x_runtime_resume(dev); +} + +static const struct snd_soc_component_driver soc_codec_dev_tas675x = { + .controls = tas675x_snd_controls, + .num_controls = ARRAY_SIZE(tas675x_snd_controls), + .dapm_widgets = tas675x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas675x_dapm_widgets), + .dapm_routes = tas675x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tas675x_dapm_routes), + .endianness = 1, +}; + +/* Fault register flags */ +#define TAS675X_FAULT_CRITICAL BIT(0) /* causes FAULT state, FAULT_CLEAR required */ +#define TAS675X_FAULT_TRACK BIT(1) /* track last value, only log on change */ +#define TAS675X_FAULT_ACTIVE BIT(2) /* skip when no stream is active */ + +struct tas675x_fault_reg { + unsigned int reg; + unsigned int flags; + const char *name; +}; + +static const struct tas675x_fault_reg tas675x_fault_table[] = { + /* Critical */ + { TAS675X_OTSD_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK, + "Overtemperature Shutdown" }, + { TAS675X_OC_DC_FAULT_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK, + "Overcurrent / DC Fault" }, + { TAS675X_RTLDG_OL_SL_FAULT_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK, + "Real-Time Load Diagnostic Fault" }, + { TAS675X_CBC_FAULT_WARN_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK, + "CBC Fault/Warning" }, + /* Warning */ + { TAS675X_POWER_FAULT_STATUS_1_REG, TAS675X_FAULT_TRACK, + "CP / OUTM Fault" }, + { TAS675X_POWER_FAULT_LATCHED_REG, TAS675X_FAULT_TRACK, + "Power Fault" }, + { TAS675X_CLK_FAULT_LATCHED_REG, TAS675X_FAULT_TRACK | TAS675X_FAULT_ACTIVE, + "Clock Fault" }, + { TAS675X_OTW_LATCHED_REG, TAS675X_FAULT_TRACK, + "Overtemperature Warning" }, + { TAS675X_CLIP_WARN_LATCHED_REG, TAS675X_FAULT_ACTIVE, + "Clip Warning" }, +}; + +static_assert(ARRAY_SIZE(tas675x_fault_table) == TAS675X_FAULT_REGS_NUM); + +/* + * Read and log all latched fault registers. + * Shared by both the polled fault_check_work and IRQ handler paths + * (which are mutually exclusive, only one is active per device). + * Returns true if any fault register needs to be cleared. + * + * For deciphering fault messages, see "Fault Monitoring" in + * Documentation/sound/codecs/tas675x.rst + */ +static bool tas675x_check_faults(struct tas675x_priv *tas) +{ + struct device *dev = tas->dev; + bool needs_clear = false; + unsigned int reg; + int i, ret; + + for (i = 0; i < ARRAY_SIZE(tas675x_fault_table); i++) { + const struct tas675x_fault_reg *f = &tas675x_fault_table[i]; + + ret = regmap_read(tas->regmap, f->reg, ®); + if (ret) { + if (f->flags & TAS675X_FAULT_CRITICAL) { + dev_err(dev, "failed to read %s: %d\n", f->name, ret); + return needs_clear; + } + continue; + } + + if (reg) + needs_clear = true; + + /* Skip logging stream-dependent events when no stream is active */ + if ((f->flags & TAS675X_FAULT_ACTIVE) && + !READ_ONCE(tas->active_playback_dais) && + !READ_ONCE(tas->active_capture_dais)) + continue; + + /* Log on change or on every non-zero read */ + if (reg && (!(f->flags & TAS675X_FAULT_TRACK) || + reg != tas->last_status[i])) { + if (f->flags & TAS675X_FAULT_CRITICAL) + dev_crit(dev, "%s Latched: 0x%02x\n", f->name, reg); + else + dev_warn(dev, "%s Latched: 0x%02x\n", f->name, reg); + } + + if (f->flags & TAS675X_FAULT_TRACK) + tas->last_status[i] = reg; + } + + return needs_clear; +} + +static void tas675x_fault_check_work(struct work_struct *work) +{ + struct tas675x_priv *tas = container_of(work, struct tas675x_priv, + fault_check_work.work); + + if (tas675x_check_faults(tas)) + regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR); + + schedule_delayed_work(&tas->fault_check_work, + msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS)); +} + +static irqreturn_t tas675x_irq_handler(int irq, void *data) +{ + struct tas675x_priv *tas = data; + irqreturn_t ret = IRQ_NONE; + + if (pm_runtime_resume_and_get(tas->dev) < 0) + return IRQ_NONE; + + if (tas675x_check_faults(tas)) { + regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR); + ret = IRQ_HANDLED; + } + + pm_runtime_mark_last_busy(tas->dev); + pm_runtime_put_autosuspend(tas->dev); + return ret; +} + +static const struct reg_default tas675x_reg_defaults[] = { + { TAS675X_PAGE_CTRL_REG, 0x00 }, + { TAS675X_OUTPUT_CTRL_REG, 0x00 }, + { TAS675X_STATE_CTRL_CH1_CH2_REG, TAS675X_STATE_SLEEP_BOTH }, + { TAS675X_STATE_CTRL_CH3_CH4_REG, TAS675X_STATE_SLEEP_BOTH }, + { TAS675X_ISENSE_CTRL_REG, 0x0F }, + { TAS675X_DC_DETECT_CTRL_REG, 0x00 }, + { TAS675X_SCLK_INV_CTRL_REG, 0x00 }, + { TAS675X_AUDIO_IF_CTRL_REG, 0x00 }, + { TAS675X_SDIN_CTRL_REG, 0x0A }, + { TAS675X_SDOUT_CTRL_REG, 0x1A }, + { TAS675X_SDIN_OFFSET_MSB_REG, 0x00 }, + { TAS675X_SDIN_AUDIO_OFFSET_REG, 0x00 }, + { TAS675X_SDIN_LL_OFFSET_REG, 0x60 }, + { TAS675X_SDIN_CH_SWAP_REG, 0x00 }, + { TAS675X_SDOUT_OFFSET_MSB_REG, 0xCF }, + { TAS675X_VPREDICT_OFFSET_REG, 0xFF }, + { TAS675X_ISENSE_OFFSET_REG, 0x00 }, + { TAS675X_SDOUT_EN_REG, 0x00 }, + { TAS675X_LL_EN_REG, 0x00 }, + { TAS675X_RTLDG_EN_REG, 0x10 }, + { TAS675X_DC_BLOCK_BYP_REG, 0x00 }, + { TAS675X_DSP_CTRL_REG, 0x00 }, + { TAS675X_PAGE_AUTO_INC_REG, 0x00 }, + { TAS675X_DIG_VOL_CH1_REG, 0x30 }, + { TAS675X_DIG_VOL_CH2_REG, 0x30 }, + { TAS675X_DIG_VOL_CH3_REG, 0x30 }, + { TAS675X_DIG_VOL_CH4_REG, 0x30 }, + { TAS675X_DIG_VOL_RAMP_CTRL_REG, 0x77 }, + { TAS675X_DIG_VOL_COMBINE_CTRL_REG, 0x00 }, + { TAS675X_AUTO_MUTE_EN_REG, 0x00 }, + { TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG, 0x00 }, + { TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG, 0x00 }, + { TAS675X_ANALOG_GAIN_CH1_CH2_REG, 0x00 }, + { TAS675X_ANALOG_GAIN_CH3_CH4_REG, 0x00 }, + { TAS675X_ANALOG_GAIN_RAMP_CTRL_REG, 0x00 }, + { TAS675X_PULSE_INJECTION_EN_REG, 0x03 }, + { TAS675X_CBC_CTRL_REG, 0x07 }, + { TAS675X_CURRENT_LIMIT_CTRL_REG, 0x00 }, + { TAS675X_ISENSE_CAL_REG, 0x00 }, + { TAS675X_PWM_PHASE_CTRL_REG, 0x00 }, + { TAS675X_SS_CTRL_REG, 0x00 }, + { TAS675X_SS_RANGE_CTRL_REG, 0x00 }, + { TAS675X_SS_DWELL_CTRL_REG, 0x00 }, + { TAS675X_RAMP_PHASE_CTRL_GPO_REG, 0x00 }, + { TAS675X_PWM_PHASE_M_CTRL_CH1_REG, 0x00 }, + { TAS675X_PWM_PHASE_M_CTRL_CH2_REG, 0x00 }, + { TAS675X_PWM_PHASE_M_CTRL_CH3_REG, 0x00 }, + { TAS675X_PWM_PHASE_M_CTRL_CH4_REG, 0x00 }, + { TAS675X_DC_LDG_CTRL_REG, 0x00 }, + { TAS675X_DC_LDG_LO_CTRL_REG, 0x00 }, + { TAS675X_DC_LDG_TIME_CTRL_REG, 0x00 }, + { TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG, 0x11 }, + { TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG, 0x11 }, + { TAS675X_AC_LDG_CTRL_REG, 0x10 }, + { TAS675X_TWEETER_DETECT_CTRL_REG, 0x08 }, + { TAS675X_TWEETER_DETECT_THRESH_REG, 0x00 }, + { TAS675X_AC_LDG_FREQ_CTRL_REG, 0xC8 }, + { TAS675X_REPORT_ROUTING_1_REG, 0x00 }, + { TAS675X_OTSD_RECOVERY_EN_REG, 0x00 }, + { TAS675X_REPORT_ROUTING_2_REG, 0xA2 }, + { TAS675X_REPORT_ROUTING_3_REG, 0x00 }, + { TAS675X_REPORT_ROUTING_4_REG, 0x06 }, + { TAS675X_CLIP_DETECT_CTRL_REG, 0x00 }, + { TAS675X_REPORT_ROUTING_5_REG, 0x00 }, + { TAS675X_GPIO1_OUTPUT_SEL_REG, 0x00 }, + { TAS675X_GPIO2_OUTPUT_SEL_REG, 0x00 }, + { TAS675X_GPIO_CTRL_REG, TAS675X_GPIO_CTRL_RSTVAL }, + { TAS675X_OTW_CTRL_CH1_CH2_REG, 0x11 }, + { TAS675X_OTW_CTRL_CH3_CH4_REG, 0x11 }, +}; + +static bool tas675x_is_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TAS675X_RESET_REG: + return false; + default: + return true; + } +} + +static bool tas675x_is_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TAS675X_RESET_REG: + case TAS675X_BOOK_CTRL_REG: + case TAS675X_AUTO_MUTE_STATUS_REG: + case TAS675X_STATE_REPORT_CH1_CH2_REG: + case TAS675X_STATE_REPORT_CH3_CH4_REG: + case TAS675X_PVDD_SENSE_REG: + case TAS675X_TEMP_GLOBAL_REG: + case TAS675X_TEMP_CH1_CH2_REG: + case TAS675X_TEMP_CH3_CH4_REG: + case TAS675X_FS_MON_REG: + case TAS675X_SCLK_MON_REG: + case TAS675X_POWER_FAULT_STATUS_1_REG: + case TAS675X_POWER_FAULT_STATUS_2_REG: + case TAS675X_OT_FAULT_REG: + case TAS675X_OTW_STATUS_REG: + case TAS675X_CLIP_WARN_STATUS_REG: + case TAS675X_CBC_WARNING_STATUS_REG: + case TAS675X_POWER_FAULT_LATCHED_REG: + case TAS675X_OTSD_LATCHED_REG: + case TAS675X_OTW_LATCHED_REG: + case TAS675X_CLIP_WARN_LATCHED_REG: + case TAS675X_CLK_FAULT_LATCHED_REG: + case TAS675X_RTLDG_OL_SL_FAULT_LATCHED_REG: + case TAS675X_CBC_FAULT_WARN_LATCHED_REG: + case TAS675X_OC_DC_FAULT_LATCHED_REG: + case TAS675X_WARN_OT_MAX_FLAG_REG: + case TAS675X_DC_LDG_REPORT_CH1_CH2_REG ... TAS675X_TWEETER_REPORT_REG: + case TAS675X_CH1_RTLDG_IMP_MSB_REG ... TAS675X_CH4_DC_LDG_DCR_LSB_REG: + return true; + default: + return false; + } +} + +static const struct regmap_range_cfg tas675x_ranges[] = { + { + .name = "Pages", + .range_min = 0, + .range_max = TAS675X_PAGE_SIZE * TAS675X_PAGE_SIZE - 1, + .selector_reg = TAS675X_PAGE_CTRL_REG, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = TAS675X_PAGE_SIZE, + }, +}; + +static void tas675x_regmap_lock(void *lock_arg) +{ + struct tas675x_priv *tas = lock_arg; + + mutex_lock(&tas->io_lock); +} + +static void tas675x_regmap_unlock(void *lock_arg) +{ + struct tas675x_priv *tas = lock_arg; + + mutex_unlock(&tas->io_lock); +} + +static const struct regmap_config tas675x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TAS675X_PAGE_SIZE * TAS675X_PAGE_SIZE - 1, + .ranges = tas675x_ranges, + .num_ranges = ARRAY_SIZE(tas675x_ranges), + .cache_type = REGCACHE_MAPLE, + .reg_defaults = tas675x_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tas675x_reg_defaults), + .readable_reg = tas675x_is_readable_register, + .volatile_reg = tas675x_is_volatile_register, +}; + +static int tas675x_i2c_probe(struct i2c_client *client) +{ + struct regmap_config cfg = tas675x_regmap_config; + struct tas675x_priv *tas; + u32 val; + int i, ret; + + tas = devm_kzalloc(&client->dev, sizeof(*tas), GFP_KERNEL); + if (!tas) + return -ENOMEM; + + tas->dev = &client->dev; + i2c_set_clientdata(client, tas); + + mutex_init(&tas->io_lock); + cfg.lock = tas675x_regmap_lock; + cfg.unlock = tas675x_regmap_unlock; + cfg.lock_arg = tas; + + memcpy(tas->dsp_params, tas675x_dsp_defaults, sizeof(tas->dsp_params)); + INIT_DELAYED_WORK(&tas->fault_check_work, tas675x_fault_check_work); + + tas->regmap = devm_regmap_init_i2c(client, &cfg); + if (IS_ERR(tas->regmap)) + return PTR_ERR(tas->regmap); + + /* Keep regmap cache-only until hardware is powered on */ + regcache_cache_only(tas->regmap, true); + + tas->dev_type = (enum tas675x_type)(unsigned long)device_get_match_data(tas->dev); + tas->fast_boot = device_property_read_bool(tas->dev, "ti,fast-boot"); + + tas->audio_slot = -1; + tas->llp_slot = -1; + tas->vpredict_slot = -1; + tas->isense_slot = -1; + if (!device_property_read_u32(tas->dev, "ti,audio-slot-no", &val)) + tas->audio_slot = val; + if (!device_property_read_u32(tas->dev, "ti,llp-slot-no", &val)) + tas->llp_slot = val; + if (!device_property_read_u32(tas->dev, "ti,vpredict-slot-no", &val)) + tas->vpredict_slot = val; + if (!device_property_read_u32(tas->dev, "ti,isense-slot-no", &val)) + tas->isense_slot = val; + + tas->gpio1_func = tas675x_gpio_func_parse(tas->dev, "ti,gpio1-function"); + tas->gpio2_func = tas675x_gpio_func_parse(tas->dev, "ti,gpio2-function"); + + for (i = 0; i < ARRAY_SIZE(tas675x_supply_names); i++) + tas->supplies[i].supply = tas675x_supply_names[i]; + + ret = devm_regulator_bulk_get(tas->dev, ARRAY_SIZE(tas->supplies), tas->supplies); + if (ret) + return dev_err_probe(tas->dev, ret, "Failed to request supplies\n"); + + tas->vbat = devm_regulator_get_optional(tas->dev, "vbat"); + if (IS_ERR(tas->vbat) && PTR_ERR(tas->vbat) != -ENODEV) + return dev_err_probe(tas->dev, PTR_ERR(tas->vbat), + "Failed to get vbat supply\n"); + + tas->pd_gpio = devm_gpiod_get_optional(tas->dev, "powerdown", GPIOD_OUT_HIGH); + if (IS_ERR(tas->pd_gpio)) + return dev_err_probe(tas->dev, PTR_ERR(tas->pd_gpio), "Failed powerdown-gpios\n"); + + tas->stby_gpio = devm_gpiod_get_optional(tas->dev, "standby", GPIOD_OUT_HIGH); + if (IS_ERR(tas->stby_gpio)) + return dev_err_probe(tas->dev, PTR_ERR(tas->stby_gpio), "Failed standby-gpios\n"); + + if (!tas->pd_gpio && !tas->stby_gpio) + return dev_err_probe(tas->dev, -EINVAL, + "At least one of powerdown-gpios or standby-gpios is required\n"); + + ret = tas675x_power_on(tas); + if (ret) + return ret; + + if (client->irq) { + ret = devm_request_threaded_irq(tas->dev, client->irq, NULL, + tas675x_irq_handler, + IRQF_ONESHOT | IRQF_TRIGGER_FALLING, + "tas675x-fault", tas); + if (ret) { + tas675x_power_off(tas); + return dev_err_probe(tas->dev, ret, "Failed to request IRQ\n"); + } + } else { + /* Schedule delayed work for fault checking at probe and runtime resume */ + schedule_delayed_work(&tas->fault_check_work, + msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS)); + } + + /* Enable runtime PM with 2s autosuspend */ + pm_runtime_set_autosuspend_delay(tas->dev, 2000); + pm_runtime_use_autosuspend(tas->dev); + pm_runtime_set_active(tas->dev); + pm_runtime_mark_last_busy(tas->dev); + pm_runtime_enable(tas->dev); + + ret = devm_snd_soc_register_component(tas->dev, &soc_codec_dev_tas675x, + tas675x_dais, ARRAY_SIZE(tas675x_dais)); + if (ret) + goto err_pm_disable; + + return 0; + +err_pm_disable: + pm_runtime_force_suspend(tas->dev); + pm_runtime_disable(tas->dev); + tas675x_power_off(tas); + return ret; +} + +static void tas675x_i2c_remove(struct i2c_client *client) +{ + struct tas675x_priv *tas = dev_get_drvdata(&client->dev); + + disable_delayed_work_sync(&tas->fault_check_work); + if (client->irq) + disable_irq(client->irq); + + pm_runtime_force_suspend(&client->dev); + pm_runtime_disable(&client->dev); + tas675x_power_off(tas); +} + +static const struct dev_pm_ops tas675x_pm_ops = { + SYSTEM_SLEEP_PM_OPS(tas675x_system_suspend, tas675x_system_resume) + RUNTIME_PM_OPS(tas675x_runtime_suspend, tas675x_runtime_resume, NULL) +}; + +static const struct of_device_id tas675x_of_match[] = { + { .compatible = "ti,tas67524", .data = (void *)TAS67524 }, + { } +}; +MODULE_DEVICE_TABLE(of, tas675x_of_match); + +static const struct i2c_device_id tas675x_i2c_id[] = { + { "tas67524", TAS67524 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tas675x_i2c_id); + +static struct i2c_driver tas675x_i2c_driver = { + .driver = { + .name = "tas675x", + .of_match_table = tas675x_of_match, + .pm = pm_ptr(&tas675x_pm_ops), + }, + .probe = tas675x_i2c_probe, + .remove = tas675x_i2c_remove, + .id_table = tas675x_i2c_id, +}; + +module_i2c_driver(tas675x_i2c_driver); + +MODULE_AUTHOR("Sen Wang "); +MODULE_DESCRIPTION("ASoC TAS675x Audio Amplifier Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tas675x.h b/sound/soc/codecs/tas675x.h new file mode 100644 index 000000000000..db29bb377336 --- /dev/null +++ b/sound/soc/codecs/tas675x.h @@ -0,0 +1,367 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ALSA SoC Texas Instruments TAS675x Quad-Channel Audio Amplifier + * + * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/ + * Author: Sen Wang + */ + +#ifndef __TAS675X_H__ +#define __TAS675X_H__ + +/* + * Book 0, Page 0 — Register Addresses + */ + +#define TAS675X_PAGE_SIZE 256 +#define TAS675X_PAGE_REG(page, reg) ((page) * TAS675X_PAGE_SIZE + (reg)) + +/* Page Control & Basic Config */ +#define TAS675X_PAGE_CTRL_REG 0x00 +#define TAS675X_RESET_REG 0x01 +#define TAS675X_OUTPUT_CTRL_REG 0x02 +#define TAS675X_STATE_CTRL_CH1_CH2_REG 0x03 +#define TAS675X_STATE_CTRL_CH3_CH4_REG 0x04 +#define TAS675X_ISENSE_CTRL_REG 0x05 +#define TAS675X_DC_DETECT_CTRL_REG 0x06 + +/* Serial Audio Port */ +#define TAS675X_SCLK_INV_CTRL_REG 0x20 +#define TAS675X_AUDIO_IF_CTRL_REG 0x21 +#define TAS675X_SDIN_CTRL_REG 0x23 +#define TAS675X_SDOUT_CTRL_REG 0x25 +#define TAS675X_SDIN_OFFSET_MSB_REG 0x27 +#define TAS675X_SDIN_AUDIO_OFFSET_REG 0x28 +#define TAS675X_SDIN_LL_OFFSET_REG 0x29 +#define TAS675X_SDIN_CH_SWAP_REG 0x2A +#define TAS675X_SDOUT_OFFSET_MSB_REG 0x2C +#define TAS675X_VPREDICT_OFFSET_REG 0x2D +#define TAS675X_ISENSE_OFFSET_REG 0x2E +#define TAS675X_SDOUT_EN_REG 0x31 +#define TAS675X_LL_EN_REG 0x32 + +/* DSP & Core Audio Control */ +#define TAS675X_RTLDG_EN_REG 0x37 +#define TAS675X_DC_BLOCK_BYP_REG 0x39 +#define TAS675X_DSP_CTRL_REG 0x3A +#define TAS675X_PAGE_AUTO_INC_REG 0x3B + +/* Volume & Mute */ +#define TAS675X_DIG_VOL_CH1_REG 0x40 +#define TAS675X_DIG_VOL_CH2_REG 0x41 +#define TAS675X_DIG_VOL_CH3_REG 0x42 +#define TAS675X_DIG_VOL_CH4_REG 0x43 +#define TAS675X_DIG_VOL_RAMP_CTRL_REG 0x44 +#define TAS675X_DIG_VOL_COMBINE_CTRL_REG 0x46 +#define TAS675X_AUTO_MUTE_EN_REG 0x47 +#define TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG 0x48 +#define TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG 0x49 + +/* Analog Gain & Power Stage */ +#define TAS675X_ANALOG_GAIN_CH1_CH2_REG 0x4A +#define TAS675X_ANALOG_GAIN_CH3_CH4_REG 0x4B +#define TAS675X_ANALOG_GAIN_RAMP_CTRL_REG 0x4E +#define TAS675X_PULSE_INJECTION_EN_REG 0x52 +#define TAS675X_CBC_CTRL_REG 0x54 +#define TAS675X_CURRENT_LIMIT_CTRL_REG 0x55 +#define TAS675X_DAC_CLK_REG 0x5A +#define TAS675X_ISENSE_CAL_REG 0x5B + +/* Spread Spectrum & PWM Phase */ +#define TAS675X_PWM_PHASE_CTRL_REG 0x60 +#define TAS675X_SS_CTRL_REG 0x61 +#define TAS675X_SS_RANGE_CTRL_REG 0x62 +#define TAS675X_SS_DWELL_CTRL_REG 0x66 +#define TAS675X_RAMP_PHASE_CTRL_GPO_REG 0x68 +#define TAS675X_PWM_PHASE_M_CTRL_CH1_REG 0x69 +#define TAS675X_PWM_PHASE_M_CTRL_CH2_REG 0x6A +#define TAS675X_PWM_PHASE_M_CTRL_CH3_REG 0x6B +#define TAS675X_PWM_PHASE_M_CTRL_CH4_REG 0x6C + +/* Status & Reporting */ +#define TAS675X_AUTO_MUTE_STATUS_REG 0x71 +#define TAS675X_STATE_REPORT_CH1_CH2_REG 0x72 +#define TAS675X_STATE_REPORT_CH3_CH4_REG 0x73 +#define TAS675X_PVDD_SENSE_REG 0x74 +#define TAS675X_TEMP_GLOBAL_REG 0x75 +#define TAS675X_FS_MON_REG 0x76 +#define TAS675X_SCLK_MON_REG 0x77 +#define TAS675X_REPORT_ROUTING_1_REG 0x7C + +/* Memory Paging & Book Control */ +#define TAS675X_SETUP_REG1 0x7D +#define TAS675X_SETUP_REG2 0x7E +#define TAS675X_BOOK_CTRL_REG 0x7F + +/* Fault Status */ +#define TAS675X_POWER_FAULT_STATUS_1_REG 0x7D +#define TAS675X_POWER_FAULT_STATUS_2_REG 0x80 +#define TAS675X_OT_FAULT_REG 0x81 +#define TAS675X_OTW_STATUS_REG 0x82 +#define TAS675X_CLIP_WARN_STATUS_REG 0x83 +#define TAS675X_CBC_WARNING_STATUS_REG 0x85 + +/* Latched Fault Registers */ +#define TAS675X_POWER_FAULT_LATCHED_REG 0x86 +#define TAS675X_OTSD_LATCHED_REG 0x87 +#define TAS675X_OTW_LATCHED_REG 0x88 +#define TAS675X_CLIP_WARN_LATCHED_REG 0x89 +#define TAS675X_CLK_FAULT_LATCHED_REG 0x8A +#define TAS675X_RTLDG_OL_SL_FAULT_LATCHED_REG 0x8B +#define TAS675X_CBC_FAULT_WARN_LATCHED_REG 0x8D +#define TAS675X_OC_DC_FAULT_LATCHED_REG 0x8E +#define TAS675X_OTSD_RECOVERY_EN_REG 0x8F + +/* Protection & Routing Controls */ +#define TAS675X_REPORT_ROUTING_2_REG 0x90 +#define TAS675X_REPORT_ROUTING_3_REG 0x91 +#define TAS675X_REPORT_ROUTING_4_REG 0x92 +#define TAS675X_CLIP_DETECT_CTRL_REG 0x93 +#define TAS675X_REPORT_ROUTING_5_REG 0x94 + +/* GPIO Pin Configuration */ +#define TAS675X_GPIO1_OUTPUT_SEL_REG 0x95 +#define TAS675X_GPIO2_OUTPUT_SEL_REG 0x96 +#define TAS675X_GPIO_INPUT_SLEEP_HIZ_REG 0x9B +#define TAS675X_GPIO_INPUT_PLAY_SLEEP_REG 0x9C +#define TAS675X_GPIO_INPUT_MUTE_REG 0x9D +#define TAS675X_GPIO_INPUT_SYNC_REG 0x9E +#define TAS675X_GPIO_INPUT_SDIN2_REG 0x9F +#define TAS675X_GPIO_CTRL_REG 0xA0 +#define TAS675X_GPIO_INVERT_REG 0xA1 + +/* Load Diagnostics Config */ +#define TAS675X_DC_LDG_CTRL_REG 0xB0 +#define TAS675X_DC_LDG_LO_CTRL_REG 0xB1 +#define TAS675X_DC_LDG_TIME_CTRL_REG 0xB2 +#define TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG 0xB3 +#define TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG 0xB4 +#define TAS675X_AC_LDG_CTRL_REG 0xB5 +#define TAS675X_TWEETER_DETECT_CTRL_REG 0xB6 +#define TAS675X_TWEETER_DETECT_THRESH_REG 0xB7 +#define TAS675X_AC_LDG_FREQ_CTRL_REG 0xB8 +#define TAS675X_TEMP_CH1_CH2_REG 0xBB +#define TAS675X_TEMP_CH3_CH4_REG 0xBC +#define TAS675X_WARN_OT_MAX_FLAG_REG 0xBD + +/* DC Load Diagnostic Reports */ +#define TAS675X_DC_LDG_REPORT_CH1_CH2_REG 0xC0 +#define TAS675X_DC_LDG_REPORT_CH3_CH4_REG 0xC1 +#define TAS675X_DC_LDG_RESULT_REG 0xC2 +#define TAS675X_AC_LDG_REPORT_CH1_R_REG 0xC3 +#define TAS675X_AC_LDG_REPORT_CH1_I_REG 0xC4 +#define TAS675X_AC_LDG_REPORT_CH2_R_REG 0xC5 +#define TAS675X_AC_LDG_REPORT_CH2_I_REG 0xC6 +#define TAS675X_AC_LDG_REPORT_CH3_R_REG 0xC7 +#define TAS675X_AC_LDG_REPORT_CH3_I_REG 0xC8 +#define TAS675X_AC_LDG_REPORT_CH4_R_REG 0xC9 +#define TAS675X_AC_LDG_REPORT_CH4_I_REG 0xCA +#define TAS675X_TWEETER_REPORT_REG 0xCB + +/* RTLDG Impedance */ +#define TAS675X_CH1_RTLDG_IMP_MSB_REG 0xD1 +#define TAS675X_CH1_RTLDG_IMP_LSB_REG 0xD2 +#define TAS675X_CH2_RTLDG_IMP_MSB_REG 0xD3 +#define TAS675X_CH2_RTLDG_IMP_LSB_REG 0xD4 +#define TAS675X_CH3_RTLDG_IMP_MSB_REG 0xD5 +#define TAS675X_CH3_RTLDG_IMP_LSB_REG 0xD6 +#define TAS675X_CH4_RTLDG_IMP_MSB_REG 0xD7 +#define TAS675X_CH4_RTLDG_IMP_LSB_REG 0xD8 + +/* DC Load Diagnostic Resistance */ +#define TAS675X_DC_LDG_DCR_MSB_REG 0xD9 +#define TAS675X_CH1_DC_LDG_DCR_LSB_REG 0xDA +#define TAS675X_CH2_DC_LDG_DCR_LSB_REG 0xDB +#define TAS675X_CH3_DC_LDG_DCR_LSB_REG 0xDC +#define TAS675X_CH4_DC_LDG_DCR_LSB_REG 0xDD + +/* Over-Temperature Warning */ +#define TAS675X_OTW_CTRL_CH1_CH2_REG 0xE2 +#define TAS675X_OTW_CTRL_CH3_CH4_REG 0xE3 + +/* RESET_REG (all bits auto-clear) */ +#define TAS675X_DEVICE_RESET BIT(4) +#define TAS675X_FAULT_CLEAR BIT(3) +#define TAS675X_REGISTER_RESET BIT(0) + +/* STATE_CTRL and STATE_REPORT — Channel state values */ +#define TAS675X_STATE_DEEPSLEEP 0x00 +#define TAS675X_STATE_LOAD_DIAG 0x01 +#define TAS675X_STATE_SLEEP 0x02 +#define TAS675X_STATE_HIZ 0x03 +#define TAS675X_STATE_PLAY 0x04 + +/* Additional STATE_REPORT values */ +#define TAS675X_STATE_FAULT 0x05 +#define TAS675X_STATE_AUTOREC 0x06 + +/* Combined values for both channel pairs in one register */ +#define TAS675X_STATE_DEEPSLEEP_BOTH \ + (TAS675X_STATE_DEEPSLEEP | (TAS675X_STATE_DEEPSLEEP << 4)) +#define TAS675X_STATE_LOAD_DIAG_BOTH \ + (TAS675X_STATE_LOAD_DIAG | (TAS675X_STATE_LOAD_DIAG << 4)) +#define TAS675X_STATE_SLEEP_BOTH \ + (TAS675X_STATE_SLEEP | (TAS675X_STATE_SLEEP << 4)) +#define TAS675X_STATE_HIZ_BOTH \ + (TAS675X_STATE_HIZ | (TAS675X_STATE_HIZ << 4)) +#define TAS675X_STATE_PLAY_BOTH \ + (TAS675X_STATE_PLAY | (TAS675X_STATE_PLAY << 4)) +#define TAS675X_STATE_FAULT_BOTH \ + (TAS675X_STATE_FAULT | (TAS675X_STATE_FAULT << 4)) + +/* STATE_CTRL_CH1_CH2 / STATE_CTRL_CH3_CH4 — mute bits */ +#define TAS675X_CH1_MUTE_BIT BIT(7) +#define TAS675X_CH2_MUTE_BIT BIT(3) +#define TAS675X_CH_MUTE_BOTH (TAS675X_CH1_MUTE_BIT | TAS675X_CH2_MUTE_BIT) + +/* SCLK_INV_CTRL_REG */ +#define TAS675X_SCLK_INV_TX_BIT BIT(5) +#define TAS675X_SCLK_INV_RX_BIT BIT(4) +#define TAS675X_SCLK_INV_MASK (TAS675X_SCLK_INV_TX_BIT | TAS675X_SCLK_INV_RX_BIT) + +/* AUDIO_IF_CTRL_REG */ +#define TAS675X_TDM_EN_BIT BIT(4) +#define TAS675X_SAP_FMT_MASK GENMASK(3, 2) +#define TAS675X_SAP_FMT_I2S (0x00 << 2) +#define TAS675X_SAP_FMT_TDM (0x01 << 2) +#define TAS675X_SAP_FMT_RIGHT_J (0x02 << 2) +#define TAS675X_SAP_FMT_LEFT_J (0x03 << 2) +#define TAS675X_FS_PULSE_MASK GENMASK(1, 0) +#define TAS675X_FS_PULSE_SHORT 0x01 + +/* SDIN_CTRL_REG */ +#define TAS675X_SDIN_AUDIO_WL_MASK GENMASK(3, 2) +#define TAS675X_SDIN_LL_WL_MASK GENMASK(1, 0) +#define TAS675X_SDIN_WL_MASK (TAS675X_SDIN_AUDIO_WL_MASK | TAS675X_SDIN_LL_WL_MASK) + +/* SDOUT_CTRL_REG */ +#define TAS675X_SDOUT_SELECT_MASK GENMASK(7, 4) +#define TAS675X_SDOUT_SELECT_TDM_SDOUT1 0x00 +#define TAS675X_SDOUT_SELECT_NON_TDM 0x10 +#define TAS675X_SDOUT_VP_WL_MASK GENMASK(3, 2) +#define TAS675X_SDOUT_IS_WL_MASK GENMASK(1, 0) +#define TAS675X_SDOUT_WL_MASK (TAS675X_SDOUT_VP_WL_MASK | TAS675X_SDOUT_IS_WL_MASK) + +/* SDOUT_EN_REG */ +#define TAS675X_SDOUT_NON_TDM_SEL_MASK GENMASK(5, 4) +#define TAS675X_SDOUT_NON_TDM_SEL_VPREDICT (0x0 << 4) +#define TAS675X_SDOUT_NON_TDM_SEL_ISENSE (0x1 << 4) +#define TAS675X_SDOUT_EN_VPREDICT BIT(0) +#define TAS675X_SDOUT_EN_ISENSE BIT(1) +#define TAS675X_SDOUT_EN_NON_TDM_ALL GENMASK(1, 0) + +/* Word length values (shared by SDIN_CTRL and SDOUT_CTRL) */ +#define TAS675X_WL_16BIT 0x00 +#define TAS675X_WL_20BIT 0x01 +#define TAS675X_WL_24BIT 0x02 +#define TAS675X_WL_32BIT 0x03 + +/* SDIN_OFFSET_MSB_REG */ +#define TAS675X_SDIN_AUDIO_OFF_MSB_MASK GENMASK(7, 6) +#define TAS675X_SDIN_LL_OFF_MSB_MASK GENMASK(5, 4) + +/* SDOUT_OFFSET_MSB_REG */ +#define TAS675X_SDOUT_VP_OFF_MSB_MASK GENMASK(7, 6) +#define TAS675X_SDOUT_IS_OFF_MSB_MASK GENMASK(5, 4) + +/* RTLDG_EN_REG */ +#define TAS675X_RTLDG_CLIP_MASK_BIT BIT(4) +#define TAS675X_RTLDG_CH_EN_MASK GENMASK(3, 0) + +/* DC_LDG_CTRL_REG */ +#define TAS675X_LDG_ABORT_BIT BIT(7) +#define TAS675X_LDG_BUFFER_WAIT_MASK GENMASK(6, 5) +#define TAS675X_LDG_WAIT_BYPASS_BIT BIT(2) +#define TAS675X_SLOL_DISABLE_BIT BIT(1) +#define TAS675X_LDG_BYPASS_BIT BIT(0) + +/* DC_LDG_TIME_CTRL_REG */ +#define TAS675X_LDG_RAMP_SLOL_MASK GENMASK(7, 6) +#define TAS675X_LDG_SETTLING_SLOL_MASK GENMASK(5, 4) +#define TAS675X_LDG_RAMP_S2PG_MASK GENMASK(3, 2) +#define TAS675X_LDG_SETTLING_S2PG_MASK GENMASK(1, 0) + +/* AC_LDG_CTRL_REG */ +#define TAS675X_AC_DIAG_GAIN_BIT BIT(4) +#define TAS675X_AC_DIAG_START_MASK GENMASK(3, 0) + +/* DC_LDG_RESULT_REG */ +#define TAS675X_DC_LDG_LO_RESULT_MASK GENMASK(7, 4) +#define TAS675X_DC_LDG_PASS_MASK GENMASK(3, 0) + +/* Load Diagnostics Timing Constants */ +#define TAS675X_POLL_INTERVAL_US 10000 +#define TAS675X_STATE_TRANSITION_TIMEOUT_US 50000 +#define TAS675X_DC_LDG_TIMEOUT_US 300000 +#define TAS675X_AC_LDG_TIMEOUT_US 400000 + +/* GPIO_CTRL_REG */ +#define TAS675X_GPIO1_OUTPUT_EN BIT(7) +#define TAS675X_GPIO2_OUTPUT_EN BIT(6) +#define TAS675X_GPIO_CTRL_RSTVAL 0x22 + +/* GPIO output select values */ +#define TAS675X_GPIO_SEL_LOW 0x00 +#define TAS675X_GPIO_SEL_AUTO_MUTE_ALL 0x02 +#define TAS675X_GPIO_SEL_AUTO_MUTE_CH4 0x03 +#define TAS675X_GPIO_SEL_AUTO_MUTE_CH3 0x04 +#define TAS675X_GPIO_SEL_AUTO_MUTE_CH2 0x05 +#define TAS675X_GPIO_SEL_AUTO_MUTE_CH1 0x06 +#define TAS675X_GPIO_SEL_SDOUT2 0x08 +#define TAS675X_GPIO_SEL_SDOUT1 0x09 +#define TAS675X_GPIO_SEL_WARN 0x0A +#define TAS675X_GPIO_SEL_FAULT 0x0B +#define TAS675X_GPIO_SEL_CLOCK_SYNC 0x0E +#define TAS675X_GPIO_SEL_INVALID_CLK 0x0F +#define TAS675X_GPIO_SEL_HIGH 0x13 + +/* GPIO input function encoding (flag bit | function ID) */ +#define TAS675X_GPIO_FUNC_INPUT 0x100 + +/* Input Function IDs */ +#define TAS675X_GPIO_IN_ID_MUTE 0 +#define TAS675X_GPIO_IN_ID_PHASE_SYNC 1 +#define TAS675X_GPIO_IN_ID_SDIN2 2 +#define TAS675X_GPIO_IN_ID_DEEP_SLEEP 3 +#define TAS675X_GPIO_IN_ID_HIZ 4 +#define TAS675X_GPIO_IN_ID_PLAY 5 +#define TAS675X_GPIO_IN_ID_SLEEP 6 +#define TAS675X_GPIO_IN_NUM 7 + +#define TAS675X_GPIO_IN_MUTE (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_MUTE) +#define TAS675X_GPIO_IN_PHASE_SYNC \ + (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_PHASE_SYNC) +#define TAS675X_GPIO_IN_SDIN2 (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_SDIN2) +#define TAS675X_GPIO_IN_DEEP_SLEEP \ + (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_DEEP_SLEEP) +#define TAS675X_GPIO_IN_HIZ (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_HIZ) +#define TAS675X_GPIO_IN_PLAY (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_PLAY) +#define TAS675X_GPIO_IN_SLEEP (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_SLEEP) + +/* GPIO input 3-bit mux field masks */ +#define TAS675X_GPIO_IN_MUTE_MASK GENMASK(2, 0) +#define TAS675X_GPIO_IN_SYNC_MASK GENMASK(2, 0) +#define TAS675X_GPIO_IN_SDIN2_MASK GENMASK(6, 4) +#define TAS675X_GPIO_IN_DEEP_SLEEP_MASK GENMASK(6, 4) +#define TAS675X_GPIO_IN_HIZ_MASK GENMASK(2, 0) +#define TAS675X_GPIO_IN_PLAY_MASK GENMASK(6, 4) +#define TAS675X_GPIO_IN_SLEEP_MASK GENMASK(2, 0) + +/* Book addresses for tas675x_select_book() */ +#define TAS675X_BOOK_DEFAULT 0x00 +#define TAS675X_BOOK_DSP 0x8C + +/* DSP memory addresses (DSP Book) */ +#define TAS675X_DSP_PAGE_RTLDG 0x22 +#define TAS675X_DSP_RTLDG_OL_THRESH_REG 0x98 +#define TAS675X_DSP_RTLDG_SL_THRESH_REG 0x9C + +#define TAS675X_DSP_PARAM_ID_OL_THRESH 0 +#define TAS675X_DSP_PARAM_ID_SL_THRESH 1 + +/* Setup Mode Entry/Exit*/ +#define TAS675X_SETUP_ENTER_VAL1 0x11 +#define TAS675X_SETUP_ENTER_VAL2 0xFF +#define TAS675X_SETUP_EXIT_VAL 0x00 + +#endif /* __TAS675X_H__ */ diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c index 7d6fcba9986e..7ddea2fbe2d2 100644 --- a/sound/soc/codecs/tda7419.c +++ b/sound/soc/codecs/tda7419.c @@ -614,7 +614,7 @@ static int tda7419_probe(struct i2c_client *i2c) } static const struct i2c_device_id tda7419_i2c_id[] = { - { "tda7419" }, + { .name = "tda7419" }, { } }; MODULE_DEVICE_TABLE(i2c, tda7419_i2c_id); diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index ac0c5c337677..f30479f1f53b 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c @@ -296,7 +296,7 @@ static int tfa9879_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tfa9879_i2c_id[] = { - { "tfa9879" }, + { .name = "tfa9879" }, { } }; MODULE_DEVICE_TABLE(i2c, tfa9879_i2c_id); diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c index 270eee1ea534..d7d958ecd8db 100644 --- a/sound/soc/codecs/tlv320adc3xxx.c +++ b/sound/soc/codecs/tlv320adc3xxx.c @@ -1391,9 +1391,9 @@ static const struct snd_soc_component_driver soc_component_dev_adc3xxx = { }; static const struct i2c_device_id adc3xxx_i2c_id[] = { - { "tlv320adc3001", ADC3001 }, - { "tlv320adc3101", ADC3101 }, - {} + { .name = "tlv320adc3001", .driver_data = ADC3001 }, + { .name = "tlv320adc3101", .driver_data = ADC3101 }, + { } }; MODULE_DEVICE_TABLE(i2c, adc3xxx_i2c_id); diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index e4f27a734501..4eb9cea27276 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -1326,10 +1326,10 @@ static int adcx140_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id adcx140_i2c_id[] = { - { "tlv320adc3140", 0 }, - { "tlv320adc5140", 1 }, - { "tlv320adc6140", 2 }, - {} + { .name = "tlv320adc3140", .driver_data = 0 }, + { .name = "tlv320adc5140", .driver_data = 1 }, + { .name = "tlv320adc6140", .driver_data = 2 }, + { } }; MODULE_DEVICE_TABLE(i2c, adcx140_i2c_id); diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c index a31fb95048b8..2f928ae23887 100644 --- a/sound/soc/codecs/tlv320aic23-i2c.c +++ b/sound/soc/codecs/tlv320aic23-i2c.c @@ -28,8 +28,8 @@ static int tlv320aic23_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23"}, - {} + { .name = "tlv320aic23" }, + { } }; MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c index 4362c2c06ce8..1d2e0ea6d4fe 100644 --- a/sound/soc/codecs/tlv320aic31xx.c +++ b/sound/soc/codecs/tlv320aic31xx.c @@ -1630,14 +1630,14 @@ static void aic31xx_configure_ocmv(struct aic31xx_priv *priv) } static const struct i2c_device_id aic31xx_i2c_id[] = { - { "tlv320aic310x", AIC3100 }, - { "tlv320aic311x", AIC3110 }, - { "tlv320aic3100", AIC3100 }, - { "tlv320aic3110", AIC3110 }, - { "tlv320aic3120", AIC3120 }, - { "tlv320aic3111", AIC3111 }, - { "tlv320dac3100", DAC3100 }, - { "tlv320dac3101", DAC3101 }, + { .name = "tlv320aic310x", .driver_data = AIC3100 }, + { .name = "tlv320aic311x", .driver_data = AIC3110 }, + { .name = "tlv320aic3100", .driver_data = AIC3100 }, + { .name = "tlv320aic3110", .driver_data = AIC3110 }, + { .name = "tlv320aic3120", .driver_data = AIC3120 }, + { .name = "tlv320aic3111", .driver_data = AIC3111 }, + { .name = "tlv320dac3100", .driver_data = DAC3100 }, + { .name = "tlv320dac3101", .driver_data = DAC3101 }, { } }; MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id); diff --git a/sound/soc/codecs/tlv320aic32x4-i2c.c b/sound/soc/codecs/tlv320aic32x4-i2c.c index b27b5ae1e4b2..449353d5f088 100644 --- a/sound/soc/codecs/tlv320aic32x4-i2c.c +++ b/sound/soc/codecs/tlv320aic32x4-i2c.c @@ -38,9 +38,9 @@ static void aic32x4_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id aic32x4_i2c_id[] = { - { "tlv320aic32x4", (kernel_ulong_t)AIC32X4_TYPE_AIC32X4 }, - { "tlv320aic32x6", (kernel_ulong_t)AIC32X4_TYPE_AIC32X6 }, - { "tas2505", (kernel_ulong_t)AIC32X4_TYPE_TAS2505 }, + { .name = "tlv320aic32x4", .driver_data = (kernel_ulong_t)AIC32X4_TYPE_AIC32X4 }, + { .name = "tlv320aic32x6", .driver_data = (kernel_ulong_t)AIC32X4_TYPE_AIC32X6 }, + { .name = "tas2505", .driver_data = (kernel_ulong_t)AIC32X4_TYPE_TAS2505 }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); diff --git a/sound/soc/codecs/tlv320aic3x-i2c.c b/sound/soc/codecs/tlv320aic3x-i2c.c index 0b585925c1ac..71528ad3a3b6 100644 --- a/sound/soc/codecs/tlv320aic3x-i2c.c +++ b/sound/soc/codecs/tlv320aic3x-i2c.c @@ -18,11 +18,11 @@ #include "tlv320aic3x.h" static const struct i2c_device_id aic3x_i2c_id[] = { - { "tlv320aic3x", AIC3X_MODEL_3X }, - { "tlv320aic33", AIC3X_MODEL_33 }, - { "tlv320aic3007", AIC3X_MODEL_3007 }, - { "tlv320aic3104", AIC3X_MODEL_3104 }, - { "tlv320aic3106", AIC3X_MODEL_3106 }, + { .name = "tlv320aic3x", .driver_data = AIC3X_MODEL_3X }, + { .name = "tlv320aic33", .driver_data = AIC3X_MODEL_33 }, + { .name = "tlv320aic3007", .driver_data = AIC3X_MODEL_3007 }, + { .name = "tlv320aic3104", .driver_data = AIC3X_MODEL_3104 }, + { .name = "tlv320aic3106", .driver_data = AIC3X_MODEL_3106 }, { } }; MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index ce22298b43ef..b12c1952823b 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1689,8 +1689,15 @@ static int aic3x_component_probe(struct snd_soc_component *component) return 0; } +static int aic3x_of_xlate_dai_id(struct snd_soc_component *component, + struct device_node *endpoint) +{ + return 0; +} + static const struct snd_soc_component_driver soc_component_dev_aic3x = { .set_bias_level = aic3x_set_bias_level, + .of_xlate_dai_id = aic3x_of_xlate_dai_id, .probe = aic3x_component_probe, .controls = aic3x_snd_controls, .num_controls = ARRAY_SIZE(aic3x_snd_controls), diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c index 5a7beeadb009..39284e4d420e 100644 --- a/sound/soc/codecs/ts3a227e.c +++ b/sound/soc/codecs/ts3a227e.c @@ -423,7 +423,7 @@ static const struct dev_pm_ops ts3a227e_pm = { }; static const struct i2c_device_id ts3a227e_i2c_ids[] = { - { "ts3a227e" }, + { .name = "ts3a227e" }, { } }; MODULE_DEVICE_TABLE(i2c, ts3a227e_i2c_ids); diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index 7390ab250ebb..dba581857920 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -1483,8 +1483,8 @@ static int tscs42xx_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tscs42xx_i2c_id[] = { - { "tscs42A1" }, - { "tscs42A2" }, + { .name = "tscs42A1" }, + { .name = "tscs42A2" }, { } }; MODULE_DEVICE_TABLE(i2c, tscs42xx_i2c_id); diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index 64d0da40fbaf..aad394937ce6 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -3454,7 +3454,7 @@ static int tscs454_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tscs454_i2c_id[] = { - { "tscs454" }, + { .name = "tscs454" }, { } }; MODULE_DEVICE_TABLE(i2c, tscs454_i2c_id); diff --git a/sound/soc/codecs/uda1342.c b/sound/soc/codecs/uda1342.c index b0b29012842d..12f5757f4210 100644 --- a/sound/soc/codecs/uda1342.c +++ b/sound/soc/codecs/uda1342.c @@ -319,7 +319,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(uda1342_pm_ops, uda1342_suspend, uda1342_resume, NULL); static const struct i2c_device_id uda1342_i2c_id[] = { - { "uda1342" }, + { .name = "uda1342" }, { } }; MODULE_DEVICE_TABLE(i2c, uda1342_i2c_id); diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 55c83d95bfba..1dd09d10fc4a 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -38,9 +38,9 @@ struct uda1380_priv { unsigned int dac_clk; struct work_struct work; struct i2c_client *i2c; - u16 *reg_cache; struct gpio_desc *power; struct gpio_desc *reset; + u16 reg_cache[]; }; /* @@ -767,11 +767,15 @@ static int uda1380_i2c_probe(struct i2c_client *i2c) struct uda1380_priv *uda1380; int ret; - uda1380 = devm_kzalloc(&i2c->dev, sizeof(struct uda1380_priv), + uda1380 = devm_kzalloc(&i2c->dev, + struct_size(uda1380, reg_cache, ARRAY_SIZE(uda1380_reg)), GFP_KERNEL); if (uda1380 == NULL) return -ENOMEM; + memcpy(uda1380->reg_cache, uda1380_reg, + ARRAY_SIZE(uda1380_reg) * sizeof(*uda1380->reg_cache)); + uda1380->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(uda1380->reset)) return dev_err_probe(dev, PTR_ERR(uda1380->reset), @@ -789,11 +793,6 @@ static int uda1380_i2c_probe(struct i2c_client *i2c) if (device_property_match_string(dev, "dac-clk", "wspll") >= 0) uda1380->dac_clk = UDA1380_DAC_CLK_WSPLL; - uda1380->reg_cache = devm_kmemdup_array(&i2c->dev, uda1380_reg, ARRAY_SIZE(uda1380_reg), - sizeof(uda1380_reg[0]), GFP_KERNEL); - if (!uda1380->reg_cache) - return -ENOMEM; - i2c_set_clientdata(i2c, uda1380); uda1380->i2c = i2c; @@ -803,7 +802,7 @@ static int uda1380_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id uda1380_i2c_id[] = { - { "uda1380" }, + { .name = "uda1380" }, { } }; MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index 72a53f95d688..e0169e783ee9 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -2499,18 +2499,13 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) { struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component); - struct sdw_slave *tx_sdw_dev = wcd937x->tx_sdw_dev; struct device *dev = component->dev; - unsigned long time_left; int i, ret; u32 chipid; - time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, - msecs_to_jiffies(5000)); - if (!time_left) { - dev_err(dev, "soundwire device init timeout\n"); - return -ETIMEDOUT; - } + ret = sdw_slave_wait_for_init(wcd937x->tx_sdw_dev, 5000); + if (ret) + return ret; snd_soc_component_init_regmap(component, wcd937x->regmap); ret = pm_runtime_resume_and_get(dev); diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index cb0a0bfdb6e3..c69e18667a85 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -3016,18 +3016,13 @@ static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev) static int wcd938x_soc_codec_probe(struct snd_soc_component *component) { struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); - struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev; struct device *dev = component->dev; - unsigned long time_left; unsigned int variant; int ret, i; - time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, - msecs_to_jiffies(2000)); - if (!time_left) { - dev_err(dev, "soundwire device init timeout\n"); - return -ETIMEDOUT; - } + ret = sdw_slave_wait_for_init(wcd938x->tx_sdw_dev, 2000); + if (ret) + return ret; snd_soc_component_init_regmap(component, wcd938x->regmap); diff --git a/sound/soc/codecs/wcd939x.c b/sound/soc/codecs/wcd939x.c index 01f1a08f48e6..010d12466722 100644 --- a/sound/soc/codecs/wcd939x.c +++ b/sound/soc/codecs/wcd939x.c @@ -2968,17 +2968,12 @@ static int wcd939x_irq_init(struct wcd939x_priv *wcd, struct device *dev) static int wcd939x_soc_codec_probe(struct snd_soc_component *component) { struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component); - struct sdw_slave *tx_sdw_dev = wcd939x->tx_sdw_dev; struct device *dev = component->dev; - unsigned long time_left; int ret, i; - time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete, - msecs_to_jiffies(2000)); - if (!time_left) { - dev_err(dev, "soundwire device init timeout\n"); - return -ETIMEDOUT; - } + ret = sdw_slave_wait_for_init(wcd939x->tx_sdw_dev, 2000); + if (ret) + return ret; snd_soc_component_init_regmap(component, wcd939x->regmap); diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 1f59309d8c69..5c1b00acb5bf 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -204,7 +204,7 @@ static int wm1250_ev1_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm1250_ev1_i2c_id[] = { - { "wm1250-ev1" }, + { .name = "wm1250-ev1" }, { } }; MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id); diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 126be2a2a8f3..9b68ee69324b 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -929,7 +929,7 @@ static int wm2000_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm2000_i2c_id[] = { - { "wm2000" }, + { .name = "wm2000" }, { } }; MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 87418c838ca0..ba8ce2e6e615 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2471,7 +2471,7 @@ static const struct dev_pm_ops wm2200_pm = { }; static const struct i2c_device_id wm2200_i2c_id[] = { - { "wm2200" }, + { .name = "wm2200" }, { } }; MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 96fd098a9d36..bd94fa53c362 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2669,7 +2669,7 @@ static const struct dev_pm_ops wm5100_pm = { }; static const struct i2c_device_id wm5100_i2c_id[] = { - { "wm5100" }, + { .name = "wm5100" }, { } }; MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id); diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index bebee333d3fd..589a89564813 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -669,7 +669,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8510_i2c_id[] = { - { "wm8510" }, + { .name = "wm8510" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index f003f19766e2..65108a041c92 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -518,7 +518,7 @@ static int wm8523_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8523_i2c_id[] = { - { "wm8523" }, + { .name = "wm8523" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 2be265bb0751..ca7bbe5d4fc3 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -1034,8 +1034,8 @@ static const struct of_device_id wm8580_of_match[] = { MODULE_DEVICE_TABLE(of, wm8580_of_match); static const struct i2c_device_id wm8580_i2c_id[] = { - { "wm8580", (kernel_ulong_t)&wm8580_data }, - { "wm8581", (kernel_ulong_t)&wm8581_data }, + { .name = "wm8580", .driver_data = (kernel_ulong_t)&wm8580_data }, + { .name = "wm8581", .driver_data = (kernel_ulong_t)&wm8581_data }, { } }; MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 2bab9d189519..5271966b1615 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -455,7 +455,7 @@ static int wm8711_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id wm8711_i2c_id[] = { - { "wm8711" }, + { .name = "wm8711" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 4c1a80561f06..6e6fd77c3020 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -296,7 +296,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8728_i2c_id[] = { - { "wm8728" }, + { .name = "wm8728" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); diff --git a/sound/soc/codecs/wm8731-i2c.c b/sound/soc/codecs/wm8731-i2c.c index 1254e583af51..5d19fcc46606 100644 --- a/sound/soc/codecs/wm8731-i2c.c +++ b/sound/soc/codecs/wm8731-i2c.c @@ -47,7 +47,7 @@ static int wm8731_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8731_i2c_id[] = { - { "wm8731" }, + { .name = "wm8731" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index fee8a37ed1df..4eb42d19bc7e 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -641,7 +641,7 @@ static int wm8737_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8737_i2c_id[] = { - { "wm8737" }, + { .name = "wm8737" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id); diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 4dfbb33edb09..ca56fdfb5088 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -606,7 +606,7 @@ static int wm8741_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8741_i2c_id[] = { - { "wm8741" }, + { .name = "wm8741" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 0e1d3ebb15c4..d3f1178c2d34 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -803,8 +803,8 @@ static int wm8750_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8750_i2c_id[] = { - { "wm8750" }, - { "wm8987" }, + { .name = "wm8750" }, + { .name = "wm8987" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index a532a95e8048..95b23504f68d 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1581,7 +1581,7 @@ static int wm8753_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8753_i2c_id[] = { - { "wm8753" }, + { .name = "wm8753" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index c3f340657f0c..f3b02c77314f 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -513,8 +513,8 @@ static int wm8776_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8776_i2c_id[] = { - { "wm8775", WM8775 }, - { "wm8776", WM8776 }, + { .name = "wm8775", .driver_data = WM8775 }, + { .name = "wm8776", .driver_data = WM8776 }, { } }; MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c index 3380d7301b17..3c49abd33d28 100644 --- a/sound/soc/codecs/wm8804-i2c.c +++ b/sound/soc/codecs/wm8804-i2c.c @@ -31,7 +31,7 @@ static void wm8804_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id wm8804_i2c_id[] = { - { "wm8804" }, + { .name = "wm8804" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id); diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index fea629541acd..a9128cfa6ff1 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1286,11 +1286,8 @@ static int wm8900_i2c_probe(struct i2c_client *i2c) return ret; } -static void wm8900_i2c_remove(struct i2c_client *client) -{} - static const struct i2c_device_id wm8900_i2c_id[] = { - { "wm8900" }, + { .name = "wm8900" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); @@ -1299,8 +1296,7 @@ static struct i2c_driver wm8900_i2c_driver = { .driver = { .name = "wm8900", }, - .probe = wm8900_i2c_probe, - .remove = wm8900_i2c_remove, + .probe = wm8900_i2c_probe, .id_table = wm8900_i2c_id, }; #endif diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index f73f6ad06b38..320d7737699d 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2203,7 +2203,7 @@ static const struct of_device_id wm8903_of_match[] = { MODULE_DEVICE_TABLE(of, wm8903_of_match); static const struct i2c_device_id wm8903_i2c_id[] = { - { "wm8903" }, + { .name = "wm8903" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 4c73a340f25f..9e5782e50f47 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2621,9 +2621,9 @@ static int wm8904_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8904_i2c_id[] = { - { "wm8904", WM8904 }, - { "wm8912", WM8912 }, - { "wm8918", WM8904 }, /* Actually a subset, updates to follow */ + { .name = "wm8904", .driver_data = WM8904 }, + { .name = "wm8912", .driver_data = WM8912 }, + { .name = "wm8918", .driver_data = WM8904 }, /* Actually a subset, updates to follow */ { } }; MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id); diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 2f55d0c572a4..e631ec072249 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -851,7 +851,7 @@ static int wm8940_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8940_i2c_id[] = { - { "wm8940" }, + { .name = "wm8940" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index e1c61e026cbc..c897a9ab764d 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -996,7 +996,7 @@ static int wm8955_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8955_i2c_id[] = { - { "wm8955" }, + { .name = "wm8955" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 384e8e703446..a810732c6af0 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1551,7 +1551,7 @@ static void wm8960_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id wm8960_i2c_id[] = { - { "wm8960" }, + { .name = "wm8960" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index cfb8cfc91873..504fc59e4be2 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -967,7 +967,7 @@ static int wm8961_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8961_i2c_id[] = { - { "wm8961" }, + { .name = "wm8961" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 8d2435bf44ea..de18b1f85a32 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3991,7 +3991,7 @@ static const struct dev_pm_ops wm8962_pm = { }; static const struct i2c_device_id wm8962_i2c_id[] = { - { "wm8962" }, + { .name = "wm8962" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 46aa556b44fa..a5d2e91b66bb 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -692,7 +692,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8971_i2c_id[] = { - { "wm8971" }, + { .name = "wm8971" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id); diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 0bb5e947f46d..4656652b8e97 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -712,7 +712,7 @@ static int wm8974_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8974_i2c_id[] = { - { "wm8974" }, + { .name = "wm8974" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 935761e50865..ad8064bbaaac 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -1059,7 +1059,7 @@ static int wm8978_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8978_i2c_id[] = { - { "wm8978" }, + { .name = "wm8978" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index cd34f71cf42a..fab25f35fd14 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1060,7 +1060,7 @@ static int wm8983_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8983_i2c_id[] = { - { "wm8983" }, + { .name = "wm8983" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id); diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index be23c0c608d1..2a64d5a851da 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c @@ -1195,8 +1195,8 @@ static int wm8985_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8985_i2c_id[] = { - { "wm8985", WM8985 }, - { "wm8758", WM8758 }, + { .name = "wm8985", .driver_data = WM8985 }, + { .name = "wm8758", .driver_data = WM8758 }, { } }; MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id); diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 9bffe7a6ccec..741aecc7641a 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -897,7 +897,7 @@ static int wm8988_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8988_i2c_id[] = { - { "wm8988" }, + { .name = "wm8988" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 9f2b42025ec9..11dfbbbdcd92 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1241,7 +1241,7 @@ static int wm8990_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8990_i2c_id[] = { - { "wm8990" }, + { .name = "wm8990" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index b8ed2a3e699b..225c235d3d89 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1315,7 +1315,7 @@ static int wm8991_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8991_i2c_id[] = { - { "wm8991" }, + { .name = "wm8991" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id); diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 1c9299979898..2a94b23319b5 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1735,7 +1735,7 @@ static void wm8993_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id wm8993_i2c_id[] = { - { "wm8993" }, + { .name = "wm8993" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 104ce09c02e0..799989a5bf0f 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -2259,8 +2259,8 @@ static int wm8995_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8995_i2c_id[] = { - {"wm8995"}, - {} + { .name = "wm8995" }, + { } }; MODULE_DEVICE_TABLE(i2c, wm8995_i2c_id); diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 2d9cbf66f7d4..dface555f928 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -3072,7 +3072,7 @@ static void wm8996_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id wm8996_i2c_id[] = { - { "wm8996" }, + { .name = "wm8996" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8996_i2c_id); diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 5bfe43c6c1f4..2e4e0a76499d 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1357,11 +1357,8 @@ static int wm9081_i2c_probe(struct i2c_client *i2c) return 0; } -static void wm9081_i2c_remove(struct i2c_client *client) -{} - static const struct i2c_device_id wm9081_i2c_id[] = { - { "wm9081" }, + { .name = "wm9081" }, { } }; MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); @@ -1370,8 +1367,7 @@ static struct i2c_driver wm9081_i2c_driver = { .driver = { .name = "wm9081", }, - .probe = wm9081_i2c_probe, - .remove = wm9081_i2c_remove, + .probe = wm9081_i2c_probe, .id_table = wm9081_i2c_id, }; diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 5182f0839b7c..8fc24b19313d 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -607,8 +607,8 @@ static int wm9090_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm9090_id[] = { - { "wm9090" }, - { "wm9093" }, + { .name = "wm9090" }, + { .name = "wm9093" }, { } }; MODULE_DEVICE_TABLE(i2c, wm9090_id); diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index ca630c9948e4..baa75e7ff53b 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1170,7 +1170,14 @@ EXPORT_SYMBOL_GPL(wm_adsp2_component_probe); int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component) { + if (!dsp) + return 0; + + if (!dsp->component) + return 0; + cs_dsp_cleanup_debugfs(&dsp->cs_dsp); + dsp->component = NULL; return 0; } diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index d15fda648dad..5174614c3e83 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1167,16 +1167,14 @@ static int wsa881x_runtime_resume(struct device *dev) struct sdw_slave *slave = dev_to_sdw_dev(dev); struct regmap *regmap = dev_get_regmap(dev, NULL); struct wsa881x_priv *wsa881x = dev_get_drvdata(dev); - unsigned long time; + int ret; gpiod_direction_output(wsa881x->sd_n, 0); - time = wait_for_completion_timeout(&slave->initialization_complete, - msecs_to_jiffies(WSA881X_PROBE_TIMEOUT)); - if (!time) { - dev_err(dev, "Initialization not complete, timed out\n"); + ret = sdw_slave_wait_for_init(slave, WSA881X_PROBE_TIMEOUT); + if (ret) { gpiod_direction_output(wsa881x->sd_n, 1); - return -ETIMEDOUT; + return ret; } regcache_cache_only(regmap, false); diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 828524c90f17..8ae59c094878 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -165,7 +165,7 @@ config SND_SOC_IMX_AUDMUX config SND_POWERPC_SOC tristate "SoC Audio for Freescale PowerPC CPUs" - depends on FSL_SOC || PPC_MPC52xx + depends on FSL_SOC || PPC_MPC52xx || (PPC && COMPILE_TEST) help Say Y or M if you want to add support for codecs attached to the PowerPC CPUs. @@ -226,7 +226,7 @@ config SND_SOC_P1022_RDK config SND_SOC_MPC5200_I2S tristate "Freescale MPC5200 PSC in I2S mode driver" - depends on PPC_MPC52xx && PPC_BESTCOMM + depends on PPC_BESTCOMM select SND_MPC52xx_DMA select PPC_BESTCOMM_GEN_BD help @@ -234,7 +234,7 @@ config SND_SOC_MPC5200_I2S config SND_SOC_MPC5200_AC97 tristate "Freescale MPC5200 PSC in AC97 mode driver" - depends on PPC_MPC52xx && PPC_BESTCOMM + depends on PPC_BESTCOMM select SND_SOC_AC97_BUS select SND_MPC52xx_DMA select PPC_BESTCOMM_GEN_BD @@ -358,6 +358,7 @@ config SND_SOC_IMX_RPMSG depends on OF && I2C select SND_SOC_IMX_PCM_RPMSG select SND_SOC_IMX_AUDIO_RPMSG + select SND_SIMPLE_CARD_UTILS help SoC Audio support for i.MX boards with rpmsg. There should be rpmsg devices defined in other core (M core) diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 6be074ea0b3f..5bb31a5cdf23 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "../codecs/tlv320aic23.h" #include "imx-ssi.h" @@ -142,7 +141,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) eukrea_tlv320.name = "cpuimx-audio"; } - if (machine_is_eukrea_cpuimx27() || + if (of_machine_is_compatible("eukrea,cpuimx27") || (tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux"))) { imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, IMX_AUDMUX_V1_PCR_SYN | @@ -159,12 +158,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) ); of_node_put(tmp_np); - } else if (machine_is_eukrea_cpuimx25sd() || - machine_is_eukrea_cpuimx35sd() || - machine_is_eukrea_cpuimx51sd() || + } else if (of_machine_is_compatible("eukrea,cpuimx25") || + of_machine_is_compatible("eukrea,cpuimx35") || + of_machine_is_compatible("eukrea,cpuimx51") || (tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux"))) { if (!np) - ext_port = machine_is_eukrea_cpuimx25sd() ? + ext_port = of_machine_is_compatible("eukrea,cpuimx25") ? 4 : 3; imx_audmux_v2_configure_port(int_port, diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 70a6159430ed..709543308fe9 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -40,6 +40,33 @@ /* Default DAI format without Master and Slave flag */ #define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF) +static const u32 cs42888_rates_48k[] = { + 48000, 96000, 192000, +}; + +static const u32 cs42888_rates_44k[] = { + 44100, 88200, 176400, +}; + +static const u32 cs42888_channels[] = { + 1, 2, 4, 6, 8, +}; + +static const struct snd_pcm_hw_constraint_list cs42888_rate_48k_constraints = { + .list = cs42888_rates_48k, + .count = ARRAY_SIZE(cs42888_rates_48k), +}; + +static const struct snd_pcm_hw_constraint_list cs42888_rate_44k_constraints = { + .list = cs42888_rates_44k, + .count = ARRAY_SIZE(cs42888_rates_44k), +}; + +static const struct snd_pcm_hw_constraint_list cs42888_channel_constraints = { + .list = cs42888_channels, + .count = ARRAY_SIZE(cs42888_channels), +}; + /** * struct codec_priv - CODEC private data * @mclk: Main clock of the CODEC @@ -48,6 +75,9 @@ * @mclk_id: MCLK (or main clock) id for set_sysclk() * @fll_id: FLL (or secordary clock) id for set_sysclk() * @pll_id: PLL id for set_pll() + * @pll_ratio_s24: PLL output ratio for S24_LE format (PLL_freq = sample_rate × ratio) + * Default is 384, but some codecs (e.g., WM8904) require lower values + * to stay within PLL frequency limits */ struct codec_priv { struct clk *mclk; @@ -56,6 +86,7 @@ struct codec_priv { u32 mclk_id; int fll_id; int pll_id; + int pll_ratio_s24; }; /** @@ -87,12 +118,15 @@ struct cpu_priv { * @codec_priv: CODEC private data * @cpu_priv: CPU private data * @card: ASoC card structure + * @constraint_rates: array of supported rates + * @constraint_channels: array of supported channels * @streams: Mask of current active streams * @sample_rate: Current sample rate * @sample_format: Current sample format * @asrc_rate: ASRC sample rate used by Back-Ends * @asrc_format: ASRC sample format used by Back-Ends * @dai_fmt: DAI format between CPU and CODEC + * @exclude_format: excluded format; * @name: Card name */ @@ -104,12 +138,15 @@ struct fsl_asoc_card_priv { struct codec_priv codec_priv[2]; struct cpu_priv cpu_priv; struct snd_soc_card card; + const struct snd_pcm_hw_constraint_list *constraint_rates; + const struct snd_pcm_hw_constraint_list *constraint_channels; u8 streams; u32 sample_rate; snd_pcm_format_t sample_format; u32 asrc_rate; snd_pcm_format_t asrc_format; u32 dai_fmt; + u64 exclude_format; char name[32]; }; @@ -222,7 +259,7 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) - pll_out = priv->sample_rate * 384; + pll_out = priv->sample_rate * codec_priv->pll_ratio_s24; else pll_out = priv->sample_rate * 256; @@ -291,7 +328,47 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream) return 0; } +static int fsl_asoc_card_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + if (priv->exclude_format && !rtd->dai_link->no_pcm) { + ret = snd_pcm_hw_constraint_mask64(runtime, + SNDRV_PCM_HW_PARAM_FORMAT, + ~priv->exclude_format); + if (ret) + return ret; + } + + if (priv->constraint_channels) { + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + priv->constraint_channels); + if (ret) + return ret; + } + + /* + * Apply rate constraints only to frontend DAI links (no_pcm = 0). + * Skip DPCM backend (no_pcm = 1) as rate is fixed by be_hw_params_fixup() + * and ASRC frontend handles rate conversion. + */ + if (priv->constraint_rates && !rtd->dai_link->no_pcm) { + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + priv->constraint_rates); + if (ret) + return ret; + } + + return 0; +} + static const struct snd_soc_ops fsl_asoc_card_ops = { + .startup = fsl_asoc_card_startup, .hw_params = fsl_asoc_card_hw_params, .hw_free = fsl_asoc_card_hw_free, }; @@ -742,6 +819,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) for (codec_idx = 0; codec_idx < 2; codec_idx++) { priv->codec_priv[codec_idx].fll_id = -1; priv->codec_priv[codec_idx].pll_id = -1; + priv->codec_priv[codec_idx].pll_ratio_s24 = 384; } /* Diversify the card configurations */ @@ -753,6 +831,14 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT; priv->cpu_priv.slot_width = 32; priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC; + priv->constraint_channels = &cs42888_channel_constraints; + if (priv->codec_priv[0].mclk_freq % 12288000 == 0) + priv->constraint_rates = &cs42888_rate_48k_constraints; + else if (priv->codec_priv[0].mclk_freq % 11289600 == 0) + priv->constraint_rates = &cs42888_rate_44k_constraints; + else + dev_warn(&pdev->dev, "Unknown MCLK frequency %lu, no rate constraints\n", + priv->codec_priv[0].mclk_freq); } else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) { codec_dai_name[0] = "cs4271-hifi"; priv->codec_priv[0].mclk_id = CS427x_SYSCLK_MCLK; @@ -779,11 +865,30 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->codec_priv[0].fll_id = WM8962_SYSCLK_FLL; priv->codec_priv[0].pll_id = WM8962_FLL; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; + /* + * WM8962 has same BCLK generation limitations as WM8960. + * See WM8960 section for detailed explanation. + */ + if (of_node_name_eq(cpu_np, "sai")) + priv->exclude_format = SNDRV_PCM_FMTBIT_S20_3LE; } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) { codec_dai_name[0] = "wm8960-hifi"; priv->codec_priv[0].fll_id = WM8960_SYSCLK_AUTO; priv->codec_priv[0].pll_id = WM8960_SYSCLK_AUTO; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; + /* + * WM8960 in master mode cannot generate exact 1.92 MHz BCLK + * required for S20_3LE (48kHz × 2ch × 20bit). Closest available + * is 2.048 MHz (SYSCLK/6), which causes right channel corruption. + * + * In SAI master mode, SAI derive BCLK from MCLK using integer + * dividers only. S20_3LE requires non-integer divider ratios + * with standard MCLK frequencies. For example, 48kHz stereo + * needs 1.920 MHz BCLK, which requires a divider of 6.4 from + * 12.288 MHz MCLK (not an integer). + */ + if (of_node_name_eq(cpu_np, "sai")) + priv->exclude_format = SNDRV_PCM_FMTBIT_S20_3LE; } else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) { codec_dai_name[0] = "ac97-hifi"; priv->dai_fmt = SND_SOC_DAIFMT_AC97; @@ -835,6 +940,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->codec_priv[0].mclk_id = WM8904_FLL_MCLK; priv->codec_priv[0].fll_id = WM8904_CLK_FLL; priv->codec_priv[0].pll_id = WM8904_FLL_MCLK; + priv->codec_priv[0].pll_ratio_s24 = 192; priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else if (of_device_is_compatible(np, "fsl,imx-audio-spdif")) { ret = fsl_asoc_card_spdif_init(codec_np, cpu_np, codec_dai_name, priv); @@ -989,6 +1095,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) if (asrc_pdev) { /* DPCM DAI Links only if ASRC exists */ + priv->dai_link[1].dpcm_merged_chan = 1; + priv->dai_link[1].ignore_pmdown_time = 1; priv->dai_link[1].cpus->of_node = asrc_np; priv->dai_link[1].platforms->of_node = asrc_np; for_each_link_codecs((&(priv->dai_link[2])), codec_idx, codec_comp) { @@ -998,6 +1106,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } priv->dai_link[2].cpus->of_node = cpu_np; priv->dai_link[2].dai_fmt = priv->dai_fmt; + priv->dai_link[2].ignore_pmdown_time = 1; priv->card.num_links = 3; ret = of_property_read_u32(asrc_np, "fsl,asrc-rate", diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 40a3b7432174..f819f33ec46b 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -117,6 +117,9 @@ static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol, unsigned int *item = ucontrol->value.enumerated.item; unsigned int reg_val, val, mix_clk; + if (item[0] >= e->items) + return -EINVAL; + /* Get current state */ reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR); mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK) @@ -157,6 +160,9 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol, unsigned int reg_val, val, mask = 0, ctr = 0; int ret; + if (item[0] >= e->items) + return -EINVAL; + /* Get current state */ reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR); diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 2e887f1f1f36..60ac8eabab9d 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -74,6 +74,7 @@ struct fsl_micfil { int irq[MICFIL_IRQ_LINES]; enum quality quality; int dc_remover; + int dc_out_remover; int vad_init_mode; int vad_enabled; int vad_detected; @@ -347,6 +348,11 @@ static const char * const micfil_dc_remover_texts[] = { "Cut-off @152Hz", "Bypass", }; +static const char * const micfil_dc_out_remover_texts[] = { + "Cut-off @20Hz", "Cut-off @13.3Hz", + "Cut-off @40Hz", "Bypass", +}; + static const struct soc_enum hwvad_enable_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_enable), micfil_hwvad_enable); @@ -360,6 +366,9 @@ static const struct soc_enum hwvad_hpf_enum = static const struct soc_enum fsl_micfil_dc_remover_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_dc_remover_texts), micfil_dc_remover_texts); +static const struct soc_enum fsl_micfil_dc_out_remover_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_dc_out_remover_texts), + micfil_dc_out_remover_texts); static int micfil_put_dc_remover_state(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -405,6 +414,50 @@ static int micfil_get_dc_remover_state(struct snd_kcontrol *kcontrol, return 0; } +static int micfil_put_dc_out_remover_state(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp); + unsigned int *item = ucontrol->value.enumerated.item; + int val = snd_soc_enum_item_to_val(e, item[0]); + int i = 0, ret = 0; + u32 reg_val = 0; + + if (val < 0 || val > 3) + return -EINVAL; + + ret = pm_runtime_resume_and_get(comp->dev); + if (ret) + return ret; + + micfil->dc_out_remover = val; + + /* Calculate total value for all channels */ + for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++) + reg_val |= val << MICFIL_DC_CHX_SHIFT(i); + + /* Update DC Remover mode for all channels */ + ret = snd_soc_component_update_bits(comp, REG_MICFIL_DC_OUT_CTRL, + MICFIL_DC_CTRL_CONFIG, reg_val); + + pm_runtime_put_autosuspend(comp->dev); + + return ret; +} + +static int micfil_get_dc_out_remover_state(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp); + + ucontrol->value.enumerated.item[0] = micfil->dc_out_remover; + + return 0; +} + static int hwvad_put_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -525,6 +578,11 @@ static const struct snd_kcontrol_new fsl_micfil_volume_sx_controls[] = { MICFIL_OUTGAIN_CHX_SHIFT(7), 0x8, 0xF, gain_tlv), }; +static const struct snd_kcontrol_new fsl_micfil_dc_out_controls[] = { + SOC_ENUM_EXT("MICFIL DC Out Remover Control", fsl_micfil_dc_out_remover_enum, + micfil_get_dc_out_remover_state, micfil_put_dc_out_remover_state), +}; + static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = { SOC_ENUM_EXT("MICFIL Quality Select", fsl_micfil_quality_enum, @@ -1047,6 +1105,19 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai) } micfil->dc_remover = MICFIL_DC_BYPASS; + if (micfil->soc->use_verid) { + val = 0; + for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++) + val |= MICFIL_DC_BYPASS << MICFIL_DC_CHX_SHIFT(i); + ret = regmap_update_bits(micfil->regmap, REG_MICFIL_DC_OUT_CTRL, + MICFIL_DC_CTRL_CONFIG, val); + if (ret) { + dev_err(dev, "failed to set DC OUT Remover mode bits\n"); + return ret; + } + micfil->dc_out_remover = MICFIL_DC_BYPASS; + } + snd_soc_dai_init_dma_data(cpu_dai, NULL, &micfil->dma_params_rx); @@ -1071,6 +1142,10 @@ static int fsl_micfil_component_probe(struct snd_soc_component *component) snd_soc_add_component_controls(component, fsl_micfil_range_controls, ARRAY_SIZE(fsl_micfil_range_controls)); + if (micfil->soc->use_verid) + snd_soc_add_component_controls(component, fsl_micfil_dc_out_controls, + ARRAY_SIZE(fsl_micfil_dc_out_controls)); + return 0; } @@ -1117,6 +1192,7 @@ static const struct reg_default fsl_micfil_reg_defaults[] = { {REG_MICFIL_DATACH6, 0x00000000}, {REG_MICFIL_DATACH7, 0x00000000}, {REG_MICFIL_DC_CTRL, 0x00000000}, + {REG_MICFIL_DC_OUT_CTRL, 0x00000000}, {REG_MICFIL_OUT_CTRL, 0x00000000}, {REG_MICFIL_OUT_STAT, 0x00000000}, {REG_MICFIL_VAD0_CTRL1, 0x00000000}, @@ -1143,6 +1219,7 @@ static const struct reg_default fsl_micfil_reg_defaults_v2[] = { {REG_MICFIL_DATACH6 - 0x4, 0x00000000}, {REG_MICFIL_DATACH7 - 0x4, 0x00000000}, {REG_MICFIL_DC_CTRL, 0x00000000}, + {REG_MICFIL_DC_OUT_CTRL, 0x00000000}, {REG_MICFIL_OUT_CTRL, 0x00000000}, {REG_MICFIL_OUT_STAT, 0x00000000}, {REG_MICFIL_VAD0_CTRL1, 0x00000000}, @@ -1179,6 +1256,7 @@ static bool fsl_micfil_readable_reg(struct device *dev, unsigned int reg) case REG_MICFIL_VAD0_NDATA: case REG_MICFIL_VAD0_ZCD: return true; + case REG_MICFIL_DC_OUT_CTRL: case REG_MICFIL_FSYNC_CTRL: case REG_MICFIL_VERID: case REG_MICFIL_PARAM: @@ -1210,6 +1288,7 @@ static bool fsl_micfil_writeable_reg(struct device *dev, unsigned int reg) case REG_MICFIL_VAD0_NCONFIG: case REG_MICFIL_VAD0_ZCD: return true; + case REG_MICFIL_DC_OUT_CTRL: case REG_MICFIL_FSYNC_CTRL: if (micfil->soc->use_verid) return true; diff --git a/sound/soc/fsl/fsl_micfil.h b/sound/soc/fsl/fsl_micfil.h index fdfe4e7125bc..e271c6073f42 100644 --- a/sound/soc/fsl/fsl_micfil.h +++ b/sound/soc/fsl/fsl_micfil.h @@ -22,6 +22,7 @@ #define REG_MICFIL_DATACH6 0x3C #define REG_MICFIL_DATACH7 0x40 #define REG_MICFIL_DC_CTRL 0x64 +#define REG_MICFIL_DC_OUT_CTRL 0x68 #define REG_MICFIL_OUT_CTRL 0x74 #define REG_MICFIL_OUT_STAT 0x7C #define REG_MICFIL_FSYNC_CTRL 0x80 diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 76e014dfb6d7..d0f644573f49 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -905,7 +905,6 @@ static int qmc_audio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct qmc_audio *qmc_audio; - struct device_node *child; unsigned int i; int ret; @@ -931,14 +930,12 @@ static int qmc_audio_probe(struct platform_device *pdev) } i = 0; - for_each_available_child_of_node(np, child) { + for_each_available_child_of_node_scoped(np, child) { ret = qmc_audio_dai_parse(qmc_audio, child, qmc_audio->dais + i, qmc_audio->dai_drivers + i); - if (ret) { - of_node_put(child); + if (ret) return ret; - } i++; } diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 78e953cd3e9f..9661602b53c5 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -355,6 +355,9 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, unsigned int ofs = sai->soc_data->reg_offset; u32 val_cr2 = 0, val_cr4 = 0; + if (sai->is_bit_clock_swap) + val_cr2 |= FSL_SAI_CR2_BCS; + if (!sai->is_lsb_first) val_cr4 |= FSL_SAI_CR4_MF; @@ -453,7 +456,8 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, } regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs), - FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2); + FSL_SAI_CR2_BCS | FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, + val_cr2); regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs), FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4); @@ -1532,6 +1536,7 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->soc_data = of_device_get_match_data(dev); sai->is_lsb_first = of_property_read_bool(np, "lsb-first"); + sai->is_bit_clock_swap = of_property_read_bool(np, "fsl,sai-bit-clock-swap"); base = devm_platform_get_and_ioremap_resource(pdev, 0, &sai->res); if (IS_ERR(base)) diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index af967833b6ed..6d84e5ff2258 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -118,6 +118,7 @@ /* SAI Transmit and Receive Configuration 2 Register */ #define FSL_SAI_CR2_SYNC BIT(30) +#define FSL_SAI_CR2_BCS BIT(29) #define FSL_SAI_CR2_BCI BIT(28) #define FSL_SAI_CR2_MSEL_MASK (0x3 << 26) #define FSL_SAI_CR2_MSEL_BUS 0 @@ -301,6 +302,7 @@ struct fsl_sai { struct fsl_sai_dl_cfg *dl_cfg; unsigned int dl_cfg_cnt; bool mclk_direction_output; + bool is_bit_clock_swap; unsigned int mclk_id[2]; unsigned int mclk_streams; diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index 031e5272215d..2a4813c6cda9 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -632,6 +632,7 @@ static const struct snd_soc_component_driver imx_rpmsg_soc_component = { .pointer = imx_rpmsg_pcm_pointer, .ack = imx_rpmsg_pcm_ack, .prepare = imx_rpmsg_pcm_prepare, + .debugfs_prefix = "rpmsg", }; static void imx_rpmsg_pcm_work(struct work_struct *work) @@ -689,7 +690,6 @@ static void imx_rpmsg_pcm_work(struct work_struct *work) static int imx_rpmsg_pcm_probe(struct platform_device *pdev) { - struct snd_soc_component *component; struct rpmsg_info *info; int ret, i; @@ -741,16 +741,6 @@ static int imx_rpmsg_pcm_probe(struct platform_device *pdev) if (ret) goto fail; - component = snd_soc_lookup_component(&pdev->dev, NULL); - if (!component) { - ret = -EINVAL; - goto fail; - } - -#ifdef CONFIG_DEBUG_FS - component->debugfs_prefix = "rpmsg"; -#endif - return 0; fail: diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c index 40e0043cfe15..5f1af258caf2 100644 --- a/sound/soc/fsl/imx-rpmsg.c +++ b/sound/soc/fsl/imx-rpmsg.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "imx-pcm-rpmsg.h" struct imx_rpmsg { @@ -19,6 +20,7 @@ struct imx_rpmsg { struct snd_soc_card card; unsigned long sysclk; bool lpa; + struct simple_util_jack hp_jack; }; static struct dev_pm_ops lpa_pm; @@ -86,8 +88,16 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card) struct device *dev = card->dev; int ret; + if (of_property_present(card->dev->of_node, "hp-det-gpios")) { + ret = simple_util_init_jack(card, &data->hp_jack, + 1, NULL, "Headphone Jack"); + if (ret) { + dev_err(dev, "failed to init hp jack\n"); + return ret; + } + } + if (data->lpa) { - struct snd_soc_component *codec_comp; struct device_node *codec_np; struct device_driver *codec_drv; struct device *codec_dev = NULL; @@ -107,22 +117,6 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card) } } if (codec_dev) { - codec_comp = snd_soc_lookup_component_nolocked(codec_dev, NULL); - if (codec_comp) { - int i, num_widgets; - const char *widgets; - struct snd_soc_dapm_context *dapm; - - num_widgets = of_property_count_strings(data->card.dev->of_node, - "ignore-suspend-widgets"); - for (i = 0; i < num_widgets; i++) { - of_property_read_string_index(data->card.dev->of_node, - "ignore-suspend-widgets", - i, &widgets); - dapm = snd_soc_component_to_dapm(codec_comp); - snd_soc_dapm_ignore_suspend(dapm, widgets); - } - } codec_drv = codec_dev->driver; if (codec_drv->pm) { memcpy(&lpa_pm, codec_drv->pm, sizeof(lpa_pm)); @@ -256,6 +250,7 @@ static int imx_rpmsg_probe(struct platform_device *pdev) data->card.dapm_widgets = imx_rpmsg_dapm_widgets; data->card.num_dapm_widgets = ARRAY_SIZE(imx_rpmsg_dapm_widgets); data->card.late_probe = imx_rpmsg_late_probe; + data->card.driver_name = "imx-audio-rpmsg"; /* * Inoder to use common api to get card name and audio routing. * Use parent of_node for this device, revert it after finishing using @@ -274,6 +269,15 @@ static int imx_rpmsg_probe(struct platform_device *pdev) } } + if (data->lpa && of_property_present(np, "ignore-suspend-widgets")) { + ret = snd_soc_of_parse_ignore_suspend_widgets(&data->card, + "ignore-suspend-widgets"); + if (ret) { + dev_err(&pdev->dev, "failed to parse ignore-suspend-widgets: %d\n", ret); + goto fail; + } + } + platform_set_drvdata(pdev, &data->card); snd_soc_card_set_drvdata(&data->card, data); ret = devm_snd_soc_register_card(&pdev->dev, &data->card); diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 0202ed0ee78e..6894bb936cfd 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -778,6 +778,18 @@ static void graph_link_init(struct simple_util_priv *priv, graph_parse_daifmt(ports_cpu, &daifmt); graph_parse_daifmt(ports_codec, &daifmt); graph_parse_daifmt(lnk, &daifmt); + if (daifmt) { + struct device *dev = simple_priv_to_dev(priv); + + /* + * Recommend to use Auto Select by using .auto_selectable_formats. + * linux/sound/soc/renesas/rcar/core.c can be good sample for it. + * + * One note is that Audio Graph Card2 still keeps compatible to set + * DAI format via DT. + */ + dev_warn_once(dev, "use .auto_selectable_formats on each corresponding CPU/Codec driver"); + } graph_util_parse_link_direction(lnk, &playback_only, &capture_only); graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index b24ba1330896..b4957e025211 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -13,9 +13,9 @@ #include #include #include -#include -#include +#include #include +#include #define DPCM_SELECTABLE 1 @@ -708,7 +708,6 @@ static int simple_probe(struct platform_device *pdev) { struct simple_util_priv *priv; struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; struct snd_soc_card *card; int ret; @@ -740,58 +739,10 @@ static int simple_probe(struct platform_device *pdev) if (ret < 0) goto end; - if (np && of_device_is_available(np)) { - - ret = simple_parse_of(priv, li); - if (ret < 0) { - dev_err_probe(dev, ret, "parse error\n"); - goto err; - } - - } else { - struct simple_util_info *cinfo; - struct snd_soc_dai_link_component *cpus; - struct snd_soc_dai_link_component *codecs; - struct snd_soc_dai_link_component *platform; - struct snd_soc_dai_link *dai_link = priv->dai_link; - struct simple_dai_props *dai_props = priv->dai_props; - - ret = -EINVAL; - - cinfo = dev->platform_data; - if (!cinfo) { - dev_err(dev, "no info for asoc-simple-card\n"); - goto err; - } - - if (!cinfo->name || - !cinfo->codec_dai.name || - !cinfo->codec || - !cinfo->platform || - !cinfo->cpu_dai.name) { - dev_err(dev, "insufficient simple_util_info settings\n"); - goto err; - } - - cpus = dai_link->cpus; - cpus->dai_name = cinfo->cpu_dai.name; - - codecs = dai_link->codecs; - codecs->name = cinfo->codec; - codecs->dai_name = cinfo->codec_dai.name; - - platform = dai_link->platforms; - platform->name = cinfo->platform; - - card->name = (cinfo->card) ? cinfo->card : cinfo->name; - dai_link->name = cinfo->name; - dai_link->stream_name = cinfo->name; - dai_link->dai_fmt = cinfo->daifmt; - dai_link->init = simple_util_dai_init; - memcpy(dai_props->cpu_dai, &cinfo->cpu_dai, - sizeof(*dai_props->cpu_dai)); - memcpy(dai_props->codec_dai, &cinfo->codec_dai, - sizeof(*dai_props->codec_dai)); + ret = simple_parse_of(priv, li); + if (ret < 0) { + dev_err_probe(dev, ret, "parse error\n"); + goto err; } snd_soc_card_set_drvdata(card, priv); diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index fc40d024152e..6f9f498c4c5c 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -191,13 +191,6 @@ static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct } static const u64 test_dai_formats = - /* - * Select below from Sound Card, not auto - * SND_SOC_POSSIBLE_DAIFMT_BP_FP - * SND_SOC_POSSIBLE_DAIFMT_BC_FP - * SND_SOC_POSSIBLE_DAIFMT_BP_FC - * SND_SOC_POSSIBLE_DAIFMT_BC_FC - */ SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | SND_SOC_POSSIBLE_DAIFMT_LEFT_J | diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index 250ae3781d14..33b1dafb2540 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c @@ -185,7 +185,7 @@ static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on) struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); u32 val; - spin_lock(&i2s->lock); + guard(spinlock)(&i2s->lock); if (on) { /* enable S2 TX */ val = hi6210_read_reg(i2s, HII2S_I2S_CFG); @@ -197,7 +197,6 @@ static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on) val &= ~HII2S_I2S_CFG__S2_IF_TX_EN; hi6210_write_reg(i2s, HII2S_I2S_CFG, val); } - spin_unlock(&i2s->lock); } static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on) @@ -205,7 +204,7 @@ static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on) struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev); u32 val; - spin_lock(&i2s->lock); + guard(spinlock)(&i2s->lock); if (on) { val = hi6210_read_reg(i2s, HII2S_I2S_CFG); val |= HII2S_I2S_CFG__S2_IF_RX_EN; @@ -215,7 +214,6 @@ static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on) val &= ~HII2S_I2S_CFG__S2_IF_RX_EN; hi6210_write_reg(i2s, HII2S_I2S_CFG, val); } - spin_unlock(&i2s->lock); } static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c index 82295e2508fa..b630644f20cc 100644 --- a/sound/soc/img/img-spdif-in.c +++ b/sound/soc/img/img-spdif-in.c @@ -179,7 +179,7 @@ static int img_spdif_in_do_clkgen_single(struct img_spdif_in *spdif, unsigned int rate) { unsigned int nom, hld; - unsigned long flags, clk_rate; + unsigned long clk_rate; int ret = 0; u32 reg; @@ -196,19 +196,15 @@ static int img_spdif_in_do_clkgen_single(struct img_spdif_in *spdif, reg |= (hld << IMG_SPDIF_IN_CLKGEN_HLD_SHIFT) & IMG_SPDIF_IN_CLKGEN_HLD_MASK; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); - if (spdif->active) { - spin_unlock_irqrestore(&spdif->lock, flags); + if (spdif->active) return -EBUSY; - } img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CLKGEN); spdif->single_freq = rate; - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -216,7 +212,7 @@ static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif, unsigned int multi_freqs[]) { unsigned int nom, hld, rate, max_rate = 0; - unsigned long flags, clk_rate; + unsigned long clk_rate; int i, ret = 0; u32 reg, trk_reg, temp_regs[IMG_SPDIF_IN_NUM_ACLKGEN]; @@ -242,12 +238,10 @@ static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif, temp_regs[i] = reg; } - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); - if (spdif->active) { - spin_unlock_irqrestore(&spdif->lock, flags); + if (spdif->active) return -EBUSY; - } trk_reg = spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT; @@ -262,8 +256,6 @@ static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif, spdif->multi_freqs[2] = multi_freqs[2]; spdif->multi_freqs[3] = multi_freqs[3]; - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -323,9 +315,8 @@ static int img_spdif_in_get_multi_freq(struct snd_kcontrol *kcontrol, { struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); if (spdif->multi_freq) { ucontrol->value.integer.value[0] = spdif->multi_freqs[0]; ucontrol->value.integer.value[1] = spdif->multi_freqs[1]; @@ -337,7 +328,6 @@ static int img_spdif_in_get_multi_freq(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[2] = 0; ucontrol->value.integer.value[3] = 0; } - spin_unlock_irqrestore(&spdif->lock, flags); return 0; } @@ -349,7 +339,6 @@ static int img_spdif_in_set_multi_freq(struct snd_kcontrol *kcontrol, struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai); unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN]; bool multi_freq; - unsigned long flags; if ((ucontrol->value.integer.value[0] == 0) && (ucontrol->value.integer.value[1] == 0) && @@ -367,17 +356,13 @@ static int img_spdif_in_set_multi_freq(struct snd_kcontrol *kcontrol, if (multi_freq) return img_spdif_in_do_clkgen_multi(spdif, multi_freqs); - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); - if (spdif->active) { - spin_unlock_irqrestore(&spdif->lock, flags); + if (spdif->active) return -EBUSY; - } spdif->multi_freq = false; - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -399,9 +384,8 @@ static int img_spdif_in_get_lock_freq(struct snd_kcontrol *kcontrol, struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai); u32 reg; int i; - unsigned long flags; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_STATUS); if (reg & IMG_SPDIF_IN_STATUS_LOCK_MASK) { @@ -416,8 +400,6 @@ static int img_spdif_in_get_lock_freq(struct snd_kcontrol *kcontrol, uc->value.integer.value[0] = 0; } - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -448,16 +430,13 @@ static int img_spdif_in_set_trk(struct snd_kcontrol *kcontrol, { struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; int i; u32 reg; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); - if (spdif->active) { - spin_unlock_irqrestore(&spdif->lock, flags); + if (spdif->active) return -EBUSY; - } spdif->trk = ucontrol->value.integer.value[0]; @@ -474,8 +453,6 @@ static int img_spdif_in_set_trk(struct snd_kcontrol *kcontrol, img_spdif_in_aclkgen_writel(spdif, i); } - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -506,15 +483,12 @@ static int img_spdif_in_set_lock_acquire(struct snd_kcontrol *kcontrol, { struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; u32 reg; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); - if (spdif->active) { - spin_unlock_irqrestore(&spdif->lock, flags); + if (spdif->active) return -EBUSY; - } spdif->lock_acquire = ucontrol->value.integer.value[0]; @@ -524,8 +498,6 @@ static int img_spdif_in_set_lock_acquire(struct snd_kcontrol *kcontrol, IMG_SPDIF_IN_CTL_LOCKHI_MASK; img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL); - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -545,15 +517,12 @@ static int img_spdif_in_set_lock_release(struct snd_kcontrol *kcontrol, { struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; u32 reg; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); - if (spdif->active) { - spin_unlock_irqrestore(&spdif->lock, flags); + if (spdif->active) return -EBUSY; - } spdif->lock_release = ucontrol->value.integer.value[0]; @@ -563,8 +532,6 @@ static int img_spdif_in_set_lock_release(struct snd_kcontrol *kcontrol, IMG_SPDIF_IN_CTL_LOCKLO_MASK; img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL); - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -625,12 +592,11 @@ static struct snd_kcontrol_new img_spdif_in_controls[] = { static int img_spdif_in_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - unsigned long flags; struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai); int ret = 0; u32 reg; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -657,8 +623,6 @@ static int img_spdif_in_trigger(struct snd_pcm_substream *substream, int cmd, ret = -EINVAL; } - spin_unlock_irqrestore(&spdif->lock, flags); - return ret; } diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c index 52f696219ef4..39a37e4830d8 100644 --- a/sound/soc/img/img-spdif-out.c +++ b/sound/soc/img/img-spdif-out.c @@ -135,9 +135,8 @@ static int img_spdif_out_get_status(struct snd_kcontrol *kcontrol, struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(cpu_dai); u32 reg; - unsigned long flags; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); reg = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CSL); ucontrol->value.iec958.status[0] = reg & 0xff; @@ -150,8 +149,6 @@ static int img_spdif_out_get_status(struct snd_kcontrol *kcontrol, (reg & IMG_SPDIF_OUT_CSH_UV_CSH_MASK) >> IMG_SPDIF_OUT_CSH_UV_CSH_SHIFT; - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -161,14 +158,13 @@ static int img_spdif_out_set_status(struct snd_kcontrol *kcontrol, struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol); struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(cpu_dai); u32 reg; - unsigned long flags; reg = ((u32)ucontrol->value.iec958.status[3] << 24); reg |= ((u32)ucontrol->value.iec958.status[2] << 16); reg |= ((u32)ucontrol->value.iec958.status[1] << 8); reg |= (u32)ucontrol->value.iec958.status[0]; - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CSL); @@ -178,8 +174,6 @@ static int img_spdif_out_set_status(struct snd_kcontrol *kcontrol, IMG_SPDIF_OUT_CSH_UV_CSH_SHIFT; img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CSH_UV); - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; } @@ -205,7 +199,6 @@ static int img_spdif_out_trigger(struct snd_pcm_substream *substream, int cmd, { struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(dai); u32 reg; - unsigned long flags; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -218,9 +211,8 @@ static int img_spdif_out_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(&spdif->lock, flags); - img_spdif_out_reset(spdif); - spin_unlock_irqrestore(&spdif->lock, flags); + scoped_guard(spinlock_irqsave, &spdif->lock) + img_spdif_out_reset(spdif); break; default: return -EINVAL; diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index d53af8f7e55b..cddbd2aa424e 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -532,6 +532,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select MFD_CS42L43_SDW select SND_SOC_CS35L56_SPI select SND_SOC_CS35L56_SDW + select SND_SOC_ES9356 select SND_SOC_DMIC select SND_SOC_INTEL_HDA_DSP_COMMON imply SND_SOC_SDW_MOCKUP diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index fd4cefd298d2..eddb179eaa21 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -63,13 +63,11 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, } if (SND_SOC_DAPM_EVENT_ON(event)) { - if (ctx->mclk) { - ret = clk_prepare_enable(ctx->mclk); - if (ret < 0) { - dev_err(card->dev, - "could not configure MCLK state: %d\n", ret); - return ret; - } + ret = clk_prepare_enable(ctx->mclk); + if (ret < 0) { + dev_err(card->dev, + "could not configure MCLK state: %d\n", ret); + return ret; } /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ @@ -77,8 +75,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, CHT_PLAT_CLK_3_HZ, 48000 * 512); if (ret < 0) { dev_err(card->dev, "can't set codec pll: %d\n", ret); - if (ctx->mclk) - clk_disable_unprepare(ctx->mclk); + clk_disable_unprepare(ctx->mclk); return ret; } @@ -87,8 +84,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, 48000 * 512, SND_SOC_CLOCK_IN); if (ret < 0) { dev_err(card->dev, "can't set codec sysclk: %d\n", ret); - if (ctx->mclk) - clk_disable_unprepare(ctx->mclk); + clk_disable_unprepare(ctx->mclk); return ret; } } else { @@ -104,8 +100,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w, return ret; } - if (ctx->mclk) - clk_disable_unprepare(ctx->mclk); + clk_disable_unprepare(ctx->mclk); } return 0; } @@ -244,28 +239,25 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); rt5670_set_jack_detect(component, &ctx->headset); - if (ctx->mclk) { - /* - * The firmware might enable the clock at - * boot (this information may or may not - * be reflected in the enable clock register). - * To change the rate we must disable the clock - * first to cover these cases. Due to common - * clock framework restrictions that do not allow - * to disable a clock that has not been enabled, - * we need to enable the clock first. - */ - ret = clk_prepare_enable(ctx->mclk); - if (!ret) - clk_disable_unprepare(ctx->mclk); - ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ); + /* + * The firmware might enable the clock at boot (this information + * may or may not be reflected in the enable clock register). + * To change the rate we must disable the clock first to cover + * these cases. Due to Common Clock Framework restrictions that + * do not allow to disable a clock that has not been enabled, we + * need to enable the clock first. + */ + ret = clk_prepare_enable(ctx->mclk); + if (!ret) + clk_disable_unprepare(ctx->mclk); - if (ret) { - dev_err(runtime->dev, "unable to set MCLK rate\n"); - return ret; - } + ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ); + if (ret) { + dev_err(runtime->dev, "unable to set MCLK rate\n"); + return ret; } + return 0; } @@ -454,12 +446,13 @@ static int snd_cht_mc_probe(struct platform_device *pdev) struct cht_mc_private *drv; struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; const char *platform_name; + struct device *dev = &pdev->dev; struct acpi_device *adev; bool sof_parent; int dai_index = 0; int i; - drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); + drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) return -ENOMEM; @@ -481,7 +474,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) "i2c-%s", acpi_dev_name(adev)); cht_dailink[dai_index].codecs->name = drv->codec_name; } else { - dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id); + dev_err(dev, "Error cannot find '%s' dev\n", mach->id); return -ENOENT; } @@ -494,7 +487,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) } /* override platform name, if required */ - snd_soc_card_cht.dev = &pdev->dev; + snd_soc_card_cht.dev = dev; platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht, @@ -504,16 +497,16 @@ static int snd_cht_mc_probe(struct platform_device *pdev) snd_soc_card_cht.components = rt5670_components(); - drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); + drv->mclk = devm_clk_get(dev, "pmc_plt_clk_3"); if (IS_ERR(drv->mclk)) { - dev_err(&pdev->dev, + dev_err(dev, "Failed to get MCLK from pmc_plt_clk_3: %ld\n", PTR_ERR(drv->mclk)); return PTR_ERR(drv->mclk); } snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); - sof_parent = snd_soc_acpi_sof_parent(&pdev->dev); + sof_parent = snd_soc_acpi_sof_parent(dev); /* set card and driver name */ if (sof_parent) { @@ -529,9 +522,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev) pdev->dev.driver->pm = &snd_soc_pm_ops; /* register the soc card */ - ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht); + ret_val = devm_snd_soc_register_card(dev, &snd_soc_card_cht); if (ret_val) { - dev_err(&pdev->dev, + dev_err(dev, "snd_soc_register_card failed %d\n", ret_val); return ret_val; } diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index ce7718338e6b..d43daf9b025d 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -909,10 +909,16 @@ static int create_sdw_dailink(struct snd_soc_card *card, } } + /* + * The dai_type is used to select function topologies. Since the topology stream name + * and DAI link name use partial matching, unconditionally appending the dai_type provides + * necessary selection metadata without breaking existing topologies. Although + * ctx->append_dai_type is not checked here, we overwrite it to ensure consistency in case + * it is referenced elsewhere. + */ + ctx->append_dai_type = true; for_each_pcm_streams(stream) { static const char * const sdw_stream_name[] = { - "SDW%d-Playback", - "SDW%d-Capture", "SDW%d-Playback-%s", "SDW%d-Capture-%s", }; @@ -940,15 +946,10 @@ static int create_sdw_dailink(struct snd_soc_card *card, } /* create stream name according to first link id */ - if (ctx->append_dai_type) - name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream + 2], - ffs(sof_end->link_mask) - 1, - type_strings[sof_end->dai_info->dai_type]); - else - name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream], - ffs(sof_end->link_mask) - 1); + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], + ffs(sof_end->link_mask) - 1, + type_strings[sof_end->dai_info->dai_type]); if (!name) return -ENOMEM; diff --git a/sound/soc/intel/catpt/Makefile b/sound/soc/intel/catpt/Makefile index e8316e33b820..8005fc677f28 100644 --- a/sound/soc/intel/catpt/Makefile +++ b/sound/soc/intel/catpt/Makefile @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 snd-soc-catpt-y := device.o dsp.o loader.o ipc.o messages.o pcm.o sysfs.o +snd-soc-catpt-y += trace.o # tell define_trace.h where to find the trace header -CFLAGS_device.o := -I$(src) +CFLAGS_trace.o := -I$(src) obj-$(CONFIG_SND_SOC_INTEL_CATPT) += snd-soc-catpt.o diff --git a/sound/soc/intel/catpt/core.h b/sound/soc/intel/catpt/core.h index 7e479ef89ad0..3881164422b8 100644 --- a/sound/soc/intel/catpt/core.h +++ b/sound/soc/intel/catpt/core.h @@ -17,7 +17,6 @@ struct catpt_dev; extern const struct attribute_group *catpt_attr_groups[]; -void catpt_sram_init(struct resource *sram, u32 start, u32 size); void catpt_sram_free(struct resource *sram); struct resource * catpt_request_region(struct resource *root, resource_size_t size); diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c index ca4fd18b6a6e..b176aebea9d5 100644 --- a/sound/soc/intel/catpt/device.c +++ b/sound/soc/intel/catpt/device.c @@ -25,9 +25,6 @@ #include "core.h" #include "registers.h" -#define CREATE_TRACE_POINTS -#include "trace.h" - static int catpt_do_suspend(struct device *dev) { struct catpt_dev *cdev = dev_get_drvdata(dev); @@ -157,7 +154,7 @@ static int catpt_register_board(struct catpt_dev *cdev) PLATFORM_DEVID_NONE, (const void *)mach, sizeof(*mach)); if (IS_ERR(board)) { - dev_err(cdev->dev, "board register failed\n"); + dev_err(cdev->dev, "register board failed: %ld\n", PTR_ERR(board)); return PTR_ERR(board); } @@ -236,12 +233,9 @@ static void catpt_dev_init(struct catpt_dev *cdev, struct device *dev, cdev->devfmt[CATPT_SSP_IFACE_0].iface = UINT_MAX; cdev->devfmt[CATPT_SSP_IFACE_1].iface = UINT_MAX; + resource_set_range(&cdev->dram, spec->host_dram_offset, catpt_dram_size(cdev)); + resource_set_range(&cdev->iram, spec->host_iram_offset, catpt_iram_size(cdev)); catpt_ipc_init(&cdev->ipc, dev); - - catpt_sram_init(&cdev->dram, spec->host_dram_offset, - catpt_dram_size(cdev)); - catpt_sram_init(&cdev->iram, spec->host_iram_offset, - catpt_iram_size(cdev)); } static int catpt_acpi_probe(struct platform_device *pdev) @@ -290,7 +284,7 @@ static int catpt_acpi_probe(struct platform_device *pdev) if (ret) return ret; - cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev), + cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, resource_size(&cdev->dram), &cdev->dxbuf_paddr, GFP_KERNEL); if (!cdev->dxbuf_vaddr) return -ENOMEM; diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c index 677f348909c8..960344991b11 100644 --- a/sound/soc/intel/catpt/dsp.c +++ b/sound/soc/intel/catpt/dsp.c @@ -5,6 +5,7 @@ // Author: Cezary Rojewski // +#include #include #include #include @@ -43,7 +44,6 @@ struct dma_chan *catpt_dma_request_config_chan(struct catpt_dev *cdev) } memset(&config, 0, sizeof(config)); - config.direction = DMA_MEM_TO_DEV; config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; config.src_maxburst = 16; @@ -121,7 +121,7 @@ int catpt_dmac_probe(struct catpt_dev *cdev) if (!dmac) return -ENOMEM; - dmac->regs = cdev->lpe_ba + cdev->spec->host_dma_offset[CATPT_DMA_DEVID]; + dmac->regs = catpt_dma_addr(cdev, CATPT_DMA_DEVID); dmac->dev = cdev->dev; dmac->irq = cdev->irq; @@ -256,17 +256,15 @@ static int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti) u32 mask, reg, val; int ret; - mutex_lock(&cdev->clk_mutex); + guard(mutex)(&cdev->clk_mutex); val = lp ? CATPT_CS_LPCS : 0; reg = catpt_readl_shim(cdev, CS1) & CATPT_CS_LPCS; dev_dbg(cdev->dev, "LPCS [0x%08lx] 0x%08x -> 0x%08x", CATPT_CS_LPCS, reg, val); - if (reg == val) { - mutex_unlock(&cdev->clk_mutex); + if (reg == val) return 0; - } if (waiti) { /* wait for DSP to signal WAIT state */ @@ -276,10 +274,8 @@ static int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti) if (ret) { dev_warn(cdev->dev, "await WAITI timeout\n"); /* no signal - only high clock selection allowed */ - if (lp) { - mutex_unlock(&cdev->clk_mutex); + if (lp) return 0; - } } } @@ -303,7 +299,6 @@ static int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti) /* update PLL accordingly */ cdev->spec->pll_shutdown(cdev, lp); - mutex_unlock(&cdev->clk_mutex); return 0; } @@ -502,7 +497,7 @@ int catpt_coredump(struct catpt_dev *cdev) hdr->size = resource_size(&cdev->iram); pos += sizeof(*hdr); - memcpy_fromio(pos, cdev->lpe_ba + cdev->iram.start, hdr->size); + memcpy_fromio(pos, catpt_iram_addr(cdev), hdr->size); pos += hdr->size; hdr = (struct catpt_dump_section_hdr *)pos; @@ -512,7 +507,7 @@ int catpt_coredump(struct catpt_dev *cdev) hdr->size = resource_size(&cdev->dram); pos += sizeof(*hdr); - memcpy_fromio(pos, cdev->lpe_ba + cdev->dram.start, hdr->size); + memcpy_fromio(pos, catpt_dram_addr(cdev), hdr->size); pos += hdr->size; hdr = (struct catpt_dump_section_hdr *)pos; diff --git a/sound/soc/intel/catpt/ipc.c b/sound/soc/intel/catpt/ipc.c index 2e3b7a5cbb9b..8092944d6cb7 100644 --- a/sound/soc/intel/catpt/ipc.c +++ b/sound/soc/intel/catpt/ipc.c @@ -128,14 +128,9 @@ int catpt_dsp_send_msg_timeout(struct catpt_dev *cdev, struct catpt_ipc_msg request, struct catpt_ipc_msg *reply, int timeout, const char *name) { - struct catpt_ipc *ipc = &cdev->ipc; - int ret; + guard(mutex)(&cdev->ipc.mutex); - mutex_lock(&ipc->mutex); - ret = catpt_dsp_do_send_msg(cdev, request, reply, timeout, name); - mutex_unlock(&ipc->mutex); - - return ret; + return catpt_dsp_do_send_msg(cdev, request, reply, timeout, name); } int catpt_dsp_send_msg(struct catpt_dev *cdev, struct catpt_ipc_msg request, @@ -210,6 +205,7 @@ static void catpt_dsp_process_response(struct catpt_dev *cdev, u32 header) memcpy_fromio(&config, cdev->lpe_ba + off, sizeof(config)); trace_catpt_ipc_payload((u8 *)&config, sizeof(config)); + dev_dbg(cdev->dev, "FW READY 0x%08x\n", header); catpt_ipc_arm(ipc, &config); complete(&cdev->fw_ready); return; @@ -220,6 +216,13 @@ static void catpt_dsp_process_response(struct catpt_dev *cdev, u32 header) dev_err(cdev->dev, "ADSP device coredump received\n"); ipc->ready = false; catpt_coredump(cdev); + + if (catpt_readl_dram(cdev, COREDUMP) == CATPT_COREDUMP_REQUEST) { + dev_dbg(cdev->dev, "releasing firmware from the coredump state\n"); + catpt_writel_dram(cdev, COREDUMP, CATPT_COREDUMP_RELEASE); + } + + complete(&cdev->fw_ready); /* TODO: attempt recovery */ break; diff --git a/sound/soc/intel/catpt/loader.c b/sound/soc/intel/catpt/loader.c index 432cb1f0ab4e..c577f2e17ddf 100644 --- a/sound/soc/intel/catpt/loader.c +++ b/sound/soc/intel/catpt/loader.c @@ -7,6 +7,7 @@ #include #include +#include #include #include "core.h" #include "registers.h" @@ -50,12 +51,6 @@ struct catpt_fw_block_hdr { u32 rsvd; } __packed; -void catpt_sram_init(struct resource *sram, u32 start, u32 size) -{ - sram->start = start; - sram->end = start + size - 1; -} - void catpt_sram_free(struct resource *sram) { struct resource *res, *save; @@ -624,6 +619,9 @@ int catpt_boot_firmware(struct catpt_dev *cdev, bool restore) if (!ret) { dev_err(cdev->dev, "firmware ready timeout\n"); return -ETIMEDOUT; + /* Wake up does not mean FW is ready, an exception could occur. */ + } else if (!cdev->ipc.ready) { + return -EREMOTEIO; } /* update sram pg & clock once done booting */ diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c index 7b2bab12c707..8fb0efb67eb1 100644 --- a/sound/soc/intel/catpt/pcm.c +++ b/sound/soc/intel/catpt/pcm.c @@ -99,19 +99,15 @@ catpt_get_stream_template(struct snd_pcm_substream *substream) } /* Caller responsible for holding ->stream_mutex. */ -struct catpt_stream_runtime * -catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id) +struct catpt_stream_runtime *catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id) { - struct catpt_stream_runtime *pos, *result = NULL; + struct catpt_stream_runtime *stream; - list_for_each_entry(pos, &cdev->stream_list, node) { - if (pos->info.stream_hw_id == stream_hw_id) { - result = pos; - break; - } - } + list_for_each_entry(stream, &cdev->stream_list, node) + if (stream->info.stream_hw_id == stream_hw_id) + return stream; - return result; + return NULL; } /* Caller responsible for holding ->stream_mutex. */ @@ -972,32 +968,7 @@ static int catpt_loopback_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_ele return 1; } -static int catpt_waves_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return 0; -} - -static int catpt_waves_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return 0; -} - -static int catpt_waves_param_get(struct snd_kcontrol *kcontrol, - unsigned int __user *bytes, - unsigned int size) -{ - return 0; -} - -static int catpt_waves_param_put(struct snd_kcontrol *kcontrol, - const unsigned int __user *bytes, - unsigned int size) -{ - return 0; -} - +static bool catpt_loopback_mute; static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1); #define CATPT_VOLUME_CTL(kname, pname) { \ @@ -1014,20 +985,12 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1); } static const struct snd_kcontrol_new component_kcontrols[] = { -/* Master volume (mixer stream) */ -CATPT_VOLUME_CTL("Master Playback Volume", MIXER), -/* Individual volume controls for offload and capture */ -CATPT_VOLUME_CTL("Media0 Playback Volume", OFFLOAD1), -CATPT_VOLUME_CTL("Media1 Playback Volume", OFFLOAD2), -CATPT_VOLUME_CTL("Mic Capture Volume", CAPTURE1), -SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&(bool[1]) {0}, - catpt_loopback_mute_get, catpt_loopback_mute_put), -/* Enable or disable WAVES module */ -SOC_SINGLE_BOOL_EXT("Waves Switch", 0, - catpt_waves_switch_get, catpt_waves_switch_put), -/* WAVES module parameter control */ -SND_SOC_BYTES_TLV("Waves Set Param", 128, - catpt_waves_param_get, catpt_waves_param_put), + CATPT_VOLUME_CTL("Master Playback Volume", MIXER), + CATPT_VOLUME_CTL("Media0 Playback Volume", OFFLOAD1), + CATPT_VOLUME_CTL("Media1 Playback Volume", OFFLOAD2), + CATPT_VOLUME_CTL("Mic Capture Volume", CAPTURE1), + SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&catpt_loopback_mute, + catpt_loopback_mute_get, catpt_loopback_mute_put), }; static const struct snd_soc_dapm_widget component_widgets[] = { diff --git a/sound/soc/intel/catpt/registers.h b/sound/soc/intel/catpt/registers.h index 6c1ad28c6d69..864802bd7809 100644 --- a/sound/soc/intel/catpt/registers.h +++ b/sound/soc/intel/catpt/registers.h @@ -124,6 +124,11 @@ #define CATPT_SSCR2_DEFAULT 0x0 #define CATPT_SSPSP2_DEFAULT 0x0 +/* Coredump register and its states */ +#define CATPT_DRAM_COREDUMP 0x1F4 +#define CATPT_COREDUMP_REQUEST UINT_MAX +#define CATPT_COREDUMP_RELEASE 0 + /* Physically the same block, access address differs between host and dsp */ #define CATPT_DSP_DRAM_OFFSET 0x400000 #define catpt_to_host_offset(offset) ((offset) & ~(CATPT_DSP_DRAM_OFFSET)) @@ -137,6 +142,10 @@ /* registry I/O helpers */ +#define catpt_dram_addr(cdev) \ + ((cdev)->lpe_ba + (cdev)->spec->host_dram_offset) +#define catpt_iram_addr(cdev) \ + ((cdev)->lpe_ba + (cdev)->spec->host_iram_offset) #define catpt_shim_addr(cdev) \ ((cdev)->lpe_ba + (cdev)->spec->host_shim_offset) #define catpt_dma_addr(cdev, dma) \ @@ -151,6 +160,11 @@ #define catpt_writel_ssp(cdev, ssp, reg, val) \ writel(val, catpt_ssp_addr(cdev, ssp) + (reg)) +#define catpt_readl_dram(cdev, reg) \ + readl(catpt_dram_addr(cdev) + CATPT_DRAM_##reg) +#define catpt_writel_dram(cdev, reg, val) \ + writel(val, catpt_dram_addr(cdev) + CATPT_DRAM_##reg) + #define catpt_readl_shim(cdev, reg) \ readl(catpt_shim_addr(cdev) + CATPT_SHIM_##reg) #define catpt_writel_shim(cdev, reg, val) \ diff --git a/sound/soc/intel/catpt/trace.c b/sound/soc/intel/catpt/trace.c new file mode 100644 index 000000000000..e97c372cc2af --- /dev/null +++ b/sound/soc/intel/catpt/trace.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include + +#define CREATE_TRACE_POINTS +#include "trace.h" + +#define BYTES_PER_LINE 16 +#define MAX_CHUNK_SIZE ((PAGE_SIZE - 150) /* Place for trace header */ \ + / (2 * BYTES_PER_LINE + 4) /* chars per line */ \ + * BYTES_PER_LINE) + +void trace_catpt_ipc_payload(const void *data, size_t size) +{ + size_t remaining = size; + size_t offset = 0; + + while (remaining > 0) { + u32 chunk; + + chunk = min_t(size_t, remaining, MAX_CHUNK_SIZE); + trace_catpt_ipc_payload_chunk(data, chunk, offset, size); + + remaining -= chunk; + offset += chunk; + } +} diff --git a/sound/soc/intel/catpt/trace.h b/sound/soc/intel/catpt/trace.h index 010f57b6a7a8..6b528d933734 100644 --- a/sound/soc/intel/catpt/trace.h +++ b/sound/soc/intel/catpt/trace.h @@ -51,29 +51,37 @@ DEFINE_EVENT(catpt_ipc_msg, catpt_ipc_notify, TP_ARGS(header) ); -TRACE_EVENT_CONDITION(catpt_ipc_payload, +TRACE_EVENT_CONDITION(catpt_ipc_payload_chunk, - TP_PROTO(const u8 *data, size_t size), + TP_PROTO(const u8 *data, size_t size, size_t offset, size_t total), - TP_ARGS(data, size), + TP_ARGS(data, size, offset, total), TP_CONDITION(data && size), TP_STRUCT__entry( - __dynamic_array(u8, buf, size) + __dynamic_array(u8, buf, size ) + __field(size_t, offset ) + __field(size_t, pos ) + __field(size_t, total ) ), TP_fast_assign( - memcpy(__get_dynamic_array(buf), data, size); + memcpy(__get_dynamic_array(buf), data + offset, size); + __entry->offset = offset; + __entry->pos = offset + size; + __entry->total = total; ), - TP_printk("%u byte(s)%s", - __get_dynamic_array_len(buf), + TP_printk("range %zu-%zu out of %zu bytes%s", + __entry->offset, __entry->pos, __entry->total, __print_hex_dump("", DUMP_PREFIX_NONE, 16, 4, __get_dynamic_array(buf), __get_dynamic_array_len(buf), false)) ); +void trace_catpt_ipc_payload(const void *data, size_t size); + #endif /* __SND_SOC_INTEL_CATPT_TRACE_H */ /* This part must be outside protection */ diff --git a/sound/soc/intel/common/soc-acpi-intel-arl-match.c b/sound/soc/intel/common/soc-acpi-intel-arl-match.c index 52c5b5719f51..59bfd5248819 100644 --- a/sound/soc/intel/common/soc-acpi-intel-arl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-arl-match.c @@ -193,6 +193,42 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { }, }; +static const struct snd_soc_acpi_endpoint es9356_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device es9356_adr[] = { + { + .adr = 0x00013004b3935601ull, + .num_endpoints = ARRAY_SIZE(es9356_endpoints), + .endpoints = es9356_endpoints, + .name_prefix = "es9356" + } +}; + static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { { .adr = 0x00003001FA424301ull, @@ -265,6 +301,15 @@ static const struct snd_soc_acpi_adr_device rt1320_2_single_adr[] = { } }; +static const struct snd_soc_acpi_link_adr arl_n_mrd_es9356_link1[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(es9356_adr), + .adr_d = es9356_adr, + }, + {} +}; + static const struct snd_soc_acpi_adr_device rt1320_3_group1_adr[] = { { .adr = 0x000330025D132001ull, @@ -569,6 +614,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = { .sof_tplg_filename = "sof-arl-cs42l43-l2.tplg", .get_function_tplg_files = sof_sdw_get_tplg_files, }, + { + .link_mask = BIT(1), + .links = arl_n_mrd_es9356_link1, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-arl-es9356.tplg", + .get_function_tplg_files = sof_sdw_get_tplg_files, + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_arl_sdw_machines); diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 72c35e73078e..2e4222456f27 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -122,6 +122,42 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = { .group_id = 1, }; +static const struct snd_soc_acpi_endpoint tac5xx2_endpoints[] = { + { /* Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Mic Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* UAJ-HP with Mic Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_endpoint tas2883_endpoints[] = { + { /* Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Mic Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_endpoint rt712_endpoints[] = { { .num = 0, @@ -1011,6 +1047,33 @@ static const struct snd_soc_acpi_adr_device cs42l42_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device tac5572_0_adr[] = { + { + .adr = 0x0000300102557201ull, + .num_endpoints = ARRAY_SIZE(tac5xx2_endpoints), + .endpoints = tac5xx2_endpoints, + .name_prefix = "tac5572" + } +}; + +static const struct snd_soc_acpi_adr_device tac5672_0_adr[] = { + { + .adr = 0x0000300102567201ull, + .num_endpoints = ARRAY_SIZE(tac5xx2_endpoints), + .endpoints = tac5xx2_endpoints, + .name_prefix = "tac5672" + } +}; + +static const struct snd_soc_acpi_adr_device tac5682_0_adr[] = { + { + .adr = 0x0000300102568201ull, + .num_endpoints = ARRAY_SIZE(tac5xx2_endpoints), + .endpoints = tac5xx2_endpoints, + .name_prefix = "tac5682" + } +}; + static const struct snd_soc_acpi_adr_device tas2783_0_adr[] = { { .adr = 0x00003c0102000001ull, @@ -1035,9 +1098,45 @@ static const struct snd_soc_acpi_adr_device tas2783_0_adr[] = { .num_endpoints = 1, .endpoints = &spk_r_endpoint, .name_prefix = "tas2783-4" + }, +}; + +static const struct snd_soc_acpi_adr_device tas2883_0_adr[] = { + { + .adr = 0x0000300102288301ull, + .num_endpoints = ARRAY_SIZE(tas2883_endpoints), + .endpoints = tas2883_endpoints, + .name_prefix = "tas2883" } }; +static const struct snd_soc_acpi_link_adr tac5572_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(tac5572_0_adr), + .adr_d = tac5572_0_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr tac5672_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(tac5672_0_adr), + .adr_d = tac5672_0_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr tac5682_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(tac5682_0_adr), + .adr_d = tac5682_0_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr tas2783_link0[] = { { .mask = BIT(0), @@ -1047,6 +1146,15 @@ static const struct snd_soc_acpi_link_adr tas2783_link0[] = { {} }; +static const struct snd_soc_acpi_link_adr tas2883_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(tas2883_0_adr), + .adr_d = tas2883_0_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr cs42l42_link0_max98363_link2[] = { /* Expected order: jack -> amp */ { @@ -1208,12 +1316,36 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-mtl-rt715-rt711-rt1308-mono.tplg", }, + { + .link_mask = BIT(0), + .links = tac5572_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-tac5572.tplg", + }, + { + .link_mask = BIT(0), + .links = tac5672_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-tac5672.tplg", + }, + { + .link_mask = BIT(0), + .links = tac5682_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-tac5682.tplg", + }, { .link_mask = BIT(0), .links = tas2783_link0, .drv_name = "sof_sdw", .sof_tplg_filename = "sof-mtl-tas2783.tplg", }, + { + .link_mask = BIT(0), + .links = tas2883_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-tas2883.tplg", + }, { .link_mask = GENMASK(3, 0), .links = mtl_rt713_l0_rt1316_l12_rt1713_l3, diff --git a/sound/soc/intel/common/sof-function-topology-lib.c b/sound/soc/intel/common/sof-function-topology-lib.c index 0daa7d83808b..2f2c902ef90c 100644 --- a/sound/soc/intel/common/sof-function-topology-lib.c +++ b/sound/soc/intel/common/sof-function-topology-lib.c @@ -19,6 +19,7 @@ enum tplg_device_id { TPLG_DEVICE_SDCA_MIC, TPLG_DEVICE_INTEL_PCH_DMIC, TPLG_DEVICE_HDMI, + TPLG_DEVICE_LOOPBACK_VIRTUAL, TPLG_DEVICE_MAX }; @@ -81,7 +82,15 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_ } else if (strstr(dai_link->name, "iDisp")) { tplg_dev = TPLG_DEVICE_HDMI; tplg_dev_name = "hdmi-pcm5"; - + } else if (strstr(dai_link->name, "Loopback_Virtual")) { + tplg_dev = TPLG_DEVICE_LOOPBACK_VIRTUAL; + /* + * Mark the LOOPBACK_VIRTUAL device but no need to create the + * LOOPBACK_VIRTUAL topology. Just to avoid the dai_link is not supported + * error. + */ + tplg_mask |= BIT(tplg_dev); + continue; } else { /* The dai link is not supported by separated tplg yet */ dev_dbg(card->dev, diff --git a/sound/soc/loongson/Makefile b/sound/soc/loongson/Makefile index 4c6d3130bcee..6e43672071fc 100644 --- a/sound/soc/loongson/Makefile +++ b/sound/soc/loongson/Makefile @@ -1,12 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 #Platform Support -snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_dma.o +snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o snd-soc-loongson-i2s.o snd-soc-loongson-i2s-plat-y := loongson_i2s_plat.o obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PLATFORM) += snd-soc-loongson-i2s-plat.o snd-soc-loongson-i2s.o -snd-soc-loongson-i2s-y := loongson_i2s.o +snd-soc-loongson-i2s-y := loongson_i2s.o loongson_dma.o obj-$(CONFIG_SND_LOONGSON1_AC97) += loongson1_ac97.o diff --git a/sound/soc/loongson/loongson_dma.c b/sound/soc/loongson/loongson_dma.c index f3ed14a48bd5..44fdce22f58c 100644 --- a/sound/soc/loongson/loongson_dma.c +++ b/sound/soc/loongson/loongson_dma.c @@ -4,6 +4,7 @@ // // Copyright (C) 2023 Loongson Technology Corporation Limited // Author: Yingkun Meng +// Binbin ZHou // #include @@ -16,7 +17,7 @@ #include #include "loongson_i2s.h" -/* DMA dma_order Register */ +/* Internal DMA dma_order Register */ #define DMA_ORDER_STOP BIT(4) /* DMA stop */ #define DMA_ORDER_START BIT(3) /* DMA start */ #define DMA_ORDER_ASK_VALID BIT(2) /* DMA ask valid flag */ @@ -27,9 +28,9 @@ #define DMA_ORDER_CTRL_MASK (0x0fUL) /* Control mask */ /* - * DMA registers descriptor. + * Internal DMA registers descriptor. */ -struct loongson_dma_desc { +struct loongson_idma_desc { u32 order; /* Next descriptor address register */ u32 saddr; /* Source address register */ u32 daddr; /* Device address register */ @@ -44,17 +45,17 @@ struct loongson_dma_desc { } __packed; struct loongson_runtime_data { - struct loongson_dma_data *dma_data; + struct loongson_idma_data *dma_data; - struct loongson_dma_desc *dma_desc_arr; + struct loongson_idma_desc *dma_desc_arr; dma_addr_t dma_desc_arr_phy; int dma_desc_arr_size; - struct loongson_dma_desc *dma_pos_desc; + struct loongson_idma_desc *dma_pos_desc; dma_addr_t dma_pos_desc_phy; }; -static const struct snd_pcm_hardware ls_pcm_hardware = { +static const struct snd_pcm_hardware loongson_idma_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID | @@ -67,12 +68,11 @@ static const struct snd_pcm_hardware ls_pcm_hardware = { .period_bytes_min = 128, .period_bytes_max = 128 * 1024, .periods_min = 1, - .periods_max = PAGE_SIZE / sizeof(struct loongson_dma_desc), + .periods_max = PAGE_SIZE / sizeof(struct loongson_idma_desc), .buffer_bytes_max = 1024 * 1024, }; -static struct -loongson_dma_desc *dma_desc_save(struct loongson_runtime_data *prtd) +static struct loongson_idma_desc *dma_desc_save(struct loongson_runtime_data *prtd) { void __iomem *order_reg = prtd->dma_data->order_addr; u64 val; @@ -88,8 +88,8 @@ loongson_dma_desc *dma_desc_save(struct loongson_runtime_data *prtd) return prtd->dma_pos_desc; } -static int loongson_pcm_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, int cmd) +static int loongson_idma_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) { struct loongson_runtime_data *prtd = substream->runtime->private_data; struct device *dev = substream->pcm->card->dev; @@ -131,9 +131,9 @@ static int loongson_pcm_trigger(struct snd_soc_component *component, return 0; } -static int loongson_pcm_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) +static int loongson_idma_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct device *dev = substream->pcm->card->dev; @@ -141,7 +141,7 @@ static int loongson_pcm_hw_params(struct snd_soc_component *component, size_t buf_len = params_buffer_bytes(params); size_t period_len = params_period_bytes(params); dma_addr_t order_addr, mem_addr; - struct loongson_dma_desc *desc; + struct loongson_idma_desc *desc; u32 num_periods; int i; @@ -195,13 +195,13 @@ static int loongson_pcm_hw_params(struct snd_soc_component *component, } static snd_pcm_uframes_t -loongson_pcm_pointer(struct snd_soc_component *component, - struct snd_pcm_substream *substream) +loongson_idma_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct device *dev = substream->pcm->card->dev; struct loongson_runtime_data *prtd = runtime->private_data; - struct loongson_dma_desc *desc; + struct loongson_idma_desc *desc; snd_pcm_uframes_t x; u64 addr; @@ -221,7 +221,7 @@ loongson_pcm_pointer(struct snd_soc_component *component, return x; } -static irqreturn_t loongson_pcm_dma_irq(int irq, void *devid) +static irqreturn_t loongson_idma_pcm_dma_irq(int irq, void *devid) { struct snd_pcm_substream *substream = devid; @@ -229,14 +229,14 @@ static irqreturn_t loongson_pcm_dma_irq(int irq, void *devid) return IRQ_HANDLED; } -static int loongson_pcm_open(struct snd_soc_component *component, - struct snd_pcm_substream *substream) +static int loongson_idma_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_card *card = substream->pcm->card; struct loongson_runtime_data *prtd; - struct loongson_dma_data *dma_data; + struct loongson_idma_data *dma_data; /* * For mysterious reasons (and despite what the manual says) @@ -249,7 +249,7 @@ static int loongson_pcm_open(struct snd_soc_component *component, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128); snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); - snd_soc_set_runtime_hwparams(substream, &ls_pcm_hardware); + snd_soc_set_runtime_hwparams(substream, &loongson_idma_hardware); prtd = kzalloc_obj(*prtd); if (!prtd) @@ -285,8 +285,8 @@ static int loongson_pcm_open(struct snd_soc_component *component, return -ENOMEM; } -static int loongson_pcm_close(struct snd_soc_component *component, - struct snd_pcm_substream *substream) +static int loongson_idma_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) { struct snd_card *card = substream->pcm->card; struct loongson_runtime_data *prtd = substream->runtime->private_data; @@ -301,21 +301,21 @@ static int loongson_pcm_close(struct snd_soc_component *component, return 0; } -static int loongson_pcm_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma) +static int loongson_idma_pcm_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) { return remap_pfn_range(vma, vma->vm_start, - substream->dma_buffer.addr >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, vma->vm_page_prot); + substream->dma_buffer.addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); } -static int loongson_pcm_new(struct snd_soc_component *component, - struct snd_soc_pcm_runtime *rtd) +static int loongson_idma_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; struct snd_pcm_substream *substream; - struct loongson_dma_data *dma_data; + struct loongson_idma_data *dma_data; unsigned int i; int ret; @@ -327,7 +327,7 @@ static int loongson_pcm_new(struct snd_soc_component *component, dma_data = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream); ret = devm_request_irq(card->dev, dma_data->irq, - loongson_pcm_dma_irq, + loongson_idma_pcm_dma_irq, IRQF_TRIGGER_HIGH, LS_I2S_DRVNAME, substream); if (ret < 0) { @@ -338,16 +338,76 @@ static int loongson_pcm_new(struct snd_soc_component *component, return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, - ls_pcm_hardware.buffer_bytes_max); + loongson_idma_hardware.buffer_bytes_max); } -const struct snd_soc_component_driver loongson_i2s_component = { +/* Internal DMA component */ +const struct snd_soc_component_driver loongson_i2s_idma_component = { .name = LS_I2S_DRVNAME, - .open = loongson_pcm_open, - .close = loongson_pcm_close, - .hw_params = loongson_pcm_hw_params, - .trigger = loongson_pcm_trigger, - .pointer = loongson_pcm_pointer, - .mmap = loongson_pcm_mmap, - .pcm_new = loongson_pcm_new, + .open = loongson_idma_pcm_open, + .close = loongson_idma_pcm_close, + .hw_params = loongson_idma_pcm_hw_params, + .trigger = loongson_idma_pcm_trigger, + .pointer = loongson_idma_pcm_pointer, + .mmap = loongson_idma_pcm_mmap, + .pcm_new = loongson_idma_pcm_new, }; +EXPORT_SYMBOL_GPL(loongson_i2s_idma_component); + +static const struct snd_pcm_hardware loongson_edma_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_PAUSE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE, + .period_bytes_min = 128, + .period_bytes_max = 128 * 1024, + .periods_min = 1, + .periods_max = 64, + .buffer_bytes_max = 1024 * 1024, +}; + +const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = { + .pcm_hardware = &loongson_edma_hardware, + .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, + .prealloc_buffer_size = 128 * 1024, +}; +EXPORT_SYMBOL_GPL(loongson_dmaengine_pcm_config); + +/* External DMA component */ +static int loongson_edma_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + if (substream->pcm->device & 1) { + runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; + runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; + } + + if (substream->pcm->device & 2) + runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID); + /* + * For mysterious reasons (and despite what the manual says) + * playback samples are lost if the DMA count is not a multiple + * of the DMA burst size. Let's add a rule to enforce that. + */ + snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); + snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128); + snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + + return 0; +} + +const struct snd_soc_component_driver loongson_i2s_edma_component = { + .name = LS_I2S_DRVNAME, + .open = loongson_edma_pcm_open, +}; +EXPORT_SYMBOL_GPL(loongson_i2s_edma_component); diff --git a/sound/soc/loongson/loongson_dma.h b/sound/soc/loongson/loongson_dma.h index 073ee8c0c046..a040681d2693 100644 --- a/sound/soc/loongson/loongson_dma.h +++ b/sound/soc/loongson/loongson_dma.h @@ -9,8 +9,8 @@ #ifndef _LOONGSON_DMA_H #define _LOONGSON_DMA_H -#include - -extern const struct snd_soc_component_driver loongson_i2s_component; +extern const struct snd_soc_component_driver loongson_i2s_idma_component; +extern const struct snd_soc_component_driver loongson_i2s_edma_component; +extern const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config; #endif diff --git a/sound/soc/loongson/loongson_i2s.c b/sound/soc/loongson/loongson_i2s.c index e336656e13eb..cfe102a8b604 100644 --- a/sound/soc/loongson/loongson_i2s.c +++ b/sound/soc/loongson/loongson_i2s.c @@ -254,6 +254,7 @@ static int i2s_suspend(struct device *dev) struct loongson_i2s *i2s = dev_get_drvdata(dev); regcache_cache_only(i2s->regmap, true); + regcache_mark_dirty(i2s->regmap); return 0; } @@ -263,7 +264,7 @@ static int i2s_resume(struct device *dev) struct loongson_i2s *i2s = dev_get_drvdata(dev); regcache_cache_only(i2s->regmap, false); - regcache_mark_dirty(i2s->regmap); + return regcache_sync(i2s->regmap); } @@ -272,5 +273,58 @@ const struct dev_pm_ops loongson_i2s_pm = { }; EXPORT_SYMBOL_GPL(loongson_i2s_pm); +static bool loongson_i2s_rd_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LS_I2S_VER: + case LS_I2S_CFG: + case LS_I2S_CTRL: + case LS_I2S_RX_DATA: + case LS_I2S_TX_DATA: + case LS_I2S_CFG1: + return true; + default: + return false; + }; +} + +static bool loongson_i2s_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LS_I2S_CFG: + case LS_I2S_CTRL: + case LS_I2S_RX_DATA: + case LS_I2S_TX_DATA: + case LS_I2S_CFG1: + return true; + default: + return false; + }; +} + +static bool loongson_i2s_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LS_I2S_CTRL: + case LS_I2S_RX_DATA: + case LS_I2S_TX_DATA: + return true; + default: + return false; + }; +} + +const struct regmap_config loongson_i2s_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = LS_I2S_CFG1, + .readable_reg = loongson_i2s_rd_reg, + .writeable_reg = loongson_i2s_wr_reg, + .volatile_reg = loongson_i2s_volatile_reg, + .cache_type = REGCACHE_MAPLE, +}; +EXPORT_SYMBOL_GPL(loongson_i2s_regmap_config); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Common functions for loongson I2S controller driver"); diff --git a/sound/soc/loongson/loongson_i2s.h b/sound/soc/loongson/loongson_i2s.h index c8052a762c1b..8b4603c876c5 100644 --- a/sound/soc/loongson/loongson_i2s.h +++ b/sound/soc/loongson/loongson_i2s.h @@ -42,7 +42,7 @@ #define LS_I2S_DRVNAME "loongson-i2s" -struct loongson_dma_data { +struct loongson_idma_data { dma_addr_t dev_addr; /* device physical address for DMA */ void __iomem *order_addr; /* DMA order register */ int irq; /* DMA irq */ @@ -52,11 +52,11 @@ struct loongson_i2s { struct device *dev; union { struct snd_dmaengine_dai_dma_data playback_dma_data; - struct loongson_dma_data tx_dma_data; + struct loongson_idma_data tx_dma_data; }; union { struct snd_dmaengine_dai_dma_data capture_dma_data; - struct loongson_dma_data rx_dma_data; + struct loongson_idma_data rx_dma_data; }; struct regmap *regmap; void __iomem *reg_base; @@ -65,6 +65,7 @@ struct loongson_i2s { u32 sysclk; }; +extern const struct regmap_config loongson_i2s_regmap_config; extern const struct dev_pm_ops loongson_i2s_pm; extern struct snd_soc_dai_driver loongson_i2s_dai; diff --git a/sound/soc/loongson/loongson_i2s_pci.c b/sound/soc/loongson/loongson_i2s_pci.c index 1ea5501a97f8..f5b560465706 100644 --- a/sound/soc/loongson/loongson_i2s_pci.c +++ b/sound/soc/loongson/loongson_i2s_pci.c @@ -13,70 +13,17 @@ #include #include #include + #include "loongson_i2s.h" #include "loongson_dma.h" #define DRIVER_NAME "loongson-i2s-pci" -static bool loongson_i2s_wr_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case LS_I2S_CFG: - case LS_I2S_CTRL: - case LS_I2S_RX_DATA: - case LS_I2S_TX_DATA: - case LS_I2S_CFG1: - return true; - default: - return false; - }; -} - -static bool loongson_i2s_rd_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case LS_I2S_VER: - case LS_I2S_CFG: - case LS_I2S_CTRL: - case LS_I2S_RX_DATA: - case LS_I2S_TX_DATA: - case LS_I2S_CFG1: - return true; - default: - return false; - }; -} - -static bool loongson_i2s_volatile_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case LS_I2S_CFG: - case LS_I2S_CTRL: - case LS_I2S_RX_DATA: - case LS_I2S_TX_DATA: - case LS_I2S_CFG1: - return true; - default: - return false; - }; -} - -static const struct regmap_config loongson_i2s_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = LS_I2S_CFG1, - .writeable_reg = loongson_i2s_wr_reg, - .readable_reg = loongson_i2s_rd_reg, - .volatile_reg = loongson_i2s_volatile_reg, - .cache_type = REGCACHE_FLAT, -}; - static int loongson_i2s_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) { const struct fwnode_handle *fwnode = pdev->dev.fwnode; - struct loongson_dma_data *tx_data, *rx_data; + struct loongson_idma_data *tx_data, *rx_data; struct device *dev = &pdev->dev; struct loongson_i2s *i2s; int ret; @@ -133,7 +80,7 @@ static int loongson_i2s_pci_probe(struct pci_dev *pdev, udelay(200); } - ret = devm_snd_soc_register_component(dev, &loongson_i2s_component, + ret = devm_snd_soc_register_component(dev, &loongson_i2s_idma_component, &loongson_i2s_dai, 1); if (ret) return dev_err_probe(dev, ret, "register DAI failed\n"); diff --git a/sound/soc/loongson/loongson_i2s_plat.c b/sound/soc/loongson/loongson_i2s_plat.c index fa2e450ff618..ac054b6ce632 100644 --- a/sound/soc/loongson/loongson_i2s_plat.c +++ b/sound/soc/loongson/loongson_i2s_plat.c @@ -19,6 +19,7 @@ #include #include "loongson_i2s.h" +#include "loongson_dma.h" #define LOONGSON_I2S_RX_DMA_OFFSET 21 #define LOONGSON_I2S_TX_DMA_OFFSET 18 @@ -29,70 +30,6 @@ #define LOONGSON_DMA3_CONF 0x3 #define LOONGSON_DMA4_CONF 0x4 -/* periods_max = PAGE_SIZE / sizeof(struct ls_dma_chan_reg) */ -static const struct snd_pcm_hardware loongson_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_PAUSE, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE, - .period_bytes_min = 128, - .period_bytes_max = 128 * 1024, - .periods_min = 1, - .periods_max = 64, - .buffer_bytes_max = 1024 * 1024, -}; - -static const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = { - .pcm_hardware = &loongson_pcm_hardware, - .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, - .prealloc_buffer_size = 128 * 1024, -}; - -static int loongson_pcm_open(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - if (substream->pcm->device & 1) { - runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; - runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; - } - - if (substream->pcm->device & 2) - runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID); - /* - * For mysterious reasons (and despite what the manual says) - * playback samples are lost if the DMA count is not a multiple - * of the DMA burst size. Let's add a rule to enforce that. - */ - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); - snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128); - snd_pcm_hw_constraint_integer(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - - return 0; -} - -static const struct snd_soc_component_driver loongson_i2s_component_driver = { - .name = LS_I2S_DRVNAME, - .open = loongson_pcm_open, -}; - -static const struct regmap_config loongson_i2s_regmap_config = { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = 0x14, - .cache_type = REGCACHE_FLAT, -}; - static int loongson_i2s_apbdma_config(struct platform_device *pdev) { int val; @@ -155,7 +92,7 @@ static int loongson_i2s_plat_probe(struct platform_device *pdev) dev_set_name(dev, LS_I2S_DRVNAME); dev_set_drvdata(dev, i2s); - ret = devm_snd_soc_register_component(dev, &loongson_i2s_component_driver, + ret = devm_snd_soc_register_component(dev, &loongson_i2s_edma_component, &loongson_i2s_dai, 1); if (ret) return dev_err_probe(dev, ret, "failed to register DAI\n"); diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 3a1e1fa3fe5c..4af7bbb58010 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -26,6 +26,16 @@ config SND_SOC_MT2701_CS42448 Select Y if you have such device. If unsure select "N". +config SND_SOC_MT2701_HDMI + tristate "ASoC Audio driver for MT2701 with on-chip HDMI codec" + depends on SND_SOC_MT2701 + select SND_SOC_HDMI_CODEC + help + This adds the ASoC machine driver for MediaTek MT2701 and + MT7623N boards routing the AFE I2S back-end to the on-chip + HDMI transmitter via the generic HDMI codec. + If unsure select "N". + config SND_SOC_MT2701_WM8960 tristate "ASoc Audio driver for MT2701 with WM8960 codec" depends on SND_SOC_MT2701 && I2C @@ -353,4 +363,34 @@ config SND_SOC_MT8365_MT6357 Select Y if you have such device. If unsure select "N". +config SND_SOC_MT8196 + tristate "ASoC support for Mediatek MT8196 chip" + depends on ARCH_MEDIATEK + select SND_SOC_MEDIATEK + help + This adds ASoC driver for Mediatek MT8196 boards + that can be used with other codecs. + Select Y if you have such device. + If unsure select "N". + +config SND_SOC_MT8196_NAU8825 + tristate "ASoc Audio driver for MT8196 with NAU8825 and I2S codec" + depends on SND_SOC_MT8196 + depends on I2C + select SND_SOC_HDMI_CODEC + select SND_SOC_DMIC + select SND_SOC_NAU8315 + select SND_SOC_NAU8825 + select SND_SOC_RT5645 + select SND_SOC_RT5682_I2C + select SND_SOC_RT5682S + select SND_SOC_TAS2781_COMLIB + select SND_SOC_TAS2781_FMWLIB + select SND_SOC_TAS2781_I2C + help + This adds support for ASoC machine driver for MediaTek MT8196 + boards with the NAU8825 and other I2S audio codecs. + Select Y if you have such device. + If unsure select "N". + endmenu diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile index 7cd67bce92e9..a6815a3c5988 100644 --- a/sound/soc/mediatek/Makefile +++ b/sound/soc/mediatek/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_SND_SOC_MT8192) += mt8192/ obj-$(CONFIG_SND_SOC_MT8195) += mt8195/ obj-$(CONFIG_SND_SOC_MT8365) += mt8365/ obj-$(CONFIG_SND_SOC_MT8189) += mt8189/ +obj-$(CONFIG_SND_SOC_MT8196) += mt8196/ diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c index 3809068f5620..2a20fa5dba49 100644 --- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c +++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c @@ -292,28 +292,24 @@ int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe) { int i; - mutex_lock(&afe->irq_alloc_lock); + guard(mutex)(&afe->irq_alloc_lock); for (i = 0; i < afe->irqs_size; ++i) { if (afe->irqs[i].irq_occupyed == 0) { afe->irqs[i].irq_occupyed = 1; - mutex_unlock(&afe->irq_alloc_lock); return i; } } - mutex_unlock(&afe->irq_alloc_lock); return afe->irqs_size; } EXPORT_SYMBOL_GPL(mtk_dynamic_irq_acquire); int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id) { - mutex_lock(&afe->irq_alloc_lock); + guard(mutex)(&afe->irq_alloc_lock); if (irq_id >= 0 && irq_id < afe->irqs_size) { afe->irqs[irq_id].irq_occupyed = 0; - mutex_unlock(&afe->irq_alloc_lock); return 0; } - mutex_unlock(&afe->irq_alloc_lock); return -EINVAL; } EXPORT_SYMBOL_GPL(mtk_dynamic_irq_release); diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c index f2b39fc9ec81..477284e12396 100644 --- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c +++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c @@ -87,29 +87,49 @@ snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component, const struct mtk_base_memif_data *memif_data = memif->data; struct regmap *regmap = afe->regmap; struct device *dev = afe->dev; - int reg_ofs_base = memif_data->reg_ofs_base; - int reg_ofs_cur = memif_data->reg_ofs_cur; - unsigned int hw_ptr = 0, hw_base = 0; - int ret, pcm_ptr_bytes; + unsigned int hw_ptr_lower32 = 0, hw_ptr_upper32 = 0; + unsigned int hw_base_lower32 = 0, hw_base_upper32 = 0; + unsigned long long hw_ptr = 0, hw_base = 0; + int ret; + unsigned long long pcm_ptr_bytes = 0; - ret = regmap_read(regmap, reg_ofs_cur, &hw_ptr); - if (ret || hw_ptr == 0) { - dev_err(dev, "%s hw_ptr err\n", __func__); - pcm_ptr_bytes = 0; - goto POINTER_RETURN_FRAMES; + ret = regmap_read(regmap, memif_data->reg_ofs_cur, &hw_ptr_lower32); + if (ret) { + dev_err(dev, "%s hw_ptr_lower32 err\n", __func__); + return 0; } - ret = regmap_read(regmap, reg_ofs_base, &hw_base); - if (ret || hw_base == 0) { - dev_err(dev, "%s hw_ptr err\n", __func__); - pcm_ptr_bytes = 0; - goto POINTER_RETURN_FRAMES; + if (memif_data->reg_ofs_cur_msb) { + ret = regmap_read(regmap, memif_data->reg_ofs_cur_msb, &hw_ptr_upper32); + if (ret) { + dev_err(dev, "%s hw_ptr_upper32 err\n", __func__); + return 0; + } } - pcm_ptr_bytes = hw_ptr - hw_base; + ret = regmap_read(regmap, memif_data->reg_ofs_base, &hw_base_lower32); + if (ret) { + dev_err(dev, "%s hw_base_lower32 err\n", __func__); + return 0; + } + if (memif_data->reg_ofs_base_msb) { + ret = regmap_read(regmap, memif_data->reg_ofs_base_msb, &hw_base_upper32); + if (ret) { + dev_err(dev, "%s hw_base_upper32 err\n", __func__); + return 0; + } + } -POINTER_RETURN_FRAMES: - return bytes_to_frames(substream->runtime, pcm_ptr_bytes); + hw_ptr = ((unsigned long long)hw_ptr_upper32 << 32) | hw_ptr_lower32; + hw_base = ((unsigned long long)hw_base_upper32 << 32) | hw_base_lower32; + + if (!hw_ptr || !hw_base) { + dev_err(dev, "hw_ptr or hw_base = 0 err\n"); + return 0; + } + + pcm_ptr_bytes = MTK_ALIGN_16BYTES(hw_ptr - hw_base); + return bytes_to_frames(substream->runtime, (ssize_t)pcm_ptr_bytes); } EXPORT_SYMBOL_GPL(mtk_afe_pcm_pointer); diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.h b/sound/soc/mediatek/common/mtk-afe-platform-driver.h index fcc923b88f12..71070b26f8f8 100644 --- a/sound/soc/mediatek/common/mtk-afe-platform-driver.h +++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.h @@ -12,6 +12,8 @@ #define AFE_PCM_NAME "mtk-afe-pcm" extern const struct snd_soc_component_driver mtk_afe_pcm_platform; +#define MTK_ALIGN_16BYTES(x) ((x) & GENMASK_ULL(39, 4)) + struct mtk_base_afe; struct snd_pcm; struct snd_soc_component; diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index 5e7e85b4c98a..85cfc602dfd3 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c @@ -319,7 +319,6 @@ static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt) { unsigned int i; unsigned int num_valid_addr; - unsigned long flags; enum BT_SCO_BAND band = bt->band; /* prepare encoded mute data */ @@ -330,7 +329,7 @@ static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt) table_msbc_silence, SCO_PACKET_180); /* write mute data to bt tx sram buffer */ - spin_lock_irqsave(&bt->tx_lock, flags); + guard(spinlock_irqsave)(&bt->tx_lock); num_valid_addr = bt->tx->buffer_info.num_valid_addr; dev_info(bt->dev, "%s(), band %d, num_valid_addr %u\n", @@ -349,7 +348,6 @@ static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt) bt->tx->buffer_info.packet_length, bt->tx->buffer_info.packet_num); } - spin_unlock_irqrestore(&bt->tx_lock, flags); return 0; } @@ -365,7 +363,6 @@ static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt, int pv; u8 *src; unsigned int packet_buf_ofs; - unsigned long flags; unsigned long connsys_addr_rx, ap_addr_rx; connsys_addr_rx = *bt->bt_reg_pkt_r; @@ -385,7 +382,7 @@ static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt, bt->rx->temp_packet_buf, packet_length, packet_num); - spin_lock_irqsave(&bt->rx_lock, flags); + guard(spinlock_irqsave)(&bt->rx_lock); for (i = 0; i < blk_size; i++) { packet_buf_ofs = (bt->rx->packet_w & SCO_RX_PACKET_MASK) * bt->rx->packet_size; @@ -403,7 +400,7 @@ static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt, SCO_CVSD_PACKET_VALID_SIZE); bt->rx->packet_w++; } - spin_unlock_irqrestore(&bt->rx_lock, flags); + return 0; } @@ -414,7 +411,6 @@ static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt, unsigned int blk_size) { unsigned int i; - unsigned long flags; u8 *dst; unsigned long connsys_addr_tx, ap_addr_tx; bool new_ap_addr_tx = true; @@ -430,17 +426,17 @@ static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt, return -EIO; } - spin_lock_irqsave(&bt->tx_lock, flags); - for (i = 0; i < blk_size; i++) { - memcpy(bt->tx->temp_packet_buf + (bt->tx->packet_size * i), - (bt->tx_packet_buf + - (bt->tx->packet_r % SCO_TX_PACKER_BUF_NUM) * - bt->tx->packet_size), - bt->tx->packet_size); + scoped_guard(spinlock_irqsave, &bt->tx_lock) { + for (i = 0; i < blk_size; i++) { + memcpy(bt->tx->temp_packet_buf + (bt->tx->packet_size * i), + (bt->tx_packet_buf + + (bt->tx->packet_r % SCO_TX_PACKER_BUF_NUM) * + bt->tx->packet_size), + bt->tx->packet_size); - bt->tx->packet_r++; + bt->tx->packet_r++; + } } - spin_unlock_irqrestore(&bt->tx_lock, flags); dst = (u8 *)ap_addr_tx; @@ -462,11 +458,11 @@ static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt, if (new_ap_addr_tx) { unsigned int next_idx; - spin_lock_irqsave(&bt->tx_lock, flags); - bt->tx->buffer_info.num_valid_addr++; - next_idx = bt->tx->buffer_info.num_valid_addr - 1; - bt->tx->buffer_info.bt_sram_addr[next_idx] = ap_addr_tx; - spin_unlock_irqrestore(&bt->tx_lock, flags); + scoped_guard(spinlock_irqsave, &bt->tx_lock) { + bt->tx->buffer_info.num_valid_addr++; + next_idx = bt->tx->buffer_info.num_valid_addr - 1; + bt->tx->buffer_info.bt_sram_addr[next_idx] = ap_addr_tx; + } dev_info(bt->dev, "%s(), new ap_addr_tx = 0x%lx, num_valid_addr %d\n", __func__, ap_addr_tx, bt->tx->buffer_info.num_valid_addr); @@ -701,17 +697,16 @@ static ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt, { ssize_t read_size = 0, read_count = 0, cur_read_idx, cont; unsigned long avail; - unsigned long flags; unsigned int packet_size = bt->rx->packet_size; while (count) { - spin_lock_irqsave(&bt->rx_lock, flags); - /* available data in RX packet buffer */ - avail = (bt->rx->packet_w - bt->rx->packet_r) * packet_size; + scoped_guard(spinlock_irqsave, &bt->rx_lock) { + /* available data in RX packet buffer */ + avail = (bt->rx->packet_w - bt->rx->packet_r) * packet_size; - cur_read_idx = (bt->rx->packet_r & SCO_RX_PACKET_MASK) * - packet_size; - spin_unlock_irqrestore(&bt->rx_lock, flags); + cur_read_idx = (bt->rx->packet_r & SCO_RX_PACKET_MASK) * + packet_size; + } if (!avail) { int ret = wait_for_bt_irq(bt, bt->rx); @@ -749,9 +744,8 @@ static ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt, return -EFAULT; } - spin_lock_irqsave(&bt->rx_lock, flags); - bt->rx->packet_r += read_size / packet_size; - spin_unlock_irqrestore(&bt->rx_lock, flags); + scoped_guard(spinlock_irqsave, &bt->rx_lock) + bt->rx->packet_r += read_size / packet_size; read_count += read_size; count -= read_size; @@ -778,7 +772,6 @@ static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt, size_t count) { int written_size = count, avail, cur_write_idx, write_size, cont; - unsigned long flags; unsigned int packet_size = bt->tx->packet_size; /* @@ -794,14 +787,14 @@ static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt, bt->tx->buf_data_equivalent_time *= 1000; while (count) { - spin_lock_irqsave(&bt->tx_lock, flags); - /* free space of TX packet buffer */ - avail = bt->tx->buf_size - - (bt->tx->packet_w - bt->tx->packet_r) * packet_size; + scoped_guard(spinlock_irqsave, &bt->tx_lock) { + /* free space of TX packet buffer */ + avail = bt->tx->buf_size - + (bt->tx->packet_w - bt->tx->packet_r) * packet_size; - cur_write_idx = (bt->tx->packet_w % SCO_TX_PACKER_BUF_NUM) * - packet_size; - spin_unlock_irqrestore(&bt->tx_lock, flags); + cur_write_idx = (bt->tx->packet_w % SCO_TX_PACKER_BUF_NUM) * + packet_size; + } if (!avail) { int ret = wait_for_bt_irq(bt, bt->tx); @@ -838,9 +831,8 @@ static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt, return -EFAULT; } - spin_lock_irqsave(&bt->tx_lock, flags); - bt->tx->packet_w += write_size / packet_size; - spin_unlock_irqrestore(&bt->tx_lock, flags); + scoped_guard(spinlock_irqsave, &bt->tx_lock) + bt->tx->packet_w += write_size / packet_size; count -= write_size; } @@ -985,7 +977,6 @@ static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer( int hw_packet_ptr; int packet_diff; spinlock_t *lock; /* spinlock for bt stream control */ - unsigned long flags; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { lock = &bt->tx_lock; @@ -995,7 +986,7 @@ static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer( bt_stream = bt->rx; } - spin_lock_irqsave(lock, flags); + guard(spinlock_irqsave)(lock); hw_packet_ptr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? bt->tx->packet_r : bt->rx->packet_w; @@ -1018,8 +1009,6 @@ static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer( bt_stream->prev_frame = frame; - spin_unlock_irqrestore(lock, flags); - return frame; } diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.c b/sound/soc/mediatek/common/mtk-dsp-sof-common.c index fd10616a08a0..17b9ea6be604 100644 --- a/sound/soc/mediatek/common/mtk-dsp-sof-common.c +++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.c @@ -228,11 +228,10 @@ int mtk_sof_card_late_probe(struct snd_soc_card *card) } EXPORT_SYMBOL_GPL(mtk_sof_card_late_probe); -int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np, - const char *propname, struct snd_soc_dai_link *pre_dai_links, - int pre_num_links) +int mtk_sof_dailink_parse_of(struct device *dev, struct snd_soc_card *card, + const char *propname) { - struct device *dev = card->dev; + struct device_node *np = dev->of_node; struct snd_soc_dai_link *parsed_dai_link; const char *dai_name = NULL; int i, j, ret, num_links, parsed_num_links = 0; @@ -255,9 +254,9 @@ int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np, return ret; } dev_dbg(dev, "ASoC: Property get dai_name:%s\n", dai_name); - for (j = 0; j < pre_num_links; j++) { - if (!strcmp(dai_name, pre_dai_links[j].name)) { - memcpy(&parsed_dai_link[parsed_num_links++], &pre_dai_links[j], + for (j = 0; j < card->num_links; j++) { + if (!strcmp(dai_name, card->dai_link[j].name)) { + memcpy(&parsed_dai_link[parsed_num_links++], &card->dai_link[j], sizeof(struct snd_soc_dai_link)); break; } diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.h b/sound/soc/mediatek/common/mtk-dsp-sof-common.h index 8784ee471132..1a0a47d64761 100644 --- a/sound/soc/mediatek/common/mtk-dsp-sof-common.h +++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.h @@ -36,8 +36,7 @@ int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); int mtk_sof_card_probe(struct snd_soc_card *card); int mtk_sof_card_late_probe(struct snd_soc_card *card); -int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np, - const char *propname, struct snd_soc_dai_link *pre_dai_links, - int pre_num_links); +int mtk_sof_dailink_parse_of(struct device *dev, struct snd_soc_card *card, + const char *propname); #endif diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index a2a30a87a359..2d39ff23f854 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -15,11 +15,10 @@ #include "mtk-soc-card.h" #include "mtk-soundcard-driver.h" -static int set_card_codec_info(struct snd_soc_card *card, +static int set_card_codec_info(struct device *dev, struct device_node *sub_node, struct snd_soc_dai_link *dai_link) { - struct device *dev = card->dev; struct device_node *codec_node; int ret; @@ -45,8 +44,7 @@ static int set_card_codec_info(struct snd_soc_card *card, return 0; } -static int set_dailink_daifmt(struct snd_soc_card *card, - struct device_node *sub_node, +static int set_dailink_daifmt(struct device_node *sub_node, struct snd_soc_dai_link *dai_link) { unsigned int daifmt; @@ -107,11 +105,11 @@ int parse_dai_link_info(struct snd_soc_card *card) if (i >= card->num_links) return -EINVAL; - ret = set_card_codec_info(card, sub_node, dai_link); + ret = set_card_codec_info(dev, sub_node, dai_link); if (ret < 0) return ret; - ret = set_dailink_daifmt(card, sub_node, dai_link); + ret = set_dailink_daifmt(sub_node, dai_link); if (ret < 0) return ret; } @@ -275,9 +273,8 @@ int mtk_soundcard_common_probe(struct platform_device *pdev) if (adsp_node) { if (of_property_present(pdev->dev.of_node, "mediatek,dai-link")) { - ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node, - "mediatek,dai-link", - card->dai_link, card->num_links); + ret = mtk_sof_dailink_parse_of(&pdev->dev, card, + "mediatek,dai-link"); if (ret) { of_node_put(adsp_node); of_node_put(platform_node); @@ -289,11 +286,8 @@ int mtk_soundcard_common_probe(struct platform_device *pdev) soc_card_data->sof_priv = pdata->sof_priv; card->probe = mtk_sof_card_probe; card->late_probe = mtk_sof_card_late_probe; - if (!card->topology_shortname_created) { - snprintf(card->topology_shortname, 32, "sof-%s", card->name); - card->topology_shortname_created = true; - } - card->name = card->topology_shortname; + + snd_soc_card_set_topology_name(card, "sof"); } /* diff --git a/sound/soc/mediatek/mt2701/Makefile b/sound/soc/mediatek/mt2701/Makefile index 507fa26c3945..59623d3d3a03 100644 --- a/sound/soc/mediatek/mt2701/Makefile +++ b/sound/soc/mediatek/mt2701/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_SND_SOC_MT2701) += snd-soc-mt2701-afe.o # machine driver obj-$(CONFIG_SND_SOC_MT2701_CS42448) += mt2701-cs42448.o +obj-$(CONFIG_SND_SOC_MT2701_HDMI) += mt2701-hdmi.o obj-$(CONFIG_SND_SOC_MT2701_WM8960) += mt2701-wm8960.o diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c index ae620890bb3a..d217f9320ad2 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c @@ -25,6 +25,7 @@ static const char *const base_clks[] = { int mt2701_init_clock(struct mtk_base_afe *afe) { struct mt2701_afe_private *afe_priv = afe->platform_priv; + int i2s_num; int i; for (i = 0; i < MT2701_BASE_CLK_NUM; i++) { @@ -35,8 +36,9 @@ int mt2701_init_clock(struct mtk_base_afe *afe) } } + i2s_num = min(afe_priv->soc->i2s_num, MT2701_BASE_CLK_NUM); /* Get I2S related clocks */ - for (i = 0; i < afe_priv->soc->i2s_num; i++) { + for (i = 0; i < i2s_num; i++) { struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i]; struct clk *i2s_ck; char name[13]; @@ -95,6 +97,28 @@ int mt2701_init_clock(struct mtk_base_afe *afe) afe_priv->mrgif_ck = NULL; } + /* + * Optional HDMI audio clocks. Platforms that do not wire up the + * HDMI output (e.g. MT2701 devkits using only the I2S BE DAIs) + * may omit these; in that case the HDMI BE DAI simply cannot be + * enabled, but the rest of the AFE still probes. + */ + afe_priv->hadds2pll_ck = devm_clk_get_optional(afe->dev, "hadds2pll_294m"); + if (IS_ERR(afe_priv->hadds2pll_ck)) + return PTR_ERR(afe_priv->hadds2pll_ck); + + afe_priv->audio_hdmi_ck = devm_clk_get_optional(afe->dev, "audio_hdmi_pd"); + if (IS_ERR(afe_priv->audio_hdmi_ck)) + return PTR_ERR(afe_priv->audio_hdmi_ck); + + afe_priv->audio_spdf_ck = devm_clk_get_optional(afe->dev, "audio_spdf_pd"); + if (IS_ERR(afe_priv->audio_spdf_ck)) + return PTR_ERR(afe_priv->audio_spdf_ck); + + afe_priv->audio_apll_ck = devm_clk_get_optional(afe->dev, "audio_apll_pd"); + if (IS_ERR(afe_priv->audio_apll_ck)) + return PTR_ERR(afe_priv->audio_apll_ck); + return 0; } diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h index 32bef5e2a56d..c9477bc24ee9 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h +++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h @@ -33,6 +33,7 @@ enum { MT2701_MEMIF_UL5, MT2701_MEMIF_DLBT, MT2701_MEMIF_ULBT, + MT2701_MEMIF_HDMI, MT2701_MEMIF_NUM, MT2701_IO_I2S = MT2701_MEMIF_NUM, MT2701_IO_2ND_I2S, @@ -41,6 +42,7 @@ enum { MT2701_IO_5TH_I2S, MT2701_IO_6TH_I2S, MT2701_IO_MRG, + MT2701_IO_HDMI, }; enum { @@ -87,12 +89,16 @@ struct mt2701_soc_variants { }; struct mt2701_afe_private { - struct mt2701_i2s_path *i2s_path; struct clk *base_ck[MT2701_BASE_CLK_NUM]; struct clk *mrgif_ck; + struct clk *hadds2pll_ck; + struct clk *audio_hdmi_ck; + struct clk *audio_spdf_ck; + struct clk *audio_apll_ck; bool mrg_enable[MTK_STREAM_NUM]; const struct mt2701_soc_variants *soc; + struct mt2701_i2s_path i2s_path[]; }; #endif diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index fcae38135d93..d56b498e8c0c 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "mt2701-afe-common.h" #include "mt2701-afe-clock-ctrl.h" @@ -60,6 +61,7 @@ static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = { static const unsigned int mt2701_afe_backup_list[] = { AUDIO_TOP_CON0, + AUDIO_TOP_CON3, AUDIO_TOP_CON4, AUDIO_TOP_CON5, ASYS_TOP_CON, @@ -77,6 +79,9 @@ static const unsigned int mt2701_afe_backup_list[] = { AFE_CONN22, AFE_DAC_CON0, AFE_MEMIF_PBUF_SIZE, + AFE_HDMI_OUT_CON0, + AFE_HDMI_CONN0, + AFE_8CH_I2S_OUT_CON, }; static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num) @@ -542,6 +547,220 @@ static const struct snd_soc_dai_ops mt2701_btmrg_ops = { .hw_params = mt2701_btmrg_hw_params, }; +/* + * HDMI BE DAI -- drives the on-SoC 8-channel I2S engine whose output + * feeds the HDMI transmitter audio port. + * + * The HDMI audio hardware path is: + * HDMI memif DMA (AFE_HDMI_OUT_*) -> interconnect mux (AFE_HDMI_CONN0) + * -> 8-channel I2S engine (AFE_8CH_I2S_OUT_CON) -> HDMI TX audio port + * + * The I2S3 clock tree provides the bit/master clocks; we set its + * mclk_rate to 128*fs (matching HDMI_AUD_MCLK_128FS) and let + * mt2701_mclk_configuration program the PLL/divider path. + */ +#define MT2701_HDMI_I2S_PATH 3 + +static int mt2701_afe_hdmi_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt2701_afe_private *afe_priv = afe->platform_priv; + int ret; + + if (!afe_priv->hadds2pll_ck || !afe_priv->audio_hdmi_ck) { + dev_err(afe->dev, "HDMI audio clocks not available\n"); + return -ENODEV; + } + + ret = clk_prepare_enable(afe_priv->hadds2pll_ck); + if (ret) + return ret; + + ret = clk_prepare_enable(afe_priv->audio_hdmi_ck); + if (ret) + goto err_hdmi; + + if (afe_priv->audio_spdf_ck) { + ret = clk_prepare_enable(afe_priv->audio_spdf_ck); + if (ret) + goto err_spdf; + } + + if (afe_priv->audio_apll_ck) { + ret = clk_prepare_enable(afe_priv->audio_apll_ck); + if (ret) + goto err_apll; + } + + ret = mt2701_afe_enable_mclk(afe, MT2701_HDMI_I2S_PATH); + if (ret) + goto err_mclk; + + return 0; + +err_mclk: + if (afe_priv->audio_apll_ck) + clk_disable_unprepare(afe_priv->audio_apll_ck); +err_apll: + if (afe_priv->audio_spdf_ck) + clk_disable_unprepare(afe_priv->audio_spdf_ck); +err_spdf: + clk_disable_unprepare(afe_priv->audio_hdmi_ck); +err_hdmi: + clk_disable_unprepare(afe_priv->hadds2pll_ck); + return ret; +} + +static void mt2701_afe_hdmi_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt2701_afe_private *afe_priv = afe->platform_priv; + + mt2701_afe_disable_mclk(afe, MT2701_HDMI_I2S_PATH); + if (afe_priv->audio_apll_ck) + clk_disable_unprepare(afe_priv->audio_apll_ck); + if (afe_priv->audio_spdf_ck) + clk_disable_unprepare(afe_priv->audio_spdf_ck); + clk_disable_unprepare(afe_priv->audio_hdmi_ck); + clk_disable_unprepare(afe_priv->hadds2pll_ck); +} + +static int mt2701_afe_hdmi_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt2701_afe_private *afe_priv = afe->platform_priv; + unsigned int channels = params_channels(params); + unsigned int rate = params_rate(params); + unsigned int divp1; + unsigned int val; + unsigned int i; + int ret; + + /* + * Compute AUDIO_TOP_CON3.HDMI_BCK_DIV up front. The divider + * drives an internal reference for the HDMI transmitter's + * audio packet engine; it must scale with the sample rate so + * that the packet engine's timing matches the data flowing in + * from the AFE memif/I2S3 side. Empirically, with audpll_sel + * parented to hadds2pll_98m (98.304 MHz), the correct value at + * 48 kHz is div = 44 (i.e. (div+1) = 45), giving 1.0923 MHz. + * Scaling inversely with rate: (div + 1) = 45 * 48000 / rate. + * Integer rounding introduces small (<1%) errors at 32 kHz; + * 44.1 kHz is nearly exact via round-to-nearest. Reject rates + * that fall outside the 6-bit divider range before touching + * any hardware so no side effects are left behind on error. + */ + divp1 = (45U * 48000U + rate / 2) / rate; + if (divp1 == 0 || divp1 > 64) + return -EINVAL; + + /* + * Park the I2S3 clock tree at 128*fs -- this is the MCLK that + * the ASYS I2S3 engine uses to derive its BCK/LRCK. The engine + * outputs BCK = 64*fs (stereo, 32-bit word length). + */ + afe_priv->i2s_path[MT2701_HDMI_I2S_PATH].mclk_rate = rate * 128; + ret = mt2701_mclk_configuration(afe, MT2701_HDMI_I2S_PATH); + if (ret) + return ret; + + /* Program and start the ASYS I2S3 engine (FS, I2S mode, enable). */ + mt2701_i2s_path_enable(afe, + &afe_priv->i2s_path[MT2701_HDMI_I2S_PATH], + SNDRV_PCM_STREAM_PLAYBACK, rate); + + regmap_update_bits(afe->regmap, AUDIO_TOP_CON3, + AUDIO_TOP_CON3_HDMI_BCK_DIV_MASK, + AUDIO_TOP_CON3_HDMI_BCK_DIV(divp1 - 1)); + + /* + * HDMI output memif: set channel count and confirm 16-bit + * sample width. Both fields must be written together so that + * stale reset-default or prior-stream values in BIT_WIDTH + * cannot persist. + */ + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, + AFE_HDMI_OUT_CON0_CH_NUM_MASK | + AFE_HDMI_OUT_CON0_BIT_WIDTH_MASK, + AFE_HDMI_OUT_CON0_CH_NUM(channels) | + AFE_HDMI_OUT_CON0_BIT_WIDTH_16); + + /* + * Interconnect mux -- map DMA input slots to HDMI output slots. + * Each output takes a 3-bit field at shift (i*3). Swap the first + * two inputs so that the DMA's interleaved L/R pair lands on the + * correct HDMI L/R output slots. Remaining slots are identity. + */ + val = (1 << 0) | (0 << 3); /* O20 <- I21, O21 <- I20 */ + for (i = 2; i < 8; i++) + val |= ((i & 0x7) << (i * 3)); + regmap_write(afe->regmap, AFE_HDMI_CONN0, val); + + /* + * 8-channel I2S framing: standard I2S, 32-bit slots, + * LRCK/BCK inverted. The wire protocol is fixed. + */ + regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON, + AFE_8CH_I2S_OUT_CON_WLEN_MASK | + AFE_8CH_I2S_OUT_CON_I2S_DELAY | + AFE_8CH_I2S_OUT_CON_LRCK_INV | + AFE_8CH_I2S_OUT_CON_BCK_INV, + AFE_8CH_I2S_OUT_CON_WLEN_32BIT | + AFE_8CH_I2S_OUT_CON_I2S_DELAY | + AFE_8CH_I2S_OUT_CON_LRCK_INV | + AFE_8CH_I2S_OUT_CON_BCK_INV); + return 0; +} + +static int mt2701_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + /* Enable HDMI output memif. */ + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0x1); + /* Enable 8-channel I2S engine. */ + regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON, + AFE_8CH_I2S_OUT_CON_EN, + AFE_8CH_I2S_OUT_CON_EN); + return 0; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON, + AFE_8CH_I2S_OUT_CON_EN, 0); + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0); + return 0; + } + return -EINVAL; +} + +static int mt2701_afe_hdmi_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt2701_afe_private *afe_priv = afe->platform_priv; + + mt2701_afe_i2s_path_disable(afe, + &afe_priv->i2s_path[MT2701_HDMI_I2S_PATH], + SNDRV_PCM_STREAM_PLAYBACK); + return 0; +} + +static const struct snd_soc_dai_ops mt2701_afe_hdmi_ops = { + .startup = mt2701_afe_hdmi_startup, + .shutdown = mt2701_afe_hdmi_shutdown, + .hw_params = mt2701_afe_hdmi_hw_params, + .hw_free = mt2701_afe_hdmi_hw_free, + .trigger = mt2701_afe_hdmi_trigger, +}; + static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { /* FE DAIs: memory intefaces to CPU */ { @@ -628,6 +847,19 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { }, .ops = &mt2701_single_memif_dai_ops, }, + { + .name = "PCM_HDMI", + .id = MT2701_MEMIF_HDMI, + .playback = { + .stream_name = "HDMI Multich", + .channels_min = 2, + .channels_max = 8, + .rates = (SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &mt2701_single_memif_dai_ops, + }, /* BE DAIs */ { .name = "I2S0", @@ -748,7 +980,20 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { }, .ops = &mt2701_btmrg_ops, .symmetric_rate = 1, - } + }, + { + .name = "HDMI I2S", + .id = MT2701_IO_HDMI, + .playback = { + .stream_name = "HDMI 8CH I2S Playback", + .channels_min = 2, + .channels_max = 8, + .rates = (SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000), + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .ops = &mt2701_afe_hdmi_ops, + }, }; static const struct snd_kcontrol_new mt2701_afe_o00_mix[] = { @@ -927,6 +1172,14 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { {"I16I17", "Multich I2S2 Out Switch", "DLM"}, {"I18I19", "Multich I2S3 Out Switch", "DLM"}, + /* + * HDMI FE -> BE direct route. The HDMI memif has its own DMA + * path that feeds the 8-channel internal I2S straight into the + * HDMI transmitter; no mixer/interconnect selection is exposed + * to the user. + */ + {"HDMI 8CH I2S Playback", NULL, "HDMI Multich"}, + { "I12", NULL, "I12I13" }, { "I13", NULL, "I12I13" }, { "I14", NULL, "I14I15" }, @@ -1207,6 +1460,35 @@ static const struct mtk_base_memif_data memif_data_array[MT2701_MEMIF_NUM] = { .agent_disable_shift = 16, .msb_reg = -1, }, + { + /* + * HDMI memif feeds the on-SoC 8-channel internal I2S that + * drives the HDMI transmitter audio port. Unlike the + * standard memifs, the enable bit, channel count and bit + * width all live in AFE_HDMI_OUT_CON0, so mono/fs/hd/agent + * fields are left at -1 and programmed from the BE DAI ops + * instead. + */ + .name = "HDMI", + .id = MT2701_MEMIF_HDMI, + .reg_ofs_base = AFE_HDMI_OUT_BASE, + .reg_ofs_cur = AFE_HDMI_OUT_CUR, + .reg_ofs_end = AFE_HDMI_OUT_END, + .fs_reg = -1, + .fs_shift = -1, + .fs_maskbit = 0, + .mono_reg = -1, + .mono_shift = -1, + .enable_reg = AFE_HDMI_OUT_CON0, + .enable_shift = 0, + .hd_reg = -1, + .hd_shift = -1, + .hd_align_reg = -1, + .hd_align_mshift = 0, + .agent_disable_reg = -1, + .agent_disable_shift = 0, + .msb_reg = -1, + }, }; static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = { @@ -1311,6 +1593,7 @@ static int mt2701_afe_runtime_resume(struct device *dev) static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) { + const struct mt2701_soc_variants *soc; struct mtk_base_afe *afe; struct mt2701_afe_private *afe_priv; struct device *dev; @@ -1320,23 +1603,19 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) if (!afe) return -ENOMEM; - afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), - GFP_KERNEL); - if (!afe->platform_priv) + soc = of_device_get_match_data(&pdev->dev); + afe_priv = devm_kzalloc(&pdev->dev, + struct_size(afe_priv, i2s_path, soc->i2s_num), + GFP_KERNEL); + if (!afe_priv) return -ENOMEM; - afe_priv = afe->platform_priv; - afe_priv->soc = of_device_get_match_data(&pdev->dev); + afe_priv->soc = soc; + + afe->platform_priv = afe_priv; afe->dev = &pdev->dev; dev = afe->dev; - afe_priv->i2s_path = devm_kcalloc(dev, - afe_priv->soc->i2s_num, - sizeof(struct mt2701_i2s_path), - GFP_KERNEL); - if (!afe_priv->i2s_path) - return -ENOMEM; - irq_id = platform_get_irq_byname(pdev, "asys"); if (irq_id < 0) return irq_id; diff --git a/sound/soc/mediatek/mt2701/mt2701-hdmi.c b/sound/soc/mediatek/mt2701/mt2701-hdmi.c new file mode 100644 index 000000000000..a84907879c04 --- /dev/null +++ b/sound/soc/mediatek/mt2701/mt2701-hdmi.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mt2701-hdmi.c -- MT2701 HDMI ALSA SoC machine driver + * + * Copyright (c) 2026 Daniel Golle + * + * Based on mt2701-cs42448.c + */ + +#include +#include +#include +#include + +enum { + DAI_LINK_FE_HDMI_OUT, + DAI_LINK_BE_HDMI_I2S, +}; + +SND_SOC_DAILINK_DEFS(fe_hdmi_out, + DAILINK_COMP_ARRAY(COMP_CPU("PCM_HDMI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(be_hdmi_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI I2S")), + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link mt2701_hdmi_dai_links[] = { + [DAI_LINK_FE_HDMI_OUT] = { + .name = "HDMI Playback", + .stream_name = "HDMI Playback", + .trigger = { SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST }, + .dynamic = 1, + .playback_only = 1, + SND_SOC_DAILINK_REG(fe_hdmi_out), + }, + [DAI_LINK_BE_HDMI_I2S] = { + .name = "HDMI BE", + .no_pcm = 1, + .playback_only = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBC_CFC, + SND_SOC_DAILINK_REG(be_hdmi_i2s), + }, +}; + +static struct snd_soc_card mt2701_hdmi_soc_card = { + .name = "mt2701-hdmi", + .owner = THIS_MODULE, + .dai_link = mt2701_hdmi_dai_links, + .num_links = ARRAY_SIZE(mt2701_hdmi_dai_links), +}; + +static int mt2701_hdmi_machine_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &mt2701_hdmi_soc_card; + struct device *dev = &pdev->dev; + struct device_node *platform_node; + struct device_node *codec_node; + struct snd_soc_dai_link *dai_link; + int ret; + int i; + + platform_node = of_parse_phandle(dev->of_node, "mediatek,platform", 0); + if (!platform_node) + return dev_err_probe(dev, -EINVAL, + "Property 'mediatek,platform' missing\n"); + + for_each_card_prelinks(card, i, dai_link) { + if (dai_link->platforms->name) + continue; + dai_link->platforms->of_node = platform_node; + } + + codec_node = of_parse_phandle(dev->of_node, "mediatek,audio-codec", 0); + if (!codec_node) { + of_node_put(platform_node); + return dev_err_probe(dev, -EINVAL, + "Property 'mediatek,audio-codec' missing\n"); + } + mt2701_hdmi_dai_links[DAI_LINK_BE_HDMI_I2S].codecs->of_node = codec_node; + + card->dev = dev; + + ret = devm_snd_soc_register_card(dev, card); + + of_node_put(platform_node); + of_node_put(codec_node); + return ret; +} + +static const struct of_device_id mt2701_hdmi_machine_dt_match[] = { + { .compatible = "mediatek,mt2701-hdmi-audio" }, + { .compatible = "mediatek,mt7623n-hdmi-audio" }, + {} +}; +MODULE_DEVICE_TABLE(of, mt2701_hdmi_machine_dt_match); + +static struct platform_driver mt2701_hdmi_machine = { + .driver = { + .name = "mt2701-hdmi", + .of_match_table = mt2701_hdmi_machine_dt_match, + }, + .probe = mt2701_hdmi_machine_probe, +}; +module_platform_driver(mt2701_hdmi_machine); + +MODULE_DESCRIPTION("MT2701 HDMI ALSA SoC machine driver"); +MODULE_AUTHOR("Daniel Golle "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mt2701-hdmi"); diff --git a/sound/soc/mediatek/mt2701/mt2701-reg.h b/sound/soc/mediatek/mt2701/mt2701-reg.h index c84d14cdd7ae..ca914df02c96 100644 --- a/sound/soc/mediatek/mt2701/mt2701-reg.h +++ b/sound/soc/mediatek/mt2701/mt2701-reg.h @@ -10,10 +10,17 @@ #define _MT2701_REG_H_ #define AUDIO_TOP_CON0 0x0000 +#define AUDIO_TOP_CON3 0x000c #define AUDIO_TOP_CON4 0x0010 #define AUDIO_TOP_CON5 0x0014 #define AFE_DAIBT_CON0 0x001c #define AFE_MRGIF_CON 0x003c +#define AFE_HDMI_OUT_CON0 0x0370 +#define AFE_HDMI_OUT_BASE 0x0374 +#define AFE_HDMI_OUT_CUR 0x0378 +#define AFE_HDMI_OUT_END 0x037c +#define AFE_HDMI_CONN0 0x0390 +#define AFE_8CH_I2S_OUT_CON 0x0394 #define ASMI_TIMING_CON1 0x0100 #define ASMO_TIMING_CON1 0x0104 #define PWR1_ASM_CON1 0x0108 @@ -125,6 +132,28 @@ #define AFE_MEMIF_PBUF_SIZE_DLM_BYTE_MASK (0x3 << 12) #define AFE_MEMIF_PBUF_SIZE_DLM_32BYTES (0x1 << 12) +/* AUDIO_TOP_CON3 (0x000c) -- HDMI BCK divider */ +#define AUDIO_TOP_CON3_HDMI_BCK_DIV_MASK (0x3f << 8) +#define AUDIO_TOP_CON3_HDMI_BCK_DIV(x) (((x) & 0x3f) << 8) + +/* AFE_HDMI_OUT_CON0 (0x0370) */ +#define AFE_HDMI_OUT_CON0_OUT_ON (0x1 << 0) +#define AFE_HDMI_OUT_CON0_BIT_WIDTH_MASK (0x1 << 1) +#define AFE_HDMI_OUT_CON0_BIT_WIDTH_16 (0x0 << 1) +#define AFE_HDMI_OUT_CON0_BIT_WIDTH_32 (0x1 << 1) +#define AFE_HDMI_OUT_CON0_CH_NUM_MASK (0xf << 4) +#define AFE_HDMI_OUT_CON0_CH_NUM(x) (((x) & 0xf) << 4) + +/* AFE_8CH_I2S_OUT_CON (0x0394) -- on-SoC 8-channel I2S that feeds HDMI TX */ +#define AFE_8CH_I2S_OUT_CON_EN (0x1 << 0) +#define AFE_8CH_I2S_OUT_CON_BCK_INV (0x1 << 1) +#define AFE_8CH_I2S_OUT_CON_LRCK_INV (0x1 << 2) +#define AFE_8CH_I2S_OUT_CON_I2S_DELAY (0x1 << 3) +#define AFE_8CH_I2S_OUT_CON_WLEN_MASK (0x3 << 4) +#define AFE_8CH_I2S_OUT_CON_WLEN_16BIT (0x1 << 4) +#define AFE_8CH_I2S_OUT_CON_WLEN_24BIT (0x2 << 4) +#define AFE_8CH_I2S_OUT_CON_WLEN_32BIT (0x3 << 4) + /* I2S in/out register bit control */ #define ASYS_I2S_CON_FS (0x1f << 8) #define ASYS_I2S_CON_FS_SET(x) ((x) << 8) diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index c0fa623e0b17..69cadc91c97f 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -676,6 +676,7 @@ static const struct snd_soc_component_driver mt8173_afe_pcm_dai_component = { .num_dapm_routes = ARRAY_SIZE(mt8173_afe_pcm_routes), .suspend = mtk_afe_suspend, .resume = mtk_afe_resume, + .debugfs_prefix = "pcm", }; static const struct snd_soc_component_driver mt8173_afe_hdmi_dai_component = { @@ -684,6 +685,7 @@ static const struct snd_soc_component_driver mt8173_afe_hdmi_dai_component = { .num_dapm_routes = ARRAY_SIZE(mt8173_afe_hdmi_routes), .suspend = mtk_afe_suspend, .resume = mtk_afe_resume, + .debugfs_prefix = "hdmi", }; static const char *aud_clks[MT8173_CLK_NUM] = { @@ -1053,7 +1055,6 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) int irq_id; struct mtk_base_afe *afe; struct mt8173_afe_private *afe_priv; - struct snd_soc_component *comp_pcm, *comp_hdmi; struct device *dev = &pdev->dev; ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33)); @@ -1141,45 +1142,13 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) goto err_pm_disable; - comp_pcm = devm_kzalloc(dev, sizeof(*comp_pcm), GFP_KERNEL); - if (!comp_pcm) { - ret = -ENOMEM; - goto err_pm_disable; - } - - ret = snd_soc_component_initialize(comp_pcm, - &mt8173_afe_pcm_dai_component, - dev); - if (ret) - goto err_pm_disable; - -#ifdef CONFIG_DEBUG_FS - comp_pcm->debugfs_prefix = "pcm"; -#endif - - ret = snd_soc_add_component(comp_pcm, + ret = snd_soc_register_component(dev, &mt8173_afe_pcm_dai_component, mt8173_afe_pcm_dais, ARRAY_SIZE(mt8173_afe_pcm_dais)); if (ret) goto err_pm_disable; - comp_hdmi = devm_kzalloc(dev, sizeof(*comp_hdmi), GFP_KERNEL); - if (!comp_hdmi) { - ret = -ENOMEM; - goto err_cleanup_components; - } - - ret = snd_soc_component_initialize(comp_hdmi, - &mt8173_afe_hdmi_dai_component, - dev); - if (ret) - goto err_cleanup_components; - -#ifdef CONFIG_DEBUG_FS - comp_hdmi->debugfs_prefix = "hdmi"; -#endif - - ret = snd_soc_add_component(comp_hdmi, + ret = snd_soc_register_component(dev, &mt8173_afe_hdmi_dai_component, mt8173_afe_hdmi_dais, ARRAY_SIZE(mt8173_afe_hdmi_dais)); if (ret) diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c index 49ebb67c818a..7533c6e4955b 100644 --- a/sound/soc/mediatek/mt8173/mt8173-max98090.c +++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c @@ -1,3 +1,4 @@ + // SPDX-License-Identifier: GPL-2.0 /* * mt8173-max98090.c -- MT8173 MAX98090 ALSA SoC machine driver @@ -9,7 +10,6 @@ #include #include #include -#include "../../codecs/max98090.h" static struct snd_soc_jack mt8173_max98090_jack; @@ -78,7 +78,7 @@ static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime) return ret; } - return max98090_mic_detect(component, &mt8173_max98090_jack); + return snd_soc_component_set_jack(component, &mt8173_max98090_jack, NULL); } SND_SOC_DAILINK_DEFS(playback, diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index a7fef772760a..2634699534db 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -766,6 +766,11 @@ static const dai_register_cb dai_register_cbs[] = { mt8183_dai_memif_register, }; +static void mt8183_afe_release_reserved_mem(void *data) +{ + of_reserved_mem_device_release(data); +} + static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) { struct mtk_base_afe *afe; @@ -794,6 +799,12 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) { dev_info(dev, "no reserved memory found, pre-allocating buffers instead\n"); afe->preallocate_buffers = true; + } else { + ret = devm_add_action_or_reset(dev, + mt8183_afe_release_reserved_mem, + dev); + if (ret) + return ret; } /* initial audio related clock */ @@ -833,17 +844,21 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) /* enable clock for regcache get default value from hw */ afe_priv->pm_runtime_bypass_reg_ctl = true; - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) { + afe_priv->pm_runtime_bypass_reg_ctl = false; + goto err_pm_disable; + } ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config); + pm_runtime_put_sync(dev); + afe_priv->pm_runtime_bypass_reg_ctl = false; + if (ret) { dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret); goto err_pm_disable; } - pm_runtime_put_sync(dev); - afe_priv->pm_runtime_bypass_reg_ctl = false; - regcache_cache_only(afe->regmap, true); regcache_mark_dirty(afe->regmap); diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c index 9e86e7079718..aced8e7e920c 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -201,7 +201,7 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable, enum mt8186_afe_gpio sel; int ret = -EINVAL; - mutex_lock(&gpio_request_mutex); + guard(mutex)(&gpio_request_mutex); switch (dai) { case MT8186_DAI_ADDA: @@ -209,7 +209,7 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable, ret = mt8186_afe_gpio_adda_ul(dev, enable); else ret = mt8186_afe_gpio_adda_dl(dev, enable); - goto unlock; + return ret; case MT8186_DAI_I2S_0: sel = enable ? MT8186_AFE_GPIO_I2S0_ON : MT8186_AFE_GPIO_I2S0_OFF; break; @@ -230,13 +230,8 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable, break; default: dev_dbg(dev, "%s(), invalid dai %d\n", __func__, dai); - goto unlock; + return ret; } - ret = mt8186_afe_gpio_select(dev, sel); - -unlock: - mutex_unlock(&gpio_request_mutex); - - return ret; + return mt8186_afe_gpio_select(dev, sel); } diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c index e325d216c008..5a34d3f7fa58 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c @@ -39,7 +39,7 @@ int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL_GPL(mt8186_mt6366_init); -int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card, +int mt8186_mt6366_card_set_be_link(struct device *dev, struct snd_soc_dai_link *link, struct device_node *node, char *link_name) @@ -47,9 +47,9 @@ int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card, int ret; if (node && strcmp(link->name, link_name) == 0) { - ret = snd_soc_of_get_dai_link_codecs(card->dev, node, link); + ret = snd_soc_of_get_dai_link_codecs(dev, node, link); if (ret < 0) - return dev_err_probe(card->dev, ret, "get dai link codecs fail\n"); + return dev_err_probe(dev, ret, "get dai link codecs fail\n"); } return 0; diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h index 907d8f5e46b1..2094e786c623 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h @@ -10,7 +10,7 @@ #define _MT8186_MT6366_COMMON_H_ int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd); -int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card, +int mt8186_mt6366_card_set_be_link(struct device *dev, struct snd_soc_dai_link *link, struct device_node *node, char *link_name); diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366.c b/sound/soc/mediatek/mt8186/mt8186-mt6366.c index 2c3033f305ea..22123b087c3c 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366.c @@ -1178,21 +1178,21 @@ static int mt8186_mt6366_legacy_probe(struct mtk_soc_card_data *soc_card_data) } for_each_card_prelinks(card, i, dai_link) { - ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); + ret = mt8186_mt6366_card_set_be_link(dev, dai_link, playback_codec, "I2S3"); if (ret) { dev_err_probe(dev, ret, "%s set playback_codec fail\n", dai_link->name); break; } - ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); + ret = mt8186_mt6366_card_set_be_link(dev, dai_link, headset_codec, "I2S0"); if (ret) { dev_err_probe(dev, ret, "%s set headset_codec fail\n", dai_link->name); break; } - ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); + ret = mt8186_mt6366_card_set_be_link(dev, dai_link, headset_codec, "I2S1"); if (ret) { dev_err_probe(dev, ret, "%s set headset_codec fail\n", dai_link->name); @@ -1211,18 +1211,18 @@ static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data, struct snd_soc_card *card = card_data->card; struct snd_soc_dai_link *dai_link; struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv; + struct device *dev = card->dev; int i, ret; - mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL); + mach_priv = devm_kzalloc(dev, sizeof(*mach_priv), GFP_KERNEL); if (!mach_priv) return -ENOMEM; soc_card_data->mach_priv = mach_priv; - mach_priv->dmic_sel = devm_gpiod_get_optional(card->dev, - "dmic", GPIOD_OUT_LOW); + mach_priv->dmic_sel = devm_gpiod_get_optional(dev, "dmic", GPIOD_OUT_LOW); if (IS_ERR(mach_priv->dmic_sel)) - return dev_err_probe(card->dev, PTR_ERR(mach_priv->dmic_sel), + return dev_err_probe(dev, PTR_ERR(mach_priv->dmic_sel), "DMIC gpio failed\n"); for_each_card_prelinks(card, i, dai_link) { @@ -1250,9 +1250,9 @@ static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data, return ret; } - ret = mt8186_afe_gpio_init(card->dev); + ret = mt8186_afe_gpio_init(dev); if (ret) - return dev_err_probe(card->dev, ret, "init AFE gpio error\n"); + return dev_err_probe(dev, ret, "init AFE gpio error\n"); return 0; } diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c index 7f411b857782..fc6cb3f0469e 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c @@ -301,7 +301,6 @@ static int mt8188_afe_disable_tuner_clk(struct mtk_base_afe *afe, static int mt8188_afe_enable_apll_tuner(struct mtk_base_afe *afe, unsigned int id) { struct mt8188_afe_tuner_cfg *cfg = mt8188_afe_found_apll_tuner(id); - unsigned long flags; int ret; if (!cfg) @@ -315,8 +314,7 @@ static int mt8188_afe_enable_apll_tuner(struct mtk_base_afe *afe, unsigned int i if (ret) return ret; - spin_lock_irqsave(&cfg->ctrl_lock, flags); - + guard(spinlock_irqsave)(&cfg->ctrl_lock); cfg->ref_cnt++; if (cfg->ref_cnt == 1) regmap_update_bits(afe->regmap, @@ -324,32 +322,27 @@ static int mt8188_afe_enable_apll_tuner(struct mtk_base_afe *afe, unsigned int i cfg->tuner_en_maskbit << cfg->tuner_en_shift, BIT(cfg->tuner_en_shift)); - spin_unlock_irqrestore(&cfg->ctrl_lock, flags); - return 0; } static int mt8188_afe_disable_apll_tuner(struct mtk_base_afe *afe, unsigned int id) { struct mt8188_afe_tuner_cfg *cfg = mt8188_afe_found_apll_tuner(id); - unsigned long flags; int ret; if (!cfg) return -EINVAL; - spin_lock_irqsave(&cfg->ctrl_lock, flags); - - cfg->ref_cnt--; - if (cfg->ref_cnt == 0) - regmap_update_bits(afe->regmap, - cfg->tuner_en_reg, - cfg->tuner_en_maskbit << cfg->tuner_en_shift, - 0 << cfg->tuner_en_shift); - else if (cfg->ref_cnt < 0) - cfg->ref_cnt = 0; - - spin_unlock_irqrestore(&cfg->ctrl_lock, flags); + scoped_guard(spinlock_irqsave, &cfg->ctrl_lock) { + cfg->ref_cnt--; + if (cfg->ref_cnt == 0) + regmap_update_bits(afe->regmap, + cfg->tuner_en_reg, + cfg->tuner_en_maskbit << cfg->tuner_en_shift, + 0 << cfg->tuner_en_shift); + else if (cfg->ref_cnt < 0) + cfg->ref_cnt = 0; + } ret = mt8188_afe_disable_tuner_clk(afe, id); if (ret) diff --git a/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c b/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c index 24b0c78815f6..77cf2b604f6c 100644 --- a/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c +++ b/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c @@ -2351,9 +2351,13 @@ static int mt8189_afe_runtime_resume(struct device *dev) static int mt8189_afe_component_probe(struct snd_soc_component *component) { struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + int ret; /* enable clock for regcache get default value from hw */ - pm_runtime_get_sync(afe->dev); + ret = pm_runtime_resume_and_get(afe->dev); + if (ret) + return dev_err_probe(afe->dev, ret, "failed to resume device\n"); + mtk_afe_add_sub_dai_control(component); pm_runtime_put_sync(afe->dev); @@ -2417,6 +2421,11 @@ static const struct reg_sequence mt8189_cg_patch[] = { { AUDIO_TOP_CON4, 0x361c }, }; +static void mt8189_afe_release_reserved_mem(void *data) +{ + of_reserved_mem_device_release(data); +} + static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev) { int ret, i; @@ -2431,8 +2440,15 @@ static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev) return ret; ret = of_reserved_mem_device_init(dev); - if (ret) + if (ret) { dev_warn(dev, "failed to assign memory region: %d\n", ret); + } else { + ret = devm_add_action_or_reset(dev, + mt8189_afe_release_reserved_mem, + dev); + if (ret) + return ret; + } afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL); if (!afe) @@ -2533,18 +2549,22 @@ static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev) dev_pm_syscore_device(dev, true); /* enable clock for regcache get default value from hw */ - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return dev_err_probe(dev, ret, "failed to resume device\n"); afe->regmap = devm_regmap_init_mmio(dev, afe->base_addr, &mt8189_afe_regmap_config); - if (IS_ERR(afe->regmap)) - return PTR_ERR(afe->regmap); + if (IS_ERR(afe->regmap)) { + ret = PTR_ERR(afe->regmap); + goto err_pm_put; + } ret = regmap_register_patch(afe->regmap, mt8189_cg_patch, ARRAY_SIZE(mt8189_cg_patch)); if (ret < 0) { dev_err(dev, "Failed to apply cg patch\n"); - goto err_pm_disable; + goto err_pm_put; } regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg); @@ -2563,12 +2583,12 @@ static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev) afe->num_dai_drivers); if (ret) { dev_err(dev, "afe component err: %d\n", ret); - goto err_pm_disable; + return ret; } return 0; -err_pm_disable: +err_pm_put: pm_runtime_put_sync(dev); return ret; } @@ -2578,14 +2598,12 @@ static void mt8189_afe_pcm_dev_remove(struct platform_device *pdev) struct mtk_base_afe *afe = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; - pm_runtime_put_sync(dev); if (!pm_runtime_status_suspended(dev)) mt8189_afe_runtime_suspend(dev); mt8189_afe_disable_main_clock(afe); /* disable afe clock */ mt8189_afe_disable_reg_rw_clk(afe); - of_reserved_mem_device_release(dev); } static const struct of_device_id mt8189_afe_pcm_dt_match[] = { diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c b/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c index de5e1deaa167..b993ca2dbd7c 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c @@ -208,7 +208,7 @@ static int mt8192_afe_gpio_adda_ch34_ul(struct device *dev, bool enable) int mt8192_afe_gpio_request(struct device *dev, bool enable, int dai, int uplink) { - mutex_lock(&gpio_request_mutex); + guard(mutex)(&gpio_request_mutex); switch (dai) { case MT8192_DAI_ADDA: if (uplink) @@ -296,11 +296,9 @@ int mt8192_afe_gpio_request(struct device *dev, bool enable, } break; default: - mutex_unlock(&gpio_request_mutex); dev_warn(dev, "%s(), invalid dai %d\n", __func__, dai); return -EINVAL; } - mutex_unlock(&gpio_request_mutex); return 0; } diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index 3d32fe46118e..db0ae44a86af 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2155,6 +2155,11 @@ static const dai_register_cb dai_register_cbs[] = { mt8192_dai_memif_register, }; +static void mt8192_afe_release_reserved_mem(void *data) +{ + of_reserved_mem_device_release(data); +} + static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) { struct mtk_base_afe *afe; @@ -2184,6 +2189,10 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) { dev_info(dev, "no reserved memory found, pre-allocating buffers instead\n"); afe->preallocate_buffers = true; + } else { + ret = devm_add_action_or_reset(dev, mt8192_afe_release_reserved_mem, dev); + if (ret) + return ret; } /* init audio related clock */ @@ -2218,15 +2227,19 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) /* enable clock for regcache get default value from hw */ afe_priv->pm_runtime_bypass_reg_ctl = true; - pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) { + afe_priv->pm_runtime_bypass_reg_ctl = false; + return dev_err_probe(dev, ret, "failed to resume device\n"); + } ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config); - if (ret) - return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n"); - pm_runtime_put_sync(dev); afe_priv->pm_runtime_bypass_reg_ctl = false; + if (ret) + return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n"); + regcache_cache_only(afe->regmap, true); regcache_mark_dirty(afe->regmap); diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c index f35318ae0739..618d8400913a 100644 --- a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c +++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c @@ -283,7 +283,6 @@ static int mt8195_afe_enable_apll_tuner(struct mtk_base_afe *afe, unsigned int id) { struct mt8195_afe_tuner_cfg *cfg = mt8195_afe_found_apll_tuner(id); - unsigned long flags; int ret; if (!cfg) @@ -297,16 +296,14 @@ static int mt8195_afe_enable_apll_tuner(struct mtk_base_afe *afe, if (ret) return ret; - spin_lock_irqsave(&cfg->ctrl_lock, flags); - - cfg->ref_cnt++; - if (cfg->ref_cnt == 1) - regmap_update_bits(afe->regmap, - cfg->tuner_en_reg, - cfg->tuner_en_maskbit << cfg->tuner_en_shift, - 1 << cfg->tuner_en_shift); - - spin_unlock_irqrestore(&cfg->ctrl_lock, flags); + scoped_guard(spinlock_irqsave, &cfg->ctrl_lock) { + cfg->ref_cnt++; + if (cfg->ref_cnt == 1) + regmap_update_bits(afe->regmap, + cfg->tuner_en_reg, + cfg->tuner_en_maskbit << cfg->tuner_en_shift, + 1 << cfg->tuner_en_shift); + } return 0; } @@ -315,24 +312,21 @@ static int mt8195_afe_disable_apll_tuner(struct mtk_base_afe *afe, unsigned int id) { struct mt8195_afe_tuner_cfg *cfg = mt8195_afe_found_apll_tuner(id); - unsigned long flags; int ret; if (!cfg) return -EINVAL; - spin_lock_irqsave(&cfg->ctrl_lock, flags); - - cfg->ref_cnt--; - if (cfg->ref_cnt == 0) - regmap_update_bits(afe->regmap, - cfg->tuner_en_reg, - cfg->tuner_en_maskbit << cfg->tuner_en_shift, - 0 << cfg->tuner_en_shift); - else if (cfg->ref_cnt < 0) - cfg->ref_cnt = 0; - - spin_unlock_irqrestore(&cfg->ctrl_lock, flags); + scoped_guard(spinlock_irqsave, &cfg->ctrl_lock) { + cfg->ref_cnt--; + if (cfg->ref_cnt == 0) + regmap_update_bits(afe->regmap, + cfg->tuner_en_reg, + cfg->tuner_en_maskbit << cfg->tuner_en_shift, + 0 << cfg->tuner_en_shift); + else if (cfg->ref_cnt < 0) + cfg->ref_cnt = 0; + } ret = mt8195_afe_disable_tuner_clk(afe, id); if (ret) diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c index 5dcc8ed26e00..1a20adb2cbf5 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c @@ -1318,24 +1318,22 @@ static int mt8195_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id) struct etdm_con_reg etdm_reg; struct mt8195_afe_private *afe_priv = afe->platform_priv; struct mtk_dai_etdm_priv *etdm_data; - unsigned long flags; if (!mt8195_afe_etdm_is_valid(dai_id)) return -EINVAL; etdm_data = afe_priv->dai_priv[dai_id]; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); etdm_data->en_ref_cnt++; if (etdm_data->en_ref_cnt == 1) { ret = get_etdm_reg(dai_id, &etdm_reg); if (ret < 0) - goto out; + return ret; regmap_update_bits(afe->regmap, etdm_reg.con0, ETDM_CON0_EN, ETDM_CON0_EN); } -out: - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + return ret; } @@ -1345,26 +1343,24 @@ static int mt8195_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id) struct etdm_con_reg etdm_reg; struct mt8195_afe_private *afe_priv = afe->platform_priv; struct mtk_dai_etdm_priv *etdm_data; - unsigned long flags; if (!mt8195_afe_etdm_is_valid(dai_id)) return -EINVAL; etdm_data = afe_priv->dai_priv[dai_id]; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); if (etdm_data->en_ref_cnt > 0) { etdm_data->en_ref_cnt--; if (etdm_data->en_ref_cnt == 0) { ret = get_etdm_reg(dai_id, &etdm_reg); if (ret < 0) - goto out; + return ret; regmap_update_bits(afe->regmap, etdm_reg.con0, ETDM_CON0_EN, 0); } } -out: - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + return ret; } diff --git a/sound/soc/mediatek/mt8196/Makefile b/sound/soc/mediatek/mt8196/Makefile new file mode 100644 index 000000000000..91de200071d7 --- /dev/null +++ b/sound/soc/mediatek/mt8196/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 + +# platform driver +snd-soc-mt8196-afe-objs += \ + mt8196-afe-pcm.o \ + mt8196-afe-clk.o \ + mt8196-dai-adda.o \ + mt8196-dai-i2s.o \ + mt8196-dai-tdm.o + +obj-$(CONFIG_SND_SOC_MT8196) += snd-soc-mt8196-afe.o + +# machine driver +obj-$(CONFIG_SND_SOC_MT8196_NAU8825) += mt8196-nau8825.o diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.c b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c new file mode 100644 index 000000000000..286e39f53ae0 --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c @@ -0,0 +1,581 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mt8196-afe-clk.c -- Mediatek 8196 afe clock ctrl + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#include +#include +#include + +#include "mt8196-afe-clk.h" +#include "mt8196-afe-common.h" + +static const char *aud_clks[MT8196_CLK_NUM] = { + /* vlp clk */ + [MT8196_CLK_VLP_MUX_AUDIOINTBUS] = "top_aud_intbus", + [MT8196_CLK_VLP_MUX_AUD_ENG1] = "top_aud_eng1", + [MT8196_CLK_VLP_MUX_AUD_ENG2] = "top_aud_eng2", + [MT8196_CLK_VLP_MUX_AUDIO_H] = "top_aud_h", + /* pll */ + [MT8196_CLK_TOP_APLL1_CK] = "apll1", + [MT8196_CLK_TOP_APLL2_CK] = "apll2", + /* divider */ + [MT8196_CLK_TOP_APLL12_DIV_I2SIN0] = "apll12_div_i2sin0", + [MT8196_CLK_TOP_APLL12_DIV_I2SIN1] = "apll12_div_i2sin1", + [MT8196_CLK_TOP_APLL12_DIV_FMI2S] = "apll12_div_fmi2s", + [MT8196_CLK_TOP_APLL12_DIV_TDMOUT_M] = "apll12_div_tdmout_m", + [MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B] = "apll12_div_tdmout_b", + /* mux */ + [MT8196_CLK_TOP_ADSP_SEL] = "top_adsp", +}; + +int mt8196_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + int ret; + + ret = clk_prepare_enable(clk); + if (ret) { + dev_err(afe->dev, "failed to enable clk\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt8196_afe_enable_clk); + +void mt8196_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + if (clk) + clk_disable_unprepare(clk); + else + dev_err(afe->dev, "NULL clk\n"); +} +EXPORT_SYMBOL_GPL(mt8196_afe_disable_clk); + +static int mt8196_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, + unsigned int rate) +{ + int ret; + + if (clk) { + ret = clk_set_rate(clk, rate); + if (ret) { + dev_err(afe->dev, "failed to set clk rate\n"); + return ret; + } + } + + return 0; +} + +static unsigned int get_top_cg_reg(unsigned int cg_type) +{ + switch (cg_type) { + case MT8196_AUDIO_26M_EN_ON: + case MT8196_AUDIO_F3P25M_EN_ON: + case MT8196_AUDIO_APLL1_EN_ON: + case MT8196_AUDIO_APLL2_EN_ON: + return AUDIO_ENGEN_CON0; + case MT8196_CG_AUDIO_HOPPING_CK: + case MT8196_CG_AUDIO_F26M_CK: + case MT8196_CG_APLL1_CK: + case MT8196_CG_APLL2_CK: + case MT8196_PDN_APLL_TUNER2: + case MT8196_PDN_APLL_TUNER1: + return AUDIO_TOP_CON4; + default: + return 0; + } +} + +static unsigned int get_top_cg_mask(unsigned int cg_type) +{ + switch (cg_type) { + case MT8196_AUDIO_26M_EN_ON: + return AUDIO_26M_EN_ON_MASK_SFT; + case MT8196_AUDIO_F3P25M_EN_ON: + return AUDIO_F3P25M_EN_ON_MASK_SFT; + case MT8196_AUDIO_APLL1_EN_ON: + return AUDIO_APLL1_EN_ON_MASK_SFT; + case MT8196_AUDIO_APLL2_EN_ON: + return AUDIO_APLL2_EN_ON_MASK_SFT; + case MT8196_CG_AUDIO_HOPPING_CK: + return CG_AUDIO_HOPPING_CK_MASK_SFT; + case MT8196_CG_AUDIO_F26M_CK: + return CG_AUDIO_F26M_CK_MASK_SFT; + case MT8196_CG_APLL1_CK: + return CG_APLL1_CK_MASK_SFT; + case MT8196_CG_APLL2_CK: + return CG_APLL2_CK_MASK_SFT; + case MT8196_PDN_APLL_TUNER2: + return PDN_APLL_TUNER2_MASK_SFT; + case MT8196_PDN_APLL_TUNER1: + return PDN_APLL_TUNER1_MASK_SFT; + default: + return 0; + } +} + +static unsigned int get_top_cg_on_val(unsigned int cg_type) +{ + switch (cg_type) { + case MT8196_AUDIO_26M_EN_ON: + case MT8196_AUDIO_F3P25M_EN_ON: + case MT8196_AUDIO_APLL1_EN_ON: + case MT8196_AUDIO_APLL2_EN_ON: + return get_top_cg_mask(cg_type); + case MT8196_CG_AUDIO_HOPPING_CK: + case MT8196_CG_AUDIO_F26M_CK: + case MT8196_CG_APLL1_CK: + case MT8196_CG_APLL2_CK: + case MT8196_PDN_APLL_TUNER2: + case MT8196_PDN_APLL_TUNER1: + return 0; + default: + return 0; + } +} + +static unsigned int get_top_cg_off_val(unsigned int cg_type) +{ + switch (cg_type) { + case MT8196_AUDIO_26M_EN_ON: + case MT8196_AUDIO_F3P25M_EN_ON: + case MT8196_AUDIO_APLL1_EN_ON: + case MT8196_AUDIO_APLL2_EN_ON: + return 0; + case MT8196_CG_AUDIO_HOPPING_CK: + case MT8196_CG_AUDIO_F26M_CK: + case MT8196_CG_APLL1_CK: + case MT8196_CG_APLL2_CK: + case MT8196_PDN_APLL_TUNER2: + case MT8196_PDN_APLL_TUNER1: + return get_top_cg_mask(cg_type); + default: + return get_top_cg_mask(cg_type); + } +} + +static int mt8196_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) +{ + int ret; + unsigned int reg = get_top_cg_reg(cg_type); + unsigned int mask = get_top_cg_mask(cg_type); + unsigned int val = get_top_cg_on_val(cg_type); + + if (!afe->regmap) { + dev_err(afe->dev, "afe regmap is null !!!\n"); + return 0; + } + + dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val); + + ret = regmap_update_bits(afe->regmap, reg, mask, val); + if (ret) + dev_err(afe->dev, "regmap_update_bits failed: %d\n", ret); + + return ret; +} + +static int mt8196_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) +{ + int ret; + unsigned int reg = get_top_cg_reg(cg_type); + unsigned int mask = get_top_cg_mask(cg_type); + unsigned int val = get_top_cg_off_val(cg_type); + + if (!afe->regmap) { + dev_err(afe->dev, "afe regmap is null !!!\n"); + return 0; + } + + dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val); + + ret = regmap_update_bits(afe->regmap, reg, mask, val); + if (ret) + dev_err(afe->dev, "regmap_update_bits failed: %d\n", ret); + + return ret; +} + +static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int apll_rate; + int ret; + + dev_dbg(afe->dev, "enable: %d\n", enable); + + if (enable) { + apll_rate = mt8196_get_apll_rate(afe, MT8196_APLL1); + + /* 180.6336 / 4 = 45.1584MHz */ + ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1]); + if (ret) + return ret; + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1], + MT8196_AUD_ENG1_CLK); + if (ret) + return ret; + + ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]); + if (ret) + return ret; + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H], + apll_rate); + if (ret) + return ret; + } else { + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1], + MT8196_AFE_26M); + if (ret) + return ret; + + mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1]); + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H], + MT8196_AFE_26M); + if (ret) + return ret; + + mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]); + } + + return 0; +} + +static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int apll_rate; + int ret; + + dev_dbg(afe->dev, "enable: %d\n", enable); + + if (enable) { + apll_rate = mt8196_get_apll_rate(afe, MT8196_APLL2); + + /* 196.608 / 4 = 49.152MHz */ + ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2]); + if (ret) + return ret; + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2], + MT8196_AUD_ENG2_CLK); + if (ret) + return ret; + + ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]); + if (ret) + return ret; + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H], + apll_rate); + if (ret) + return ret; + } else { + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2], + MT8196_AFE_26M); + if (ret) + return ret; + + mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2]); + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H], + MT8196_AFE_26M); + if (ret) + return ret; + + mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]); + } + + return 0; +} + +int mt8196_apll1_enable(struct mtk_base_afe *afe) +{ + int ret; + + /* setting for APLL */ + apll1_mux_setting(afe, true); + + ret = mt8196_afe_enable_top_cg(afe, MT8196_CG_APLL1_CK); + if (ret) + goto err_clk_apll1; + + ret = mt8196_afe_enable_top_cg(afe, MT8196_PDN_APLL_TUNER1); + if (ret) + goto err_clk_apll1_tuner; + + /* sel 44.1kHz:1, apll_div:7, upper bound:3 */ + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, + XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT | UPPER_BOUND_MASK_SFT, + (0x1 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) | + (3 << UPPER_BOUND_SFT)); + + /* apll1 freq tuner enable */ + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, + FREQ_TUNER_EN_MASK_SFT, + 0x1 << FREQ_TUNER_EN_SFT); + + /* audio apll1 on */ + mt8196_afe_enable_top_cg(afe, MT8196_AUDIO_APLL1_EN_ON); + + return 0; + +err_clk_apll1_tuner: + mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER1); +err_clk_apll1: + mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL1_CK); + return ret; +} + +void mt8196_apll1_disable(struct mtk_base_afe *afe) +{ + /* audio apll1 off */ + mt8196_afe_disable_top_cg(afe, MT8196_AUDIO_APLL1_EN_ON); + + /* apll1 freq tuner disable */ + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, + FREQ_TUNER_EN_MASK_SFT, + 0x0); + + mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER1); + mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL1_CK); + apll1_mux_setting(afe, false); +} + +int mt8196_apll2_enable(struct mtk_base_afe *afe) +{ + int ret; + + /* setting for APLL */ + apll2_mux_setting(afe, true); + + ret = mt8196_afe_enable_top_cg(afe, MT8196_CG_APLL2_CK); + if (ret) + goto err_clk_apll2; + + ret = mt8196_afe_enable_top_cg(afe, MT8196_PDN_APLL_TUNER2); + if (ret) + goto err_clk_apll2_tuner; + + /* sel 48kHz: 2, apll_div: 7, upper bound: 3*/ + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, + XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT | UPPER_BOUND_MASK_SFT, + (0x2 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) | + (3 << UPPER_BOUND_SFT)); + + /* apll2 freq tuner enable */ + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, + FREQ_TUNER_EN_MASK_SFT, + 0x1 << FREQ_TUNER_EN_SFT); + + /* audio apll2 on */ + mt8196_afe_enable_top_cg(afe, MT8196_AUDIO_APLL2_EN_ON); + return 0; + +err_clk_apll2_tuner: + mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER2); +err_clk_apll2: + mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL2_CK); + return 0; +} + +void mt8196_apll2_disable(struct mtk_base_afe *afe) +{ + /* audio apll2 off */ + mt8196_afe_disable_top_cg(afe, MT8196_AUDIO_APLL2_EN_ON); + + /* apll2 freq tuner disable */ + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, + FREQ_TUNER_EN_MASK_SFT, + 0x0); + + mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER2); + mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL2_CK); + apll2_mux_setting(afe, false); +} + +int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int clk_id = 0; + + if (apll < MT8196_APLL1 || apll > MT8196_APLL2) { + dev_warn(afe->dev, "invalid clk id %d\n", apll); + return 0; + } + + if (apll == MT8196_APLL1) + clk_id = MT8196_CLK_TOP_APLL1_CK; + else + clk_id = MT8196_CLK_TOP_APLL2_CK; + + return clk_get_rate(afe_priv->clk[clk_id]); +} + +/* 48K: select APLL2; 44.1k: select APLL1 */ +int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate) +{ + return (rate % 8000) ? MT8196_APLL1 : MT8196_APLL2; +} + +int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name) +{ + if (strcmp(name, APLL1_W_NAME) == 0) + return MT8196_APLL1; + + return MT8196_APLL2; +} + +static const int mck_div[MT8196_MCK_NUM] = { + [MT8196_I2SIN0_MCK] = MT8196_CLK_TOP_APLL12_DIV_I2SIN0, + [MT8196_I2SIN1_MCK] = MT8196_CLK_TOP_APLL12_DIV_I2SIN1, + [MT8196_FMI2S_MCK] = MT8196_CLK_TOP_APLL12_DIV_FMI2S, + [MT8196_TDMOUT_MCK] = MT8196_CLK_TOP_APLL12_DIV_TDMOUT_M, + [MT8196_TDMOUT_BCK] = MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B, +}; + +int mt8196_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int div_clk_id; + int ret; + + dev_dbg(afe->dev, "mck_id: %d, rate: %d\n", mck_id, rate); + + if (mck_id >= MT8196_MCK_NUM || mck_id < 0) + return -EINVAL; + + div_clk_id = mck_div[mck_id]; + + /* enable div, set rate */ + if (div_clk_id < 0) { + dev_err(afe->dev, "invalid div_clk_id %d\n", div_clk_id); + return -EINVAL; + } + + if (div_clk_id == MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B) + rate *= 16; + + ret = mt8196_afe_enable_clk(afe, afe_priv->clk[div_clk_id]); + if (ret) + return ret; + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[div_clk_id], rate); + if (ret) + return ret; + + return 0; +} + +int mt8196_mck_disable(struct mtk_base_afe *afe, int mck_id) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int div_clk_id; + int ret; + + dev_dbg(afe->dev, "mck_id: %d.\n", mck_id); + + if (mck_id < 0) { + dev_err(afe->dev, "mck_id = %d < 0\n", mck_id); + return -EINVAL; + } + + div_clk_id = mck_div[mck_id]; + + if (div_clk_id < 0) { + dev_err(afe->dev, "div_clk_id = %d < 0\n", + div_clk_id); + return -EINVAL; + } + + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[div_clk_id], MT8196_AFE_26M); + if (ret) + return ret; + + mt8196_afe_disable_clk(afe, afe_priv->clk[div_clk_id]); + + return 0; +} + +int mt8196_afe_enable_reg_rw_clk(struct mtk_base_afe *afe) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* bus clock for AFE external access, like DRAM */ + mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_TOP_ADSP_SEL]); + + /* bus clock for AFE internal access, like AFE SRAM */ + mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIOINTBUS]); + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIOINTBUS], + MT8196_AFE_26M); + if (ret) + return ret; + + /* enable audio h clock */ + mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]); + ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H], + MT8196_AFE_26M); + if (ret) + return ret; + + /* AFE hw clock */ + /* IPM2.0: USE HOPPING & 26M */ + /* set in the regmap_register_patch */ + return 0; +} + +int mt8196_afe_disable_reg_rw_clk(struct mtk_base_afe *afe) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + + /* IPM2.0: Use HOPPING & 26M */ + /* set in the regmap_register_patch */ + + mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]); + mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIOINTBUS]); + mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_TOP_ADSP_SEL]); + return 0; +} + +int mt8196_afe_enable_main_clock(struct mtk_base_afe *afe) +{ + mt8196_afe_enable_top_cg(afe, MT8196_AUDIO_26M_EN_ON); + return 0; +} + +int mt8196_afe_disable_main_clock(struct mtk_base_afe *afe) +{ + mt8196_afe_disable_top_cg(afe, MT8196_AUDIO_26M_EN_ON); + return 0; +} + +int mt8196_init_clock(struct mtk_base_afe *afe) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int i; + + afe_priv->clk = devm_kcalloc(afe->dev, MT8196_CLK_NUM, sizeof(*afe_priv->clk), + GFP_KERNEL); + if (!afe_priv->clk) + return -ENOMEM; + + for (i = 0; i < MT8196_CLK_NUM; i++) { + afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]); + if (IS_ERR(afe_priv->clk[i])) { + dev_err(afe->dev, "devm_clk_get %s fail\n", aud_clks[i]); + return PTR_ERR(afe_priv->clk[i]); + } + } + + return 0; +} + diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.h b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h new file mode 100644 index 000000000000..7d47dcff768b --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8196-afe-clk.h -- Mediatek MT8196 AFE Clock Control definitions + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#ifndef _MT8196_AFE_CLOCK_CTRL_H_ +#define _MT8196_AFE_CLOCK_CTRL_H_ + +#define MT8196_AFE_26M 26000000 +#define MT8196_AUD_ENG1_CLK 45158400 +#define MT8196_AUD_ENG2_CLK 49152000 + +/* APLL */ +#define APLL1_W_NAME "APLL1" +#define APLL2_W_NAME "APLL2" + +enum { + MT8196_APLL1 = 0, + MT8196_APLL2, +}; + +enum { + /* vlp clk */ + MT8196_CLK_VLP_MUX_AUDIOINTBUS, + MT8196_CLK_VLP_MUX_AUD_ENG1, + MT8196_CLK_VLP_MUX_AUD_ENG2, + MT8196_CLK_VLP_MUX_AUDIO_H, + /* pll */ + MT8196_CLK_TOP_APLL1_CK, + MT8196_CLK_TOP_APLL2_CK, + /* divider */ + MT8196_CLK_TOP_APLL12_DIV_I2SIN0, + MT8196_CLK_TOP_APLL12_DIV_I2SIN1, + MT8196_CLK_TOP_APLL12_DIV_FMI2S, + MT8196_CLK_TOP_APLL12_DIV_TDMOUT_M, + MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B, + /* mux */ + MT8196_CLK_TOP_ADSP_SEL, + MT8196_CLK_NUM, +}; + +struct mtk_base_afe; + +int mt8196_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate); +int mt8196_mck_disable(struct mtk_base_afe *afe, int mck_id); +int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll); +int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate); +int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name); +int mt8196_init_clock(struct mtk_base_afe *afe); +int mt8196_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk); +void mt8196_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk); +int mt8196_apll1_enable(struct mtk_base_afe *afe); +void mt8196_apll1_disable(struct mtk_base_afe *afe); +int mt8196_apll2_enable(struct mtk_base_afe *afe); +void mt8196_apll2_disable(struct mtk_base_afe *afe); +int mt8196_afe_enable_main_clock(struct mtk_base_afe *afe); +int mt8196_afe_disable_main_clock(struct mtk_base_afe *afe); +int mt8196_afe_enable_reg_rw_clk(struct mtk_base_afe *afe); +int mt8196_afe_disable_reg_rw_clk(struct mtk_base_afe *afe); + +#endif diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-common.h b/sound/soc/mediatek/mt8196/mt8196-afe-common.h new file mode 100644 index 000000000000..4951a6f32abb --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-afe-common.h @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8196-afe-common.h -- Mediatek 8196 audio driver definitions + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#ifndef _MT_8196_AFE_COMMON_H_ +#define _MT_8196_AFE_COMMON_H_ +#include +#include + +#include "mt8196-reg.h" +#include "../common/mtk-base-afe.h" + +/* HW IPM 2.0 */ +enum { + MTK_AFE_IPM2P0_RATE_8K = 0x0, + MTK_AFE_IPM2P0_RATE_11K = 0x1, + MTK_AFE_IPM2P0_RATE_12K = 0x2, + MTK_AFE_IPM2P0_RATE_16K = 0x4, + MTK_AFE_IPM2P0_RATE_22K = 0x5, + MTK_AFE_IPM2P0_RATE_24K = 0x6, + MTK_AFE_IPM2P0_RATE_32K = 0x8, + MTK_AFE_IPM2P0_RATE_44K = 0x9, + MTK_AFE_IPM2P0_RATE_48K = 0xa, + MTK_AFE_IPM2P0_RATE_88K = 0xd, + MTK_AFE_IPM2P0_RATE_96K = 0xe, + MTK_AFE_IPM2P0_RATE_176K = 0x11, + MTK_AFE_IPM2P0_RATE_192K = 0x12, + MTK_AFE_IPM2P0_RATE_352K = 0x15, + MTK_AFE_IPM2P0_RATE_384K = 0x16, +}; + +enum { + MTKAIF_PROTOCOL_1, + MTKAIF_PROTOCOL_2, + MTKAIF_PROTOCOL_2_CLK_P2, +}; + +enum { + MT8196_MEMIF_DL0, + MT8196_MEMIF_DL1, + MT8196_MEMIF_DL2, + MT8196_MEMIF_DL3, + MT8196_MEMIF_DL4, + MT8196_MEMIF_DL5, + MT8196_MEMIF_DL6, + MT8196_MEMIF_DL7, + MT8196_MEMIF_DL8, + MT8196_MEMIF_DL23, + MT8196_MEMIF_DL24, + MT8196_MEMIF_DL25, + MT8196_MEMIF_DL26, + MT8196_MEMIF_DL_4CH, + MT8196_MEMIF_DL_24CH, + MT8196_MEMIF_VUL0, + MT8196_MEMIF_VUL1, + MT8196_MEMIF_VUL2, + MT8196_MEMIF_VUL3, + MT8196_MEMIF_VUL4, + MT8196_MEMIF_VUL5, + MT8196_MEMIF_VUL6, + MT8196_MEMIF_VUL7, + MT8196_MEMIF_VUL8, + MT8196_MEMIF_VUL9, + MT8196_MEMIF_VUL10, + MT8196_MEMIF_VUL24, + MT8196_MEMIF_VUL25, + MT8196_MEMIF_VUL26, + MT8196_MEMIF_VUL_CM0, + MT8196_MEMIF_VUL_CM1, + MT8196_MEMIF_VUL_CM2, + MT8196_MEMIF_ETDM_IN0, + MT8196_MEMIF_ETDM_IN1, + MT8196_MEMIF_ETDM_IN2, + MT8196_MEMIF_ETDM_IN3, + MT8196_MEMIF_ETDM_IN4, + MT8196_MEMIF_ETDM_IN6, + MT8196_MEMIF_HDMI, + MT8196_MEMIF_NUM, + MT8196_DAI_ADDA = MT8196_MEMIF_NUM, + MT8196_DAI_ADDA_CH34, + MT8196_DAI_ADDA_CH56, + MT8196_DAI_AP_DMIC, + MT8196_DAI_AP_DMIC_CH34, + MT8196_DAI_AP_DMIC_MULTICH, + MT8196_DAI_I2S_IN0, + MT8196_DAI_I2S_IN1, + MT8196_DAI_I2S_IN2, + MT8196_DAI_I2S_IN3, + MT8196_DAI_I2S_IN4, + MT8196_DAI_I2S_IN6, + MT8196_DAI_I2S_OUT0, + MT8196_DAI_I2S_OUT1, + MT8196_DAI_I2S_OUT2, + MT8196_DAI_I2S_OUT3, + MT8196_DAI_I2S_OUT4, + MT8196_DAI_I2S_OUT6, + MT8196_DAI_FM_I2S_MASTER, + MT8196_DAI_TDM, + MT8196_DAI_TDM_DPTX, + MT8196_DAI_NUM, +}; + +#define MT8196_DAI_I2S_MAX_NUM 13 //depends each platform's max i2s num + +/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */ +enum { + MT8196_IRQ_0, + MT8196_IRQ_1, + MT8196_IRQ_2, + MT8196_IRQ_3, + MT8196_IRQ_4, + MT8196_IRQ_5, + MT8196_IRQ_6, + MT8196_IRQ_7, + MT8196_IRQ_8, + MT8196_IRQ_9, + MT8196_IRQ_10, + MT8196_IRQ_11, + MT8196_IRQ_12, + MT8196_IRQ_13, + MT8196_IRQ_14, + MT8196_IRQ_15, + MT8196_IRQ_16, + MT8196_IRQ_17, + MT8196_IRQ_18, + MT8196_IRQ_19, + MT8196_IRQ_20, + MT8196_IRQ_21, + MT8196_IRQ_22, + MT8196_IRQ_23, + MT8196_IRQ_24, + MT8196_IRQ_25, + MT8196_IRQ_26, + MT8196_IRQ_31, /* used only for TDM */ + MT8196_IRQ_NUM, +}; + +/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */ +enum { + MT8196_CUS_IRQ_TDM, /* used only for TDM */ + MT8196_CUS_IRQ_NUM, +}; + +enum { + /* AUDIO_ENGEN_CON0 */ + MT8196_AUDIO_26M_EN_ON, + MT8196_AUDIO_F3P25M_EN_ON, + MT8196_AUDIO_APLL1_EN_ON, + MT8196_AUDIO_APLL2_EN_ON, + MT8196_AUDIO_F26M_EN_RST, + MT8196_MULTI_USER_RST, + MT8196_MULTI_USER_BYPASS, + /* AUDIO_TOP_CON4 */ + MT8196_CG_AUDIO_HOPPING_CK, + MT8196_CG_AUDIO_F26M_CK, + MT8196_CG_APLL1_CK, + MT8196_CG_APLL2_CK, + MT8196_PDN_APLL_TUNER2, + MT8196_PDN_APLL_TUNER1, + MT8196_AUDIO_CG_NUM, +}; + +/* MCLK */ +enum { + MT8196_I2SIN0_MCK, + MT8196_I2SIN1_MCK, + MT8196_FMI2S_MCK, + MT8196_TDMOUT_MCK, + MT8196_TDMOUT_BCK, + MT8196_MCK_NUM, +}; + +/* CM*/ +enum { + CM0, + CM1, + CM2, + CM_NUM, +}; + +struct clk; +struct mtk_base_afe; + +struct mt8196_afe_private { + struct clk **clk; + /* dai */ + void *dai_priv[MT8196_DAI_NUM]; + /* mck */ + int mck_rate[MT8196_MCK_NUM]; + /* channel merge */ + u32 cm_rate[CM_NUM]; + u32 cm_channels; +}; + +int mt8196_dai_adda_register(struct mtk_base_afe *afe); +int mt8196_dai_i2s_register(struct mtk_base_afe *afe); +int mt8196_dai_tdm_register(struct mtk_base_afe *afe); +int mt8196_dai_set_priv(struct mtk_base_afe *afe, int id, + int priv_size, const void *priv_data); + +#endif diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c new file mode 100644 index 000000000000..a1ae8322d8b6 --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c @@ -0,0 +1,2519 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek ALSA SoC AFE platform driver for 8196 + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mt8196-afe-clk.h" +#include "mt8196-afe-common.h" +#include "mt8196-interconnection.h" + +#include "../common/mtk-afe-fe-dai.h" +#include "../common/mtk-afe-platform-driver.h" + +static const struct snd_pcm_hardware mt8196_afe_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), + .period_bytes_min = 96, + .period_bytes_max = 4 * 48 * 1024, + .periods_min = 2, + .periods_max = 256, + .buffer_bytes_max = 256 * 1024, + .fifo_size = 0, +}; + +static unsigned int mt8196_rate_transform(struct device *dev, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_IPM2P0_RATE_8K; + case 11025: + return MTK_AFE_IPM2P0_RATE_11K; + case 12000: + return MTK_AFE_IPM2P0_RATE_12K; + case 16000: + return MTK_AFE_IPM2P0_RATE_16K; + case 22050: + return MTK_AFE_IPM2P0_RATE_22K; + case 24000: + return MTK_AFE_IPM2P0_RATE_24K; + case 32000: + return MTK_AFE_IPM2P0_RATE_32K; + case 44100: + return MTK_AFE_IPM2P0_RATE_44K; + case 48000: + return MTK_AFE_IPM2P0_RATE_48K; + case 88200: + return MTK_AFE_IPM2P0_RATE_88K; + case 96000: + return MTK_AFE_IPM2P0_RATE_96K; + case 176400: + return MTK_AFE_IPM2P0_RATE_176K; + case 192000: + return MTK_AFE_IPM2P0_RATE_192K; + /* not support 260K */ + case 352800: + return MTK_AFE_IPM2P0_RATE_352K; + case 384000: + return MTK_AFE_IPM2P0_RATE_384K; + default: + dev_err(dev, "rate %u invalid, use %d!!!\n", + rate, MTK_AFE_IPM2P0_RATE_48K); + return MTK_AFE_IPM2P0_RATE_48K; + } +} + +static int mt8196_set_cm(struct mtk_base_afe *afe, int id, + bool update, bool swap, unsigned int ch) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + unsigned int rate = afe_priv->cm_rate[id]; + unsigned int rate_val = mt8196_rate_transform(afe->dev, rate); + unsigned int ch_pair = ch / 2; + unsigned int update_val; + int reg = AFE_CM0_CON0 + 0x10 * id; + + if (update && ch_pair) + update_val = (26000000 / rate - 10) / ch_pair - 1; + else + update_val = 0x64; + + dev_dbg(afe->dev, "CM%d, rate %d, update %d, swap %d, ch %d, update_val: %d\n", + id, rate, update, swap, ch, update_val); + + /* update cnt */ + regmap_update_bits(afe->regmap, reg, + AFE_CM_UPDATE_CNT_MASK << AFE_CM_UPDATE_CNT_SFT, + update_val << AFE_CM_UPDATE_CNT_SFT); + + /* rate */ + regmap_update_bits(afe->regmap, reg, + AFE_CM_1X_EN_SEL_FS_MASK << AFE_CM_1X_EN_SEL_FS_SFT, + rate_val << AFE_CM_1X_EN_SEL_FS_SFT); + + /* ch num */ + ch = ch - 1; + regmap_update_bits(afe->regmap, reg, + AFE_CM_CH_NUM_MASK << AFE_CM_CH_NUM_SFT, + ch << AFE_CM_CH_NUM_SFT); + + /* swap */ + regmap_update_bits(afe->regmap, reg, + AFE_CM_BYTE_SWAP_MASK << AFE_CM_BYTE_SWAP_SFT, + swap << AFE_CM_BYTE_SWAP_SFT); + + return 0; +} + +static int mt8196_enable_cm_bypass(struct mtk_base_afe *afe, int id, bool en) +{ + return regmap_update_bits(afe->regmap, + AFE_CM0_CON0 + 0x10 * id, + AFE_CM_BYPASS_MODE_MASK << AFE_CM_BYPASS_MODE_SFT, + en << AFE_CM_BYPASS_MODE_SFT); +} + +static int mt8196_fe_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int memif_num = cpu_dai->id; + struct mtk_base_afe_memif *memif = &afe->memif[memif_num]; + const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware; + int ret; + + dev_dbg(afe->dev, "memif_num: %d.\n", memif_num); + + memif->substream = substream; + + snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16); + + if (memif_num == MT8196_MEMIF_VUL_CM0) + snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16); + + snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware); + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + dev_warn(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); + + /* dynamic allocate irq to memif */ + if (memif->irq_usage < 0) { + int irq_id = mtk_dynamic_irq_acquire(afe); + + if (irq_id != afe->irqs_size) { + /* link */ + memif->irq_usage = irq_id; + } else { + dev_err(afe->dev, "no more asys irq\n"); + ret = -EBUSY; + } + } + return ret; +} + +static void mt8196_fe_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + int memif_num = cpu_dai->id; + struct mtk_base_afe_memif *memif = &afe->memif[memif_num]; + int irq_id = memif->irq_usage; + + dev_dbg(afe->dev, "memif_num: %d.\n", memif_num); + + memif->substream = NULL; + + if (!memif->const_irq) { + mtk_dynamic_irq_release(afe, irq_id); + memif->irq_usage = -1; + memif->substream = NULL; + } +} + +static int mt8196_fe_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + unsigned int channels = params_channels(params); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int id = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[id]; + const struct mtk_base_memif_data *data = memif->data; + int cm; + + afe_priv->cm_channels = channels; + + /* set channels */ + if (data->ch_num_shift >= 0) { + regmap_update_bits(afe->regmap, data->ch_num_reg, + data->ch_num_maskbit << data->ch_num_shift, + channels << data->ch_num_shift); + } + + switch (id) { + case MT8196_MEMIF_VUL8: + case MT8196_MEMIF_VUL_CM0: + cm = CM0; + break; + case MT8196_MEMIF_VUL9: + case MT8196_MEMIF_VUL_CM1: + cm = CM1; + break; + case MT8196_MEMIF_VUL10: + case MT8196_MEMIF_VUL_CM2: + cm = CM2; + break; + default: + cm = CM0; + break; + } + + afe_priv->cm_rate[cm] = params_rate(params); + + return mtk_afe_fe_hw_params(substream, params, dai); +} + +static int mt8196_fe_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_pcm_runtime *const runtime = substream->runtime; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int id = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[id]; + int irq_id = memif->irq_usage; + struct mtk_base_afe_irq *irqs = &afe->irqs[irq_id]; + const struct mtk_base_irq_data *irq_data = irqs->irq_data; + unsigned int counter = runtime->period_size; + unsigned int rate = runtime->rate; + unsigned int tmp_reg; + int fs; + int ret; + + dev_dbg(afe->dev, "%s cmd %d, irq_id %d\n", memif->data->name, cmd, irq_id); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + dev_dbg(afe->dev, "%s cmd %d, id %d\n", memif->data->name, cmd, id); + + ret = mtk_memif_set_enable(afe, id); + if (ret) { + dev_err(afe->dev, "id %d, memif enable fail.\n", id); + return ret; + } + + /* + * for small latency record + * ul memif need read some data before irq enable. + * the context of this ops triger is atmoic, so it cannot sleep. + */ + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + if ((runtime->period_size * 1000) / rate <= 10) + udelay(300); + + regmap_update_bits(afe->regmap, + irq_data->irq_cnt_reg, + irq_data->irq_cnt_maskbit << irq_data->irq_cnt_shift, + counter << irq_data->irq_cnt_shift); + + /* set irq fs */ + fs = afe->irq_fs(substream, rate); + if (fs < 0) + return -EINVAL; + + if (irq_data->irq_fs_reg >= 0) + regmap_update_bits(afe->regmap, + irq_data->irq_fs_reg, + irq_data->irq_fs_maskbit << irq_data->irq_fs_shift, + fs << irq_data->irq_fs_shift); + + /* enable interrupt */ + regmap_update_bits(afe->regmap, + irq_data->irq_en_reg, + 1 << irq_data->irq_en_shift, + 1 << irq_data->irq_en_shift); + + return 0; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + ret = mtk_memif_set_disable(afe, id); + if (ret) + dev_warn(afe->dev, "id %d, memif disable fail\n", id); + + /* disable interrupt */ + regmap_update_bits(afe->regmap, + irq_data->irq_en_reg, + 1 << irq_data->irq_en_shift, + 0 << irq_data->irq_en_shift); + + /* + * clear pending IRQ, if the register read as one, there is no need to write + * one to clear operaton. + */ + regmap_read(afe->regmap, irq_data->irq_clr_reg, &tmp_reg); + regmap_update_bits(afe->regmap, irq_data->irq_clr_reg, + AFE_IRQ_CLR_CFG_MASK_SFT | AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT, + tmp_reg ^ (AFE_IRQ_CLR_CFG_MASK_SFT | + AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT)); + + return ret; + default: + return -EINVAL; + } +} + +static int mt8196_memif_fs(struct snd_pcm_substream *substream, + unsigned int rate) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); + struct mtk_base_afe *afe = NULL; + unsigned int rate_reg; + + if (!component) + return -EINVAL; + + afe = snd_soc_component_get_drvdata(component); + if (!afe) + return -EINVAL; + + rate_reg = mt8196_rate_transform(afe->dev, rate); + + return rate_reg; +} + +static int mt8196_get_dai_fs(struct mtk_base_afe *afe, + int dai_id, unsigned int rate) +{ + return mt8196_rate_transform(afe->dev, rate); +} + +static int mt8196_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); + struct mtk_base_afe *afe = NULL; + + if (!component) + return -EINVAL; + afe = snd_soc_component_get_drvdata(component); + return mt8196_rate_transform(afe->dev, rate); +} + +static int mt8196_get_memif_pbuf_size(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + if ((runtime->period_size * 1000) / runtime->rate > 10) + return MT8196_MEMIF_PBUF_SIZE_256_BYTES; + else + return MT8196_MEMIF_PBUF_SIZE_32_BYTES; +} + +/* FE DAIs */ +static const struct snd_soc_dai_ops mt8196_memif_dai_ops = { + .startup = mt8196_fe_startup, + .shutdown = mt8196_fe_shutdown, + .hw_params = mt8196_fe_hw_params, + .hw_free = mtk_afe_fe_hw_free, + .prepare = mtk_afe_fe_prepare, + .trigger = mt8196_fe_trigger, +}; + +#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_PCM_DAI_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_48000) + +#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +#define MT8196_FE_DAI(_name, _id, max_ch, dir) \ +{ \ + .name = #_name, \ + .id = _id, \ + .dir = { \ + .stream_name = #_name, \ + .channels_min = 1, \ + .channels_max = max_ch, \ + .rates = MTK_PCM_RATES, \ + .formats = MTK_PCM_FORMATS, \ + }, \ + .ops = &mt8196_memif_dai_ops, \ +} + +static struct snd_soc_dai_driver mt8196_memif_dai_driver[] = { + /* FE DAIs: memory intefaces to CPU */ + /* Playback */ + MT8196_FE_DAI(DL0, MT8196_MEMIF_DL0, 2, playback), + MT8196_FE_DAI(DL1, MT8196_MEMIF_DL1, 2, playback), + MT8196_FE_DAI(DL2, MT8196_MEMIF_DL2, 2, playback), + MT8196_FE_DAI(DL3, MT8196_MEMIF_DL3, 2, playback), + MT8196_FE_DAI(DL4, MT8196_MEMIF_DL4, 2, playback), + MT8196_FE_DAI(DL5, MT8196_MEMIF_DL5, 2, playback), + MT8196_FE_DAI(DL6, MT8196_MEMIF_DL6, 2, playback), + MT8196_FE_DAI(DL7, MT8196_MEMIF_DL7, 2, playback), + MT8196_FE_DAI(DL8, MT8196_MEMIF_DL8, 2, playback), + MT8196_FE_DAI(DL23, MT8196_MEMIF_DL23, 2, playback), + MT8196_FE_DAI(DL24, MT8196_MEMIF_DL24, 2, playback), + MT8196_FE_DAI(DL25, MT8196_MEMIF_DL25, 2, playback), + MT8196_FE_DAI(DL26, MT8196_MEMIF_DL26, 2, playback), + MT8196_FE_DAI(DL_4CH, MT8196_MEMIF_DL_4CH, 4, playback), + MT8196_FE_DAI(DL_24CH, MT8196_MEMIF_DL_24CH, 8, playback), + MT8196_FE_DAI(HDMI, MT8196_MEMIF_HDMI, 8, playback), + /* Capture */ + MT8196_FE_DAI(UL0, MT8196_MEMIF_VUL0, 2, capture), + MT8196_FE_DAI(UL1, MT8196_MEMIF_VUL1, 2, capture), + MT8196_FE_DAI(UL2, MT8196_MEMIF_VUL2, 2, capture), + MT8196_FE_DAI(UL3, MT8196_MEMIF_VUL3, 2, capture), + MT8196_FE_DAI(UL4, MT8196_MEMIF_VUL4, 2, capture), + MT8196_FE_DAI(UL5, MT8196_MEMIF_VUL5, 2, capture), + MT8196_FE_DAI(UL6, MT8196_MEMIF_VUL6, 2, capture), + MT8196_FE_DAI(UL7, MT8196_MEMIF_VUL7, 2, capture), + MT8196_FE_DAI(UL8, MT8196_MEMIF_VUL8, 2, capture), + MT8196_FE_DAI(UL9, MT8196_MEMIF_VUL9, 16, capture), + MT8196_FE_DAI(UL10, MT8196_MEMIF_VUL10, 2, capture), + MT8196_FE_DAI(UL24, MT8196_MEMIF_VUL24, 2, capture), + MT8196_FE_DAI(UL25, MT8196_MEMIF_VUL25, 2, capture), + MT8196_FE_DAI(UL26, MT8196_MEMIF_VUL26, 2, capture), + MT8196_FE_DAI(UL_CM0, MT8196_MEMIF_VUL_CM0, 8, capture), + MT8196_FE_DAI(UL_CM1, MT8196_MEMIF_VUL_CM1, 16, capture), + MT8196_FE_DAI(UL_CM2, MT8196_MEMIF_VUL_CM2, 32, capture), + MT8196_FE_DAI(UL_ETDM_IN0, MT8196_MEMIF_ETDM_IN0, 2, capture), + MT8196_FE_DAI(UL_ETDM_IN1, MT8196_MEMIF_ETDM_IN1, 2, capture), + MT8196_FE_DAI(UL_ETDM_IN2, MT8196_MEMIF_ETDM_IN2, 2, capture), + MT8196_FE_DAI(UL_ETDM_IN3, MT8196_MEMIF_ETDM_IN3, 2, capture), + MT8196_FE_DAI(UL_ETDM_IN4, MT8196_MEMIF_ETDM_IN4, 2, capture), + MT8196_FE_DAI(UL_ETDM_IN6, MT8196_MEMIF_ETDM_IN6, 2, capture), +}; + +static int ul_cm0_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + unsigned int channels = afe_priv->cm_channels; + + dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n", + event, w->name, channels); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8196_enable_cm_bypass(afe, CM0, false); + mt8196_set_cm(afe, CM0, true, false, channels); + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, + PDN_CM0_MASK_SFT, 0 << PDN_CM0_SFT); + break; + case SND_SOC_DAPM_POST_PMD: + mt8196_enable_cm_bypass(afe, CM0, true); + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, + PDN_CM0_MASK_SFT, 1 << PDN_CM0_SFT); + break; + default: + break; + } + + return 0; +} + +static int ul_cm1_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + unsigned int channels = afe_priv->cm_channels; + + dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n", + event, w->name, channels); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8196_enable_cm_bypass(afe, CM1, false); + mt8196_set_cm(afe, CM1, true, false, channels); + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, + PDN_CM1_MASK_SFT, 0 << PDN_CM1_SFT); + break; + case SND_SOC_DAPM_POST_PMD: + mt8196_enable_cm_bypass(afe, CM1, true); + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, + PDN_CM1_MASK_SFT, 1 << PDN_CM1_SFT); + break; + default: + break; + } + + return 0; +} + +static int ul_cm2_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + unsigned int channels = afe_priv->cm_channels; + + dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n", + event, w->name, channels); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8196_enable_cm_bypass(afe, CM2, false); + mt8196_set_cm(afe, CM2, true, false, channels); + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, + PDN_CM2_MASK_SFT, 0 << PDN_CM2_SFT); + break; + case SND_SOC_DAPM_POST_PMD: + mt8196_enable_cm_bypass(afe, CM2, true); + regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, + PDN_CM2_MASK_SFT, 1 << PDN_CM2_SFT); + break; + default: + break; + } + + return 0; +} + +/* + * dma widget & routes + * The mixer controls and routes are by no means fully implemented, + * only the ones that are intended to be used are, as other wise a fully + * interconnected switch bar mixer would introduce way too many unused + * controls. + */ +static const struct snd_kcontrol_new memif_ul0_ch1_mix[] = { + /* Normal record */ + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN018_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul0_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN019_0, + I_ADDA_UL_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul1_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH1", AFE_CONN020_4, + I_I2SIN4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN020_5, + I_I2SIN6_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul1_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH2", AFE_CONN021_4, + I_I2SIN4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN021_5, + I_I2SIN6_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul2_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN022_0, + I_ADDA_UL_CH3, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul2_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN023_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul3_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN024_4, + I_I2SIN0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH1", AFE_CONN024_4, + I_I2SIN1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH1", AFE_CONN024_4, + I_I2SIN3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH1", AFE_CONN024_4, + I_I2SIN4_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul3_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN025_4, + I_I2SIN0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH2", AFE_CONN025_4, + I_I2SIN1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH2", AFE_CONN025_4, + I_I2SIN3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH2", AFE_CONN025_4, + I_I2SIN4_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul4_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN026_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN026_1, + I_DL0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN026_1, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN026_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN026_1, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN026_1, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN026_1, + I_DL_24CH_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN026_4, + I_I2SIN0_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul4_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN027_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN027_1, + I_DL0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN027_1, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN027_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN027_1, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN027_1, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN027_1, + I_DL_24CH_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN027_4, + I_I2SIN0_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul5_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH1", AFE_CONN028_4, + I_I2SIN3_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul5_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH2", AFE_CONN029_4, + I_I2SIN3_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul6_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN030_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul6_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN031_0, + I_ADDA_UL_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul7_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN032_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul7_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN033_0, + I_ADDA_UL_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul8_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN034_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul8_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN035_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul9_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN036_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul9_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN037_0, + I_ADDA_UL_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul10_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN038_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul10_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN039_0, + I_ADDA_UL_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul24_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN066_4, + I_I2SIN0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN066_5, + I_I2SIN6_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul24_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN067_4, + I_I2SIN0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN067_5, + I_I2SIN6_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul25_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN068_4, + I_I2SIN0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN068_5, + I_I2SIN6_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul25_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN069_4, + I_I2SIN0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN069_5, + I_I2SIN6_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul26_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN070_4, + I_I2SIN0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN070_5, + I_I2SIN6_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul26_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN071_4, + I_I2SIN0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN071_5, + I_I2SIN6_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN040_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN041_0, + I_ADDA_UL_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch3_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN042_0, + I_ADDA_UL_CH3, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch4_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN043_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch5_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN044_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch6_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN045_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch7_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN046_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm0_ch8_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN047_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN048_0, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN049_0, + I_ADDA_UL_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch3_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN050_0, + I_ADDA_UL_CH3, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch4_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN051_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch5_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN052_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN052_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN052_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN052_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch6_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN053_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN053_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN053_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN053_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch7_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN054_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN054_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN054_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN054_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch8_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN055_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN055_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN055_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN055_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch9_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN056_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN056_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN056_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN056_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch10_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN057_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN057_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN057_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN057_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch11_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN058_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN058_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN058_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN058_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch12_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN059_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN059_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN059_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN059_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch13_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN060_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN060_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN060_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN060_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch14_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN061_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN061_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN061_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN061_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch15_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN062_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN062_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN062_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN062_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm1_ch16_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN063_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN063_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN063_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN063_0, + I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN064_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN064_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN064_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN064_0, I_ADDA_UL_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN064_0, I_ADDA_UL_CH5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN064_0, I_ADDA_UL_CH6, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN065_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN065_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN065_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN065_0, I_ADDA_UL_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN065_0, I_ADDA_UL_CH5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN065_0, I_ADDA_UL_CH6, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch3_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN066_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN066_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN066_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN066_0, I_ADDA_UL_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN066_0, I_ADDA_UL_CH5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN066_0, I_ADDA_UL_CH6, 1, 0) +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch4_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN067_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN067_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN067_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN067_0, I_ADDA_UL_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN067_0, I_ADDA_UL_CH5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN067_0, I_ADDA_UL_CH6, 1, 0) +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch5_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN068_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN068_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN068_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN068_0, I_ADDA_UL_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN068_0, I_ADDA_UL_CH5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN068_0, I_ADDA_UL_CH6, 1, 0) +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch6_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN069_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN069_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN069_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN069_0, I_ADDA_UL_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN069_0, I_ADDA_UL_CH5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN069_0, I_ADDA_UL_CH6, 1, 0) +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch7_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN070_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN070_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN070_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN070_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch8_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN071_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN071_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN071_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN071_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch9_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN072_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN072_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN072_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN072_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch10_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN073_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN073_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN073_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN073_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch11_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN074_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN074_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN074_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN074_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch12_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN075_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN075_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN075_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN075_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch13_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN076_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN076_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN076_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN076_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch14_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN077_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN077_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN077_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN077_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch15_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN078_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN078_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN078_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN078_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch16_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN079_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN079_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN079_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN079_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch17_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN080_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN080_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN080_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN080_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch18_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN081_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN081_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN081_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN081_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch19_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN082_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN082_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN082_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN082_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch20_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN083_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN083_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN083_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN083_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch21_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN084_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN084_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN084_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN084_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch22_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN085_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN085_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN085_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN085_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch23_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN086_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN086_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN086_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN086_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch24_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN087_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN087_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN087_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN087_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch25_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN088_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN088_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN088_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN088_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch26_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN089_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN089_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN089_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN089_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch27_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN090_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN090_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN090_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN090_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch28_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN091_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN091_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN091_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN091_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch29_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN092_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN092_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN092_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN092_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch30_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN093_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN093_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN093_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN093_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch31_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN094_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN094_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN094_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN094_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const struct snd_kcontrol_new memif_ul_cm2_ch32_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN095_0, I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN095_0, I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN095_0, I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN095_0, I_ADDA_UL_CH4, 1, 0), +}; + +static const char * const cm0_mux_map[] = { + "UL8_2CH_PATH", + "CM0_8CH_PATH", +}; + +static const char * const cm1_mux_map[] = { + "UL9_2CH_PATH", + "CM1_16CH_PATH", +}; + +static const char * const cm2_mux_map[] = { + "UL10_2CH_PATH", + "CM2_32CH_PATH", +}; + +static SOC_ENUM_SINGLE_DECL(ul_cm0_mux_map_enum, AFE_CM0_CON0, + AFE_CM0_OUTPUT_MUX_SFT, cm0_mux_map); + +static SOC_ENUM_SINGLE_DECL(ul_cm1_mux_map_enum, AFE_CM1_CON0, + AFE_CM1_OUTPUT_MUX_SFT, cm1_mux_map); + +static SOC_ENUM_SINGLE_DECL(ul_cm2_mux_map_enum, AFE_CM2_CON0, + AFE_CM2_OUTPUT_MUX_SFT, cm2_mux_map); + +static const struct snd_kcontrol_new ul_cm0_mux_control = + SOC_DAPM_ENUM("CM0_UL_MUX Route", ul_cm0_mux_map_enum); + +static const struct snd_kcontrol_new ul_cm1_mux_control = + SOC_DAPM_ENUM("CM1_UL_MUX Route", ul_cm1_mux_map_enum); + +static const struct snd_kcontrol_new ul_cm2_mux_control = + SOC_DAPM_ENUM("CM2_UL_MUX Route", ul_cm2_mux_map_enum); + +static const struct snd_soc_dapm_widget mt8196_memif_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("UL0_CH1", SND_SOC_NOPM, 0, 0, + memif_ul0_ch1_mix, ARRAY_SIZE(memif_ul0_ch1_mix)), + SND_SOC_DAPM_MIXER("UL0_CH2", SND_SOC_NOPM, 0, 0, + memif_ul0_ch2_mix, ARRAY_SIZE(memif_ul0_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL1_CH1", SND_SOC_NOPM, 0, 0, + memif_ul1_ch1_mix, ARRAY_SIZE(memif_ul1_ch1_mix)), + SND_SOC_DAPM_MIXER("UL1_CH2", SND_SOC_NOPM, 0, 0, + memif_ul1_ch2_mix, ARRAY_SIZE(memif_ul1_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL2_CH1", SND_SOC_NOPM, 0, 0, + memif_ul2_ch1_mix, ARRAY_SIZE(memif_ul2_ch1_mix)), + SND_SOC_DAPM_MIXER("UL2_CH2", SND_SOC_NOPM, 0, 0, + memif_ul2_ch2_mix, ARRAY_SIZE(memif_ul2_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL3_CH1", SND_SOC_NOPM, 0, 0, + memif_ul3_ch1_mix, ARRAY_SIZE(memif_ul3_ch1_mix)), + SND_SOC_DAPM_MIXER("UL3_CH2", SND_SOC_NOPM, 0, 0, + memif_ul3_ch2_mix, ARRAY_SIZE(memif_ul3_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL4_CH1", SND_SOC_NOPM, 0, 0, + memif_ul4_ch1_mix, ARRAY_SIZE(memif_ul4_ch1_mix)), + SND_SOC_DAPM_MIXER("UL4_CH2", SND_SOC_NOPM, 0, 0, + memif_ul4_ch2_mix, ARRAY_SIZE(memif_ul4_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL5_CH1", SND_SOC_NOPM, 0, 0, + memif_ul5_ch1_mix, ARRAY_SIZE(memif_ul5_ch1_mix)), + SND_SOC_DAPM_MIXER("UL5_CH2", SND_SOC_NOPM, 0, 0, + memif_ul5_ch2_mix, ARRAY_SIZE(memif_ul5_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL6_CH1", SND_SOC_NOPM, 0, 0, + memif_ul6_ch1_mix, ARRAY_SIZE(memif_ul6_ch1_mix)), + SND_SOC_DAPM_MIXER("UL6_CH2", SND_SOC_NOPM, 0, 0, + memif_ul6_ch2_mix, ARRAY_SIZE(memif_ul6_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL7_CH1", SND_SOC_NOPM, 0, 0, + memif_ul7_ch1_mix, ARRAY_SIZE(memif_ul7_ch1_mix)), + SND_SOC_DAPM_MIXER("UL7_CH2", SND_SOC_NOPM, 0, 0, + memif_ul7_ch2_mix, ARRAY_SIZE(memif_ul7_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL8_CH1", SND_SOC_NOPM, 0, 0, + memif_ul8_ch1_mix, ARRAY_SIZE(memif_ul8_ch1_mix)), + SND_SOC_DAPM_MIXER("UL8_CH2", SND_SOC_NOPM, 0, 0, + memif_ul8_ch2_mix, ARRAY_SIZE(memif_ul8_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL9_CH1", SND_SOC_NOPM, 0, 0, + memif_ul9_ch1_mix, ARRAY_SIZE(memif_ul9_ch1_mix)), + SND_SOC_DAPM_MIXER("UL9_CH2", SND_SOC_NOPM, 0, 0, + memif_ul9_ch2_mix, ARRAY_SIZE(memif_ul9_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL10_CH1", SND_SOC_NOPM, 0, 0, + memif_ul10_ch1_mix, ARRAY_SIZE(memif_ul10_ch1_mix)), + SND_SOC_DAPM_MIXER("UL10_CH2", SND_SOC_NOPM, 0, 0, + memif_ul10_ch2_mix, ARRAY_SIZE(memif_ul10_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL24_CH1", SND_SOC_NOPM, 0, 0, + memif_ul24_ch1_mix, ARRAY_SIZE(memif_ul24_ch1_mix)), + SND_SOC_DAPM_MIXER("UL24_CH2", SND_SOC_NOPM, 0, 0, + memif_ul24_ch2_mix, ARRAY_SIZE(memif_ul24_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL25_CH1", SND_SOC_NOPM, 0, 0, + memif_ul25_ch1_mix, ARRAY_SIZE(memif_ul25_ch1_mix)), + SND_SOC_DAPM_MIXER("UL25_CH2", SND_SOC_NOPM, 0, 0, + memif_ul25_ch2_mix, ARRAY_SIZE(memif_ul25_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL26_CH1", SND_SOC_NOPM, 0, 0, + memif_ul26_ch1_mix, ARRAY_SIZE(memif_ul26_ch1_mix)), + SND_SOC_DAPM_MIXER("UL26_CH2", SND_SOC_NOPM, 0, 0, + memif_ul26_ch2_mix, ARRAY_SIZE(memif_ul26_ch2_mix)), + + SND_SOC_DAPM_MIXER("UL_CM0_CH1", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch1_mix, ARRAY_SIZE(memif_ul_cm0_ch1_mix)), + SND_SOC_DAPM_MIXER("UL_CM0_CH2", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch2_mix, ARRAY_SIZE(memif_ul_cm0_ch2_mix)), + SND_SOC_DAPM_MIXER("UL_CM0_CH3", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch3_mix, ARRAY_SIZE(memif_ul_cm0_ch3_mix)), + SND_SOC_DAPM_MIXER("UL_CM0_CH4", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch4_mix, ARRAY_SIZE(memif_ul_cm0_ch4_mix)), + SND_SOC_DAPM_MIXER("UL_CM0_CH5", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch5_mix, ARRAY_SIZE(memif_ul_cm0_ch5_mix)), + SND_SOC_DAPM_MIXER("UL_CM0_CH6", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch6_mix, ARRAY_SIZE(memif_ul_cm0_ch6_mix)), + SND_SOC_DAPM_MIXER("UL_CM0_CH7", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch7_mix, ARRAY_SIZE(memif_ul_cm0_ch7_mix)), + SND_SOC_DAPM_MIXER("UL_CM0_CH8", SND_SOC_NOPM, 0, 0, + memif_ul_cm0_ch8_mix, ARRAY_SIZE(memif_ul_cm0_ch8_mix)), + SND_SOC_DAPM_MUX("CM0_UL_MUX", SND_SOC_NOPM, 0, 0, + &ul_cm0_mux_control), + + SND_SOC_DAPM_MIXER("UL_CM1_CH1", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch1_mix, ARRAY_SIZE(memif_ul_cm1_ch1_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH2", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch2_mix, ARRAY_SIZE(memif_ul_cm1_ch2_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH3", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch3_mix, ARRAY_SIZE(memif_ul_cm1_ch3_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH4", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch4_mix, ARRAY_SIZE(memif_ul_cm1_ch4_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH5", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch5_mix, ARRAY_SIZE(memif_ul_cm1_ch5_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH6", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch6_mix, ARRAY_SIZE(memif_ul_cm1_ch6_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH7", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch7_mix, ARRAY_SIZE(memif_ul_cm1_ch7_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH8", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch8_mix, ARRAY_SIZE(memif_ul_cm1_ch8_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH9", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch9_mix, ARRAY_SIZE(memif_ul_cm1_ch9_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH10", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch10_mix, ARRAY_SIZE(memif_ul_cm1_ch10_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH11", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch11_mix, ARRAY_SIZE(memif_ul_cm1_ch11_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH12", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch12_mix, ARRAY_SIZE(memif_ul_cm1_ch12_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH13", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch13_mix, ARRAY_SIZE(memif_ul_cm1_ch13_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH14", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch14_mix, ARRAY_SIZE(memif_ul_cm1_ch14_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH15", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch15_mix, ARRAY_SIZE(memif_ul_cm1_ch15_mix)), + SND_SOC_DAPM_MIXER("UL_CM1_CH16", SND_SOC_NOPM, 0, 0, + memif_ul_cm1_ch16_mix, ARRAY_SIZE(memif_ul_cm1_ch16_mix)), + SND_SOC_DAPM_MUX("CM1_UL_MUX", SND_SOC_NOPM, 0, 0, + &ul_cm1_mux_control), + + SND_SOC_DAPM_MIXER("UL_CM2_CH1", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch1_mix, ARRAY_SIZE(memif_ul_cm2_ch1_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH2", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch2_mix, ARRAY_SIZE(memif_ul_cm2_ch2_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH3", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch3_mix, ARRAY_SIZE(memif_ul_cm2_ch3_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH4", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch4_mix, ARRAY_SIZE(memif_ul_cm2_ch4_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH5", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch5_mix, ARRAY_SIZE(memif_ul_cm2_ch5_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH6", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch6_mix, ARRAY_SIZE(memif_ul_cm2_ch6_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH7", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch7_mix, ARRAY_SIZE(memif_ul_cm2_ch7_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH8", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch8_mix, ARRAY_SIZE(memif_ul_cm2_ch8_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH9", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch9_mix, ARRAY_SIZE(memif_ul_cm2_ch9_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH10", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch10_mix, ARRAY_SIZE(memif_ul_cm2_ch10_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH11", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch11_mix, ARRAY_SIZE(memif_ul_cm2_ch11_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH12", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch12_mix, ARRAY_SIZE(memif_ul_cm2_ch12_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH13", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch13_mix, ARRAY_SIZE(memif_ul_cm2_ch13_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH14", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch14_mix, ARRAY_SIZE(memif_ul_cm2_ch14_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH15", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch15_mix, ARRAY_SIZE(memif_ul_cm2_ch15_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH16", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch16_mix, ARRAY_SIZE(memif_ul_cm2_ch16_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH17", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch17_mix, ARRAY_SIZE(memif_ul_cm2_ch17_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH18", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch18_mix, ARRAY_SIZE(memif_ul_cm2_ch18_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH19", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch19_mix, ARRAY_SIZE(memif_ul_cm2_ch19_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH20", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch20_mix, ARRAY_SIZE(memif_ul_cm2_ch20_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH21", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch21_mix, ARRAY_SIZE(memif_ul_cm2_ch21_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH22", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch22_mix, ARRAY_SIZE(memif_ul_cm2_ch22_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH23", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch23_mix, ARRAY_SIZE(memif_ul_cm2_ch23_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH24", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch24_mix, ARRAY_SIZE(memif_ul_cm2_ch24_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH25", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch25_mix, ARRAY_SIZE(memif_ul_cm2_ch25_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH26", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch26_mix, ARRAY_SIZE(memif_ul_cm2_ch26_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH27", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch27_mix, ARRAY_SIZE(memif_ul_cm2_ch27_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH28", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch28_mix, ARRAY_SIZE(memif_ul_cm2_ch28_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH29", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch29_mix, ARRAY_SIZE(memif_ul_cm2_ch29_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH30", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch30_mix, ARRAY_SIZE(memif_ul_cm2_ch30_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH31", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch31_mix, ARRAY_SIZE(memif_ul_cm2_ch31_mix)), + SND_SOC_DAPM_MIXER("UL_CM2_CH32", SND_SOC_NOPM, 0, 0, + memif_ul_cm2_ch32_mix, ARRAY_SIZE(memif_ul_cm2_ch32_mix)), + SND_SOC_DAPM_MUX("CM2_UL_MUX", SND_SOC_NOPM, 0, 0, + &ul_cm2_mux_control), + + SND_SOC_DAPM_SUPPLY("CM0_Enable", + AFE_CM0_CON0, AFE_CM0_ON_SFT, 0, + ul_cm0_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY("CM1_Enable", + AFE_CM1_CON0, AFE_CM1_ON_SFT, 0, + ul_cm1_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY("CM2_Enable", + AFE_CM2_CON0, AFE_CM2_ON_SFT, 0, + ul_cm2_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_PRE_PMD), + + /* dynamic pinctrl */ + SND_SOC_DAPM_PINCTRL("I2S3_PIN", "aud-gpio-i2s3-on", "aud-gpio-i2s3-off"), + SND_SOC_DAPM_PINCTRL("I2S4_PIN", "aud-gpio-i2s4-on", "aud-gpio-i2s4-off"), + SND_SOC_DAPM_PINCTRL("I2S6_PIN", "aud-gpio-i2s6-on", "aud-gpio-i2s6-off"), + SND_SOC_DAPM_PINCTRL("AP_DMIC0_PIN", "aud-gpio-ap-dmic-on", "aud-gpio-ap-dmic-off"), + SND_SOC_DAPM_PINCTRL("AP_DMIC1_PIN", "aud-gpio-ap-dmic1-on", "aud-gpio-ap-dmic1-off"), +}; + +static const struct snd_soc_dapm_route mt8196_memif_routes[] = { + {"UL0", NULL, "UL0_CH1"}, + {"UL0", NULL, "UL0_CH2"}, + /* Normal record */ + {"UL0_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL0_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + + {"UL1", NULL, "UL1_CH1"}, + {"UL1", NULL, "UL1_CH2"}, + {"UL1_CH1", "I2SIN4_CH1", "I2SIN4"}, + {"UL1_CH2", "I2SIN4_CH2", "I2SIN4"}, + {"UL1_CH1", "I2SIN6_CH1", "I2SIN6"}, + {"UL1_CH2", "I2SIN6_CH2", "I2SIN6"}, + + {"UL2", NULL, "UL2_CH1"}, + {"UL2", NULL, "UL2_CH2"}, + {"UL2_CH1", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"}, + {"UL2_CH2", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"}, + + {"UL3", NULL, "UL3_CH1"}, + {"UL3", NULL, "UL3_CH2"}, + {"UL3_CH1", "I2SIN0_CH1", "I2SIN0"}, + {"UL3_CH2", "I2SIN0_CH2", "I2SIN0"}, + {"UL3_CH1", "I2SIN1_CH1", "I2SIN1"}, + {"UL3_CH2", "I2SIN1_CH2", "I2SIN1"}, + {"UL3_CH1", "I2SIN3_CH1", "I2SIN3"}, + {"UL3_CH2", "I2SIN3_CH2", "I2SIN3"}, + {"UL3_CH1", "I2SIN4_CH1", "I2SIN4"}, + {"UL3_CH2", "I2SIN4_CH2", "I2SIN4"}, + + {"UL4", NULL, "UL4_CH1"}, + {"UL4", NULL, "UL4_CH2"}, + {"UL4_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL4_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + {"UL4_CH1", "I2SIN0_CH1", "I2SIN0"}, + {"UL4_CH2", "I2SIN0_CH2", "I2SIN0"}, + + {"UL5", NULL, "UL5_CH1"}, + {"UL5", NULL, "UL5_CH2"}, + {"UL5_CH1", "I2SIN3_CH1", "I2SIN3"}, + {"UL5_CH2", "I2SIN3_CH2", "I2SIN3"}, + + {"UL6", NULL, "UL6_CH1"}, + {"UL6", NULL, "UL6_CH2"}, + {"UL6_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL6_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + + {"UL7", NULL, "UL7_CH1"}, + {"UL7", NULL, "UL7_CH2"}, + {"UL7_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL7_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + + {"UL8", NULL, "CM0_UL_MUX"}, + {"CM0_UL_MUX", "UL8_2CH_PATH", "UL8_CH1"}, + {"CM0_UL_MUX", "UL8_2CH_PATH", "UL8_CH2"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH1"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH2"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH3"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH4"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH5"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH6"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH7"}, + {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH8"}, + + {"UL_CM0", NULL, "CM0_Enable"}, + + /* UL9 */ + {"UL9", NULL, "CM1_UL_MUX"}, + {"CM1_UL_MUX", "UL9_2CH_PATH", "UL9_CH1"}, + {"CM1_UL_MUX", "UL9_2CH_PATH", "UL9_CH2"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH1"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH2"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH3"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH4"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH5"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH6"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH7"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH8"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH9"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH10"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH11"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH12"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH13"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH14"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH15"}, + {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH16"}, + + {"UL_CM1", NULL, "CM1_Enable"}, + + {"UL9_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL9_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + + {"UL10", NULL, "CM2_UL_MUX"}, + {"CM2_UL_MUX", "UL10_2CH_PATH", "UL10_CH1"}, + {"CM2_UL_MUX", "UL10_2CH_PATH", "UL10_CH2"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH1"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH2"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH3"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH4"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH5"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH6"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH7"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH8"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH9"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH10"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH11"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH12"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH13"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH14"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH15"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH16"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH17"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH18"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH19"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH20"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH21"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH22"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH23"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH24"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH25"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH26"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH27"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH28"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH29"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH30"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH31"}, + {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH32"}, + + {"UL_CM2", NULL, "CM2_Enable"}, + + {"UL10_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL10_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + + {"UL24", NULL, "UL24_CH1"}, + {"UL24", NULL, "UL24_CH2"}, + {"UL24_CH1", "I2SIN6_CH1", "I2SIN6"}, + {"UL24_CH2", "I2SIN6_CH2", "I2SIN6"}, + {"UL24_CH1", "I2SIN0_CH1", "I2SIN0"}, + {"UL24_CH2", "I2SIN0_CH2", "I2SIN0"}, + + {"UL25", NULL, "UL25_CH1"}, + {"UL25", NULL, "UL25_CH2"}, + {"UL25_CH1", "I2SIN6_CH1", "I2SIN6"}, + {"UL25_CH2", "I2SIN6_CH2", "I2SIN6"}, + {"UL25_CH1", "I2SIN0_CH1", "I2SIN0"}, + {"UL25_CH2", "I2SIN0_CH2", "I2SIN0"}, + + {"UL26", NULL, "UL26_CH1"}, + {"UL26", NULL, "UL26_CH2"}, + {"UL26_CH1", "I2SIN6_CH1", "I2SIN6"}, + {"UL26_CH2", "I2SIN6_CH2", "I2SIN6"}, + {"UL26_CH1", "I2SIN0_CH1", "I2SIN0"}, + {"UL26_CH2", "I2SIN0_CH2", "I2SIN0"}, + + {"UL_CM0", NULL, "UL_CM0_CH1"}, + {"UL_CM0", NULL, "UL_CM0_CH2"}, + {"UL_CM0", NULL, "UL_CM0_CH3"}, + {"UL_CM0", NULL, "UL_CM0_CH4"}, + {"UL_CM0", NULL, "UL_CM0_CH5"}, + {"UL_CM0", NULL, "UL_CM0_CH6"}, + {"UL_CM0", NULL, "UL_CM0_CH7"}, + {"UL_CM0", NULL, "UL_CM0_CH8"}, + {"UL_CM0_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL_CM0_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + {"UL_CM0_CH3", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"}, + {"UL_CM0_CH4", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"}, + + {"UL_CM1", NULL, "UL_CM1_CH1"}, + {"UL_CM1", NULL, "UL_CM1_CH2"}, + {"UL_CM1", NULL, "UL_CM1_CH3"}, + {"UL_CM1", NULL, "UL_CM1_CH4"}, + {"UL_CM1", NULL, "UL_CM1_CH5"}, + {"UL_CM1", NULL, "UL_CM1_CH6"}, + {"UL_CM1", NULL, "UL_CM1_CH7"}, + {"UL_CM1", NULL, "UL_CM1_CH8"}, + {"UL_CM1", NULL, "UL_CM1_CH9"}, + {"UL_CM1", NULL, "UL_CM1_CH10"}, + {"UL_CM1", NULL, "UL_CM1_CH11"}, + {"UL_CM1", NULL, "UL_CM1_CH12"}, + {"UL_CM1", NULL, "UL_CM1_CH13"}, + {"UL_CM1", NULL, "UL_CM1_CH14"}, + {"UL_CM1", NULL, "UL_CM1_CH15"}, + {"UL_CM1", NULL, "UL_CM1_CH16"}, + {"UL_CM1_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL_CM1_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + {"UL_CM1_CH3", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"}, + {"UL_CM1_CH4", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"}, + + {"UL_CM2", NULL, "UL_CM2_CH1"}, + {"UL_CM2", NULL, "UL_CM2_CH2"}, + {"UL_CM2", NULL, "UL_CM2_CH3"}, + {"UL_CM2", NULL, "UL_CM2_CH4"}, + {"UL_CM2", NULL, "UL_CM2_CH5"}, + {"UL_CM2", NULL, "UL_CM2_CH6"}, + {"UL_CM2", NULL, "UL_CM2_CH7"}, + {"UL_CM2", NULL, "UL_CM2_CH8"}, + {"UL_CM2", NULL, "UL_CM2_CH9"}, + {"UL_CM2", NULL, "UL_CM2_CH10"}, + {"UL_CM2", NULL, "UL_CM2_CH11"}, + {"UL_CM2", NULL, "UL_CM2_CH12"}, + {"UL_CM2", NULL, "UL_CM2_CH13"}, + {"UL_CM2", NULL, "UL_CM2_CH14"}, + {"UL_CM2", NULL, "UL_CM2_CH15"}, + {"UL_CM2", NULL, "UL_CM2_CH16"}, + {"UL_CM2", NULL, "UL_CM2_CH17"}, + {"UL_CM2", NULL, "UL_CM2_CH18"}, + {"UL_CM2", NULL, "UL_CM2_CH19"}, + {"UL_CM2", NULL, "UL_CM2_CH20"}, + {"UL_CM2", NULL, "UL_CM2_CH21"}, + {"UL_CM2", NULL, "UL_CM2_CH22"}, + {"UL_CM2", NULL, "UL_CM2_CH23"}, + {"UL_CM2", NULL, "UL_CM2_CH24"}, + {"UL_CM2", NULL, "UL_CM2_CH25"}, + {"UL_CM2", NULL, "UL_CM2_CH26"}, + {"UL_CM2", NULL, "UL_CM2_CH27"}, + {"UL_CM2", NULL, "UL_CM2_CH28"}, + {"UL_CM2", NULL, "UL_CM2_CH29"}, + {"UL_CM2", NULL, "UL_CM2_CH30"}, + {"UL_CM2", NULL, "UL_CM2_CH31"}, + {"UL_CM2", NULL, "UL_CM2_CH32"}, + {"UL_CM2_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"}, + {"UL_CM2_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"}, + {"UL_CM2_CH3", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"}, + {"UL_CM2_CH4", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"}, + + /* Audio Pin */ + {"I2SOUT4", NULL, "I2S4_PIN"}, + {"I2SIN4", NULL, "I2S4_PIN"}, + {"I2SOUT6", NULL, "I2S6_PIN"}, + {"I2SIN6", NULL, "I2S6_PIN"}, + {"I2SOUT3", NULL, "I2S3_PIN"}, + {"I2SIN3", NULL, "I2S3_PIN"}, + {"AP DMIC Capture", NULL, "AP_DMIC0_PIN"}, + {"AP DMIC CH34 Capture", NULL, "AP_DMIC1_PIN"}, +}; + +#define MT8196_DL_MEMIF(_id) \ + [MT8196_MEMIF_##_id] = { \ + .name = #_id, \ + .id = MT8196_MEMIF_##_id, \ + .reg_ofs_base = AFE_##_id##_BASE, \ + .reg_ofs_cur = AFE_##_id##_CUR, \ + .reg_ofs_end = AFE_##_id##_END, \ + .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \ + .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \ + .reg_ofs_end_msb = AFE_##_id##_END_MSB, \ + .fs_reg = AFE_##_id##_CON0, \ + .fs_shift = _id##_SEL_FS_SFT, \ + .fs_maskbit = _id##_SEL_FS_MASK, \ + .mono_reg = AFE_##_id##_CON0, \ + .mono_shift = _id##_MONO_SFT, \ + .enable_reg = AFE_##_id##_CON0, \ + .enable_shift = _id##_ON_SFT, \ + .hd_reg = AFE_##_id##_CON0, \ + .hd_shift = _id##_HD_MODE_SFT, \ + .hd_align_reg = AFE_##_id##_CON0, \ + .hd_align_mshift = _id##_HALIGN_SFT, \ + .agent_disable_reg = -1, \ + .agent_disable_shift = -1, \ + .msb_reg = -1, \ + .msb_shift = -1, \ + .pbuf_reg = AFE_##_id##_CON0, \ + .pbuf_mask = _id##_PBUF_SIZE_MASK, \ + .pbuf_shift = _id##_PBUF_SIZE_SFT, \ + .minlen_reg = AFE_##_id##_CON0, \ + .minlen_mask = _id##_MINLEN_MASK, \ + .minlen_shift = _id##_MINLEN_SFT, \ +} + +#define MT8196_MULTI_DL_MEMIF(_id) \ + [MT8196_MEMIF_##_id] = { \ + .name = #_id, \ + .id = MT8196_MEMIF_##_id, \ + .reg_ofs_base = AFE_##_id##_BASE, \ + .reg_ofs_cur = AFE_##_id##_CUR, \ + .reg_ofs_end = AFE_##_id##_END, \ + .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \ + .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \ + .reg_ofs_end_msb = AFE_##_id##_END_MSB, \ + .fs_reg = AFE_##_id##_CON0, \ + .fs_shift = _id##_SEL_FS_SFT, \ + .fs_maskbit = _id##_SEL_FS_MASK, \ + .mono_reg = -1, \ + .mono_shift = -1, \ + .enable_reg = AFE_##_id##_CON0, \ + .enable_shift = _id##_ON_SFT, \ + .hd_reg = AFE_##_id##_CON0, \ + .hd_shift = _id##_HD_MODE_SFT, \ + .hd_align_reg = AFE_##_id##_CON0, \ + .hd_align_mshift = _id##_HALIGN_SFT, \ + .agent_disable_reg = -1, \ + .agent_disable_shift = -1, \ + .msb_reg = -1, \ + .msb_shift = -1, \ + .pbuf_reg = AFE_##_id##_CON0, \ + .pbuf_mask = _id##_PBUF_SIZE_MASK, \ + .pbuf_shift = _id##_PBUF_SIZE_SFT, \ + .minlen_reg = AFE_##_id##_CON0, \ + .minlen_mask = _id##_MINLEN_MASK, \ + .minlen_shift = _id##_MINLEN_SFT, \ + .ch_num_reg = AFE_##_id##_CON0, \ + .ch_num_maskbit = _id##_NUM_MASK, \ + .ch_num_shift = _id##_NUM_SFT, \ +} + +#define MT8196_UL_MEMIF(_id, _fs_shift, _fs_maskbit, _mono_shift) \ + [MT8196_MEMIF_##_id] = { \ + .name = #_id, \ + .id = MT8196_MEMIF_##_id, \ + .reg_ofs_base = AFE_##_id##_BASE, \ + .reg_ofs_cur = AFE_##_id##_CUR, \ + .reg_ofs_end = AFE_##_id##_END, \ + .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \ + .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \ + .reg_ofs_end_msb = AFE_##_id##_END_MSB, \ + .fs_reg = AFE_##_id##_CON0, \ + .fs_shift = _fs_shift, \ + .fs_maskbit = _fs_maskbit, \ + .mono_reg = AFE_##_id##_CON0, \ + .mono_shift = _mono_shift, \ + .enable_reg = AFE_##_id##_CON0, \ + .enable_shift = _id##_ON_SFT, \ + .hd_reg = AFE_##_id##_CON0, \ + .hd_shift = _id##_HD_MODE_SFT, \ + .hd_align_reg = AFE_##_id##_CON0, \ + .hd_align_mshift = _id##_HALIGN_SFT, \ + .agent_disable_reg = -1, \ + .agent_disable_shift = -1, \ + .msb_reg = -1, \ + .msb_shift = -1, \ + } + +/* For convenience with macros: missing register fields */ +#define HDMI_SEL_FS_SFT -1 +#define HDMI_SEL_FS_MASK -1 + +/* For convenience with macros: register name differences */ +#define AFE_HDMI_BASE AFE_HDMI_OUT_BASE +#define AFE_HDMI_CUR AFE_HDMI_OUT_CUR +#define AFE_HDMI_END AFE_HDMI_OUT_END +#define AFE_HDMI_BASE_MSB AFE_HDMI_OUT_BASE_MSB +#define AFE_HDMI_CUR_MSB AFE_HDMI_OUT_CUR_MSB +#define AFE_HDMI_END_MSB AFE_HDMI_OUT_END_MSB +#define AFE_HDMI_CON0 AFE_HDMI_OUT_CON0 +#define HDMI_ON_SFT HDMI_OUT_ON_SFT +#define HDMI_HD_MODE_SFT HDMI_OUT_HD_MODE_SFT +#define HDMI_HALIGN_SFT HDMI_OUT_HALIGN_SFT +#define HDMI_PBUF_SIZE_MASK HDMI_OUT_PBUF_SIZE_MASK +#define HDMI_PBUF_SIZE_SFT HDMI_OUT_PBUF_SIZE_SFT +#define HDMI_MINLEN_MASK HDMI_OUT_MINLEN_MASK +#define HDMI_MINLEN_SFT HDMI_OUT_MINLEN_SFT +#define HDMI_NUM_MASK HDMI_CH_NUM_MASK +#define HDMI_NUM_SFT HDMI_CH_NUM_SFT + +static const struct mtk_base_memif_data memif_data[MT8196_MEMIF_NUM] = { + MT8196_DL_MEMIF(DL0), + MT8196_DL_MEMIF(DL1), + MT8196_DL_MEMIF(DL2), + MT8196_DL_MEMIF(DL3), + MT8196_DL_MEMIF(DL4), + MT8196_DL_MEMIF(DL5), + MT8196_DL_MEMIF(DL6), + MT8196_DL_MEMIF(DL7), + MT8196_DL_MEMIF(DL8), + MT8196_DL_MEMIF(DL23), + MT8196_DL_MEMIF(DL24), + MT8196_DL_MEMIF(DL25), + MT8196_DL_MEMIF(DL26), + MT8196_MULTI_DL_MEMIF(DL_4CH), + MT8196_MULTI_DL_MEMIF(DL_24CH), + MT8196_MULTI_DL_MEMIF(HDMI), + MT8196_UL_MEMIF(VUL0, VUL0_SEL_FS_SFT, VUL0_SEL_FS_MASK, VUL0_MONO_SFT), + MT8196_UL_MEMIF(VUL1, VUL1_SEL_FS_SFT, VUL1_SEL_FS_MASK, VUL1_MONO_SFT), + MT8196_UL_MEMIF(VUL2, VUL2_SEL_FS_SFT, VUL2_SEL_FS_MASK, VUL2_MONO_SFT), + MT8196_UL_MEMIF(VUL3, VUL3_SEL_FS_SFT, VUL3_SEL_FS_MASK, VUL3_MONO_SFT), + MT8196_UL_MEMIF(VUL4, VUL4_SEL_FS_SFT, VUL4_SEL_FS_MASK, VUL4_MONO_SFT), + MT8196_UL_MEMIF(VUL5, VUL5_SEL_FS_SFT, VUL5_SEL_FS_MASK, VUL5_MONO_SFT), + MT8196_UL_MEMIF(VUL6, VUL6_SEL_FS_SFT, VUL6_SEL_FS_MASK, VUL6_MONO_SFT), + MT8196_UL_MEMIF(VUL7, VUL7_SEL_FS_SFT, VUL7_SEL_FS_MASK, VUL7_MONO_SFT), + MT8196_UL_MEMIF(VUL8, VUL8_SEL_FS_SFT, VUL8_SEL_FS_MASK, VUL8_MONO_SFT), + MT8196_UL_MEMIF(VUL9, VUL9_SEL_FS_SFT, VUL9_SEL_FS_MASK, VUL9_MONO_SFT), + MT8196_UL_MEMIF(VUL10, VUL10_SEL_FS_SFT, VUL10_SEL_FS_MASK, VUL10_MONO_SFT), + MT8196_UL_MEMIF(VUL24, VUL24_SEL_FS_SFT, VUL24_SEL_FS_MASK, VUL24_MONO_SFT), + MT8196_UL_MEMIF(VUL25, VUL25_SEL_FS_SFT, VUL25_SEL_FS_MASK, VUL25_MONO_SFT), + MT8196_UL_MEMIF(VUL26, VUL26_SEL_FS_SFT, VUL26_SEL_FS_MASK, VUL26_MONO_SFT), + MT8196_UL_MEMIF(VUL_CM0, -1, -1, -1), + MT8196_UL_MEMIF(VUL_CM1, -1, -1, -1), + MT8196_UL_MEMIF(VUL_CM2, -1, -1, -1), + MT8196_UL_MEMIF(ETDM_IN0, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1), + MT8196_UL_MEMIF(ETDM_IN1, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1), + MT8196_UL_MEMIF(ETDM_IN2, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1), + MT8196_UL_MEMIF(ETDM_IN3, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1), + MT8196_UL_MEMIF(ETDM_IN4, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1), + MT8196_UL_MEMIF(ETDM_IN6, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1), +}; + +#define MT8196_AFE_IRQ(_id) \ + [MT8196_IRQ_##_id] = { \ + .id = MT8196_IRQ_##_id, \ + .irq_cnt_reg = AFE_IRQ##_id##_MCU_CFG1, \ + .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, \ + .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, \ + .irq_fs_reg = AFE_IRQ##_id##_MCU_CFG0, \ + .irq_fs_shift = AFE_IRQ##_id##_MCU_FS_SFT, \ + .irq_fs_maskbit = AFE_IRQ##_id##_MCU_FS_MASK, \ + .irq_en_reg = AFE_IRQ##_id##_MCU_CFG0, \ + .irq_en_shift = AFE_IRQ##_id##_MCU_ON_SFT, \ + .irq_clr_reg = AFE_IRQ##_id##_MCU_CFG1, \ + .irq_clr_shift = AFE_IRQ##_id##_CLR_CFG_SFT, \ + } + +#define MT8196_AFE_TDM_IRQ(_id) \ + [MT8196_IRQ_##_id] = { \ + .id = MT8196_CUS_IRQ_TDM, \ + .irq_cnt_reg = AFE_CUSTOM_IRQ0_MCU_CFG1, \ + .irq_cnt_shift = AFE_CUSTOM_IRQ0_MCU_CNT_SFT, \ + .irq_cnt_maskbit = AFE_CUSTOM_IRQ0_MCU_CNT_MASK, \ + .irq_fs_reg = -1, \ + .irq_fs_shift = -1, \ + .irq_fs_maskbit = -1, \ + .irq_en_reg = AFE_CUSTOM_IRQ0_MCU_CFG0, \ + .irq_en_shift = AFE_CUSTOM_IRQ0_MCU_ON_SFT, \ + .irq_clr_reg = AFE_CUSTOM_IRQ0_MCU_CFG1, \ + .irq_clr_shift = AFE_CUSTOM_IRQ0_CLR_CFG_SFT, \ + } + +static const struct mtk_base_irq_data irq_data[MT8196_IRQ_NUM] = { + MT8196_AFE_IRQ(0), + MT8196_AFE_IRQ(1), + MT8196_AFE_IRQ(2), + MT8196_AFE_IRQ(3), + MT8196_AFE_IRQ(4), + MT8196_AFE_IRQ(5), + MT8196_AFE_IRQ(6), + MT8196_AFE_IRQ(7), + MT8196_AFE_IRQ(8), + MT8196_AFE_IRQ(9), + MT8196_AFE_IRQ(10), + MT8196_AFE_IRQ(11), + MT8196_AFE_IRQ(12), + MT8196_AFE_IRQ(13), + MT8196_AFE_IRQ(14), + MT8196_AFE_IRQ(15), + MT8196_AFE_IRQ(16), + MT8196_AFE_IRQ(17), + MT8196_AFE_IRQ(18), + MT8196_AFE_IRQ(19), + MT8196_AFE_IRQ(20), + MT8196_AFE_IRQ(21), + MT8196_AFE_IRQ(22), + MT8196_AFE_IRQ(23), + MT8196_AFE_IRQ(24), + MT8196_AFE_IRQ(25), + MT8196_AFE_IRQ(26), + MT8196_AFE_TDM_IRQ(31), +}; + +static const int memif_irq_usage[MT8196_MEMIF_NUM] = { + /* TODO: verify each memif & irq */ + [MT8196_MEMIF_DL0] = MT8196_IRQ_0, + [MT8196_MEMIF_DL1] = MT8196_IRQ_1, + [MT8196_MEMIF_DL2] = MT8196_IRQ_2, + [MT8196_MEMIF_DL3] = MT8196_IRQ_3, + [MT8196_MEMIF_DL4] = MT8196_IRQ_4, + [MT8196_MEMIF_DL5] = MT8196_IRQ_5, + [MT8196_MEMIF_DL6] = MT8196_IRQ_6, + [MT8196_MEMIF_DL7] = MT8196_IRQ_7, + [MT8196_MEMIF_DL8] = MT8196_IRQ_8, + [MT8196_MEMIF_DL23] = MT8196_IRQ_9, + [MT8196_MEMIF_DL24] = MT8196_IRQ_10, + [MT8196_MEMIF_DL25] = MT8196_IRQ_11, + [MT8196_MEMIF_DL26] = MT8196_IRQ_0, + [MT8196_MEMIF_DL_4CH] = MT8196_IRQ_0, + [MT8196_MEMIF_DL_24CH] = MT8196_IRQ_12, + [MT8196_MEMIF_VUL0] = MT8196_IRQ_13, + [MT8196_MEMIF_VUL1] = MT8196_IRQ_14, + [MT8196_MEMIF_VUL2] = MT8196_IRQ_15, + [MT8196_MEMIF_VUL3] = MT8196_IRQ_16, + [MT8196_MEMIF_VUL4] = MT8196_IRQ_17, + [MT8196_MEMIF_VUL5] = MT8196_IRQ_18, + [MT8196_MEMIF_VUL6] = MT8196_IRQ_19, + [MT8196_MEMIF_VUL7] = MT8196_IRQ_20, + [MT8196_MEMIF_VUL8] = MT8196_IRQ_21, + [MT8196_MEMIF_VUL9] = MT8196_IRQ_22, + [MT8196_MEMIF_VUL10] = MT8196_IRQ_23, + [MT8196_MEMIF_VUL24] = MT8196_IRQ_24, + [MT8196_MEMIF_VUL25] = MT8196_IRQ_25, + [MT8196_MEMIF_VUL26] = MT8196_IRQ_0, + [MT8196_MEMIF_VUL_CM0] = MT8196_IRQ_26, + [MT8196_MEMIF_VUL_CM1] = MT8196_IRQ_0, + [MT8196_MEMIF_VUL_CM2] = MT8196_IRQ_0, + [MT8196_MEMIF_ETDM_IN0] = MT8196_IRQ_0, + [MT8196_MEMIF_ETDM_IN1] = MT8196_IRQ_0, + [MT8196_MEMIF_ETDM_IN2] = MT8196_IRQ_0, + [MT8196_MEMIF_ETDM_IN3] = MT8196_IRQ_0, + [MT8196_MEMIF_ETDM_IN4] = MT8196_IRQ_0, + [MT8196_MEMIF_ETDM_IN6] = MT8196_IRQ_0, + [MT8196_MEMIF_HDMI] = MT8196_IRQ_31 +}; + +static bool mt8196_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* these auto-gen reg has read-only bit, so put it as volatile */ + /* volatile reg cannot be cached, so cannot be set when power off */ + switch (reg) { + case AUDIO_TOP_CON0 ... AUDIO_TOP_CON4: + case AFE_APLL1_TUNER_MON0: + case AFE_APLL2_TUNER_MON0: + case AFE_SPM_CONTROL_ACK: + case AUDIO_TOP_IP_VERSION: + case AUDIO_ENGEN_CON0_MON: + case AUD_TOP_MON_RG: + case AFE_CONNSYS_I2S_IPM_VER_MON: + case AFE_CONNSYS_I2S_MON: + case AFE_PCM_INTF_MON: + case AFE_PCM_TOP_IP_VERSION: + case AFE_IRQ_MCU_STATUS: + case AFE_CUSTOM_IRQ_MCU_STATUS: + case AFE_IRQ_MCU_MON0 ... AFE_IRQ26_CNT_MON: + case AFE_CUSTOM_IRQ0_CNT_MON: + case AFE_STF_MON: + case AFE_STF_IP_VERSION: + case AFE_CM0_MON: + case AFE_CM0_IP_VERSION: + case AFE_CM1_MON: + case AFE_CM1_IP_VERSION: + case AFE_ADDA_UL0_SRC_DEBUG_MON0 ... AFE_ADDA_UL0_SRC_MON1: + case AFE_ADDA_UL0_IP_VERSION: + case AFE_ADDA_UL1_SRC_DEBUG_MON0 ... AFE_ADDA_UL1_SRC_MON1: + case AFE_ADDA_UL1_IP_VERSION: + case AFE_MTKAIF_IPM_VER_MON: + case AFE_MTKAIF_MON: + case AFE_AUD_PAD_TOP_MON: + case AFE_ADDA_MTKAIFV4_MON0 ... AFE_ADDA6_MTKAIFV4_MON0: + case ETDM_IN0_MON: + case ETDM_IN1_MON: + case ETDM_IN2_MON: + case ETDM_IN4_MON: + case ETDM_IN6_MON: + case ETDM_OUT0_MON: + case ETDM_OUT1_MON: + case ETDM_OUT2_MON: + case ETDM_OUT4_MON: + case ETDM_OUT6_MON: + case AFE_DPTX_MON: + case AFE_TDM_TOP_IP_VERSION: + case AFE_CONN_MON0 ... AFE_CONN_MON5: + case AFE_CBIP_SLV_DECODER_MON0 ... AFE_CBIP_SLV_MUX_MON1: + case AFE_DL0_CUR_MSB ... AFE_DL0_CUR: + case AFE_DL0_RCH_MON ... AFE_DL0_LCH_MON: + case AFE_DL1_CUR_MSB ... AFE_DL1_CUR: + case AFE_DL1_RCH_MON ... AFE_DL1_LCH_MON: + case AFE_DL2_CUR_MSB ... AFE_DL2_CUR: + case AFE_DL2_RCH_MON ... AFE_DL2_LCH_MON: + case AFE_DL3_CUR_MSB ... AFE_DL3_CUR: + case AFE_DL3_RCH_MON ... AFE_DL3_LCH_MON: + case AFE_DL4_CUR_MSB ... AFE_DL4_CUR: + case AFE_DL4_RCH_MON ... AFE_DL4_LCH_MON: + case AFE_DL5_CUR_MSB ... AFE_DL5_CUR: + case AFE_DL5_RCH_MON ... AFE_DL5_LCH_MON: + case AFE_DL6_CUR_MSB ... AFE_DL6_CUR: + case AFE_DL6_RCH_MON ... AFE_DL6_LCH_MON: + case AFE_DL7_CUR_MSB ... AFE_DL7_CUR: + case AFE_DL7_RCH_MON ... AFE_DL7_LCH_MON: + case AFE_DL8_CUR_MSB ... AFE_DL8_CUR: + case AFE_DL8_RCH_MON ... AFE_DL8_LCH_MON: + case AFE_DL_24CH_CUR_MSB ... AFE_DL_24CH_CUR: + case AFE_DL_4CH_CUR_MSB ... AFE_DL_4CH_CUR: + case AFE_DL23_CUR_MSB ... AFE_DL23_CUR: + case AFE_DL23_RCH_MON ... AFE_DL23_LCH_MON: + case AFE_DL24_CUR_MSB ... AFE_DL24_CUR: + case AFE_DL24_RCH_MON ... AFE_DL24_LCH_MON: + case AFE_DL25_CUR_MSB ... AFE_DL25_CUR: + case AFE_DL25_RCH_MON ... AFE_DL25_LCH_MON: + case AFE_DL26_CUR_MSB ... AFE_DL26_CUR: + case AFE_DL26_RCH_MON ... AFE_DL26_LCH_MON: + case AFE_VUL0_CUR_MSB ... AFE_VUL0_CUR: + case AFE_VUL1_CUR_MSB ... AFE_VUL1_CUR: + case AFE_VUL2_CUR_MSB ... AFE_VUL2_CUR: + case AFE_VUL3_CUR_MSB ... AFE_VUL3_CUR: + case AFE_VUL4_CUR_MSB ... AFE_VUL4_CUR: + case AFE_VUL5_CUR_MSB ... AFE_VUL5_CUR: + case AFE_VUL6_CUR_MSB ... AFE_VUL6_CUR: + case AFE_VUL7_CUR_MSB ... AFE_VUL7_CUR: + case AFE_VUL8_CUR_MSB ... AFE_VUL8_CUR: + case AFE_VUL9_CUR_MSB ... AFE_VUL9_CUR: + case AFE_VUL10_CUR_MSB ... AFE_VUL10_CUR: + case AFE_VUL24_CUR_MSB ... AFE_VUL24_CUR: + case AFE_VUL25_CUR_MSB ... AFE_VUL25_CUR: + case AFE_VUL25_RCH_MON ... AFE_VUL25_LCH_MON: + case AFE_VUL26_CUR_MSB ... AFE_VUL26_CUR: + case AFE_VUL_CM0_BASE_MSB ... AFE_VUL_CM0_CON0: + case AFE_VUL_CM1_CUR_MSB ... AFE_VUL_CM1_CUR: + case AFE_VUL_CM2_CUR_MSB ... AFE_VUL_CM2_CUR: + case AFE_ETDM_IN0_CUR_MSB ... AFE_ETDM_IN0_CUR: + case AFE_ETDM_IN1_CUR_MSB ... AFE_ETDM_IN1_CUR: + case AFE_ETDM_IN2_CUR_MSB ... AFE_ETDM_IN2_CUR: + case AFE_ETDM_IN3_CUR_MSB ... AFE_ETDM_IN3_CUR: + case AFE_ETDM_IN4_CUR_MSB ... AFE_ETDM_IN4_CUR: + case AFE_ETDM_IN6_CUR_MSB ... AFE_ETDM_IN6_CUR: + case AFE_HDMI_OUT_CUR_MSB ... AFE_HDMI_OUT_CUR: + case AFE_HDMI_OUT_END: + case AFE_PROT_SIDEBAND0_MON ... AFE_DOMAIN_SIDEBAND9_MON: + case AFE_PCM0_INTF_CON1_MASK_MON ... AFE_ADDA_UL1_SRC_CON0_MASK_MON: + case AFE_IRQ_MCU_EN ... AFE_IRQ_MCU_DSP2_EN: + case AFE_CUSTOM_IRQ_MCU_EN: + case AFE_DL5_CON0: + case AFE_DL6_CON0: + case AFE_DL23_CON0: + case AFE_DL_24CH_CON0: + case AFE_VUL1_CON0: + case AFE_VUL3_CON0: + case AFE_VUL4_CON0: + case AFE_VUL5_CON0: + case AFE_VUL9_CON0: + case AFE_VUL25_CON0: + case AFE_IRQ0_MCU_CFG0 ... AFE_IRQ26_MCU_CFG1: + return true; + default: + return false; + }; +} + +static const struct regmap_config mt8196_afe_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + + .volatile_reg = mt8196_is_volatile_reg, + + .max_register = AFE_MAX_REGISTER, + .num_reg_defaults_raw = AFE_MAX_REGISTER, + + .cache_type = REGCACHE_FLAT, +}; + +static irqreturn_t mt8196_afe_irq_handler(int irq_id, void *dev) +{ + struct mtk_base_afe *afe = dev; + struct mtk_base_afe_irq *irq; + u32 status; + u32 status_mcu; + u32 mcu_en; + u32 cus_status; + u32 cus_status_mcu; + u32 cus_mcu_en; + u32 tmp_reg; + int ret, cus_ret; + int i; + struct timespec64 ts64; + u64 t1, t2; + /* one interrupt period = 5ms */ + const u64 timeout_limit = 5000000; + + /* get irq that is sent to MCU */ + regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en); + regmap_read(afe->regmap, AFE_CUSTOM_IRQ_MCU_EN, &cus_mcu_en); + + ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status); + cus_ret = regmap_read(afe->regmap, AFE_CUSTOM_IRQ_MCU_STATUS, &cus_status); + /* only care IRQ which is sent to MCU */ + status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS; + cus_status_mcu = cus_status & cus_mcu_en & AFE_IRQ_STATUS_BITS; + if ((ret || !status_mcu) && (cus_ret || !cus_status_mcu)) { + dev_err(afe->dev, "ret %d, sat 0x%x, en 0x%x,csat 0x%x, cen 0x%x\n", + ret, status, mcu_en, cus_status_mcu, cus_mcu_en); + return IRQ_NONE; + } + + ktime_get_ts64(&ts64); + t1 = ktime_get_ns(); + + for (i = 0; i < MT8196_MEMIF_NUM; i++) { + struct mtk_base_afe_memif *memif = &afe->memif[i]; + + if (!memif->substream) + continue; + + if (memif->irq_usage < 0) + continue; + irq = &afe->irqs[memif->irq_usage]; + + if (i == MT8196_MEMIF_HDMI) { + if (cus_status_mcu & BIT(irq->irq_data->id)) + snd_pcm_period_elapsed(memif->substream); + } else { + if (status_mcu & BIT(irq->irq_data->id)) + snd_pcm_period_elapsed(memif->substream); + } + } + + ktime_get_ts64(&ts64); + t2 = ktime_get_ns(); + t2 = t2 - t1; /* in ns (10^9) */ + + if (t2 > timeout_limit) + dev_warn(afe->dev, "IRQ handler exceeded time limit by %llu ns\n", + t2 - timeout_limit); + + /* clear irq */ + for (i = 0; i < MT8196_IRQ_NUM; ++i) { + /* cus_status_mcu only bit0 is used for TDM */ + if ((status_mcu & BIT(i)) || (cus_status_mcu & 0x1)) { + regmap_read(afe->regmap, irq_data[i].irq_clr_reg, &tmp_reg); + regmap_update_bits(afe->regmap, irq_data[i].irq_clr_reg, + AFE_IRQ_CLR_CFG_MASK_SFT | + AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT, + tmp_reg ^ (AFE_IRQ_CLR_CFG_MASK_SFT | + AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT)); + } + } + + return IRQ_HANDLED; +} + +static int mt8196_afe_runtime_suspend(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + unsigned int value; + unsigned int tmp_reg; + int ret, i; + + if (!afe->regmap) { + dev_err(afe->dev, "skip regmap\n"); + goto skip_regmap; + } + + /* disable AFE */ + mt8196_afe_disable_main_clock(afe); + + ret = regmap_read_poll_timeout(afe->regmap, + AUDIO_ENGEN_CON0_MON, + value, + (value & AUDIO_ENGEN_MON_SFT) == 0, + 20, + 1 * 1000 * 1000); + dev_dbg(afe->dev, "read_poll ret %d\n", ret); + if (ret) + dev_warn(afe->dev, "ret %d\n", ret); + + /* make sure all irq status are cleared */ + for (i = 0; i < MT8196_IRQ_NUM; ++i) { + regmap_read(afe->regmap, irq_data[i].irq_clr_reg, &tmp_reg); + regmap_update_bits(afe->regmap, irq_data[i].irq_clr_reg, + AFE_IRQ_CLR_CFG_MASK_SFT | AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT, + tmp_reg ^ (AFE_IRQ_CLR_CFG_MASK_SFT | + AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT)); + } + + /* reset audio 26M request */ + regmap_update_bits(afe->regmap, + AFE_SPM_CONTROL_REQ, 0x1, 0x0); + + /* cache only */ + regcache_cache_only(afe->regmap, true); + regcache_mark_dirty(afe->regmap); + +skip_regmap: + mt8196_afe_disable_reg_rw_clk(afe); + return 0; +} + +static int mt8196_afe_runtime_resume(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + int ret = 0; + + ret = mt8196_afe_enable_reg_rw_clk(afe); + if (ret) + return ret; + + if (!afe->regmap) { + dev_warn(afe->dev, "skip regmap\n"); + goto skip_regmap; + } + regcache_cache_only(afe->regmap, false); + regcache_sync(afe->regmap); + + /* set audio 26M request */ + regmap_update_bits(afe->regmap, AFE_SPM_CONTROL_REQ, 0x1, 0x1); + regmap_update_bits(afe->regmap, AFE_CBIP_CFG0, 0x1, 0x1); + + /* force cpu use 8_24 format when writing 32bit data */ + regmap_update_bits(afe->regmap, AFE_MEMIF_CON0, + CPU_HD_ALIGN_MASK_SFT, 0 << CPU_HD_ALIGN_SFT); + + /* enable AFE */ + mt8196_afe_enable_main_clock(afe); + +skip_regmap: + return 0; +} + +static int mt8196_afe_component_probe(struct snd_soc_component *component) +{ + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + int ret; + + /* enable clock for regcache get default value from hw */ + ret = pm_runtime_resume_and_get(afe->dev); + if (ret) + return dev_err_probe(afe->dev, ret, "failed to resume device\n"); + + mtk_afe_add_sub_dai_control(component); + pm_runtime_put_sync(afe->dev); + + return 0; +} + +static int mt8196_afe_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + /* set the wait_for_avail to 2 sec*/ + substream->wait_time = msecs_to_jiffies(2 * 1000); + + return 0; +} + +static void mt8196_afe_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm) +{ + snd_pcm_lib_preallocate_free_for_all(pcm); +} + +static const struct snd_soc_component_driver mt8196_afe_component = { + .name = AFE_PCM_NAME, + .probe = mt8196_afe_component_probe, + .pcm_new = mtk_afe_pcm_new, + .pcm_free = mt8196_afe_pcm_free, + .open = mt8196_afe_pcm_open, + .pointer = mtk_afe_pcm_pointer, +}; + +static int mt8196_dai_memif_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mt8196_memif_dai_driver; + dai->num_dai_drivers = ARRAY_SIZE(mt8196_memif_dai_driver); + dai->dapm_widgets = mt8196_memif_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mt8196_memif_widgets); + dai->dapm_routes = mt8196_memif_routes; + dai->num_dapm_routes = ARRAY_SIZE(mt8196_memif_routes); + return 0; +} + +typedef int (*dai_register_cb)(struct mtk_base_afe *); +static const dai_register_cb dai_register_cbs[] = { + mt8196_dai_adda_register, + mt8196_dai_i2s_register, + mt8196_dai_tdm_register, + mt8196_dai_memif_register, +}; + +static const struct reg_sequence mt8196_cg_patch[] = { + { AUDIO_TOP_CON4, 0x361c }, +}; + +static void mt8196_afe_release_reserved_mem(void *data) +{ + of_reserved_mem_device_release(data); +} + +static int mt8196_afe_pcm_dev_probe(struct platform_device *pdev) +{ + int ret, i; + unsigned int tmp_reg; + int irq_id; + struct mtk_base_afe *afe; + struct mt8196_afe_private *afe_priv; + struct device *dev = &pdev->dev; + + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(34)); + if (ret) + return ret; + + ret = of_reserved_mem_device_init(dev); + if (ret) { + dev_err(dev, "failed to assign memory region: %d\n", ret); + } else { + ret = devm_add_action_or_reset(dev, mt8196_afe_release_reserved_mem, dev); + if (ret) + return ret; + } + + afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL); + if (!afe) + return -ENOMEM; + + platform_set_drvdata(pdev, afe); + + afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv), + GFP_KERNEL); + if (!afe->platform_priv) + return -ENOMEM; + + afe_priv = afe->platform_priv; + afe->dev = dev; + + afe->base_addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(afe->base_addr)) + return dev_err_probe(dev, PTR_ERR(afe->base_addr), + "AFE base_addr not found\n"); + + /* init audio related clock */ + ret = mt8196_init_clock(afe); + if (ret) + return dev_err_probe(dev, ret, "init clock error.\n"); + + /* init memif */ + /* IPM2.0 no need banding */ + afe->memif_32bit_supported = 1; + afe->memif_size = MT8196_MEMIF_NUM; + afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), + GFP_KERNEL); + + if (!afe->memif) + return -ENOMEM; + + for (i = 0; i < afe->memif_size; i++) { + afe->memif[i].data = &memif_data[i]; + afe->memif[i].irq_usage = memif_irq_usage[i]; + afe->memif[i].const_irq = 1; + } + + mutex_init(&afe->irq_alloc_lock); + + /* init irq */ + afe->irqs_size = MT8196_IRQ_NUM; + afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), + GFP_KERNEL); + + if (!afe->irqs) + return -ENOMEM; + + for (i = 0; i < afe->irqs_size; i++) + afe->irqs[i].irq_data = &irq_data[i]; + + /* request irq */ + irq_id = platform_get_irq(pdev, 0); + if (irq_id < 0) + return dev_err_probe(dev, irq_id, "no irq found"); + + ret = devm_request_irq(dev, irq_id, mt8196_afe_irq_handler, + IRQF_TRIGGER_NONE, + "Afe_ISR_Handle", afe); + if (ret) + return dev_err_probe(dev, ret, "could not request_irq for Afe_ISR_Handle\n"); + + /* init sub_dais */ + INIT_LIST_HEAD(&afe->sub_dais); + + for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { + ret = dai_register_cbs[i](afe); + if (ret) + return dev_err_probe(dev, ret, "dai register i %d fail\n", i); + } + + /* init dai_driver and component_driver */ + ret = mtk_afe_combine_sub_dai(afe); + if (ret) + return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n"); + + /* others */ + afe->mtk_afe_hardware = &mt8196_afe_hardware; + afe->memif_fs = mt8196_memif_fs; + afe->irq_fs = mt8196_irq_fs; + afe->get_dai_fs = mt8196_get_dai_fs; + afe->get_memif_pbuf_size = mt8196_get_memif_pbuf_size; + + afe->runtime_resume = mt8196_afe_runtime_resume; + afe->runtime_suspend = mt8196_afe_runtime_suspend; + + ret = devm_pm_runtime_enable(dev); + if (ret) + return ret; + +/* + * Audio device is part of genpd. Registering it as a syscore device ensure + * the proper power-on sequence of the AFE device. + */ + dev_pm_syscore_device(dev, true); + + /* enable clock for regcache get default value from hw */ + ret = pm_runtime_resume_and_get(dev); + if (ret) + return dev_err_probe(dev, ret, "failed to resume device\n"); + + afe->regmap = devm_regmap_init_mmio(dev, afe->base_addr, + &mt8196_afe_regmap_config); + if (IS_ERR(afe->regmap)) { + ret = PTR_ERR(afe->regmap); + goto err_pm_put; + } + + ret = regmap_register_patch(afe->regmap, mt8196_cg_patch, + ARRAY_SIZE(mt8196_cg_patch)); + if (ret < 0) { + dev_err(dev, "Failed to apply cg patch\n"); + goto err_pm_put; + } + + regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg); + regmap_write(afe->regmap, AFE_IRQ_MCU_EN, 0xffffffff); + regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg); + + pm_runtime_put_sync(dev); + + regcache_cache_only(afe->regmap, true); + regcache_mark_dirty(afe->regmap); + + /* register component */ + ret = devm_snd_soc_register_component(dev, + &mt8196_afe_component, + afe->dai_drivers, + afe->num_dai_drivers); + if (ret) { + dev_err(dev, "afe component err\n"); + return ret; + } + + return 0; + +err_pm_put: + pm_runtime_put_sync(dev); + return ret; +} + +static void mt8196_afe_pcm_dev_remove(struct platform_device *pdev) +{ + struct mtk_base_afe *afe = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + + if (!pm_runtime_status_suspended(dev)) + mt8196_afe_runtime_suspend(dev); + + mt8196_afe_disable_main_clock(afe); + /* disable afe clock */ + mt8196_afe_disable_reg_rw_clk(afe); +} + +static const struct of_device_id mt8196_afe_pcm_dt_match[] = { + { .compatible = "mediatek,mt8196-afe", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt8196_afe_pcm_dt_match); + +static const struct dev_pm_ops mt8196_afe_pm_ops = { + SET_RUNTIME_PM_OPS(mt8196_afe_runtime_suspend, + mt8196_afe_runtime_resume, NULL) +}; + +static struct platform_driver mt8196_afe_pcm_driver = { + .driver = { + .name = "mt8196-afe", + .of_match_table = mt8196_afe_pcm_dt_match, + .pm = &mt8196_afe_pm_ops, + }, + .probe = mt8196_afe_pcm_dev_probe, + .remove = mt8196_afe_pcm_dev_remove, +}; +module_platform_driver(mt8196_afe_pcm_driver); + +MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 8196"); +MODULE_AUTHOR("Darren Ye "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-adda.c b/sound/soc/mediatek/mt8196/mt8196-dai-adda.c new file mode 100644 index 000000000000..9a91db4e79ae --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-dai-adda.c @@ -0,0 +1,845 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI ADDA Control + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#include +#include + +#include "mt8196-afe-clk.h" +#include "mt8196-afe-common.h" +#include "mt8196-interconnection.h" + +enum { + UL_IIR_SW, + UL_IIR_5HZ, + UL_IIR_10HZ, + UL_IIR_25HZ, + UL_IIR_50HZ, + UL_IIR_75HZ, +}; + +enum { + MTK_AFE_ADDA_UL_RATE_8K, + MTK_AFE_ADDA_UL_RATE_16K, + MTK_AFE_ADDA_UL_RATE_32K, + MTK_AFE_ADDA_UL_RATE_48K, + MTK_AFE_ADDA_UL_RATE_96K, + MTK_AFE_ADDA_UL_RATE_192K, + MTK_AFE_ADDA_UL_RATE_48K_HD, +}; + +enum { + MTK_AFE_MTKAIF_RATE_8K, + MTK_AFE_MTKAIF_RATE_12K, + MTK_AFE_MTKAIF_RATE_16K, + MTK_AFE_MTKAIF_RATE_24K, + MTK_AFE_MTKAIF_RATE_32K, + MTK_AFE_MTKAIF_RATE_48K, + MTK_AFE_MTKAIF_RATE_64K, + MTK_AFE_MTKAIF_RATE_96K, + MTK_AFE_MTKAIF_RATE_128K, + MTK_AFE_MTKAIF_RATE_192K, + MTK_AFE_MTKAIF_RATE_256K, + MTK_AFE_MTKAIF_RATE_384K, + MTK_AFE_MTKAIF_RATE_11K = 0x10, + MTK_AFE_MTKAIF_RATE_22K, + MTK_AFE_MTKAIF_RATE_44K, + MTK_AFE_MTKAIF_RATE_88K, + MTK_AFE_MTKAIF_RATE_176K, + MTK_AFE_MTKAIF_RATE_352K, +}; + +struct mtk_afe_adda_priv { + int dl_rate; + int ul_rate; +}; + +static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_UL_RATE_8K; + case 16000: + return MTK_AFE_ADDA_UL_RATE_16K; + case 32000: + return MTK_AFE_ADDA_UL_RATE_32K; + case 48000: + return MTK_AFE_ADDA_UL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_UL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_UL_RATE_192K; + default: + dev_warn(afe->dev, "rate %d invalid, use 48kHz!!!\n", rate); + return MTK_AFE_ADDA_UL_RATE_48K; + } +} + +static unsigned int mtkaif_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_MTKAIF_RATE_8K; + case 11025: + return MTK_AFE_MTKAIF_RATE_11K; + case 12000: + return MTK_AFE_MTKAIF_RATE_12K; + case 16000: + return MTK_AFE_MTKAIF_RATE_16K; + case 22050: + return MTK_AFE_MTKAIF_RATE_22K; + case 24000: + return MTK_AFE_MTKAIF_RATE_24K; + case 32000: + return MTK_AFE_MTKAIF_RATE_32K; + case 44100: + return MTK_AFE_MTKAIF_RATE_44K; + case 48000: + return MTK_AFE_MTKAIF_RATE_48K; + case 96000: + return MTK_AFE_MTKAIF_RATE_96K; + case 192000: + return MTK_AFE_MTKAIF_RATE_192K; + default: + dev_warn(afe->dev, "rate %d invalid, use 48kHz!!!\n", rate); + return MTK_AFE_MTKAIF_RATE_48K; + } +} + +enum { + SUPPLY_SEQ_ADDA_AFE_ON, + SUPPLY_SEQ_ADDA_FIFO, + SUPPLY_SEQ_ADDA_AP_DMIC, + SUPPLY_SEQ_ADDA_UL_ON, +}; + +static int mtk_adda_ul_src_set_dmic_phase_sync(struct mtk_base_afe *afe) +{ + dev_dbg(afe->dev, "set dmic phase sync\n"); + // ul0~1 + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + UL0_PHASE_SYNC_HCLK_SET_MASK_SFT, + 0x1 << UL0_PHASE_SYNC_HCLK_SET_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + UL0_PHASE_SYNC_FCLK_SET_MASK_SFT, + 0x1 << UL0_PHASE_SYNC_FCLK_SET_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + UL1_PHASE_SYNC_HCLK_SET_MASK_SFT, + 0x1 << UL1_PHASE_SYNC_HCLK_SET_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + UL1_PHASE_SYNC_FCLK_SET_MASK_SFT, + 0x1 << UL1_PHASE_SYNC_FCLK_SET_SFT); + // dmic 0 + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + DMIC0_PHASE_SYNC_FCLK_SET_MASK_SFT, + 0x1 << DMIC0_PHASE_SYNC_FCLK_SET_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + DMIC0_PHASE_SYNC_HCLK_SET_MASK_SFT, + 0x1 << DMIC0_PHASE_SYNC_HCLK_SET_SFT); + // dmic 1 + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + DMIC1_PHASE_SYNC_FCLK_SET_MASK_SFT, + 0x1 << DMIC1_PHASE_SYNC_FCLK_SET_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + DMIC1_PHASE_SYNC_HCLK_SET_MASK_SFT, + 0x1 << DMIC1_PHASE_SYNC_HCLK_SET_SFT); + // ul0~1 phase sync clock + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + DMIC1_PHASE_HCLK_SEL_MASK_SFT, + 0x1 << DMIC1_PHASE_HCLK_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + DMIC1_PHASE_FCLK_SEL_MASK_SFT, + 0x1 << DMIC1_PHASE_FCLK_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + DMIC0_PHASE_HCLK_SEL_MASK_SFT, + 0x1 << DMIC0_PHASE_HCLK_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + DMIC0_PHASE_FCLK_SEL_MASK_SFT, + 0x1 << DMIC0_PHASE_FCLK_SEL_SFT); + // dmic 0 + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL1_PHASE_HCLK_SEL_MASK_SFT, + 0x2 << UL1_PHASE_HCLK_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL1_PHASE_FCLK_SEL_MASK_SFT, + 0x2 << UL1_PHASE_FCLK_SEL_SFT); + // dmic 1 + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL0_PHASE_HCLK_SEL_MASK_SFT, + 0x2 << UL0_PHASE_HCLK_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL0_PHASE_FCLK_SEL_MASK_SFT, + 0x2 << UL0_PHASE_FCLK_SEL_SFT); + + return 0; +} + +static int mtk_adda_ul_src_set_dmic_phase_sync_clock(struct mtk_base_afe *afe) +{ + dev_dbg(afe->dev, "dmic turn on phase sync clk\n"); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL_PHASE_SYNC_HCLK_1_ON_MASK_SFT, + 0x1 << UL_PHASE_SYNC_HCLK_1_ON_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL_PHASE_SYNC_HCLK_0_ON_MASK_SFT, + 0x1 << UL_PHASE_SYNC_HCLK_0_ON_SFT); + + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL_PHASE_SYNC_FCLK_1_ON_MASK_SFT, + 0x1 << UL_PHASE_SYNC_FCLK_1_ON_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0, + UL_PHASE_SYNC_FCLK_0_ON_MASK_SFT, + 0x1 << UL_PHASE_SYNC_FCLK_0_ON_SFT); + + return 0; +} + +static int mtk_adda_ul_src_enable_dmic(struct mtk_base_afe *afe, int id) +{ + unsigned int reg_con0 = 0, reg_con1 = 0; + + dev_dbg(afe->dev, "id: %d\n", id); + + switch (id) { + case MT8196_DAI_ADDA: + case MT8196_DAI_AP_DMIC: + reg_con0 = AFE_ADDA_UL0_SRC_CON0; + reg_con1 = AFE_ADDA_UL0_SRC_CON1; + break; + case MT8196_DAI_ADDA_CH34: + case MT8196_DAI_AP_DMIC_CH34: + reg_con0 = AFE_ADDA_UL1_SRC_CON0; + reg_con1 = AFE_ADDA_UL1_SRC_CON1; + break; + default: + return -EINVAL; + } + + switch (id) { + case MT8196_DAI_AP_DMIC: + dev_dbg(afe->dev, "clear mtkaifv4 ul ch1ch2 mux\n"); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT, + 0x0 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT); + break; + case MT8196_DAI_AP_DMIC_CH34: + dev_dbg(afe->dev, "clear mtkaifv4 ul ch3ch4 mux\n"); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT, + 0x0 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT); + break; + default: + return -EINVAL; + } + + /* choose Phase */ + regmap_update_bits(afe->regmap, reg_con0, + UL_DMIC_PHASE_SEL_CH1_MASK_SFT, + 0x0 << UL_DMIC_PHASE_SEL_CH1_SFT); + regmap_update_bits(afe->regmap, reg_con0, + UL_DMIC_PHASE_SEL_CH2_MASK_SFT, + 0x4 << UL_DMIC_PHASE_SEL_CH2_SFT); + + /* dmic mode, 3.25M*/ + regmap_update_bits(afe->regmap, reg_con0, + DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT, + 0x0); + regmap_update_bits(afe->regmap, reg_con0, + DMIC_LOW_POWER_MODE_CTL_MASK_SFT, + 0x0); + + /* turn on dmic, ch1, ch2 */ + regmap_update_bits(afe->regmap, reg_con0, + UL_SDM_3_LEVEL_CTL_MASK_SFT, + 0x1 << UL_SDM_3_LEVEL_CTL_SFT); + regmap_update_bits(afe->regmap, reg_con0, + UL_MODE_3P25M_CH1_CTL_MASK_SFT, + 0x1 << UL_MODE_3P25M_CH1_CTL_SFT); + regmap_update_bits(afe->regmap, reg_con0, + UL_MODE_3P25M_CH2_CTL_MASK_SFT, + 0x1 << UL_MODE_3P25M_CH2_CTL_SFT); + + /* ul gain: gain = 0x7fff/positive_gain = 0x0/gain_mode = 0x10 */ + regmap_update_bits(afe->regmap, reg_con1, + ADDA_UL_GAIN_VALUE_MASK_SFT, + 0x7fff << ADDA_UL_GAIN_VALUE_SFT); + regmap_update_bits(afe->regmap, reg_con1, + ADDA_UL_POSTIVEGAIN_MASK_SFT, + 0x0 << ADDA_UL_POSTIVEGAIN_SFT); + /* gain_mode = 0x10: Add 0.5 gain at CIC output */ + regmap_update_bits(afe->regmap, reg_con1, + GAIN_MODE_MASK_SFT, + 0x02 << GAIN_MODE_SFT); + return 0; +} + +static int mtk_adda_sleep_on_pmd_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(afe->dev, "name %s, event 0x%x\n", w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(120, 130); + break; + default: + break; + } + + return 0; +} + +/* ADDA UL MUX */ +#define ADDA_UL_MUX_MASK 0x3 +enum { + ADDA_UL_MUX_MTKAIF = 0, + ADDA_UL_MUX_AP_DMIC, + ADDA_UL_MUX_AP_DMIC_MULTICH, +}; + +static const char *const adda_ul_mux_map[] = { + "MTKAIF", "AP_DMIC", "AP_DMIC_MULTI_CH", +}; + +static int adda_ul_map_value[] = { + ADDA_UL_MUX_MTKAIF, + ADDA_UL_MUX_AP_DMIC, + ADDA_UL_MUX_AP_DMIC_MULTICH, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(adda_ul_mux_map_enum, + SND_SOC_NOPM, + 0, + ADDA_UL_MUX_MASK, + adda_ul_mux_map, + adda_ul_map_value); + +static const struct snd_kcontrol_new adda_ul_mux_control = + SOC_DAPM_ENUM("ADDA_UL_MUX Select", adda_ul_mux_map_enum); + +static const struct snd_kcontrol_new adda_ch34_ul_mux_control = + SOC_DAPM_ENUM("ADDA_CH34_UL_MUX Select", adda_ul_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON, + AUDIO_ENGEN_CON0, AUDIO_F3P25M_EN_ON_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON, + AFE_ADDA_UL0_SRC_CON0, + UL_SRC_ON_TMP_CTL_SFT, 0, + mtk_adda_sleep_on_pmd_event, + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("ADDA CH34 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON, + AFE_ADDA_UL1_SRC_CON0, + UL_SRC_ON_TMP_CTL_SFT, 0, + mtk_adda_sleep_on_pmd_event, + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("AP_DMIC_EN", SUPPLY_SEQ_ADDA_AP_DMIC, + AFE_ADDA_UL0_SRC_CON0, + UL_AP_DMIC_ON_SFT, 0, + mtk_adda_sleep_on_pmd_event, + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("AP_DMIC_CH34_EN", SUPPLY_SEQ_ADDA_AP_DMIC, + AFE_ADDA_UL1_SRC_CON0, + UL_AP_DMIC_ON_SFT, 0, + mtk_adda_sleep_on_pmd_event, + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("ADDA_FIFO", SUPPLY_SEQ_ADDA_FIFO, + AFE_ADDA_UL0_SRC_CON1, + FIFO_SOFT_RST_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("ADDA_CH34_FIFO", SUPPLY_SEQ_ADDA_FIFO, + AFE_ADDA_UL1_SRC_CON1, + FIFO_SOFT_RST_SFT, 1, + NULL, 0), + SND_SOC_DAPM_MUX("ADDA_UL_Mux", SND_SOC_NOPM, 0, 0, + &adda_ul_mux_control), + SND_SOC_DAPM_MUX("ADDA_CH34_UL_Mux", SND_SOC_NOPM, 0, 0, + &adda_ch34_ul_mux_control), + SND_SOC_DAPM_INPUT("AP_DMIC_INPUT"), +}; + +static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = { + /* capture */ + {"ADDA_UL_Mux", "MTKAIF", "ADDA Capture"}, + {"ADDA_UL_Mux", "AP_DMIC", "AP DMIC Capture"}, + {"ADDA_UL_Mux", "AP_DMIC_MULTI_CH", "AP DMIC MULTICH Capture"}, + + {"ADDA_CH34_UL_Mux", "MTKAIF", "ADDA CH34 Capture"}, + {"ADDA_CH34_UL_Mux", "AP_DMIC", "AP DMIC CH34 Capture"}, + {"ADDA_CH34_UL_Mux", "AP_DMIC_MULTI_CH", "AP DMIC MULTICH Capture"}, + + {"AP DMIC Capture", NULL, "ADDA Enable"}, + {"AP DMIC Capture", NULL, "ADDA Capture Enable"}, + {"AP DMIC Capture", NULL, "ADDA_FIFO"}, + {"AP DMIC Capture", NULL, "AP_DMIC_EN"}, + + {"AP DMIC CH34 Capture", NULL, "ADDA Enable"}, + {"AP DMIC CH34 Capture", NULL, "ADDA CH34 Capture Enable"}, + {"AP DMIC CH34 Capture", NULL, "ADDA_CH34_FIFO"}, + {"AP DMIC CH34 Capture", NULL, "AP_DMIC_CH34_EN"}, + + {"AP DMIC MULTICH Capture", NULL, "ADDA Enable"}, + {"AP DMIC MULTICH Capture", NULL, "ADDA Capture Enable"}, + {"AP DMIC MULTICH Capture", NULL, "ADDA CH34 Capture Enable"}, + {"AP DMIC MULTICH Capture", NULL, "ADDA_FIFO"}, + {"AP DMIC MULTICH Capture", NULL, "ADDA_CH34_FIFO"}, + {"AP DMIC MULTICH Capture", NULL, "AP_DMIC_EN"}, + {"AP DMIC MULTICH Capture", NULL, "AP_DMIC_CH34_EN"}, + + {"AP DMIC Capture", NULL, "AP_DMIC_INPUT"}, + {"AP DMIC CH34 Capture", NULL, "AP_DMIC_INPUT"}, + {"AP DMIC MULTICH Capture", NULL, "AP_DMIC_INPUT"}, +}; + +/* dai ops */ +static int set_playback_hw_params(struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + unsigned int rate = params_rate(params); + struct mtk_afe_adda_priv *adda_priv; + unsigned int mtkaif_rate = 0; + int id = dai->id; + + adda_priv = afe_priv->dai_priv[id]; + if (!adda_priv) + return -EINVAL; + + adda_priv->dl_rate = rate; + + /* get mtkaif dl rate */ + mtkaif_rate = mtkaif_rate_transform(afe, adda_priv->dl_rate); + + if (id == MT8196_DAI_ADDA) { + /* MTKAIF sample rate config */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0, + MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT, + mtkaif_rate << MTKAIFV4_TXIF_INPUT_MODE_SFT); + /* AFE_ADDA_MTKAIFV4_TX_CFG0 */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0, + MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT, + 0x0 << MTKAIFV4_TXIF_FOUR_CHANNEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0, + MTKAIFV4_ADDA_OUT_EN_SEL_MASK_SFT, + 0x1 << MTKAIFV4_ADDA_OUT_EN_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0, + MTKAIFV4_ADDA6_OUT_EN_SEL_MASK_SFT, + 0x1 << MTKAIFV4_ADDA6_OUT_EN_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0, + MTKAIFV4_TXIF_V4_MASK_SFT, + 0x1 << MTKAIFV4_TXIF_V4_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0, + MTKAIFV4_TXIF_EN_SEL_MASK_SFT, + 0x0 << MTKAIFV4_TXIF_EN_SEL_SFT); + /* clean predistortion */ + } else { + /* MTKAIF sample rate config */ + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0, + ADDA6_MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT, + mtkaif_rate << ADDA6_MTKAIFV4_TXIF_INPUT_MODE_SFT); + /* AFE_ADDA6_MTKAIFV4_TX_CFG0 */ + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0, + ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT, + 0x0 << ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0, + ADDA6_MTKAIFV4_TXIF_EN_SEL_MASK_SFT, + 0x1 << ADDA6_MTKAIFV4_TXIF_EN_SEL_SFT); + } + + return 0; +}; + +static int set_capture_hw_params(struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + unsigned int rate = params_rate(params); + struct mtk_afe_adda_priv *adda_priv; + unsigned int voice_mode = 0; + unsigned int ul_src_con0 = 0; + unsigned int mtkaif_rate = 0; + int id = dai->id; + + adda_priv = afe_priv->dai_priv[id]; + if (!adda_priv) + return -EINVAL; + + adda_priv->ul_rate = rate; + + /* get mtkaif dl rate */ + mtkaif_rate = mtkaif_rate_transform(afe, adda_priv->ul_rate); + + voice_mode = adda_ul_rate_transform(afe, rate); + + ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); + + /* enable iir */ + ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) & + UL_IIR_ON_TMP_CTL_MASK_SFT; + ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) & + UL_IIRMODE_CTL_MASK_SFT; + + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT, + mtkaif_rate << MTKAIFV4_RXIF_INPUT_MODE_SFT); + + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0, + ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT, + mtkaif_rate << ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT); + + switch (id) { + case MT8196_DAI_ADDA: + case MT8196_DAI_AP_DMIC: + case MT8196_DAI_AP_DMIC_MULTICH: + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT, + mtkaif_rate << MTKAIFV4_RXIF_INPUT_MODE_SFT); + /* AFE_ADDA_MTKAIFV4_RX_CFG0 */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT, + 0x1 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_RXIF_EN_SEL_MASK_SFT, + 0x0 << MTKAIFV4_RXIF_EN_SEL_SFT); + /* [28] loopback mode + * 0: loopback adda tx to adda rx + * 1: loopback adda6 tx to adda rx + */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_TXIF_EN_SEL_MASK_SFT, + 0x0 << MTKAIFV4_TXIF_EN_SEL_SFT); + + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT, + 0x1 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT, + 0x1 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT); + + /* 35Hz @ 48k */ + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_02_01, 0x00000000); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_04_03, 0x00003FB8); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_06_05, 0x3FB80000); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_08_07, 0x3FB80000); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_10_09, 0x0000C048); + + regmap_write(afe->regmap, + AFE_ADDA_UL1_SRC_CON0, ul_src_con0); + + /* mtkaif_rxif_data_mode = 0, amic */ + regmap_update_bits(afe->regmap, + AFE_MTKAIF1_RX_CFG0, + 0x1 << 0, + 0x0 << 0); + + /* 35Hz @ 48k */ + regmap_write(afe->regmap, + AFE_ADDA_UL0_IIR_COEF_02_01, 0x00000000); + regmap_write(afe->regmap, + AFE_ADDA_UL0_IIR_COEF_04_03, 0x00003FB8); + regmap_write(afe->regmap, + AFE_ADDA_UL0_IIR_COEF_06_05, 0x3FB80000); + regmap_write(afe->regmap, + AFE_ADDA_UL0_IIR_COEF_08_07, 0x3FB80000); + regmap_write(afe->regmap, + AFE_ADDA_UL0_IIR_COEF_10_09, 0x0000C048); + + regmap_write(afe->regmap, + AFE_ADDA_UL0_SRC_CON0, ul_src_con0); + + /* mtkaif_rxif_data_mode = 0, amic */ + regmap_update_bits(afe->regmap, + AFE_MTKAIF0_RX_CFG0, + 0x1 << 0, + 0x0 << 0); + break; + case MT8196_DAI_ADDA_CH34: + case MT8196_DAI_AP_DMIC_CH34: + /* AFE_ADDA_MTKAIFV4_RX_CFG0 */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT, + 0x1 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_RXIF_EN_SEL_MASK_SFT, + 0x0 << MTKAIFV4_RXIF_EN_SEL_SFT); + + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT, + 0x1 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT, + 0x1 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT); + + /* 35Hz @ 48k */ + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_02_01, 0x00000000); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_04_03, 0x00003FB8); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_06_05, 0x3FB80000); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_08_07, 0x3FB80000); + regmap_write(afe->regmap, + AFE_ADDA_UL1_IIR_COEF_10_09, 0x0000C048); + + regmap_write(afe->regmap, + AFE_ADDA_UL1_SRC_CON0, ul_src_con0); + + /* mtkaif_rxif_data_mode = 0, amic */ + regmap_update_bits(afe->regmap, + AFE_MTKAIF1_RX_CFG0, + 0x1 << 0, + 0x0 << 0); + break; + case MT8196_DAI_ADDA_CH56: + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0, + ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT, + mtkaif_rate << ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT); + /* AFE_ADDA6_MTKAIFV4_RX_CFG0 */ + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0, + ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT, + 0x1 << ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0, + MTKAIFV4_UL_CH5CH6_IN_EN_SEL_MASK_SFT, + 0x1 << MTKAIFV4_UL_CH5CH6_IN_EN_SEL_SFT); + regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0, + ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK_SFT, + 0x1 << ADDA6_MTKAIFV4_RXIF_EN_SEL_SFT); + break; + default: + break; + } + + /* ap dmic */ + switch (id) { + case MT8196_DAI_AP_DMIC: + case MT8196_DAI_AP_DMIC_CH34: + mtk_adda_ul_src_enable_dmic(afe, id); + break; + case MT8196_DAI_AP_DMIC_MULTICH: + regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1, + DMIC_CLK_PHASE_SYNC_SET_MASK_SFT, + 0x1 << DMIC_CLK_PHASE_SYNC_SET_SFT); + mtk_adda_ul_src_set_dmic_phase_sync(afe); + mtk_adda_ul_src_enable_dmic(afe, MT8196_DAI_AP_DMIC); + mtk_adda_ul_src_enable_dmic(afe, MT8196_DAI_AP_DMIC_CH34); + mtk_adda_ul_src_set_dmic_phase_sync_clock(afe); + break; + default: + break; + } + + return 0; +}; + +static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int id = dai->id; + + if (id >= MT8196_DAI_NUM || id < 0) + return -EINVAL; + + dev_dbg(afe->dev, "id %d, stream %d, rate %d\n", + id, substream->stream, params_rate(params)); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return set_playback_hw_params(params, dai); + else + return set_capture_hw_params(params, dai); + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_adda_ops = { + .hw_params = mtk_dai_adda_hw_params, +}; + +/* dai driver */ +#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_ADDA_CAPTURE_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) + +#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_adda_driver[] = { + { + .name = "ADDA", + .id = MT8196_DAI_ADDA, + .playback = { + .stream_name = "ADDA Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_PLAYBACK_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .capture = { + .stream_name = "ADDA Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "ADDA_CH34", + .id = MT8196_DAI_ADDA_CH34, + .playback = { + .stream_name = "ADDA CH34 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_PLAYBACK_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .capture = { + .stream_name = "ADDA CH34 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "ADDA_CH56", + .id = MT8196_DAI_ADDA_CH56, + .capture = { + .stream_name = "ADDA CH56 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "AP_DMIC", + .id = MT8196_DAI_AP_DMIC, + .capture = { + .stream_name = "AP DMIC Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "AP_DMIC_CH34", + .id = MT8196_DAI_AP_DMIC_CH34, + .capture = { + .stream_name = "AP DMIC CH34 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + /* + * Multich DMIC combines two DMIC controllers for use together, + * so AP_DMIC and Multich DMIC cannot be used at the same time. + */ + { + .name = "AP_DMIC_MULTICH", + .id = MT8196_DAI_AP_DMIC_MULTICH, + .capture = { + .stream_name = "AP DMIC MULTICH Capture", + .channels_min = 1, + .channels_max = 4, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, +}; + +static int init_adda_priv_data(struct mtk_base_afe *afe) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_adda_priv *adda_priv; + static const int adda_dai_list[] = { + MT8196_DAI_ADDA, + MT8196_DAI_ADDA_CH34, + MT8196_DAI_ADDA_CH56, + MT8196_DAI_AP_DMIC_MULTICH + }; + int i; + + for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) { + adda_priv = devm_kzalloc(afe->dev, + sizeof(struct mtk_afe_adda_priv), + GFP_KERNEL); + if (!adda_priv) + return -ENOMEM; + + afe_priv->dai_priv[adda_dai_list[i]] = adda_priv; + } + + /* ap dmic priv share with adda */ + afe_priv->dai_priv[MT8196_DAI_AP_DMIC] = + afe_priv->dai_priv[MT8196_DAI_ADDA]; + afe_priv->dai_priv[MT8196_DAI_AP_DMIC_CH34] = + afe_priv->dai_priv[MT8196_DAI_ADDA_CH34]; + + return 0; +} + +int mt8196_dai_adda_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + dai->dai_drivers = mtk_dai_adda_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver); + dai->dapm_widgets = mtk_dai_adda_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets); + dai->dapm_routes = mtk_dai_adda_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes); + + ret = init_adda_priv_data(afe); + if (ret) + return ret; + + list_add(&dai->list, &afe->sub_dais); + + return 0; +} + diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-i2s.c b/sound/soc/mediatek/mt8196/mt8196-dai-i2s.c new file mode 100644 index 000000000000..ef5cde0ba829 --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-dai-i2s.c @@ -0,0 +1,2613 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI I2S Control + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#include +#include + +#include + +#include "mt8196-afe-clk.h" +#include "mt8196-afe-common.h" +#include "mt8196-interconnection.h" + +#include "../common/mtk-afe-fe-dai.h" + +#define ETDM_22M_CLOCK_THRES 11289600 + +enum { + ETDM_CLK_SOURCE_H26M, + ETDM_CLK_SOURCE_APLL, + ETDM_CLK_SOURCE_SPDIF, + ETDM_CLK_SOURCE_HDMI, + ETDM_CLK_SOURCE_EARC, + ETDM_CLK_SOURCE_LINEIN, +}; + +enum { + ETDM_RELATCH_SEL_H26M, + ETDM_RELATCH_SEL_APLL, +}; + +enum { + ETDM_RATE_8K, + ETDM_RATE_12K, + ETDM_RATE_16K, + ETDM_RATE_24K, + ETDM_RATE_32K, + ETDM_RATE_48K, + ETDM_RATE_64K, + ETDM_RATE_96K, + ETDM_RATE_128K, + ETDM_RATE_192K, + ETDM_RATE_256K, + ETDM_RATE_384K, + ETDM_RATE_11025 = 16, + ETDM_RATE_22050, + ETDM_RATE_44100, + ETDM_RATE_88200, + ETDM_RATE_176400, + ETDM_RATE_352800, +}; + +enum { + ETDM_CONN_8K, + ETDM_CONN_11K, + ETDM_CONN_12K, + ETDM_CONN_16K = 4, + ETDM_CONN_22K, + ETDM_CONN_24K, + ETDM_CONN_32K = 8, + ETDM_CONN_44K, + ETDM_CONN_48K, + ETDM_CONN_88K = 13, + ETDM_CONN_96K, + ETDM_CONN_176K = 17, + ETDM_CONN_192K, + ETDM_CONN_352K = 21, + ETDM_CONN_384K, +}; + +enum { + ETDM_WLEN_8_BIT = 0x7, + ETDM_WLEN_16_BIT = 0xf, + ETDM_WLEN_32_BIT = 0x1f, +}; + +enum { + ETDM_SLAVE_SEL_ETDMIN0_MASTER, + ETDM_SLAVE_SEL_ETDMIN0_SLAVE, + ETDM_SLAVE_SEL_ETDMIN1_MASTER, + ETDM_SLAVE_SEL_ETDMIN1_SLAVE, + ETDM_SLAVE_SEL_ETDMIN2_MASTER, + ETDM_SLAVE_SEL_ETDMIN2_SLAVE, + ETDM_SLAVE_SEL_ETDMIN3_MASTER, + ETDM_SLAVE_SEL_ETDMIN3_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT0_MASTER, + ETDM_SLAVE_SEL_ETDMOUT0_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT1_MASTER, + ETDM_SLAVE_SEL_ETDMOUT1_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT2_MASTER, + ETDM_SLAVE_SEL_ETDMOUT2_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT3_MASTER, + ETDM_SLAVE_SEL_ETDMOUT3_SLAVE, +}; + +enum { + ETDM_SLAVE_SEL_ETDMIN4_MASTER, + ETDM_SLAVE_SEL_ETDMIN4_SLAVE, + ETDM_SLAVE_SEL_ETDMIN5_MASTER, + ETDM_SLAVE_SEL_ETDMIN5_SLAVE, + ETDM_SLAVE_SEL_ETDMIN6_MASTER, + ETDM_SLAVE_SEL_ETDMIN6_SLAVE, + ETDM_SLAVE_SEL_ETDMIN7_MASTER, + ETDM_SLAVE_SEL_ETDMIN7_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT4_MASTER, + ETDM_SLAVE_SEL_ETDMOUT4_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT5_MASTER, + ETDM_SLAVE_SEL_ETDMOUT5_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT6_MASTER, + ETDM_SLAVE_SEL_ETDMOUT6_SLAVE, + ETDM_SLAVE_SEL_ETDMOUT7_MASTER, + ETDM_SLAVE_SEL_ETDMOUT7_SLAVE, +}; + +enum { + MTK_DAI_ETDM_FORMAT_I2S, + MTK_DAI_ETDM_FORMAT_LJ, + MTK_DAI_ETDM_FORMAT_RJ, + MTK_DAI_ETDM_FORMAT_EIAJ, + MTK_DAI_ETDM_FORMAT_DSPA, + MTK_DAI_ETDM_FORMAT_DSPB, +}; + +static unsigned int get_etdm_wlen(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) < 16 ? + ETDM_WLEN_16_BIT : ETDM_WLEN_32_BIT; +} + +static unsigned int get_etdm_lrck_width(snd_pcm_format_t format) +{ + /* The valid data bit number should be large than 7 due to hardware limitation. */ + return snd_pcm_format_physical_width(format) - 1; +} + +static unsigned int get_etdm_rate(unsigned int rate) +{ + switch (rate) { + case 8000: + return ETDM_RATE_8K; + case 12000: + return ETDM_RATE_12K; + case 16000: + return ETDM_RATE_16K; + case 24000: + return ETDM_RATE_24K; + case 32000: + return ETDM_RATE_32K; + case 48000: + return ETDM_RATE_48K; + case 64000: + return ETDM_RATE_64K; + case 96000: + return ETDM_RATE_96K; + case 128000: + return ETDM_RATE_128K; + case 192000: + return ETDM_RATE_192K; + case 256000: + return ETDM_RATE_256K; + case 384000: + return ETDM_RATE_384K; + case 11025: + return ETDM_RATE_11025; + case 22050: + return ETDM_RATE_22050; + case 44100: + return ETDM_RATE_44100; + case 88200: + return ETDM_RATE_88200; + case 176400: + return ETDM_RATE_176400; + case 352800: + return ETDM_RATE_352800; + default: + return 0; + } +} + +static unsigned int get_etdm_inconn_rate(unsigned int rate) +{ + switch (rate) { + case 8000: + return ETDM_CONN_8K; + case 12000: + return ETDM_CONN_12K; + case 16000: + return ETDM_CONN_16K; + case 24000: + return ETDM_CONN_24K; + case 32000: + return ETDM_CONN_32K; + case 48000: + return ETDM_CONN_48K; + case 96000: + return ETDM_CONN_96K; + case 192000: + return ETDM_CONN_192K; + case 384000: + return ETDM_CONN_384K; + case 11025: + return ETDM_CONN_11K; + case 22050: + return ETDM_CONN_22K; + case 44100: + return ETDM_CONN_44K; + case 88200: + return ETDM_CONN_88K; + case 176400: + return ETDM_CONN_176K; + case 352800: + return ETDM_CONN_352K; + default: + return 0; + } +} + +struct mtk_afe_i2s_priv { + u8 id; + u32 rate; /* for determine which apll to use */ + int low_jitter_en; + const char *share_property_name; + int share_i2s_id; + u32 mclk_rate; + u8 mclk_id; + u8 mclk_apll; + u8 ch_num; + u8 sync; + u8 ip_mode; + u8 format; +}; + +/* this enum is merely for mtk_afe_i2s_priv & mtk_base_etdm_data declare */ +enum { + DAI_I2SIN0, + DAI_I2SIN1, + DAI_I2SIN2, + DAI_I2SIN3, + DAI_I2SIN4, + DAI_I2SIN6, + DAI_I2SOUT0, + DAI_I2SOUT1, + DAI_I2SOUT2, + DAI_I2SOUT3, + DAI_I2SOUT4, + DAI_I2SOUT6, + DAI_FMI2S_MASTER, + DAI_I2S_NUM, +}; + +static bool is_etdm_in_pad_top(unsigned int dai_num) +{ + switch (dai_num) { + case DAI_I2SOUT4: + case DAI_I2SIN4: + return true; + default: + return false; + } +} + +struct mtk_base_etdm_data { + u16 enable_reg; + u16 enable_mask; + u8 enable_shift; + u16 sync_reg; + u16 sync_mask; + u8 sync_shift; + u16 ch_reg; + u16 ch_mask; + u8 ch_shift; + u16 ip_mode_reg; + u16 ip_mode_mask; + u8 ip_mode_shift; + u16 init_count_reg; + u16 init_count_mask; + u8 init_count_shift; + u16 init_point_reg; + u16 init_point_mask; + u8 init_point_shift; + u16 lrck_reset_reg; + u16 lrck_reset_mask; + u8 lrck_reset_shift; + u16 clk_source_reg; + u16 clk_source_mask; + u8 clk_source_shift; + u16 ck_en_sel_reg; + u16 ck_en_sel_mask; + u8 ck_en_sel_shift; + u16 fs_timing_reg; + u16 fs_timing_mask; + u8 fs_timing_shift; + u16 relatch_en_sel_reg; + u16 relatch_en_sel_mask; + u8 relatch_en_sel_shift; + u16 use_afifo_reg; + u16 use_afifo_mask; + u8 use_afifo_shift; + u16 afifo_mode_reg; + u16 afifo_mode_mask; + u8 afifo_mode_shift; + u16 almost_end_ch_reg; + u16 almost_end_ch_mask; + u8 almost_end_ch_shift; + u16 almost_end_bit_reg; + u16 almost_end_bit_mask; + u8 almost_end_bit_shift; + u16 out2latch_time_reg; + u16 out2latch_time_mask; + u8 out2latch_time_shift; + u16 tdm_mode_reg; + u16 tdm_mode_mask; + u8 tdm_mode_shift; + u16 relatch_domain_sel_reg; + u16 relatch_domain_sel_mask; + u8 relatch_domain_sel_shift; + u16 bit_length_reg; + u16 bit_length_mask; + u8 bit_length_shift; + u16 word_length_reg; + u16 word_length_mask; + u8 word_length_shift; + u16 cowork_reg; + u16 cowork_mask; + u8 cowork_shift; + u32 cowork_val; + u16 in2latch_time_reg; + u16 in2latch_time_mask; + u8 in2latch_time_shift; + u16 pad_top_ck_en_reg; + u16 pad_top_ck_en_mask; + u8 pad_top_ck_en_shift; + u16 master_latch_reg; + u16 master_latch_mask; + u8 master_latch_shift; +}; + +/* + * _cfg_vlp_reg should be a variable or constant, not an expression + * with side effects. + */ +#define MTK_ETDM_IN_DATA(_id, _cowork, _cfg_vlp_reg) \ + [DAI_I2SIN##_id] = { \ + .enable_reg = ETDM_IN##_id##_CON0, \ + .enable_mask = REG_ETDM_IN_EN_MASK, \ + .enable_shift = REG_ETDM_IN_EN_SFT, \ + .sync_reg = ETDM_IN##_id##_CON0, \ + .sync_mask = REG_SYNC_MODE_MASK, \ + .sync_shift = REG_SYNC_MODE_SFT, \ + .ch_reg = ETDM_IN##_id##_CON0, \ + .ch_mask = REG_CH_NUM_MASK, \ + .ch_shift = REG_CH_NUM_SFT, \ + .ip_mode_reg = ETDM_IN##_id##_CON2, \ + .ip_mode_mask = REG_MULTI_IP_MODE_MASK, \ + .ip_mode_shift = REG_MULTI_IP_MODE_SFT, \ + .init_count_reg = ETDM_IN##_id##_CON1, \ + .init_count_mask = REG_INITIAL_COUNT_MASK, \ + .init_count_shift = REG_INITIAL_COUNT_SFT, \ + .init_point_reg = ETDM_IN##_id##_CON1, \ + .init_point_mask = REG_INITIAL_POINT_MASK, \ + .init_point_shift = REG_INITIAL_POINT_SFT, \ + .lrck_reset_reg = ETDM_IN##_id##_CON1, \ + .lrck_reset_mask = REG_LRCK_RESET_MASK, \ + .lrck_reset_shift = REG_LRCK_RESET_SFT, \ + .clk_source_reg = ETDM_IN##_id##_CON2, \ + .clk_source_mask = REG_CLOCK_SOURCE_SEL_MASK, \ + .clk_source_shift = REG_CLOCK_SOURCE_SEL_SFT, \ + .ck_en_sel_reg = ETDM_IN##_id##_CON2, \ + .ck_en_sel_mask = REG_CK_EN_SEL_AUTO_MASK, \ + .ck_en_sel_shift = REG_CK_EN_SEL_AUTO_SFT, \ + .fs_timing_reg = ETDM_IN##_id##_CON3, \ + .fs_timing_mask = REG_FS_TIMING_SEL_MASK, \ + .fs_timing_shift = REG_FS_TIMING_SEL_SFT, \ + .relatch_en_sel_reg = ETDM_IN##_id##_CON4, \ + .relatch_en_sel_mask = REG_RELATCH_1X_EN_SEL_MASK, \ + .relatch_en_sel_shift = REG_RELATCH_1X_EN_SEL_SFT, \ + .use_afifo_reg = ETDM_IN##_id##_CON8, \ + .use_afifo_mask = REG_ETDM_USE_AFIFO_MASK, \ + .use_afifo_shift = REG_ETDM_USE_AFIFO_SFT, \ + .afifo_mode_reg = ETDM_IN##_id##_CON8, \ + .afifo_mode_mask = REG_AFIFO_MODE_MASK, \ + .afifo_mode_shift = REG_AFIFO_MODE_SFT, \ + .almost_end_ch_reg = ETDM_IN##_id##_CON9, \ + .almost_end_ch_mask = REG_ALMOST_END_CH_COUNT_MASK, \ + .almost_end_ch_shift = REG_ALMOST_END_CH_COUNT_SFT, \ + .almost_end_bit_reg = ETDM_IN##_id##_CON9, \ + .almost_end_bit_mask = REG_ALMOST_END_BIT_COUNT_MASK, \ + .almost_end_bit_shift = REG_ALMOST_END_BIT_COUNT_SFT, \ + .out2latch_time_reg = ETDM_IN##_id##_CON9, \ + .out2latch_time_mask = REG_OUT2LATCH_TIME_MASK, \ + .out2latch_time_shift = REG_OUT2LATCH_TIME_SFT, \ + .tdm_mode_reg = ETDM_IN##_id##_CON0, \ + .tdm_mode_mask = REG_FMT_MASK, \ + .tdm_mode_shift = REG_FMT_SFT, \ + .relatch_domain_sel_reg = ETDM_IN##_id##_CON0, \ + .relatch_domain_sel_mask = REG_RELATCH_1X_EN_DOMAIN_SEL_MASK, \ + .relatch_domain_sel_shift = REG_RELATCH_1X_EN_DOMAIN_SEL_SFT, \ + .bit_length_reg = ETDM_IN##_id##_CON0, \ + .bit_length_mask = REG_BIT_LENGTH_MASK, \ + .bit_length_shift = REG_BIT_LENGTH_SFT, \ + .word_length_reg = ETDM_IN##_id##_CON0, \ + .word_length_mask = REG_WORD_LENGTH_MASK, \ + .word_length_shift = REG_WORD_LENGTH_SFT, \ + .cowork_reg = _cowork, \ + .cowork_mask = ETDM_IN##_id##_SLAVE_SEL_MASK, \ + .cowork_shift = ETDM_IN##_id##_SLAVE_SEL_SFT, \ + .cowork_val = ETDM_SLAVE_SEL_ETDMOUT##_id##_MASTER, \ + .pad_top_ck_en_reg = _cfg_vlp_reg, \ + .pad_top_ck_en_mask = RG_I2S4_PAD_TOP_CK_EN_MASK, \ + .pad_top_ck_en_shift = RG_I2S4_PAD_TOP_CK_EN_SFT, \ + .master_latch_reg = _cfg_vlp_reg, \ + .master_latch_mask = RG_I2S4_IN_BCK_NEG_EG_LATCH_MASK, \ + .master_latch_shift = RG_I2S4_IN_BCK_NEG_EG_LATCH_SFT, \ + } + +/* + * _cfg_vlp_reg should be a variable or constant, not an expression + * with side effects. + */ +#define MTK_ETDM_OUT_DATA(_id, _cowork, _cfg_vlp_reg) \ + [DAI_I2SOUT##_id] = { \ + .enable_reg = ETDM_OUT##_id##_CON0, \ + .enable_mask = OUT_REG_ETDM_OUT_EN_MASK, \ + .enable_shift = OUT_REG_ETDM_OUT_EN_SFT, \ + .sync_reg = ETDM_OUT##_id##_CON0, \ + .sync_mask = REG_SYNC_MODE_MASK, \ + .sync_shift = REG_SYNC_MODE_SFT, \ + .ch_reg = ETDM_OUT##_id##_CON0, \ + .ch_mask = REG_CH_NUM_MASK, \ + .ch_shift = REG_CH_NUM_SFT, \ + .init_count_reg = ETDM_OUT##_id##_CON1, \ + .init_count_mask = OUT_REG_INITIAL_COUNT_MASK, \ + .init_count_shift = OUT_REG_INITIAL_COUNT_SFT, \ + .init_point_reg = ETDM_OUT##_id##_CON1, \ + .init_point_mask = OUT_REG_INITIAL_POINT_MASK, \ + .init_point_shift = OUT_REG_INITIAL_POINT_SFT, \ + .lrck_reset_reg = ETDM_OUT##_id##_CON1, \ + .lrck_reset_mask = OUT_REG_LRCK_RESET_MASK, \ + .lrck_reset_shift = OUT_REG_LRCK_RESET_SFT, \ + .clk_source_reg = ETDM_OUT##_id##_CON4, \ + .clk_source_mask = OUT_REG_CLOCK_SOURCE_SEL_MASK, \ + .clk_source_shift = OUT_REG_CLOCK_SOURCE_SEL_SFT, \ + .fs_timing_reg = ETDM_OUT##_id##_CON4, \ + .fs_timing_mask = OUT_REG_FS_TIMING_SEL_MASK, \ + .fs_timing_shift = OUT_REG_FS_TIMING_SEL_SFT, \ + .relatch_en_sel_reg = ETDM_OUT##_id##_CON4, \ + .relatch_en_sel_mask = OUT_REG_RELATCH_EN_SEL_MASK, \ + .relatch_en_sel_shift = OUT_REG_RELATCH_EN_SEL_SFT, \ + .tdm_mode_reg = ETDM_OUT##_id##_CON0, \ + .tdm_mode_mask = OUT_REG_FMT_MASK, \ + .tdm_mode_shift = OUT_REG_FMT_SFT, \ + .relatch_domain_sel_reg = ETDM_OUT##_id##_CON0, \ + .relatch_domain_sel_mask = OUT_REG_RELATCH_DOMAIN_SEL_MASK, \ + .relatch_domain_sel_shift = OUT_REG_RELATCH_DOMAIN_SEL_SFT, \ + .bit_length_reg = ETDM_OUT##_id##_CON0, \ + .bit_length_mask = OUT_REG_BIT_LENGTH_MASK, \ + .bit_length_shift = OUT_REG_BIT_LENGTH_SFT, \ + .word_length_reg = ETDM_OUT##_id##_CON0, \ + .word_length_mask = OUT_REG_WORD_LENGTH_MASK, \ + .word_length_shift = OUT_REG_WORD_LENGTH_SFT, \ + .cowork_reg = _cowork, \ + .cowork_mask = ETDM_OUT##_id##_SLAVE_SEL_MASK, \ + .cowork_shift = ETDM_OUT##_id##_SLAVE_SEL_SFT, \ + .cowork_val = ETDM_SLAVE_SEL_ETDMIN##_id##_MASTER, \ + .in2latch_time_reg = ETDM_OUT##_id##_CON2, \ + .in2latch_time_mask = OUT_REG_IN2LATCH_TIME_MASK, \ + .in2latch_time_shift = OUT_REG_IN2LATCH_TIME_SFT, \ + .pad_top_ck_en_reg = _cfg_vlp_reg, \ + .pad_top_ck_en_mask = RG_I2S4_PAD_TOP_CK_EN_MASK, \ + .pad_top_ck_en_shift = RG_I2S4_PAD_TOP_CK_EN_SFT, \ + .master_latch_reg = _cfg_vlp_reg, \ + .master_latch_mask = RG_I2S4_OUT_BCK_NEG_EG_LATCH_MASK, \ + .master_latch_shift = RG_I2S4_OUT_BCK_NEG_EG_LATCH_SFT, \ + } + +static const struct mtk_base_etdm_data mtk_etdm_data[DAI_I2S_NUM] = { + MTK_ETDM_IN_DATA(0, ETDM_0_3_COWORK_CON0, 0), + MTK_ETDM_IN_DATA(1, ETDM_0_3_COWORK_CON1, 0), + MTK_ETDM_IN_DATA(2, ETDM_0_3_COWORK_CON2, 0), + MTK_ETDM_IN_DATA(3, ETDM_0_3_COWORK_CON3, 0), + MTK_ETDM_IN_DATA(4, ETDM_4_7_COWORK_CON0, AUD_TOP_CFG_VLP_RG), + MTK_ETDM_IN_DATA(6, ETDM_4_7_COWORK_CON2, 0), + + MTK_ETDM_OUT_DATA(0, ETDM_0_3_COWORK_CON0, 0), + MTK_ETDM_OUT_DATA(1, ETDM_0_3_COWORK_CON0, 0), + MTK_ETDM_OUT_DATA(2, ETDM_0_3_COWORK_CON2, 0), + MTK_ETDM_OUT_DATA(3, ETDM_0_3_COWORK_CON2, 0), + MTK_ETDM_OUT_DATA(4, ETDM_4_7_COWORK_CON0, AUD_TOP_CFG_VLP_RG), + MTK_ETDM_OUT_DATA(6, ETDM_4_7_COWORK_CON2, 0), +}; + +enum { + I2S_FMT_EIAJ, + I2S_FMT_I2S, +}; + +enum { + I2S_WLEN_16_BIT, + I2S_WLEN_32_BIT, +}; + +enum { + I2S_IN_PAD_CONNSYS, + I2S_IN_PAD_IO_MUX, +}; + +static unsigned int get_i2s_wlen(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) <= 16 ? + I2S_WLEN_16_BIT : I2S_WLEN_32_BIT; +} + +#define I2SIN0_MCLK_EN_W_NAME "I2SIN0_MCLK_EN" +#define I2SIN1_MCLK_EN_W_NAME "I2SIN1_MCLK_EN" +#define I2SIN2_MCLK_EN_W_NAME "I2SIN2_MCLK_EN" +#define I2SIN3_MCLK_EN_W_NAME "I2SIN3_MCLK_EN" +#define I2SIN4_MCLK_EN_W_NAME "I2SIN4_MCLK_EN" +#define I2SIN6_MCLK_EN_W_NAME "I2SIN6_MCLK_EN" +#define I2SOUT0_MCLK_EN_W_NAME "I2SOUT0_MCLK_EN" +#define I2SOUT1_MCLK_EN_W_NAME "I2SOUT1_MCLK_EN" +#define I2SOUT2_MCLK_EN_W_NAME "I2SOUT2_MCLK_EN" +#define I2SOUT3_MCLK_EN_W_NAME "I2SOUT3_MCLK_EN" +#define I2SOUT4_MCLK_EN_W_NAME "I2SOUT4_MCLK_EN" +#define I2SOUT6_MCLK_EN_W_NAME "I2SOUT6_MCLK_EN" +#define FMI2S_MASTER_MCLK_EN_W_NAME "FMI2S_MASTER_MCLK_EN" + +static int get_i2s_id_by_name(struct mtk_base_afe *afe, + const char *name) +{ + if (strncmp(name, "I2SIN0", 6) == 0) + return MT8196_DAI_I2S_IN0; + else if (strncmp(name, "I2SIN1", 6) == 0) + return MT8196_DAI_I2S_IN1; + else if (strncmp(name, "I2SIN2", 6) == 0) + return MT8196_DAI_I2S_IN2; + else if (strncmp(name, "I2SIN3", 6) == 0) + return MT8196_DAI_I2S_IN3; + else if (strncmp(name, "I2SIN4", 6) == 0) + return MT8196_DAI_I2S_IN4; + else if (strncmp(name, "I2SIN6", 6) == 0) + return MT8196_DAI_I2S_IN6; + else if (strncmp(name, "I2SOUT0", 7) == 0) + return MT8196_DAI_I2S_OUT0; + else if (strncmp(name, "I2SOUT1", 7) == 0) + return MT8196_DAI_I2S_OUT1; + else if (strncmp(name, "I2SOUT2", 7) == 0) + return MT8196_DAI_I2S_OUT2; + else if (strncmp(name, "I2SOUT3", 7) == 0) + return MT8196_DAI_I2S_OUT3; + else if (strncmp(name, "I2SOUT4", 7) == 0) + return MT8196_DAI_I2S_OUT4; + else if (strncmp(name, "I2SOUT6", 7) == 0) + return MT8196_DAI_I2S_OUT6; + else if (strncmp(name, "FMI2S_MASTER", 12) == 0) + return MT8196_DAI_FM_I2S_MASTER; + else + return -EINVAL; +} + +static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe, + const char *name) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_i2s_id_by_name(afe, name); + + if (dai_id < 0) + return NULL; + + return afe_priv->dai_priv[dai_id]; +} + +static const char * const etdm_0_3_loopback_text[] = { + "etdmin0", "etdmin1", + "etdmin2", "etdmin3", + "etdmout0", "etdmout1", + "etdmout2", "etdmout3" +}; + +static const char * const etdm_4_7_loopback_text[] = { + "etdmin4", "etdmin5", + "etdmin6", "etdmin7", + "etdmout4", "etdmout5", + "etdmout6", "etdmout7" +}; + +static const u32 etdm_loopback_values[] = { + 0, 2, 4, 6, 8, 10, 12, 14 +}; + +static const struct soc_enum i2sin0_loopback_enum = + SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON1, ETDM_IN0_SDATA0_SEL_SFT, + ETDM_IN0_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text), + etdm_0_3_loopback_text, etdm_loopback_values); + +static const struct soc_enum i2sin1_loopback_enum = + SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON1, ETDM_IN1_SDATA0_SEL_SFT, + ETDM_IN1_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text), + etdm_0_3_loopback_text, etdm_loopback_values); + +static const struct soc_enum i2sin2_loopback_enum = + SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON3, ETDM_IN2_SDATA0_SEL_SFT, + ETDM_IN2_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text), + etdm_0_3_loopback_text, etdm_loopback_values); + +static const struct soc_enum i2sin3_loopback_enum = + SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON3, ETDM_IN3_SDATA0_SEL_SFT, + ETDM_IN3_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text), + etdm_0_3_loopback_text, etdm_loopback_values); + +static const struct soc_enum i2sin4_loopback_enum = + SOC_VALUE_ENUM_SINGLE(ETDM_4_7_COWORK_CON1, ETDM_IN4_SDATA0_SEL_SFT, + ETDM_IN4_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_4_7_loopback_text), + etdm_4_7_loopback_text, etdm_loopback_values); + +static const struct soc_enum i2sin6_loopback_enum = + SOC_VALUE_ENUM_SINGLE(ETDM_4_7_COWORK_CON3, ETDM_IN6_SDATA0_SEL_SFT, + ETDM_IN6_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_4_7_loopback_text), + etdm_4_7_loopback_text, etdm_loopback_values); + +static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = { + SOC_ENUM("I2SIN0 LOOPBACK", i2sin0_loopback_enum), + SOC_ENUM("I2SIN1 LOOPBACK", i2sin1_loopback_enum), + SOC_ENUM("I2SIN2 LOOPBACK", i2sin2_loopback_enum), + SOC_ENUM("I2SIN3 LOOPBACK", i2sin3_loopback_enum), + /* The following I2S does not support multi-ip mode */ + SOC_ENUM("I2SIN4 LOOPBACK", i2sin4_loopback_enum), + SOC_ENUM("I2SIN6 LOOPBACK", i2sin6_loopback_enum), +}; + +/* interconnection */ +static const struct snd_kcontrol_new mtk_i2sout0_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN108_1, I_DL0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN108_1, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN108_1, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN108_1, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN108_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN108_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN108_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN108_1, I_DL7_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN108_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN108_1, I_DL_24CH_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH1", AFE_CONN108_2, I_DL23_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH1", AFE_CONN108_2, I_DL24_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN108_0, + I_GAIN0_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN108_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN108_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN108_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN108_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN108_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH1", AFE_CONN108_6, + I_SRC_2_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout0_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN109_1, I_DL0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN109_1, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN109_1, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN109_1, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN109_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN109_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN109_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN109_1, I_DL7_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN109_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN109_1, I_DL_24CH_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH2", AFE_CONN109_2, I_DL23_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH2", AFE_CONN109_2, I_DL24_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN109_0, + I_GAIN0_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN109_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN109_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN109_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN109_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN109_4, + I_PCM_0_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN109_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN109_4, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH2", AFE_CONN109_6, + I_SRC_2_OUT_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout1_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN110_1, I_DL0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN110_1, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN110_1, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN110_1, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN110_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN110_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN110_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN110_1, I_DL7_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN110_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN110_1, I_DL_24CH_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN110_0, + I_GAIN0_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN110_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN110_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN110_4, + I_PCM_1_CAP_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout1_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN111_1, I_DL0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN111_1, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN111_1, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN111_1, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN111_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN111_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN111_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN111_1, I_DL7_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN111_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN111_1, I_DL_24CH_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN111_0, + I_GAIN0_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN111_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN111_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN111_4, + I_PCM_0_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN111_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN111_4, + I_PCM_1_CAP_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout2_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN112_1, I_DL0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN112_1, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN112_1, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN112_1, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN112_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN112_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN112_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN112_1, I_DL7_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN112_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN112_1, I_DL_24CH_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN112_0, + I_GAIN0_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN112_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN112_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN112_4, + I_PCM_1_CAP_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout2_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN113_1, I_DL0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN113_1, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN113_1, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN113_1, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN113_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN113_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN113_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN113_1, I_DL7_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN113_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN113_1, I_DL_24CH_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN113_0, + I_GAIN0_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN113_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN113_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN113_4, + I_PCM_0_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN113_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN113_4, + I_PCM_1_CAP_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout3_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN114_1, I_DL0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN114_1, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN114_1, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN114_1, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN114_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN114_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN114_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN114_1, I_DL7_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN114_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN114_1, I_DL_24CH_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN114_0, + I_GAIN0_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN114_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN114_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN114_4, + I_PCM_1_CAP_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout3_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN115_1, I_DL0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN115_1, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN115_1, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN115_1, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN115_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN115_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN115_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN115_1, I_DL7_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN115_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN115_1, I_DL_24CH_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN115_0, + I_GAIN0_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN115_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN115_4, + I_PCM_0_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN115_4, + I_PCM_1_CAP_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN116_1, I_DL0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN116_1, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN116_1, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN116_1, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN116_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN116_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN116_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN116_1, I_DL7_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN116_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN116_1, I_DL_24CH_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH1", AFE_CONN116_2, I_DL24_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN116_0, + I_GAIN0_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN116_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN116_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN116_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN116_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN116_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH1", AFE_CONN116_6, + I_SRC_2_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN117_1, I_DL0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN117_1, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN117_1, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN117_1, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN117_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN117_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN117_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN117_1, I_DL7_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN117_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN117_1, I_DL_24CH_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH2", AFE_CONN117_2, I_DL24_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN117_0, + I_GAIN0_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN117_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN117_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN117_0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN117_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN117_4, + I_PCM_0_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN117_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN117_4, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH2", AFE_CONN117_6, + I_SRC_2_OUT_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch3_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH3", AFE_CONN118_1, I_DL_24CH_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN118_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN118_4, + I_PCM_1_CAP_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch4_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH4", AFE_CONN119_1, I_DL_24CH_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN118_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN118_4, + I_PCM_1_CAP_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch5_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH5", AFE_CONN120_1, I_DL_24CH_CH5, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch6_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH6", AFE_CONN121_1, I_DL_24CH_CH6, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch7_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH7", AFE_CONN122_1, I_DL_24CH_CH7, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout4_ch8_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH8", AFE_CONN123_1, I_DL_24CH_CH8, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout6_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN148_1, I_DL0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN148_1, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN148_1, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN148_1, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN148_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN148_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN148_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN148_1, I_DL7_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN148_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH1", AFE_CONN148_2, I_DL23_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN148_1, I_DL_24CH_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN148_0, + I_GAIN0_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN148_0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN148_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN148_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH1", AFE_CONN148_6, + I_SRC_1_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2sout6_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN149_1, I_DL0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN149_1, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN149_1, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN149_1, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN149_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN149_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN149_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN149_1, I_DL7_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN149_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH2", AFE_CONN149_2, I_DL23_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN149_1, I_DL_24CH_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN149_0, + I_GAIN0_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN149_0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN149_4, + I_PCM_0_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN149_4, + I_PCM_0_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN149_4, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN149_4, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH2", AFE_CONN148_6, + I_SRC_1_OUT_CH2, 1, 0), +}; + +enum { + SUPPLY_SEQ_APLL, + SUPPLY_SEQ_I2S_MCLK_EN, + SUPPLY_SEQ_I2S_CG_EN, + SUPPLY_SEQ_I2S_EN, +}; + +static int mtk_apll_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(cmpnt->dev, "name %s, event 0x%x\n", w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (strcmp(w->name, APLL1_W_NAME) == 0) + mt8196_apll1_enable(afe); + else + mt8196_apll2_enable(afe); + break; + case SND_SOC_DAPM_POST_PMD: + if (strcmp(w->name, APLL1_W_NAME) == 0) + mt8196_apll1_disable(afe); + else + mt8196_apll2_disable(afe); + break; + default: + break; + } + + return 0; +} + +static int mtk_mclk_en_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + dev_dbg(cmpnt->dev, "name %s, event 0x%x\n", w->name, event); + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) + return -EINVAL; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8196_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate); + break; + case SND_SOC_DAPM_POST_PMD: + i2s_priv->mclk_rate = 0; + mt8196_mck_disable(afe, i2s_priv->mclk_id); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = { + SND_SOC_DAPM_MIXER("I2SOUT0_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2sout0_ch1_mix, + ARRAY_SIZE(mtk_i2sout0_ch1_mix)), + SND_SOC_DAPM_MIXER("I2SOUT0_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2sout0_ch2_mix, + ARRAY_SIZE(mtk_i2sout0_ch2_mix)), + + SND_SOC_DAPM_MIXER("I2SOUT1_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2sout1_ch1_mix, + ARRAY_SIZE(mtk_i2sout1_ch1_mix)), + SND_SOC_DAPM_MIXER("I2SOUT1_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2sout1_ch2_mix, + ARRAY_SIZE(mtk_i2sout1_ch2_mix)), + + SND_SOC_DAPM_MIXER("I2SOUT2_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2sout2_ch1_mix, + ARRAY_SIZE(mtk_i2sout2_ch1_mix)), + SND_SOC_DAPM_MIXER("I2SOUT2_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2sout2_ch2_mix, + ARRAY_SIZE(mtk_i2sout2_ch2_mix)), + + SND_SOC_DAPM_MIXER("I2SOUT3_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2sout3_ch1_mix, + ARRAY_SIZE(mtk_i2sout3_ch1_mix)), + SND_SOC_DAPM_MIXER("I2SOUT3_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2sout3_ch2_mix, + ARRAY_SIZE(mtk_i2sout3_ch2_mix)), + + SND_SOC_DAPM_MIXER("I2SOUT4_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch1_mix, + ARRAY_SIZE(mtk_i2sout4_ch1_mix)), + SND_SOC_DAPM_MIXER("I2SOUT4_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch2_mix, + ARRAY_SIZE(mtk_i2sout4_ch2_mix)), + SND_SOC_DAPM_MIXER("I2SOUT4_CH3", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch3_mix, + ARRAY_SIZE(mtk_i2sout4_ch3_mix)), + SND_SOC_DAPM_MIXER("I2SOUT4_CH4", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch4_mix, + ARRAY_SIZE(mtk_i2sout4_ch4_mix)), + SND_SOC_DAPM_MIXER("I2SOUT4_CH5", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch5_mix, + ARRAY_SIZE(mtk_i2sout4_ch5_mix)), + SND_SOC_DAPM_MIXER("I2SOUT4_CH6", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch6_mix, + ARRAY_SIZE(mtk_i2sout4_ch6_mix)), + SND_SOC_DAPM_MIXER("I2SOUT4_CH7", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch7_mix, + ARRAY_SIZE(mtk_i2sout4_ch7_mix)), + SND_SOC_DAPM_MIXER("I2SOUT4_CH8", SND_SOC_NOPM, 0, 0, + mtk_i2sout4_ch8_mix, + ARRAY_SIZE(mtk_i2sout4_ch8_mix)), + + SND_SOC_DAPM_MIXER("I2SOUT6_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2sout6_ch1_mix, + ARRAY_SIZE(mtk_i2sout6_ch1_mix)), + SND_SOC_DAPM_MIXER("I2SOUT6_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2sout6_ch2_mix, + ARRAY_SIZE(mtk_i2sout6_ch2_mix)), + + /* i2s en*/ + SND_SOC_DAPM_SUPPLY_S("I2SIN0_EN", SUPPLY_SEQ_I2S_EN, + ETDM_IN0_CON0, REG_ETDM_IN_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN1_EN", SUPPLY_SEQ_I2S_EN, + ETDM_IN1_CON0, REG_ETDM_IN_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN2_EN", SUPPLY_SEQ_I2S_EN, + ETDM_IN2_CON0, REG_ETDM_IN_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN3_EN", SUPPLY_SEQ_I2S_EN, + ETDM_IN3_CON0, REG_ETDM_IN_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN4_EN", SUPPLY_SEQ_I2S_EN, + ETDM_IN4_CON0, REG_ETDM_IN_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN6_EN", SUPPLY_SEQ_I2S_EN, + ETDM_IN6_CON0, REG_ETDM_IN_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT0_EN", SUPPLY_SEQ_I2S_EN, + ETDM_OUT0_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT1_EN", SUPPLY_SEQ_I2S_EN, + ETDM_OUT1_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT2_EN", SUPPLY_SEQ_I2S_EN, + ETDM_OUT2_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT3_EN", SUPPLY_SEQ_I2S_EN, + ETDM_OUT3_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT4_EN", SUPPLY_SEQ_I2S_EN, + ETDM_OUT4_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT6_EN", SUPPLY_SEQ_I2S_EN, + ETDM_OUT6_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("FMI2S_MASTER_EN", SUPPLY_SEQ_I2S_EN, + AFE_CONNSYS_I2S_CON, I2S_EN_SFT, 0, + NULL, 0), + + /* i2s mclk en */ + SND_SOC_DAPM_SUPPLY_S(I2SIN0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SIN1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SIN2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SIN3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SIN4_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SIN6_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SOUT0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SOUT1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SOUT2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SOUT3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SOUT4_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2SOUT6_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(FMI2S_MASTER_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* cg */ + SND_SOC_DAPM_SUPPLY_S("I2SOUT0_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_OUT0_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT1_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_OUT1_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT2_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_OUT2_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT3_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_OUT3_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT4_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_OUT4_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SOUT6_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_OUT6_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN0_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_IN0_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN1_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_IN1_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN2_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_IN2_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN3_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_IN3_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN4_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_IN4_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("I2SIN6_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON2, PDN_ETDM_IN6_SFT, 1, + NULL, 0), + SND_SOC_DAPM_SUPPLY_S("FMI2S_MASTER_CG", SUPPLY_SEQ_I2S_CG_EN, + AUDIO_TOP_CON0, PDN_FM_I2S_SFT, 1, + NULL, 0), + + /* apll */ + SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL, + SND_SOC_NOPM, 0, 0, + mtk_apll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL, + SND_SOC_NOPM, 0, 0, + mtk_apll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_MIXER("SOF_DMA_DL_24CH", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("SOF_DMA_DL1", SND_SOC_NOPM, 0, 0, NULL, 0), +}; + +static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + if (!i2s_priv) + return 0; + + if (i2s_priv->share_i2s_id < 0) + return 0; + + return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name); +} + +static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + int cur_apll; + int needed_apll; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + if (!i2s_priv) + return 0; + + /* which apll */ + cur_apll = mt8196_get_apll_by_name(afe, source->name); + + /* choose APLL from i2s rate */ + needed_apll = mt8196_get_apll_by_rate(afe, i2s_priv->rate); + + return needed_apll == cur_apll; +} + +static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + int i2s_num; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + if (!i2s_priv) + return 0; + + i2s_num = get_i2s_id_by_name(afe, source->name); + if (get_i2s_id_by_name(afe, sink->name) == i2s_num) + return i2s_priv->mclk_rate > 0; + + /* check if share i2s need mclk */ + if (i2s_priv->share_i2s_id < 0) + return 0; + + if (i2s_priv->share_i2s_id == i2s_num) + return i2s_priv->mclk_rate > 0; + + return 0; +} + +static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + int cur_apll; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + if (!i2s_priv) + return 0; + + /* which apll */ + cur_apll = mt8196_get_apll_by_name(afe, source->name); + + return i2s_priv->mclk_apll == cur_apll; +} + +static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = { + /* i2sin0 */ + {"I2SIN0", NULL, "I2SIN0_EN"}, + {"I2SIN0", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN0", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SIN0", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SIN0", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SIN0", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN0", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + + {I2SIN0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SIN0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SIN0", NULL, "I2SIN0_CG"}, + + /* i2sin1 */ + {"I2SIN1", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SIN1_EN"}, + {"I2SIN1", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN1", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SIN1", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SIN1", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SIN1", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN1", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SIN1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SIN1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SIN1", NULL, "I2SIN1_CG"}, + + /* i2sin2 */ + {"I2SIN2", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SIN2_EN"}, + {"I2SIN2", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN2", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SIN2", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SIN2", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SIN2", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN2", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SIN2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SIN2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SIN2", NULL, "I2SIN2_CG"}, + + /* i2sin3 */ + {"I2SIN3", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SIN3_EN"}, + {"I2SIN3", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN3", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SIN3", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SIN3", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SIN3", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN3", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SIN3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SIN3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SIN3", NULL, "I2SIN3_CG"}, + + /* i2sin4 */ + {"I2SIN4", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SIN4_EN"}, + {"I2SIN4", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN4", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SIN4", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SIN4", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SIN4", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN4", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SIN4_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SIN4_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SIN4", NULL, "I2SIN4_CG"}, + + /* i2sin6 */ + {"I2SIN6", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SIN6_EN"}, + {"I2SIN6", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SIN6", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SIN6", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SIN6", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SIN6", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SIN6", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SIN6_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SIN6_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SIN6", NULL, "I2SIN6_CG"}, + {"I2SIN6", NULL, "I2SOUT6_CG"}, + + /* i2sout0 */ + {"I2SOUT0_CH1", "DL0_CH1", "DL0"}, + {"I2SOUT0_CH2", "DL0_CH2", "DL0"}, + {"I2SOUT0_CH1", "DL1_CH1", "DL1"}, + {"I2SOUT0_CH2", "DL1_CH2", "DL1"}, + {"I2SOUT0_CH1", "DL2_CH1", "DL2"}, + {"I2SOUT0_CH2", "DL2_CH2", "DL2"}, + {"I2SOUT0_CH1", "DL3_CH1", "DL3"}, + {"I2SOUT0_CH2", "DL3_CH2", "DL3"}, + {"I2SOUT0_CH1", "DL4_CH1", "DL4"}, + {"I2SOUT0_CH2", "DL4_CH2", "DL4"}, + {"I2SOUT0_CH1", "DL5_CH1", "DL5"}, + {"I2SOUT0_CH2", "DL5_CH2", "DL5"}, + {"I2SOUT0_CH1", "DL6_CH1", "DL6"}, + {"I2SOUT0_CH2", "DL6_CH2", "DL6"}, + {"I2SOUT0_CH1", "DL7_CH1", "DL7"}, + {"I2SOUT0_CH2", "DL7_CH2", "DL7"}, + {"I2SOUT0_CH1", "DL8_CH1", "DL8"}, + {"I2SOUT0_CH2", "DL8_CH2", "DL8"}, + {"I2SOUT0_CH1", "DL23_CH1", "DL23"}, + {"I2SOUT0_CH2", "DL23_CH2", "DL23"}, + {"I2SOUT0_CH1", "DL_24CH_CH1", "DL_24CH"}, + {"I2SOUT0_CH2", "DL_24CH_CH2", "DL_24CH"}, + + {"I2SOUT0_CH1", "DL24_CH1", "DL24"}, + {"I2SOUT0_CH2", "DL24_CH2", "DL24"}, + + {"I2SOUT0", NULL, "I2SOUT0_CH1"}, + {"I2SOUT0", NULL, "I2SOUT0_CH2"}, + + {"I2SOUT0", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SOUT0_EN"}, + {"I2SOUT0", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT0", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SOUT0", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SOUT0", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SOUT0", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT0", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SOUT0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SOUT0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SOUT0", NULL, "I2SOUT0_CG"}, + {"I2SOUT0", NULL, "I2SIN0_CG"}, + + /* i2sout1 */ + {"I2SOUT1_CH1", "DL0_CH1", "DL0"}, + {"I2SOUT1_CH2", "DL0_CH2", "DL0"}, + {"I2SOUT1_CH1", "DL1_CH1", "DL1"}, + {"I2SOUT1_CH2", "DL1_CH2", "DL1"}, + {"I2SOUT1_CH1", "DL2_CH1", "DL2"}, + {"I2SOUT1_CH2", "DL2_CH2", "DL2"}, + {"I2SOUT1_CH1", "DL3_CH1", "DL3"}, + {"I2SOUT1_CH2", "DL3_CH2", "DL3"}, + {"I2SOUT1_CH1", "DL4_CH1", "DL4"}, + {"I2SOUT1_CH2", "DL4_CH2", "DL4"}, + {"I2SOUT1_CH1", "DL5_CH1", "DL5"}, + {"I2SOUT1_CH2", "DL5_CH2", "DL5"}, + {"I2SOUT1_CH1", "DL6_CH1", "DL6"}, + {"I2SOUT1_CH2", "DL6_CH2", "DL6"}, + {"I2SOUT1_CH1", "DL7_CH1", "DL7"}, + {"I2SOUT1_CH2", "DL7_CH2", "DL7"}, + {"I2SOUT1_CH1", "DL8_CH1", "DL8"}, + {"I2SOUT1_CH2", "DL8_CH2", "DL8"}, + {"I2SOUT1_CH1", "DL_24CH_CH1", "DL_24CH"}, + {"I2SOUT1_CH2", "DL_24CH_CH2", "DL_24CH"}, + + {"I2SOUT1", NULL, "I2SOUT1_CH1"}, + {"I2SOUT1", NULL, "I2SOUT1_CH2"}, + + {"I2SOUT1", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SOUT1_EN"}, + {"I2SOUT1", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT1", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SOUT1", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SOUT1", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SOUT1", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT1", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SOUT1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SOUT1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SOUT1", NULL, "I2SOUT1_CG"}, + {"I2SOUT1", NULL, "I2SIN1_CG"}, + + /* i2sout2 */ + {"I2SOUT2_CH1", "DL0_CH1", "DL0"}, + {"I2SOUT2_CH2", "DL0_CH2", "DL0"}, + {"I2SOUT2_CH1", "DL1_CH1", "DL1"}, + {"I2SOUT2_CH2", "DL1_CH2", "DL1"}, + {"I2SOUT2_CH1", "DL2_CH1", "DL2"}, + {"I2SOUT2_CH2", "DL2_CH2", "DL2"}, + {"I2SOUT2_CH1", "DL3_CH1", "DL3"}, + {"I2SOUT2_CH2", "DL3_CH2", "DL3"}, + {"I2SOUT2_CH1", "DL4_CH1", "DL4"}, + {"I2SOUT2_CH2", "DL4_CH2", "DL4"}, + {"I2SOUT2_CH1", "DL5_CH1", "DL5"}, + {"I2SOUT2_CH2", "DL5_CH2", "DL5"}, + {"I2SOUT2_CH1", "DL6_CH1", "DL6"}, + {"I2SOUT2_CH2", "DL6_CH2", "DL6"}, + {"I2SOUT2_CH1", "DL7_CH1", "DL7"}, + {"I2SOUT2_CH2", "DL7_CH2", "DL7"}, + {"I2SOUT2_CH1", "DL8_CH1", "DL8"}, + {"I2SOUT2_CH2", "DL8_CH2", "DL8"}, + {"I2SOUT2_CH1", "DL_24CH_CH1", "DL_24CH"}, + {"I2SOUT2_CH2", "DL_24CH_CH2", "DL_24CH"}, + + {"I2SOUT2", NULL, "I2SOUT2_CH1"}, + {"I2SOUT2", NULL, "I2SOUT2_CH2"}, + + {"I2SOUT2", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SOUT2_EN"}, + {"I2SOUT2", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT2", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SOUT2", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SOUT2", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SOUT2", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT2", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SOUT2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SOUT2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SOUT2", NULL, "I2SOUT2_CG"}, + {"I2SOUT2", NULL, "I2SIN2_CG"}, + + /* i2sout3 */ + {"I2SOUT3_CH1", "DL0_CH1", "DL0"}, + {"I2SOUT3_CH2", "DL0_CH2", "DL0"}, + {"I2SOUT3_CH1", "DL1_CH1", "DL1"}, + {"I2SOUT3_CH2", "DL1_CH2", "DL1"}, + {"I2SOUT3_CH1", "DL2_CH1", "DL2"}, + {"I2SOUT3_CH2", "DL2_CH2", "DL2"}, + {"I2SOUT3_CH1", "DL3_CH1", "DL3"}, + {"I2SOUT3_CH2", "DL3_CH2", "DL3"}, + {"I2SOUT3_CH1", "DL4_CH1", "DL4"}, + {"I2SOUT3_CH2", "DL4_CH2", "DL4"}, + {"I2SOUT3_CH1", "DL5_CH1", "DL5"}, + {"I2SOUT3_CH2", "DL5_CH2", "DL5"}, + {"I2SOUT3_CH1", "DL6_CH1", "DL6"}, + {"I2SOUT3_CH2", "DL6_CH2", "DL6"}, + {"I2SOUT3_CH1", "DL7_CH1", "DL7"}, + {"I2SOUT3_CH2", "DL7_CH2", "DL7"}, + {"I2SOUT3_CH1", "DL8_CH1", "DL8"}, + {"I2SOUT3_CH2", "DL8_CH2", "DL8"}, + {"I2SOUT3_CH1", "DL_24CH_CH1", "DL_24CH"}, + {"I2SOUT3_CH2", "DL_24CH_CH2", "DL_24CH"}, + + {"I2SOUT3", NULL, "I2SOUT3_CH1"}, + {"I2SOUT3", NULL, "I2SOUT3_CH2"}, + + {"I2SOUT3", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SOUT3_EN"}, + {"I2SOUT3", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT3", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SOUT3", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SOUT3", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SOUT3", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT3", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SOUT3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SOUT3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + {"I2SOUT3", NULL, "I2SOUT3_CG"}, + {"I2SOUT3", NULL, "I2SIN3_CG"}, + + /* i2sout4 */ + {"I2SOUT4_CH1", "DL0_CH1", "DL0"}, + {"I2SOUT4_CH2", "DL0_CH2", "DL0"}, + {"I2SOUT4_CH1", "DL1_CH1", "DL1"}, + {"I2SOUT4_CH2", "DL1_CH2", "DL1"}, + {"I2SOUT4_CH1", "DL2_CH1", "DL2"}, + {"I2SOUT4_CH2", "DL2_CH2", "DL2"}, + {"I2SOUT4_CH1", "DL3_CH1", "DL3"}, + {"I2SOUT4_CH2", "DL3_CH2", "DL3"}, + {"I2SOUT4_CH1", "DL4_CH1", "DL4"}, + {"I2SOUT4_CH2", "DL4_CH2", "DL4"}, + {"I2SOUT4_CH1", "DL5_CH1", "DL5"}, + {"I2SOUT4_CH2", "DL5_CH2", "DL5"}, + {"I2SOUT4_CH1", "DL6_CH1", "DL6"}, + {"I2SOUT4_CH2", "DL6_CH2", "DL6"}, + {"I2SOUT4_CH1", "DL7_CH1", "DL7"}, + {"I2SOUT4_CH2", "DL7_CH2", "DL7"}, + {"I2SOUT4_CH1", "DL8_CH1", "DL8"}, + {"I2SOUT4_CH2", "DL8_CH2", "DL8"}, + {"I2SOUT4_CH1", "DL_24CH_CH1", "DL_24CH"}, + {"I2SOUT4_CH2", "DL_24CH_CH2", "DL_24CH"}, + {"I2SOUT4_CH3", "DL_24CH_CH3", "DL_24CH"}, + {"I2SOUT4_CH4", "DL_24CH_CH4", "DL_24CH"}, + {"I2SOUT4_CH5", "DL_24CH_CH5", "DL_24CH"}, + {"I2SOUT4_CH6", "DL_24CH_CH6", "DL_24CH"}, + {"I2SOUT4_CH7", "DL_24CH_CH7", "DL_24CH"}, + {"I2SOUT4_CH8", "DL_24CH_CH8", "DL_24CH"}, + {"I2SOUT4_CH1", "DL24_CH1", "DL24"}, + {"I2SOUT4_CH2", "DL24_CH2", "DL24"}, + + /* SOF Downlink */ + {"I2SOUT4_CH1", "DL_24CH_CH1", "SOF_DMA_DL_24CH"}, + {"I2SOUT4_CH2", "DL_24CH_CH2", "SOF_DMA_DL_24CH"}, + {"I2SOUT4_CH3", "DL_24CH_CH3", "SOF_DMA_DL_24CH"}, + {"I2SOUT4_CH4", "DL_24CH_CH4", "SOF_DMA_DL_24CH"}, + + {"I2SOUT4", NULL, "I2SOUT4_CH1"}, + {"I2SOUT4", NULL, "I2SOUT4_CH2"}, + {"I2SOUT4", NULL, "I2SOUT4_CH3"}, + {"I2SOUT4", NULL, "I2SOUT4_CH4"}, + {"I2SOUT4", NULL, "I2SOUT4_CH5"}, + {"I2SOUT4", NULL, "I2SOUT4_CH6"}, + {"I2SOUT4", NULL, "I2SOUT4_CH7"}, + {"I2SOUT4", NULL, "I2SOUT4_CH8"}, + + {"I2SOUT4", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "I2SOUT4_EN"}, + {"I2SOUT4", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT4", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SOUT4", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SOUT4", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SOUT4", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT4", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SOUT4_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SOUT4_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + /* CG */ + {"I2SOUT4", NULL, "I2SOUT4_CG"}, + {"I2SOUT4", NULL, "I2SIN4_CG"}, + + /* i2sout6 */ + {"I2SOUT6_CH1", "DL0_CH1", "DL0"}, + {"I2SOUT6_CH2", "DL0_CH2", "DL0"}, + {"I2SOUT6_CH1", "DL1_CH1", "DL1"}, + {"I2SOUT6_CH2", "DL1_CH2", "DL1"}, + {"I2SOUT6_CH1", "DL2_CH1", "DL2"}, + {"I2SOUT6_CH2", "DL2_CH2", "DL2"}, + {"I2SOUT6_CH1", "DL3_CH1", "DL3"}, + {"I2SOUT6_CH2", "DL3_CH2", "DL3"}, + {"I2SOUT6_CH1", "DL4_CH1", "DL4"}, + {"I2SOUT6_CH2", "DL4_CH2", "DL4"}, + {"I2SOUT6_CH1", "DL5_CH1", "DL5"}, + {"I2SOUT6_CH2", "DL5_CH2", "DL5"}, + {"I2SOUT6_CH1", "DL6_CH1", "DL6"}, + {"I2SOUT6_CH2", "DL6_CH2", "DL6"}, + {"I2SOUT6_CH1", "DL7_CH1", "DL7"}, + {"I2SOUT6_CH2", "DL7_CH2", "DL7"}, + {"I2SOUT6_CH1", "DL8_CH1", "DL8"}, + {"I2SOUT6_CH2", "DL8_CH2", "DL8"}, + {"I2SOUT6_CH1", "DL23_CH1", "DL23"}, + {"I2SOUT6_CH2", "DL23_CH2", "DL23"}, + {"I2SOUT6_CH1", "DL_24CH_CH1", "DL_24CH"}, + {"I2SOUT6_CH2", "DL_24CH_CH2", "DL_24CH"}, + + /* SOF Downlink */ + {"I2SOUT6_CH1", "DL1_CH1", "SOF_DMA_DL1"}, + {"I2SOUT6_CH2", "DL1_CH2", "SOF_DMA_DL1"}, + {"I2SOUT6_CH1", "DL_24CH_CH1", "SOF_DMA_DL_24CH"}, + {"I2SOUT6_CH2", "DL_24CH_CH2", "SOF_DMA_DL_24CH"}, + + {"I2SOUT6", NULL, "I2SOUT6_CH1"}, + {"I2SOUT6", NULL, "I2SOUT6_CH2"}, + + {"I2SOUT6", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"I2SOUT6", NULL, "I2SOUT6_EN"}, + {"I2SOUT6", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect}, + + {"I2SOUT6", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"I2SOUT6", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2SOUT6", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2SOUT6", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2SOUT6_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2SOUT6_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + /* CG */ + {"I2SOUT6", NULL, "I2SOUT6_CG"}, + {"I2SOUT6", NULL, "I2SIN6_CG"}, + + /* fmi2s */ + {"FMI2S_MASTER", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect}, + {"FMI2S_MASTER", NULL, "FMI2S_MASTER_EN"}, + + {"FMI2S_MASTER", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {"FMI2S_MASTER", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"FMI2S_MASTER", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"FMI2S_MASTER", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {FMI2S_MASTER_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {FMI2S_MASTER_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + /* CG */ + {"FMI2S_MASTER", NULL, "FMI2S_MASTER_CG"}, +}; + +/* i2s dai ops*/ +static int mtk_dai_i2s_config(struct mtk_base_afe *afe, + struct snd_pcm_hw_params *params, + int i2s_id) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv; + struct mtk_afe_i2s_priv *i2sin_priv = NULL; + int id = i2s_id - MT8196_DAI_I2S_IN0; + struct mtk_base_etdm_data etdm_data; + unsigned int rate = params_rate(params); + unsigned int rate_reg = get_etdm_inconn_rate(rate); + snd_pcm_format_t format = params_format(params); + unsigned int channels = params_channels(params); + int ret; + unsigned int i2s_con; + int pad_top; + + if (i2s_id >= MT8196_DAI_NUM || i2s_id < 0 || id < 0 || id >= DAI_I2S_NUM) + return -EINVAL; + + i2s_priv = afe_priv->dai_priv[i2s_id]; + if (!i2s_priv) + return -EINVAL; + + dev_dbg(afe->dev, "id: %d, rate: %d, pcm_fmt: %d, fmt: %d, ch: %d\n", + i2s_id, rate, format, i2s_priv->format, channels); + + i2s_priv->rate = rate; + etdm_data = mtk_etdm_data[id]; + + if (is_etdm_in_pad_top(id)) + pad_top = 0x3; + else + pad_top = 0x5; + + switch (id) { + case DAI_FMI2S_MASTER: + i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT; + i2s_con |= rate_reg << I2S_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + 0xffffeffe, i2s_con); + break; + + case DAI_I2SIN0: + case DAI_I2SIN1: + case DAI_I2SIN2: + case DAI_I2SIN3: + case DAI_I2SIN4: + case DAI_I2SIN6: + /* ---etdm in --- */ + regmap_update_bits(afe->regmap, + etdm_data.init_count_reg, + etdm_data.init_count_mask << etdm_data.init_count_shift, + 0x5 << etdm_data.init_count_shift); + + /* 3: pad top 5: no pad top */ + regmap_update_bits(afe->regmap, + etdm_data.init_point_reg, + etdm_data.init_point_mask << etdm_data.init_point_shift, + pad_top << etdm_data.init_point_shift); + + regmap_update_bits(afe->regmap, + etdm_data.lrck_reset_reg, + etdm_data.lrck_reset_mask << etdm_data.lrck_reset_shift, + 0x1 << etdm_data.lrck_reset_shift); + + regmap_update_bits(afe->regmap, + etdm_data.clk_source_reg, + etdm_data.clk_source_mask << etdm_data.clk_source_shift, + ETDM_CLK_SOURCE_APLL << etdm_data.clk_source_shift); + + /* 0: manual 1: auto */ + regmap_update_bits(afe->regmap, + etdm_data.ck_en_sel_reg, + etdm_data.ck_en_sel_mask << etdm_data.ck_en_sel_shift, + 0x1 << etdm_data.ck_en_sel_shift); + + regmap_update_bits(afe->regmap, + etdm_data.fs_timing_reg, + etdm_data.fs_timing_mask << etdm_data.fs_timing_shift, + get_etdm_rate(rate) << etdm_data.fs_timing_shift); + + regmap_update_bits(afe->regmap, + etdm_data.relatch_en_sel_reg, + etdm_data.relatch_en_sel_mask << etdm_data.relatch_en_sel_shift, + get_etdm_inconn_rate(rate) << etdm_data.relatch_en_sel_shift); + + regmap_update_bits(afe->regmap, + etdm_data.use_afifo_reg, + etdm_data.use_afifo_mask << etdm_data.use_afifo_shift, + 0x0); + + regmap_update_bits(afe->regmap, + etdm_data.afifo_mode_reg, + etdm_data.afifo_mode_mask << etdm_data.afifo_mode_shift, + 0x0); + + regmap_update_bits(afe->regmap, + etdm_data.almost_end_ch_reg, + etdm_data.almost_end_ch_mask << etdm_data.almost_end_ch_shift, + 0x0); + + regmap_update_bits(afe->regmap, + etdm_data.almost_end_bit_reg, + etdm_data.almost_end_bit_mask << etdm_data.almost_end_bit_shift, + 0x0); + + if (is_etdm_in_pad_top(id)) { + regmap_update_bits(afe->regmap, + etdm_data.out2latch_time_reg, + etdm_data.out2latch_time_mask << + etdm_data.out2latch_time_shift, + 0x6 << etdm_data.out2latch_time_shift); + } else { + regmap_update_bits(afe->regmap, + etdm_data.out2latch_time_reg, + etdm_data.out2latch_time_mask << + etdm_data.out2latch_time_shift, + 0x4 << etdm_data.out2latch_time_shift); + } + + if (id == DAI_I2SIN4) { + dev_dbg(afe->dev, "i2sin4, id: %d, fmt: %d, ch: %d, ip_mode: %d, sync: %d\n", + id, i2s_priv->format, channels, i2s_priv->ip_mode, i2s_priv->sync); + + /* Fmt Mode: 0x00 i2s, 0x04 adsp_a, DSP_A mode for multi-channel */ + regmap_update_bits(afe->regmap, + etdm_data.tdm_mode_reg, + etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift, + i2s_priv->format << etdm_data.tdm_mode_shift); + + /* set etdm ch */ + regmap_update_bits(afe->regmap, + etdm_data.ch_reg, + etdm_data.ch_mask << etdm_data.ch_shift, + (channels - 1) << etdm_data.ch_shift); + + /* set etdm ip mode */ + regmap_update_bits(afe->regmap, + etdm_data.ip_mode_reg, + etdm_data.ip_mode_mask << etdm_data.ip_mode_shift, + i2s_priv->ip_mode << etdm_data.ip_mode_shift); + + /* set etdm sync */ + regmap_update_bits(afe->regmap, + etdm_data.sync_reg, + etdm_data.sync_mask << etdm_data.sync_shift, + i2s_priv->sync << etdm_data.sync_shift); + } else { + /* default i2s */ + regmap_update_bits(afe->regmap, + etdm_data.tdm_mode_reg, + etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift, + 0x0 << etdm_data.tdm_mode_shift); + + /* set etdm sync */ + regmap_update_bits(afe->regmap, + etdm_data.sync_reg, + etdm_data.sync_mask << etdm_data.sync_shift, + 0x0 << etdm_data.sync_shift); + } + + /* APLL */ + regmap_update_bits(afe->regmap, + etdm_data.relatch_domain_sel_reg, + etdm_data.relatch_domain_sel_mask << + etdm_data.relatch_domain_sel_shift, + ETDM_RELATCH_SEL_APLL << etdm_data.relatch_domain_sel_shift); + + regmap_update_bits(afe->regmap, + etdm_data.bit_length_reg, + etdm_data.bit_length_mask << etdm_data.bit_length_shift, + get_etdm_lrck_width(format) << etdm_data.bit_length_shift); + + regmap_update_bits(afe->regmap, + etdm_data.word_length_reg, + etdm_data.word_length_mask << etdm_data.word_length_shift, + get_etdm_wlen(format) << etdm_data.word_length_shift); + + /* ---etdm cowork --- */ + regmap_update_bits(afe->regmap, + etdm_data.cowork_reg, + etdm_data.cowork_mask << etdm_data.cowork_shift, + etdm_data.cowork_val << etdm_data.cowork_shift); + + /* i2s with pad top setting */ + if (is_etdm_in_pad_top(id) && etdm_data.pad_top_ck_en_reg != 0) { + regmap_update_bits(afe->regmap, + etdm_data.pad_top_ck_en_reg, + etdm_data.pad_top_ck_en_mask << + etdm_data.pad_top_ck_en_shift, + 0x1 << etdm_data.pad_top_ck_en_shift); + + regmap_update_bits(afe->regmap, + etdm_data.master_latch_reg, + etdm_data.master_latch_mask << + etdm_data.master_latch_shift, + 0x0); + } + break; + + case DAI_I2SOUT0: + case DAI_I2SOUT1: + case DAI_I2SOUT2: + case DAI_I2SOUT3: + case DAI_I2SOUT4: + case DAI_I2SOUT6: + /* ---etdm out --- */ + regmap_update_bits(afe->regmap, + etdm_data.init_count_reg, + etdm_data.init_count_mask << etdm_data.init_count_shift, + 0x5 << etdm_data.init_count_shift); + + regmap_update_bits(afe->regmap, + etdm_data.init_point_reg, + etdm_data.init_point_mask << etdm_data.init_point_shift, + 0x6 << etdm_data.init_point_shift); + + // clock speed > 22M need to set relatch time to avoid duplicate porint + if (rate * channels * (get_etdm_wlen(format) + 1) >= ETDM_22M_CLOCK_THRES && + get_etdm_wlen(format) >= 2) { + regmap_update_bits(afe->regmap, + etdm_data.in2latch_time_reg, + etdm_data.in2latch_time_mask << + etdm_data.in2latch_time_shift, + (get_etdm_wlen(format) - 2) << + etdm_data.in2latch_time_shift); + } else { + regmap_update_bits(afe->regmap, + etdm_data.in2latch_time_reg, + etdm_data.in2latch_time_mask << + etdm_data.in2latch_time_shift, + 0x6 << etdm_data.in2latch_time_shift); + } + + regmap_update_bits(afe->regmap, + etdm_data.lrck_reset_reg, + etdm_data.lrck_reset_mask << etdm_data.lrck_reset_shift, + 0x1 << etdm_data.lrck_reset_shift); + + regmap_update_bits(afe->regmap, + etdm_data.fs_timing_reg, + etdm_data.fs_timing_mask << etdm_data.fs_timing_shift, + get_etdm_rate(rate) << etdm_data.fs_timing_shift); + + regmap_update_bits(afe->regmap, + etdm_data.clk_source_reg, + etdm_data.clk_source_mask << etdm_data.clk_source_shift, + ETDM_CLK_SOURCE_APLL << etdm_data.clk_source_shift); + + regmap_update_bits(afe->regmap, + etdm_data.relatch_en_sel_reg, + etdm_data.relatch_en_sel_mask << etdm_data.relatch_en_sel_shift, + get_etdm_inconn_rate(rate) << etdm_data.relatch_en_sel_shift); + + if (id == DAI_I2SOUT4) { + dev_dbg(afe->dev, "i2sout4, id: %d fmt: %d, ch: %d, sync: %d\n", + id, i2s_priv->format, channels, i2s_priv->sync); + + /* Fmt Mode: 0x00 i2s, 0x04 adsp_a, DSP_A mode for multi-channel */ + regmap_update_bits(afe->regmap, + etdm_data.tdm_mode_reg, + etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift, + i2s_priv->format << etdm_data.tdm_mode_shift); + + /* set etdm ch */ + regmap_update_bits(afe->regmap, + etdm_data.ch_reg, + etdm_data.ch_mask << etdm_data.ch_shift, + (channels - 1) << etdm_data.ch_shift); + + /* set etdm sync */ + regmap_update_bits(afe->regmap, + etdm_data.sync_reg, + etdm_data.sync_mask << etdm_data.sync_shift, + i2s_priv->sync << etdm_data.sync_shift); + } else { + regmap_update_bits(afe->regmap, + etdm_data.tdm_mode_reg, + etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift, + 0x0); + } + + /* APLL */ + regmap_update_bits(afe->regmap, + etdm_data.relatch_domain_sel_reg, + etdm_data.relatch_domain_sel_mask << + etdm_data.relatch_domain_sel_shift, + ETDM_RELATCH_SEL_APLL << etdm_data.relatch_domain_sel_shift); + + regmap_update_bits(afe->regmap, + etdm_data.bit_length_reg, + etdm_data.bit_length_mask << etdm_data.bit_length_shift, + get_etdm_lrck_width(format) << etdm_data.bit_length_shift); + + regmap_update_bits(afe->regmap, + etdm_data.word_length_reg, + etdm_data.word_length_mask << etdm_data.word_length_shift, + get_etdm_wlen(format) << etdm_data.word_length_shift); + + /* ---etdm cowork --- */ + regmap_update_bits(afe->regmap, + etdm_data.cowork_reg, + etdm_data.cowork_mask << etdm_data.cowork_shift, + etdm_data.cowork_val << etdm_data.cowork_shift); + + /* i2s with pad top setting */ + if (is_etdm_in_pad_top(id) && etdm_data.pad_top_ck_en_reg != 0) { + regmap_update_bits(afe->regmap, + etdm_data.pad_top_ck_en_reg, + etdm_data.cowork_mask << etdm_data.pad_top_ck_en_shift, + 0x1 << etdm_data.pad_top_ck_en_shift); + + regmap_update_bits(afe->regmap, + etdm_data.master_latch_reg, + etdm_data.master_latch_mask << + etdm_data.master_latch_shift, + 0x0); + } + break; + + default: + dev_err(afe->dev, "id %d not support\n", id); + return -EINVAL; + } + + /* set share i2s */ + if (i2s_priv && i2s_priv->share_i2s_id >= 0) { + i2sin_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id]; + i2sin_priv->format = i2s_priv->format; + ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id); + if (ret) + return ret; + } + + return 0; +} + +static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + return mtk_dai_i2s_config(afe, params, dai->id); +} + +static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv; + int apll; + int apll_rate; + + if (dai->id >= MT8196_DAI_NUM || dai->id < 0 || dir != SND_SOC_CLOCK_OUT) + return -EINVAL; + + i2s_priv = afe_priv->dai_priv[dai->id]; + if (!i2s_priv) + return -EINVAL; + + dev_dbg(afe->dev, "freq: %u\n", freq); + + apll = mt8196_get_apll_by_rate(afe, freq); + apll_rate = mt8196_get_apll_rate(afe, apll); + + if (freq > apll_rate || apll_rate % freq) + return -EINVAL; + + i2s_priv->mclk_rate = freq; + i2s_priv->mclk_apll = apll; + + if (i2s_priv->share_i2s_id > 0) { + struct mtk_afe_i2s_priv *share_i2s_priv; + + share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id]; + if (!share_i2s_priv) + return -EINVAL; + + share_i2s_priv->mclk_rate = i2s_priv->mclk_rate; + share_i2s_priv->mclk_apll = i2s_priv->mclk_apll; + } + + return 0; +} + +static int mtk_dai_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv; + + if (dai->id >= MT8196_DAI_NUM || dai->id < 0) + return -EINVAL; + + i2s_priv = afe_priv->dai_priv[dai->id]; + if (!i2s_priv) + return -EINVAL; + + dev_dbg(afe->dev, "dai->id: %d, fmt: 0x%x\n", dai->id, fmt); + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + i2s_priv->format = MTK_DAI_ETDM_FORMAT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + i2s_priv->format = MTK_DAI_ETDM_FORMAT_LJ; + break; + case SND_SOC_DAIFMT_RIGHT_J: + i2s_priv->format = MTK_DAI_ETDM_FORMAT_RJ; + break; + case SND_SOC_DAIFMT_DSP_A: + i2s_priv->format = MTK_DAI_ETDM_FORMAT_DSPA; + break; + case SND_SOC_DAIFMT_DSP_B: + i2s_priv->format = MTK_DAI_ETDM_FORMAT_DSPB; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_i2s_ops = { + .hw_params = mtk_dai_i2s_hw_params, + .set_sysclk = mtk_dai_i2s_set_sysclk, + .set_fmt = mtk_dai_i2s_set_fmt, +}; + +/* dai driver */ +#define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_384000) +#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S8 |\ + SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +#define MT8196_I2S_DAI(_name, _id, max_ch, dir) \ +{ \ + .name = #_name, \ + .id = _id, \ + .dir = { \ + .stream_name = #_name, \ + .channels_min = 1, \ + .channels_max = max_ch, \ + .rates = MTK_ETDM_RATES, \ + .formats = MTK_ETDM_FORMATS, \ + }, \ + .ops = &mtk_dai_i2s_ops, \ +} + +static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = { + /* capture */ + MT8196_I2S_DAI(I2SIN0, MT8196_DAI_I2S_IN0, 2, capture), + MT8196_I2S_DAI(I2SIN1, MT8196_DAI_I2S_IN1, 2, capture), + MT8196_I2S_DAI(I2SIN2, MT8196_DAI_I2S_IN2, 2, capture), + MT8196_I2S_DAI(I2SIN3, MT8196_DAI_I2S_IN3, 2, capture), + MT8196_I2S_DAI(I2SIN4, MT8196_DAI_I2S_IN4, 8, capture), + MT8196_I2S_DAI(I2SIN6, MT8196_DAI_I2S_IN6, 2, capture), + MT8196_I2S_DAI(FMI2S_MASTER, MT8196_DAI_FM_I2S_MASTER, 2, capture), + /* playback */ + MT8196_I2S_DAI(I2SOUT0, MT8196_DAI_I2S_OUT0, 2, playback), + MT8196_I2S_DAI(I2SOUT1, MT8196_DAI_I2S_OUT1, 2, playback), + MT8196_I2S_DAI(I2SOUT2, MT8196_DAI_I2S_OUT2, 2, playback), + MT8196_I2S_DAI(I2SOUT3, MT8196_DAI_I2S_OUT3, 2, playback), + MT8196_I2S_DAI(I2SOUT4, MT8196_DAI_I2S_OUT4, 8, playback), + MT8196_I2S_DAI(I2SOUT6, MT8196_DAI_I2S_OUT6, 2, playback), +}; + +static const struct mtk_afe_i2s_priv mt8196_i2s_priv[DAI_I2S_NUM] = { + [DAI_I2SIN0] = { + .id = MT8196_DAI_I2S_IN0, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sin0-share", + .share_i2s_id = -1, + }, + [DAI_I2SIN1] = { + .id = MT8196_DAI_I2S_IN1, + .mclk_id = MT8196_I2SIN1_MCK, + .share_property_name = "i2sin1-share", + .share_i2s_id = -1, + }, + [DAI_I2SIN2] = { + .id = MT8196_DAI_I2S_IN2, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sin2-share", + .share_i2s_id = -1, + }, + [DAI_I2SIN3] = { + .id = MT8196_DAI_I2S_IN3, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sin3-share", + .share_i2s_id = -1, + }, + [DAI_I2SIN4] = { + .id = MT8196_DAI_I2S_IN4, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sin4-share", + .share_i2s_id = -1, + .sync = 0, + .ip_mode = 0, + }, + [DAI_I2SIN6] = { + .id = MT8196_DAI_I2S_IN6, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sout6-share", + .share_i2s_id = -1, + }, + [DAI_I2SOUT0] = { + .id = MT8196_DAI_I2S_OUT0, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sout0-share", + .share_i2s_id = MT8196_DAI_I2S_IN0, + }, + [DAI_I2SOUT1] = { + .id = MT8196_DAI_I2S_OUT1, + .mclk_id = MT8196_I2SIN1_MCK, + .share_property_name = "i2sout1-share", + .share_i2s_id = MT8196_DAI_I2S_IN1, + }, + [DAI_I2SOUT2] = { + .id = MT8196_DAI_I2S_OUT2, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sout2-share", + .share_i2s_id = MT8196_DAI_I2S_IN2, + }, + [DAI_I2SOUT3] = { + .id = MT8196_DAI_I2S_OUT3, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sout3-share", + .share_i2s_id = MT8196_DAI_I2S_IN3, + }, + [DAI_I2SOUT4] = { + .id = MT8196_DAI_I2S_OUT4, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sout4-share", + .share_i2s_id = MT8196_DAI_I2S_IN4, + .sync = 0, + }, + [DAI_I2SOUT6] = { + .id = MT8196_DAI_I2S_OUT6, + .mclk_id = MT8196_I2SIN0_MCK, + .share_property_name = "i2sout6-share", + .share_i2s_id = MT8196_DAI_I2S_IN6, + }, + [DAI_FMI2S_MASTER] = { + .id = MT8196_DAI_FM_I2S_MASTER, + .mclk_id = MT8196_FMI2S_MCK, + .share_property_name = "fmi2s-share", + .share_i2s_id = -1, + }, +}; + +static int mt8196_dai_i2s_get_share(struct mtk_base_afe *afe) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + const struct device_node *of_node = afe->dev->of_node; + + for (int i = 0; i < DAI_I2S_NUM; i++) { + const char *of_str; + struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[mt8196_i2s_priv[i].id]; + const char *property_name = mt8196_i2s_priv[i].share_property_name; + + if (of_property_read_string(of_node, property_name, &of_str)) + continue; + + i2s_priv->share_i2s_id = get_i2s_id_by_name(afe, of_str); + } + + return 0; +} + +static int init_i2s_priv_data(struct mtk_base_afe *afe) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv; + + for (int i = 0; i < DAI_I2S_NUM; i++) { + int id = mt8196_i2s_priv[i].id; + size_t size = sizeof(struct mtk_afe_i2s_priv); + + if (id >= MT8196_DAI_NUM || id < 0) + return -EINVAL; + + i2s_priv = devm_kzalloc(afe->dev, size, GFP_KERNEL); + if (!i2s_priv) + return -ENOMEM; + + memcpy(i2s_priv, &mt8196_i2s_priv[i], size); + + afe_priv->dai_priv[id] = i2s_priv; + } + + return 0; +} + +int mt8196_dai_i2s_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + dai->dai_drivers = mtk_dai_i2s_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver); + + dai->controls = mtk_dai_i2s_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls); + dai->dapm_widgets = mtk_dai_i2s_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets); + dai->dapm_routes = mtk_dai_i2s_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes); + + /* set all dai i2s private data */ + ret = init_i2s_priv_data(afe); + if (ret) + return ret; + + /* parse share i2s */ + ret = mt8196_dai_i2s_get_share(afe); + if (ret) + return ret; + + list_add(&dai->list, &afe->sub_dais); + + return 0; +} diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c b/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c new file mode 100644 index 000000000000..b7aeee939d88 --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c @@ -0,0 +1,675 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI TDM Control + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#include +#include + +#include "mt8196-afe-clk.h" +#include "mt8196-afe-common.h" +#include "mt8196-interconnection.h" + +struct mtk_afe_tdm_priv { + int bck_id; + int bck_rate; + + int mclk_id; + int mclk_multiple; /* according to sample rate */ + int mclk_rate; + int mclk_apll; +}; + +enum { + TDM_WLEN_8_BIT, + TDM_WLEN_16_BIT, + TDM_WLEN_24_BIT, + TDM_WLEN_32_BIT, +}; + +enum { + TDM_CHANNEL_BCK_16, + TDM_CHANNEL_BCK_24, + TDM_CHANNEL_BCK_32, +}; + +enum { + TDM_CHANNEL_NUM_2, + TDM_CHANNEL_NUM_4, + TDM_CHANNEL_NUM_8, +}; + +enum { + TDM_CH_START_O30_O31, + TDM_CH_START_O32_O33, + TDM_CH_START_O34_O35, + TDM_CH_START_O36_O37, + TDM_CH_ZERO, +}; + +enum { + DPTX_CHANNEL_2, + DPTX_CHANNEL_8, +}; + +enum { + DPTX_WLEN_24_BIT, + DPTX_WLEN_16_BIT, +}; + +#define DPTX_CH_EN_MASK_2CH (0x3) +#define DPTX_CH_EN_MASK_4CH (0xf) +#define DPTX_CH_EN_MASK_6CH (0x3f) +#define DPTX_CH_EN_MASK_8CH (0xff) + +static unsigned int get_tdm_wlen(snd_pcm_format_t format) +{ + return (snd_pcm_format_physical_width(format) / 8) - 1; +} + +static unsigned int get_tdm_channel_bck(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) <= 16 ? + TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32; +} + +static unsigned int get_tdm_lrck_width(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) - 1; +} + +static unsigned int get_tdm_ch(unsigned int ch) +{ + switch (ch) { + case 1: + case 2: + return TDM_CHANNEL_NUM_2; + case 3: + case 4: + return TDM_CHANNEL_NUM_4; + case 5: + case 6: + case 7: + case 8: + default: + return TDM_CHANNEL_NUM_8; + } +} + +static unsigned int get_dptx_ch_enable_mask(struct device *dev, unsigned int ch) +{ + switch (ch) { + case 1: + case 2: + return DPTX_CH_EN_MASK_2CH; + case 3: + case 4: + return DPTX_CH_EN_MASK_4CH; + case 5: + case 6: + return DPTX_CH_EN_MASK_6CH; + case 7: + case 8: + return DPTX_CH_EN_MASK_8CH; + default: + dev_warn(dev, "invalid channel num, default use 2ch\n"); + return DPTX_CH_EN_MASK_2CH; + } +} + +static unsigned int get_dptx_ch(unsigned int ch) +{ + if (ch == 2) + return DPTX_CHANNEL_2; + else + return DPTX_CHANNEL_8; +} + +static unsigned int get_dptx_wlen(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) <= 16 ? + DPTX_WLEN_16_BIT : DPTX_WLEN_24_BIT; +} + +/* interconnection */ +enum { + HDMI_CONN_CH0, + HDMI_CONN_CH1, + HDMI_CONN_CH2, + HDMI_CONN_CH3, + HDMI_CONN_CH4, + HDMI_CONN_CH5, + HDMI_CONN_CH6, + HDMI_CONN_CH7, +}; + +static const char *const hdmi_conn_mux_map[] = { + "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", +}; + +static int hdmi_conn_mux_map_value[] = { + HDMI_CONN_CH0, HDMI_CONN_CH1, HDMI_CONN_CH2, HDMI_CONN_CH3, + HDMI_CONN_CH4, HDMI_CONN_CH5, HDMI_CONN_CH6, HDMI_CONN_CH7, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum, + AFE_HDMI_CONN0, HDMI_O_0_SFT, HDMI_O_0_MASK, + hdmi_conn_mux_map, hdmi_conn_mux_map_value); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum, + AFE_HDMI_CONN0, + HDMI_O_1_SFT, + HDMI_O_1_MASK, + hdmi_conn_mux_map, + hdmi_conn_mux_map_value); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum, + AFE_HDMI_CONN0, + HDMI_O_2_SFT, + HDMI_O_2_MASK, + hdmi_conn_mux_map, + hdmi_conn_mux_map_value); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum, + AFE_HDMI_CONN0, + HDMI_O_3_SFT, + HDMI_O_3_MASK, + hdmi_conn_mux_map, + hdmi_conn_mux_map_value); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum, + AFE_HDMI_CONN0, + HDMI_O_4_SFT, + HDMI_O_4_MASK, + hdmi_conn_mux_map, + hdmi_conn_mux_map_value); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum, + AFE_HDMI_CONN0, + HDMI_O_5_SFT, + HDMI_O_5_MASK, + hdmi_conn_mux_map, + hdmi_conn_mux_map_value); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum, + AFE_HDMI_CONN0, + HDMI_O_6_SFT, + HDMI_O_6_MASK, + hdmi_conn_mux_map, + hdmi_conn_mux_map_value); + +static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum, + AFE_HDMI_CONN0, + HDMI_O_7_SFT, + HDMI_O_7_MASK, + hdmi_conn_mux_map, + hdmi_conn_mux_map_value); + +static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = { + SOC_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum), + SOC_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum), + SOC_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum), + SOC_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum), + SOC_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum), + SOC_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum), + SOC_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum), + SOC_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum), +}; + +static const char *const tdm_out_demux_texts[] = { + "NONE", "TDMOUT", "DPTXOUT", +}; + +static SOC_ENUM_SINGLE_DECL(tdm_out_demux_enum, + SND_SOC_NOPM, + 0, + tdm_out_demux_texts); +static const struct snd_kcontrol_new tdm_out_demux_control = + SOC_DAPM_ENUM("TDM DEMUX ROUTE", tdm_out_demux_enum); + +enum { + SUPPLY_SEQ_APLL, + SUPPLY_SEQ_TDM_MCK_EN, + SUPPLY_SEQ_TDM_BCK_EN, + SUPPLY_SEQ_TDM_DPTX_MCK_EN, + SUPPLY_SEQ_TDM_DPTX_BCK_EN, + SUPPLY_SEQ_TDM_CG_EN, +}; + +static int get_tdm_id_by_name(const char *name) +{ + if (strstr(name, "DPTX")) + return MT8196_DAI_TDM_DPTX; + else + return MT8196_DAI_TDM; +} + +static int mtk_tdm_bck_en_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d\n", + w->name, event, dai_id); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8196_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate); + break; + case SND_SOC_DAPM_POST_PMD: + mt8196_mck_disable(afe, tdm_priv->bck_id); + break; + default: + break; + } + + return 0; +} + +static int mtk_tdm_mck_en_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 mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d\n", + w->name, event, dai_id); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8196_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate); + break; + case SND_SOC_DAPM_POST_PMD: + tdm_priv->mclk_rate = 0; + mt8196_mck_disable(afe, tdm_priv->mclk_id); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = { + SND_SOC_DAPM_DEMUX("TDM_DEMUX", SND_SOC_NOPM, 0, 0, + &tdm_out_demux_control), + + SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN, + SND_SOC_NOPM, 0, 0, + mtk_tdm_bck_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN, + SND_SOC_NOPM, 0, 0, + mtk_tdm_mck_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_BCK", SUPPLY_SEQ_TDM_DPTX_BCK_EN, + SND_SOC_NOPM, 0, 0, + mtk_tdm_bck_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_MCK", SUPPLY_SEQ_TDM_DPTX_MCK_EN, + SND_SOC_NOPM, 0, 0, + mtk_tdm_mck_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* cg */ + SND_SOC_DAPM_SUPPLY_S("TDM_CG", SUPPLY_SEQ_TDM_CG_EN, + AUDIO_TOP_CON2, PDN_TDM_OUT_SFT, 1, + NULL, 0), +}; + +static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(sink->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + int cur_apll; + + /* which apll */ + cur_apll = mt8196_get_apll_by_name(afe, source->name); + + return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0; +} + +static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = { + {"TDM_DEMUX", NULL, "HDMI"}, + + {"TDM", "TDMOUT", "TDM_DEMUX"}, + {"TDM", NULL, "TDM_BCK"}, + {"TDM", NULL, "TDM_CG"}, + + {"TDM_DPTX", "DPTXOUT", "TDM_DEMUX"}, + {"TDM_DPTX", NULL, "TDM_DPTX_BCK"}, + {"TDM_DPTX", NULL, "TDM_CG"}, + + {"TDM_BCK", NULL, "TDM_MCK"}, + {"TDM_DPTX_BCK", NULL, "TDM_DPTX_MCK"}, + {"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect}, + {"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect}, + {"TDM_DPTX_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect}, + {"TDM_DPTX_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect}, +}; + +/* dai ops */ +static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe, + struct mtk_afe_tdm_priv *tdm_priv, + int freq) +{ + int apll; + int apll_rate; + + apll = mt8196_get_apll_by_rate(afe, freq); + apll_rate = mt8196_get_apll_rate(afe, apll); + + if (freq > apll_rate) + return -EINVAL; + + if (apll_rate % freq != 0) + return -EINVAL; + + tdm_priv->mclk_rate = freq; + tdm_priv->mclk_apll = apll; + + return 0; +} + +static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + int tdm_id = dai->id; + struct mtk_afe_tdm_priv *tdm_priv; + unsigned int rate = params_rate(params); + unsigned int channels = params_channels(params); + snd_pcm_format_t format = params_format(params); + unsigned int tdm_con = 0; + + if (tdm_id >= MT8196_DAI_NUM || tdm_id < 0) + return -EINVAL; + + tdm_priv = afe_priv->dai_priv[tdm_id]; + + if (!tdm_priv) + return -EINVAL; + + /* calculate mclk_rate, if not set explicitly */ + if (!tdm_priv->mclk_rate) { + tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple; + mtk_dai_tdm_cal_mclk(afe, + tdm_priv, + tdm_priv->mclk_rate); + } + + /* calculate bck */ + tdm_priv->bck_rate = rate * + channels * + snd_pcm_format_physical_width(format); + + if (tdm_priv->bck_rate > tdm_priv->mclk_rate) + return -EINVAL; + + if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0) + return -EINVAL; + + dev_dbg(afe->dev, "id %d, rate %d, ch %d, fmt %d, mclk %d, bck %d\n", + tdm_id, rate, channels, format, tdm_priv->mclk_rate, tdm_priv->bck_rate); + + /* set tdm */ + tdm_con = 0 << BCK_INVERSE_SFT; + tdm_con |= 0 << LRCK_INVERSE_SFT; + tdm_con |= 0 << DELAY_DATA_SFT; + tdm_con |= 1 << LEFT_ALIGN_SFT; + tdm_con |= get_tdm_wlen(format) << WLEN_SFT; + tdm_con |= get_tdm_ch(channels) << CHANNEL_NUM_SFT; + tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT; + tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT; + regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con); + + /* set dptx */ + if (tdm_id == MT8196_DAI_TDM_DPTX) { + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + DPTX_CHANNEL_ENABLE_MASK_SFT, + get_dptx_ch_enable_mask(afe->dev, channels) << + DPTX_CHANNEL_ENABLE_SFT); + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + DPTX_CHANNEL_NUMBER_MASK_SFT, + get_dptx_ch(channels) << + DPTX_CHANNEL_NUMBER_SFT); + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + DPTX_16BIT_MASK_SFT, + get_dptx_wlen(format) << DPTX_16BIT_SFT); + } + switch (channels) { + case 1: + case 2: + tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; + tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT; + tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; + tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; + break; + case 3: + case 4: + tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; + tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; + tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; + tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; + break; + case 5: + case 6: + tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; + tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; + tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; + tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; + break; + case 7: + case 8: + tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; + tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; + tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; + tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT; + break; + default: + tdm_con = 0; + } + + regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con); + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, + HDMI_CH_NUM_MASK_SFT, + channels << HDMI_CH_NUM_SFT); + + return 0; +} + +static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream, + int cmd, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int tdm_id = dai->id; + + dev_dbg(afe->dev, "cmd %d, tdm_id %d\n", cmd, tdm_id); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + /* enable Out control */ + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, + HDMI_OUT_ON_MASK_SFT, + 0x1 << HDMI_OUT_ON_SFT); + + /* enable dptx */ + if (tdm_id == MT8196_DAI_TDM_DPTX) { + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + DPTX_ON_MASK_SFT, 0x1 << + DPTX_ON_SFT); + } + + /* enable tdm */ + regmap_update_bits(afe->regmap, AFE_TDM_CON1, + TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + /* disable tdm */ + regmap_update_bits(afe->regmap, AFE_TDM_CON1, + TDM_EN_MASK_SFT, 0); + + /* disable dptx */ + if (tdm_id == MT8196_DAI_TDM_DPTX) { + regmap_update_bits(afe->regmap, AFE_DPTX_CON, + DPTX_ON_MASK_SFT, 0); + } + + /* disable Out control */ + regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, + HDMI_OUT_ON_MASK_SFT, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8196_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv; + + if (dai->id >= MT8196_DAI_NUM || dai->id < 0) + return -EINVAL; + + tdm_priv = afe_priv->dai_priv[dai->id]; + + if (!tdm_priv) + return -EINVAL; + + if (dir != SND_SOC_CLOCK_OUT) + return -EINVAL; + + dev_dbg(afe->dev, "freq %d\n", freq); + + return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); +} + +static const struct snd_soc_dai_ops mtk_dai_tdm_ops = { + .hw_params = mtk_dai_tdm_hw_params, + .trigger = mtk_dai_tdm_trigger, + .set_sysclk = mtk_dai_tdm_set_sysclk, +}; + +/* dai driver */ +#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = { + { + .name = "TDM", + .id = MT8196_DAI_TDM, + .playback = { + .stream_name = "TDM", + .channels_min = 2, + .channels_max = 8, + .rates = MTK_TDM_RATES, + .formats = MTK_TDM_FORMATS, + }, + .ops = &mtk_dai_tdm_ops, + }, + { + .name = "TDM_DPTX", + .id = MT8196_DAI_TDM_DPTX, + .playback = { + .stream_name = "TDM_DPTX", + .channels_min = 2, + .channels_max = 8, + .rates = MTK_TDM_RATES, + .formats = MTK_TDM_FORMATS, + }, + .ops = &mtk_dai_tdm_ops, + }, +}; + +static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe, + int id) +{ + struct mtk_afe_tdm_priv *tdm_priv; + + tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv), + GFP_KERNEL); + if (!tdm_priv) + return NULL; + + if (id == MT8196_DAI_TDM_DPTX) + tdm_priv->mclk_multiple = 256; + else + tdm_priv->mclk_multiple = 128; + + tdm_priv->bck_id = MT8196_TDMOUT_BCK; + tdm_priv->mclk_id = MT8196_TDMOUT_MCK; + + return tdm_priv; +} + +int mt8196_dai_tdm_register(struct mtk_base_afe *afe) +{ + struct mt8196_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv, *tdm_dptx_priv; + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + dai->dai_drivers = mtk_dai_tdm_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver); + dai->controls = mtk_dai_tdm_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls); + dai->dapm_widgets = mtk_dai_tdm_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets); + dai->dapm_routes = mtk_dai_tdm_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes); + + tdm_priv = init_tdm_priv_data(afe, MT8196_DAI_TDM); + if (!tdm_priv) + return -ENOMEM; + + tdm_dptx_priv = init_tdm_priv_data(afe, MT8196_DAI_TDM_DPTX); + if (!tdm_dptx_priv) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + afe_priv->dai_priv[MT8196_DAI_TDM] = tdm_priv; + afe_priv->dai_priv[MT8196_DAI_TDM_DPTX] = tdm_dptx_priv; + + return 0; +} + diff --git a/sound/soc/mediatek/mt8196/mt8196-interconnection.h b/sound/soc/mediatek/mt8196/mt8196-interconnection.h new file mode 100644 index 000000000000..acb91da3b4db --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-interconnection.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Mediatek MT8196 audio driver interconnection definition + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#ifndef _MT8196_INTERCONNECTION_H_ +#define _MT8196_INTERCONNECTION_H_ + +/* in port define */ + +#define I_CONNSYS_I2S_CH1 0 +#define I_CONNSYS_I2S_CH2 1 +#define I_GAIN0_OUT_CH1 6 +#define I_GAIN0_OUT_CH2 7 +#define I_GAIN1_OUT_CH1 8 +#define I_GAIN1_OUT_CH2 9 +#define I_GAIN2_OUT_CH1 10 +#define I_GAIN2_OUT_CH2 11 +#define I_GAIN3_OUT_CH1 12 +#define I_GAIN3_OUT_CH2 13 +#define I_STF_CH1 14 +#define I_ADDA_UL_CH1 16 +#define I_ADDA_UL_CH2 17 +#define I_ADDA_UL_CH3 18 +#define I_ADDA_UL_CH4 19 +#define I_UL_PROX_CH1 20 +#define I_UL_PROX_CH2 21 +#define I_ADDA_UL_CH5 24 +#define I_ADDA_UL_CH6 25 +#define I_DMIC0_CH1 28 +#define I_DMIC0_CH2 29 +#define I_DMIC1_CH1 30 +#define I_DMIC1_CH2 31 + +/* in port define >= 32 */ +#define I_32_OFFSET 32 +#define I_DL0_CH1 (32 - I_32_OFFSET) +#define I_DL0_CH2 (33 - I_32_OFFSET) +#define I_DL1_CH1 (34 - I_32_OFFSET) +#define I_DL1_CH2 (35 - I_32_OFFSET) +#define I_DL2_CH1 (36 - I_32_OFFSET) +#define I_DL2_CH2 (37 - I_32_OFFSET) +#define I_DL3_CH1 (38 - I_32_OFFSET) +#define I_DL3_CH2 (39 - I_32_OFFSET) +#define I_DL4_CH1 (40 - I_32_OFFSET) +#define I_DL4_CH2 (41 - I_32_OFFSET) +#define I_DL5_CH1 (42 - I_32_OFFSET) +#define I_DL5_CH2 (43 - I_32_OFFSET) +#define I_DL6_CH1 (44 - I_32_OFFSET) +#define I_DL6_CH2 (45 - I_32_OFFSET) +#define I_DL7_CH1 (46 - I_32_OFFSET) +#define I_DL7_CH2 (47 - I_32_OFFSET) +#define I_DL8_CH1 (48 - I_32_OFFSET) +#define I_DL8_CH2 (49 - I_32_OFFSET) +#define I_DL_4CH_CH1 (50 - I_32_OFFSET) +#define I_DL_4CH_CH2 (51 - I_32_OFFSET) +#define I_DL_4CH_CH3 (52 - I_32_OFFSET) +#define I_DL_4CH_CH4 (53 - I_32_OFFSET) +#define I_DL_24CH_CH1 (54 - I_32_OFFSET) +#define I_DL_24CH_CH2 (55 - I_32_OFFSET) +#define I_DL_24CH_CH3 (56 - I_32_OFFSET) +#define I_DL_24CH_CH4 (57 - I_32_OFFSET) +#define I_DL_24CH_CH5 (58 - I_32_OFFSET) +#define I_DL_24CH_CH6 (59 - I_32_OFFSET) +#define I_DL_24CH_CH7 (60 - I_32_OFFSET) +#define I_DL_24CH_CH8 (61 - I_32_OFFSET) + +/* in port define >= 64 */ +#define I_64_OFFSET 64 +#define I_DL23_CH1 (78 - I_64_OFFSET) +#define I_DL23_CH2 (79 - I_64_OFFSET) +#define I_DL24_CH1 (80 - I_64_OFFSET) +#define I_DL24_CH2 (81 - I_64_OFFSET) +#define I_DL25_CH1 (82 - I_64_OFFSET) +#define I_DL25_CH2 (83 - I_64_OFFSET) +#define I_DL26_CH1 (84 - I_64_OFFSET) +#define I_DL26_CH2 (85 - I_64_OFFSET) + +/* in port define >= 128 */ +#define I_128_OFFSET 128 +#define I_PCM_0_CAP_CH1 (130 - I_128_OFFSET) +#define I_PCM_0_CAP_CH2 (131 - I_128_OFFSET) +#define I_PCM_1_CAP_CH1 (132 - I_128_OFFSET) +#define I_PCM_1_CAP_CH2 (133 - I_128_OFFSET) +#define I_I2SIN0_CH1 (134 - I_128_OFFSET) +#define I_I2SIN0_CH2 (135 - I_128_OFFSET) +#define I_I2SIN1_CH1 (136 - I_128_OFFSET) +#define I_I2SIN1_CH2 (137 - I_128_OFFSET) +#define I_I2SIN2_CH1 (138 - I_128_OFFSET) +#define I_I2SIN2_CH2 (139 - I_128_OFFSET) +#define I_I2SIN3_CH1 (140 - I_128_OFFSET) +#define I_I2SIN3_CH2 (141 - I_128_OFFSET) +#define I_I2SIN4_CH1 (142 - I_128_OFFSET) +#define I_I2SIN4_CH2 (143 - I_128_OFFSET) +#define I_I2SIN4_CH3 (144 - I_128_OFFSET) +#define I_I2SIN4_CH4 (145 - I_128_OFFSET) +#define I_I2SIN4_CH5 (146 - I_128_OFFSET) +#define I_I2SIN4_CH6 (147 - I_128_OFFSET) +#define I_I2SIN4_CH7 (148 - I_128_OFFSET) +#define I_I2SIN4_CH8 (149 - I_128_OFFSET) + +/* in port define >= 160 */ +#define I_160_OFFSET 160 +#define I_I2SIN6_CH1 (166 - I_160_OFFSET) +#define I_I2SIN6_CH2 (167 - I_160_OFFSET) + +/* in port define >= 192 */ +#define I_192_OFFSET 192 +#define I_SRC_0_OUT_CH1 (198 - I_192_OFFSET) +#define I_SRC_0_OUT_CH2 (199 - I_192_OFFSET) +#define I_SRC_1_OUT_CH1 (200 - I_192_OFFSET) +#define I_SRC_1_OUT_CH2 (201 - I_192_OFFSET) +#define I_SRC_2_OUT_CH1 (202 - I_192_OFFSET) +#define I_SRC_2_OUT_CH2 (203 - I_192_OFFSET) +#define I_SRC_3_OUT_CH1 (204 - I_192_OFFSET) +#define I_SRC_3_OUT_CH2 (205 - I_192_OFFSET) + +#endif diff --git a/sound/soc/mediatek/mt8196/mt8196-nau8825.c b/sound/soc/mediatek/mt8196/mt8196-nau8825.c new file mode 100644 index 000000000000..c9424786c53d --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-nau8825.c @@ -0,0 +1,870 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mt8196-nau8825.c -- mt8196 nau8825 ALSA SoC machine driver + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "mt8196-afe-common.h" + +#include "../../codecs/nau8825.h" +#include "../../codecs/rt5682s.h" + +#include "../common/mtk-soc-card.h" +#include "../common/mtk-dsp-sof-common.h" +#include "../common/mtk-soundcard-driver.h" +#include "../common/mtk-afe-platform-driver.h" + +#define NAU8825_HS_PRESENT BIT(0) +#define RT5682S_HS_PRESENT BIT(1) +#define RT5650_HS_PRESENT BIT(2) + +/* + * Nau88l25 + */ +#define NAU8825_CODEC_DAI "nau8825-hifi" + +/* + * Rt5682s + */ +#define RT5682S_CODEC_DAI "rt5682s-aif1" + +/* + * Rt5650 + */ +#define RT5650_CODEC_DAI "rt5645-aif1" + +#define SOF_DMA_DL1 "SOF_DMA_DL1" +#define SOF_DMA_DL_24CH "SOF_DMA_DL_24CH" +#define SOF_DMA_UL0 "SOF_DMA_UL0" +#define SOF_DMA_UL1 "SOF_DMA_UL1" +#define SOF_DMA_UL2 "SOF_DMA_UL2" + +enum mt8196_jacks { + MT8196_JACK_HEADSET, + MT8196_JACK_DP, + MT8196_JACK_HDMI, + MT8196_JACK_MAX, +}; + +static struct snd_soc_jack_pin mt8196_dp_jack_pins[] = { + { + .pin = "DP", + .mask = SND_JACK_AVOUT, + }, +}; + +static struct snd_soc_jack_pin mt8196_hdmi_jack_pins[] = { + { + .pin = "HDMI", + .mask = SND_JACK_AVOUT, + }, +}; + +static struct snd_soc_jack_pin nau8825_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static const struct snd_kcontrol_new mt8196_dumb_spk_controls[] = { + SOC_DAPM_PIN_SWITCH("Ext Spk"), +}; + +static const struct snd_soc_dapm_widget mt8196_dumb_spk_widgets[] = { + SND_SOC_DAPM_SPK("Ext Spk", NULL), +}; + +static const struct snd_soc_dapm_widget mt8196_nau8825_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_SINK("DP"), +}; + +static const struct snd_kcontrol_new mt8196_nau8825_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +#define EXT_SPK_AMP_W_NAME "Ext_Speaker_Amp" + +static struct snd_soc_card mt8196_nau8825_soc_card; + +static const struct snd_soc_dapm_widget mt8196_nau8825_card_widgets[] = { + /* SOF Uplink */ + SND_SOC_DAPM_MIXER("SOF_DMA_UL0", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("SOF_DMA_UL1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("SOF_DMA_UL2", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* + * SOF Downlink + * the widgets on the machine driver cannot use the parameter with kcontrol + * because the widget domain is its platform driver. so sof downlink route + * is written in the i2s dai driver. + */ +}; + +static const struct snd_soc_dapm_route mt8196_nau8825_card_routes[] = { + /* SOF Uplink */ + {"SOF_DMA_UL0", NULL, "UL0_CH1"}, + {"SOF_DMA_UL0", NULL, "UL0_CH2"}, + /* SOF Uplink */ + {"SOF_DMA_UL1", NULL, "UL1_CH1"}, + {"SOF_DMA_UL1", NULL, "UL1_CH2"}, + /* SOF Uplink */ + {"SOF_DMA_UL2", NULL, "UL2_CH1"}, + {"SOF_DMA_UL2", NULL, "UL2_CH2"}, +}; + +static const struct snd_kcontrol_new mt8196_nau8825_card_controls[] = { + SOC_DAPM_PIN_SWITCH(EXT_SPK_AMP_W_NAME), +}; + +/* + * define mtk_spk_i2s_mck node in dts when need mclk, + * BE i2s need assign snd_soc_ops = mt8196_nau8825_i2s_ops + */ +static int mt8196_nau8825_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 128; + unsigned int mclk_fs = rate * mclk_fs_ratio; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + + return snd_soc_dai_set_sysclk(cpu_dai, + 0, mclk_fs, SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8196_nau8825_i2s_ops = { + .hw_params = mt8196_nau8825_i2s_hw_params, +}; + +static int mt8196_dptx_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 256; + unsigned int mclk_fs = rate * mclk_fs_ratio; + struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0); + + return snd_soc_dai_set_sysclk(dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8196_dptx_ops = { + .hw_params = mt8196_dptx_hw_params, +}; + +static int mt8196_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + dev_info(rtd->dev, "fix format to 32bit\n"); + + /* fix BE i2s format to 32bit, clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, SNDRV_PCM_FORMAT_S32_LE); + return 0; +} + +static int mt8196_sof_be_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_component *cmpnt_afe = NULL; + struct snd_soc_pcm_runtime *runtime; + + /* find afe component */ + for_each_card_rtds(rtd->card, runtime) { + cmpnt_afe = snd_soc_rtdcom_lookup(runtime, AFE_PCM_NAME); + if (cmpnt_afe) { + dev_info(rtd->dev, "component->name: %s\n", cmpnt_afe->name); + break; + } + } + + if (cmpnt_afe && !pm_runtime_active(cmpnt_afe->dev)) { + dev_err(rtd->dev, "afe pm runtime is not active!!\n"); + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_ops mt8196_sof_be_ops = { + .hw_params = mt8196_sof_be_hw_params, +}; + +static const struct sof_conn_stream g_sof_conn_streams[] = { + { + .sof_link = "AFE_SOF_DL1", + .sof_dma = SOF_DMA_DL1, + .stream_dir = SNDRV_PCM_STREAM_PLAYBACK + }, + { + .sof_link = "AFE_SOF_DL_24CH", + .sof_dma = SOF_DMA_DL_24CH, + .stream_dir = SNDRV_PCM_STREAM_PLAYBACK + }, + { + .sof_link = "AFE_SOF_UL0", + .sof_dma = SOF_DMA_UL0, + .stream_dir = SNDRV_PCM_STREAM_CAPTURE + }, + { + .sof_link = "AFE_SOF_UL1", + .sof_dma = SOF_DMA_UL1, + .stream_dir = SNDRV_PCM_STREAM_CAPTURE + }, + { + .sof_link = "AFE_SOF_UL2", + .sof_dma = SOF_DMA_UL2, + .stream_dir = SNDRV_PCM_STREAM_CAPTURE + }, +}; + +/* FE */ +SND_SOC_DAILINK_DEFS(playback1, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(playback_24ch, + DAILINK_COMP_ARRAY(COMP_CPU("DL_24CH")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(capture0, + DAILINK_COMP_ARRAY(COMP_CPU("UL0")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(capture1, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(capture2, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(playback_hdmi, + DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(playback2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(capture_cm0, + DAILINK_COMP_ARRAY(COMP_CPU("UL_CM0")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +/* BE */ +SND_SOC_DAILINK_DEFS(ap_dmic, + DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(ap_dmic_ch34, + DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_CH34")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(ap_dmic_multich, + DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_MULTICH")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2sin6, + DAILINK_COMP_ARRAY(COMP_CPU("I2SIN6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2sout3, + DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2sout4, + DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2sout6, + DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(tdm_dptx, + DAILINK_COMP_ARRAY(COMP_CPU("TDM_DPTX")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(AFE_SOF_DL_24CH, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL_24CH")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(AFE_SOF_DL1, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(AFE_SOF_UL0, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL0")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(AFE_SOF_UL1, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(AFE_SOF_UL2, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static struct snd_soc_dai_link mt8196_nau8825_dai_links[] = { + /* + * The SOF topology expects PCM streams 0~4 to be available + * for the SOF PCM streams. Put the SOF BE definitions here + * so that the PCM device numbers are skipped over. + * (BE dailinks do not have PCM devices created.) + */ + { + .name = "AFE_SOF_DL_24CH", + .no_pcm = 1, + .playback_only = 1, + .ops = &mt8196_sof_be_ops, + SND_SOC_DAILINK_REG(AFE_SOF_DL_24CH), + }, + { + .name = "AFE_SOF_DL1", + .no_pcm = 1, + .playback_only = 1, + .ops = &mt8196_sof_be_ops, + SND_SOC_DAILINK_REG(AFE_SOF_DL1), + }, + { + .name = "AFE_SOF_UL0", + .no_pcm = 1, + .capture_only = 1, + .ops = &mt8196_sof_be_ops, + SND_SOC_DAILINK_REG(AFE_SOF_UL0), + }, + { + .name = "AFE_SOF_UL1", + .no_pcm = 1, + .capture_only = 1, + .ops = &mt8196_sof_be_ops, + SND_SOC_DAILINK_REG(AFE_SOF_UL1), + }, + { + .name = "AFE_SOF_UL2", + .no_pcm = 1, + .capture_only = 1, + .ops = &mt8196_sof_be_ops, + SND_SOC_DAILINK_REG(AFE_SOF_UL2), + }, + /* Front End DAI links */ + { + .name = "HDMI_FE", + .stream_name = "HDMI Playback", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .playback_only = 1, + SND_SOC_DAILINK_REG(playback_hdmi), + }, + { + .name = "DL2_FE", + .stream_name = "DL2 Playback", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .playback_only = 1, + SND_SOC_DAILINK_REG(playback2), + }, + { + .name = "UL_CM0_FE", + .stream_name = "UL_CM0 Capture", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .capture_only = 1, + SND_SOC_DAILINK_REG(capture_cm0), + }, + { + .name = "DL_24CH_FE", + .stream_name = "DL_24CH Playback", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .playback_only = 1, + SND_SOC_DAILINK_REG(playback_24ch), + }, + { + .name = "DL1_FE", + .stream_name = "DL1 Playback", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .playback_only = 1, + SND_SOC_DAILINK_REG(playback1), + }, + { + .name = "UL0_FE", + .stream_name = "UL0 Capture", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .capture_only = 1, + SND_SOC_DAILINK_REG(capture0), + }, + { + .name = "UL1_FE", + .stream_name = "UL1 Capture", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .capture_only = 1, + SND_SOC_DAILINK_REG(capture1), + }, + { + .name = "UL2_FE", + .stream_name = "UL2 Capture", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .capture_only = 1, + SND_SOC_DAILINK_REG(capture2), + }, + /* Back End DAI links */ + { + .name = "I2SIN6_BE", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC + | SND_SOC_DAIFMT_GATED, + .ops = &mt8196_nau8825_i2s_ops, + .no_pcm = 1, + .capture_only = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8196_hw_params_fixup, + SND_SOC_DAILINK_REG(i2sin6), + }, + { + .name = "I2SOUT4_BE", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC + | SND_SOC_DAIFMT_GATED, + .ops = &mt8196_nau8825_i2s_ops, + .no_pcm = 1, + .playback_only = 1, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .be_hw_params_fixup = mt8196_hw_params_fixup, + SND_SOC_DAILINK_REG(i2sout4), + }, + { + .name = "I2SOUT6_BE", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC + | SND_SOC_DAIFMT_GATED, + .ops = &mt8196_nau8825_i2s_ops, + .no_pcm = 1, + .playback_only = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8196_hw_params_fixup, + SND_SOC_DAILINK_REG(i2sout6), + }, + { + .name = "AP_DMIC_BE", + .no_pcm = 1, + .capture_only = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(ap_dmic), + }, + { + .name = "AP_DMIC_CH34_BE", + .no_pcm = 1, + .capture_only = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(ap_dmic_ch34), + }, + { + .name = "AP_DMIC_MULTICH_BE", + .no_pcm = 1, + .capture_only = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(ap_dmic_multich), + }, + { + .name = "TDM_DPTX_BE", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC + | SND_SOC_DAIFMT_GATED, + .ops = &mt8196_dptx_ops, + .be_hw_params_fixup = mt8196_hw_params_fixup, + .no_pcm = 1, + .playback_only = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(tdm_dptx), + }, + { + .name = "I2SOUT3_BE", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC + | SND_SOC_DAIFMT_GATED, + .ops = &mt8196_nau8825_i2s_ops, + .no_pcm = 1, + .playback_only = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(i2sout3), + }, +}; + +static int mt8196_dumb_amp_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + int ret = 0; + + ret = snd_soc_dapm_new_controls(dapm, mt8196_dumb_spk_widgets, + ARRAY_SIZE(mt8196_dumb_spk_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, mt8196_dumb_spk_controls, + ARRAY_SIZE(mt8196_dumb_spk_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret); + return ret; + } + + return 0; +} + +static int mt8196_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_DP]; + struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + int ret = 0; + + ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_AVOUT, + jack, mt8196_dp_jack_pins, + ARRAY_SIZE(mt8196_dp_jack_pins)); + if (ret) { + dev_err(rtd->dev, "new jack failed: %d\n", ret); + return ret; + } + + ret = snd_soc_component_set_jack(component, jack, NULL); + if (ret) { + dev_err(rtd->dev, "set jack failed on %s (ret=%d)\n", + component->name, ret); + return ret; + } + + return 0; +} + +static int mt8196_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HDMI]; + struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + int ret = 0; + + ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", SND_JACK_AVOUT, + jack, mt8196_hdmi_jack_pins, + ARRAY_SIZE(mt8196_hdmi_jack_pins)); + if (ret) { + dev_err(rtd->dev, "new jack failed: %d\n", ret); + return ret; + } + + ret = snd_soc_component_set_jack(component, jack, NULL); + if (ret) { + dev_err(rtd->dev, "set jack failed on %s (ret=%d)\n", + component->name, ret); + return ret; + } + + return 0; +} + +static int mt8196_headset_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HEADSET]; + struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + int ret; + int type; + + ret = snd_soc_dapm_new_controls(dapm, mt8196_nau8825_widgets, + ARRAY_SIZE(mt8196_nau8825_widgets)); + if (ret) { + dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, mt8196_nau8825_controls, + ARRAY_SIZE(mt8196_nau8825_controls)); + if (ret) { + dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + jack, + nau8825_jack_pins, + ARRAY_SIZE(nau8825_jack_pins)); + if (ret) { + dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); + return ret; + } + + 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); + + type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3; + ret = snd_soc_component_set_jack(component, jack, (void *)&type); + + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + + return 0; +}; + +static void mt8196_headset_codec_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_set_jack(component, NULL, NULL); +} + +static int mt8196_nau8825_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + unsigned int rate = params_rate(params); + unsigned int bit_width = params_width(params); + int clk_freq, ret; + + clk_freq = rate * 2 * bit_width; + + /* Configure clock for codec */ + ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret); + return ret; + } + + /* Configure pll for codec */ + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq, + params_rate(params) * 256); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8196_nau8825_ops = { + .hw_params = mt8196_nau8825_hw_params, +}; + +static int mt8196_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + unsigned int rate = params_rate(params); + int bitwidth; + int ret; + + bitwidth = snd_pcm_format_width(params_format(params)); + if (bitwidth < 0) { + dev_err(card->dev, "invalid bit width: %d\n", bitwidth); + return bitwidth; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); + if (ret) { + dev_err(card->dev, "failed to set tdm slot\n"); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1, + rate * 32, rate * 512); + if (ret) { + dev_err(card->dev, "failed to set pll\n"); + return ret; + } + + dev_info(card->dev, "%s set mclk rate: %d\n", __func__, rate * 512); + + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_MCLK, + rate * 512, SND_SOC_CLOCK_IN); + if (ret) { + dev_err(card->dev, "failed to set sysclk\n"); + return ret; + } + + return snd_soc_dai_set_sysclk(cpu_dai, 0, rate * 512, + SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8196_rt5682s_i2s_ops = { + .hw_params = mt8196_rt5682s_i2s_hw_params, +}; + +static int mt8196_nau8825_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) +{ + struct snd_soc_card *card = soc_card_data->card_data->card; + struct snd_soc_dai_link *dai_link; + bool init_nau8825 = false; + bool init_rt5682s = false; + bool init_rt5650 = false; + bool init_dumb = false; + int i; + + dev_info(card->dev, "legacy: %d\n", legacy); + + for_each_card_prelinks(card, i, dai_link) { + if (strcmp(dai_link->name, "TDM_DPTX_BE") == 0) { + if (dai_link->num_codecs && + strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8196_dptx_codec_init; + } else if (strcmp(dai_link->name, "I2SOUT3_BE") == 0) { + if (dai_link->num_codecs && + strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8196_hdmi_codec_init; + } else if (strcmp(dai_link->name, "I2SOUT6_BE") == 0 || + strcmp(dai_link->name, "I2SIN6_BE") == 0) { + if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) { + dai_link->ops = &mt8196_nau8825_ops; + if (!init_nau8825) { + dai_link->init = mt8196_headset_codec_init; + dai_link->exit = mt8196_headset_codec_exit; + init_nau8825 = true; + } + } else if (!strcmp(dai_link->codecs->dai_name, RT5682S_CODEC_DAI)) { + dai_link->ops = &mt8196_rt5682s_i2s_ops; + if (!init_rt5682s) { + dai_link->init = mt8196_headset_codec_init; + dai_link->exit = mt8196_headset_codec_exit; + init_rt5682s = true; + } + } else if (!strcmp(dai_link->codecs->dai_name, RT5650_CODEC_DAI)) { + dai_link->ops = &mt8196_rt5682s_i2s_ops; + if (!init_rt5650) { + dai_link->init = mt8196_headset_codec_init; + dai_link->exit = mt8196_headset_codec_exit; + init_rt5650 = true; + } + } else { + if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) { + if (!init_dumb) { + dai_link->init = mt8196_dumb_amp_init; + init_dumb = true; + } + } + } + } + } + + return 0; +} + +static const struct mtk_sof_priv mt8196_sof_priv = { + .conn_streams = g_sof_conn_streams, + .num_streams = ARRAY_SIZE(g_sof_conn_streams), +}; + +static struct snd_soc_card mt8196_nau8825_soc_card = { + .owner = THIS_MODULE, + .dai_link = mt8196_nau8825_dai_links, + .num_links = ARRAY_SIZE(mt8196_nau8825_dai_links), + .dapm_widgets = mt8196_nau8825_card_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8196_nau8825_card_widgets), + .dapm_routes = mt8196_nau8825_card_routes, + .num_dapm_routes = ARRAY_SIZE(mt8196_nau8825_card_routes), + .controls = mt8196_nau8825_card_controls, + .num_controls = ARRAY_SIZE(mt8196_nau8825_card_controls), +}; + +static const struct mtk_soundcard_pdata mt8196_nau8825_card = { + .card_name = "mt8196_nau8825", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8196_nau8825_soc_card, + .num_jacks = MT8196_JACK_MAX, + .flags = NAU8825_HS_PRESENT + }, + .sof_priv = &mt8196_sof_priv, + .soc_probe = mt8196_nau8825_soc_card_probe, +}; + +static const struct mtk_soundcard_pdata mt8196_rt5682s_card = { + .card_name = "mt8196_rt5682s", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8196_nau8825_soc_card, + .num_jacks = MT8196_JACK_MAX, + .flags = RT5682S_HS_PRESENT + }, + .sof_priv = &mt8196_sof_priv, + .soc_probe = mt8196_nau8825_soc_card_probe, +}; + +static const struct mtk_soundcard_pdata mt8196_rt5650_card = { + .card_name = "mt8196_rt5650", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8196_nau8825_soc_card, + .num_jacks = MT8196_JACK_MAX, + .flags = RT5650_HS_PRESENT + }, + .sof_priv = &mt8196_sof_priv, + .soc_probe = mt8196_nau8825_soc_card_probe, +}; + +static const struct of_device_id mt8196_nau8825_dt_match[] = { + {.compatible = "mediatek,mt8196-nau8825-sound", .data = &mt8196_nau8825_card,}, + {.compatible = "mediatek,mt8196-rt5682s-sound", .data = &mt8196_rt5682s_card,}, + {.compatible = "mediatek,mt8196-rt5650-sound", .data = &mt8196_rt5650_card,}, + {} +}; +MODULE_DEVICE_TABLE(of, mt8196_nau8825_dt_match); + +static struct platform_driver mt8196_nau8825_driver = { + .driver = { + .name = "mt8196-nau8825", + .of_match_table = mt8196_nau8825_dt_match, + .pm = &snd_soc_pm_ops, + }, + .probe = mtk_soundcard_common_probe, +}; +module_platform_driver(mt8196_nau8825_driver); + +/* Module information */ +MODULE_DESCRIPTION("MT8196 nau8825 ALSA SoC machine driver"); +MODULE_AUTHOR("Darren Ye "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("mt8196 nau8825 soc card"); + diff --git a/sound/soc/mediatek/mt8196/mt8196-reg.h b/sound/soc/mediatek/mt8196/mt8196-reg.h new file mode 100644 index 000000000000..eb689d2655be --- /dev/null +++ b/sound/soc/mediatek/mt8196/mt8196-reg.h @@ -0,0 +1,12068 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8196-reg.h -- Mediatek 8196 audio driver reg definition + * + * Copyright (c) 2025 MediaTek Inc. + * Author: Darren Ye + */ + +#ifndef _MT8196_REG_H_ +#define _MT8196_REG_H_ + + /* reg bit enum */ +enum { + MT8196_MEMIF_PBUF_SIZE_32_BYTES, + MT8196_MEMIF_PBUF_SIZE_64_BYTES, + MT8196_MEMIF_PBUF_SIZE_128_BYTES, + MT8196_MEMIF_PBUF_SIZE_256_BYTES, + MT8196_MEMIF_PBUF_SIZE_NUM, +}; + +enum { + MT8196_MEMIF_MAX_LEN_0_BYTES, + MT8196_MEMIF_MAX_LEN_16_BYTES, + MT8196_MEMIF_MAX_LEN_32_BYTES, + MT8196_MEMIF_MAX_LEN_64_BYTES, +}; + +enum { + MT8196_MEMIF_MIN_LEN_NOT_SUPPORT, + MT8196_MEMIF_MIN_LEN_16_BYTES, + MT8196_MEMIF_MIN_LEN_32_BYTES, + MT8196_MEMIF_MIN_LEN_64_BYTES, +}; + +/***************************************************************************** + * R E G I S T E R D E F I N I T I O N + *****************************************************************************/ +/* AUDIO_TOP_CON0 */ +#define PDN_MTKAIFV4_SFT 25 +#define PDN_MTKAIFV4_MASK 0x1 +#define PDN_MTKAIFV4_MASK_SFT (0x1 << 25) +#define PDN_FM_I2S_SFT 24 +#define PDN_FM_I2S_MASK 0x1 +#define PDN_FM_I2S_MASK_SFT (0x1 << 24) +#define PDN_HW_GAIN01_SFT 21 +#define PDN_HW_GAIN01_MASK 0x1 +#define PDN_HW_GAIN01_MASK_SFT (0x1 << 21) +#define PDN_HW_GAIN23_SFT 20 +#define PDN_HW_GAIN23_MASK 0x1 +#define PDN_HW_GAIN23_MASK_SFT (0x1 << 20) +#define PDN_STF_SFT 19 +#define PDN_STF_MASK 0x1 +#define PDN_STF_MASK_SFT (0x1 << 19) +#define PDN_CM0_SFT 18 +#define PDN_CM0_MASK 0x1 +#define PDN_CM0_MASK_SFT (0x1 << 18) +#define PDN_CM1_SFT 17 +#define PDN_CM1_MASK 0x1 +#define PDN_CM1_MASK_SFT (0x1 << 17) +#define PDN_CM2_SFT 16 +#define PDN_CM2_MASK 0x1 +#define PDN_CM2_MASK_SFT (0x1 << 16) +#define PDN_PCM0_SFT 14 +#define PDN_PCM0_MASK 0x1 +#define PDN_PCM0_MASK_SFT (0x1 << 14) +#define PDN_PCM1_SFT 13 +#define PDN_PCM1_MASK 0x1 +#define PDN_PCM1_MASK_SFT (0x1 << 13) + +/* AUDIO_TOP_CON1 */ +#define PDN_UL0_ADC_SFT 23 +#define PDN_UL0_ADC_MASK 0x1 +#define PDN_UL0_ADC_MASK_SFT (0x1 << 23) +#define PDN_UL0_TML_SFT 22 +#define PDN_UL0_TML_MASK 0x1 +#define PDN_UL0_TML_MASK_SFT (0x1 << 22) +#define PDN_UL0_ADC_HIRES_SFT 21 +#define PDN_UL0_ADC_HIRES_MASK 0x1 +#define PDN_UL0_ADC_HIRES_MASK_SFT (0x1 << 21) +#define PDN_UL0_ADC_HIRES_TML_SFT 20 +#define PDN_UL0_ADC_HIRES_TML_MASK 0x1 +#define PDN_UL0_ADC_HIRES_TML_MASK_SFT (0x1 << 20) +#define PDN_UL1_ADC_SFT 19 +#define PDN_UL1_ADC_MASK 0x1 +#define PDN_UL1_ADC_MASK_SFT (0x1 << 19) +#define PDN_UL1_TML_SFT 18 +#define PDN_UL1_TML_MASK 0x1 +#define PDN_UL1_TML_MASK_SFT (0x1 << 18) +#define PDN_UL1_ADC_HIRES_SFT 17 +#define PDN_UL1_ADC_HIRES_MASK 0x1 +#define PDN_UL1_ADC_HIRES_MASK_SFT (0x1 << 17) +#define PDN_UL1_ADC_HIRES_TML_SFT 16 +#define PDN_UL1_ADC_HIRES_TML_MASK 0x1 +#define PDN_UL1_ADC_HIRES_TML_MASK_SFT (0x1 << 16) +#define PDN_UL2_ADC_SFT 15 +#define PDN_UL2_ADC_MASK 0x1 +#define PDN_UL2_ADC_MASK_SFT (0x1 << 15) +#define PDN_UL2_TML_SFT 14 +#define PDN_UL2_TML_MASK 0x1 +#define PDN_UL2_TML_MASK_SFT (0x1 << 14) +#define PDN_UL2_ADC_HIRES_SFT 13 +#define PDN_UL2_ADC_HIRES_MASK 0x1 +#define PDN_UL2_ADC_HIRES_MASK_SFT (0x1 << 13) +#define PDN_UL2_ADC_HIRES_TML_SFT 12 +#define PDN_UL2_ADC_HIRES_TML_MASK 0x1 +#define PDN_UL2_ADC_HIRES_TML_MASK_SFT (0x1 << 12) + +/* AUDIO_TOP_CON2 */ +#define PDN_TDM_OUT_SFT 24 +#define PDN_TDM_OUT_MASK 0x1 +#define PDN_TDM_OUT_MASK_SFT (0x1 << 24) +#define PDN_ETDM_OUT0_SFT 21 +#define PDN_ETDM_OUT0_MASK 0x1 +#define PDN_ETDM_OUT0_MASK_SFT (0x1 << 21) +#define PDN_ETDM_OUT1_SFT 20 +#define PDN_ETDM_OUT1_MASK 0x1 +#define PDN_ETDM_OUT1_MASK_SFT (0x1 << 20) +#define PDN_ETDM_OUT2_SFT 19 +#define PDN_ETDM_OUT2_MASK 0x1 +#define PDN_ETDM_OUT2_MASK_SFT (0x1 << 19) +#define PDN_ETDM_OUT3_SFT 18 +#define PDN_ETDM_OUT3_MASK 0x1 +#define PDN_ETDM_OUT3_MASK_SFT (0x1 << 18) +#define PDN_ETDM_OUT4_SFT 17 +#define PDN_ETDM_OUT4_MASK 0x1 +#define PDN_ETDM_OUT4_MASK_SFT (0x1 << 17) +#define PDN_ETDM_OUT5_SFT 16 +#define PDN_ETDM_OUT5_MASK 0x1 +#define PDN_ETDM_OUT5_MASK_SFT (0x1 << 16) +#define PDN_ETDM_OUT6_SFT 15 +#define PDN_ETDM_OUT6_MASK 0x1 +#define PDN_ETDM_OUT6_MASK_SFT (0x1 << 15) +#define PDN_ETDM_IN0_SFT 13 +#define PDN_ETDM_IN0_MASK 0x1 +#define PDN_ETDM_IN0_MASK_SFT (0x1 << 13) +#define PDN_ETDM_IN1_SFT 12 +#define PDN_ETDM_IN1_MASK 0x1 +#define PDN_ETDM_IN1_MASK_SFT (0x1 << 12) +#define PDN_ETDM_IN2_SFT 11 +#define PDN_ETDM_IN2_MASK 0x1 +#define PDN_ETDM_IN2_MASK_SFT (0x1 << 11) +#define PDN_ETDM_IN3_SFT 10 +#define PDN_ETDM_IN3_MASK 0x1 +#define PDN_ETDM_IN3_MASK_SFT (0x1 << 10) +#define PDN_ETDM_IN4_SFT 9 +#define PDN_ETDM_IN4_MASK 0x1 +#define PDN_ETDM_IN4_MASK_SFT (0x1 << 9) +#define PDN_ETDM_IN5_SFT 8 +#define PDN_ETDM_IN5_MASK 0x1 +#define PDN_ETDM_IN5_MASK_SFT (0x1 << 8) +#define PDN_ETDM_IN6_SFT 7 +#define PDN_ETDM_IN6_MASK 0x1 +#define PDN_ETDM_IN6_MASK_SFT (0x1 << 7) + +/* AUDIO_TOP_CON3 */ +#define PDN_CONNSYS_I2S_ASRC_SFT 25 +#define PDN_CONNSYS_I2S_ASRC_MASK 0x1 +#define PDN_CONNSYS_I2S_ASRC_MASK_SFT (0x1 << 25) +#define PDN_GENERAL0_ASRC_SFT 24 +#define PDN_GENERAL0_ASRC_MASK 0x1 +#define PDN_GENERAL0_ASRC_MASK_SFT (0x1 << 24) +#define PDN_GENERAL1_ASRC_SFT 23 +#define PDN_GENERAL1_ASRC_MASK 0x1 +#define PDN_GENERAL1_ASRC_MASK_SFT (0x1 << 23) +#define PDN_GENERAL2_ASRC_SFT 22 +#define PDN_GENERAL2_ASRC_MASK 0x1 +#define PDN_GENERAL2_ASRC_MASK_SFT (0x1 << 22) +#define PDN_GENERAL3_ASRC_SFT 21 +#define PDN_GENERAL3_ASRC_MASK 0x1 +#define PDN_GENERAL3_ASRC_MASK_SFT (0x1 << 21) +#define PDN_GENERAL4_ASRC_SFT 20 +#define PDN_GENERAL4_ASRC_MASK 0x1 +#define PDN_GENERAL4_ASRC_MASK_SFT (0x1 << 20) +#define PDN_GENERAL5_ASRC_SFT 19 +#define PDN_GENERAL5_ASRC_MASK 0x1 +#define PDN_GENERAL5_ASRC_MASK_SFT (0x1 << 19) +#define PDN_GENERAL6_ASRC_SFT 18 +#define PDN_GENERAL6_ASRC_MASK 0x1 +#define PDN_GENERAL6_ASRC_MASK_SFT (0x1 << 18) +#define PDN_GENERAL7_ASRC_SFT 17 +#define PDN_GENERAL7_ASRC_MASK 0x1 +#define PDN_GENERAL7_ASRC_MASK_SFT (0x1 << 17) +#define PDN_GENERAL8_ASRC_SFT 16 +#define PDN_GENERAL8_ASRC_MASK 0x1 +#define PDN_GENERAL8_ASRC_MASK_SFT (0x1 << 16) +#define PDN_GENERAL9_ASRC_SFT 15 +#define PDN_GENERAL9_ASRC_MASK 0x1 +#define PDN_GENERAL9_ASRC_MASK_SFT (0x1 << 15) +#define PDN_GENERAL10_ASRC_SFT 14 +#define PDN_GENERAL10_ASRC_MASK 0x1 +#define PDN_GENERAL10_ASRC_MASK_SFT (0x1 << 14) +#define PDN_GENERAL11_ASRC_SFT 13 +#define PDN_GENERAL11_ASRC_MASK 0x1 +#define PDN_GENERAL11_ASRC_MASK_SFT (0x1 << 13) +#define PDN_GENERAL12_ASRC_SFT 12 +#define PDN_GENERAL12_ASRC_MASK 0x1 +#define PDN_GENERAL12_ASRC_MASK_SFT (0x1 << 12) +#define PDN_GENERAL13_ASRC_SFT 11 +#define PDN_GENERAL13_ASRC_MASK 0x1 +#define PDN_GENERAL13_ASRC_MASK_SFT (0x1 << 11) +#define PDN_GENERAL14_ASRC_SFT 10 +#define PDN_GENERAL14_ASRC_MASK 0x1 +#define PDN_GENERAL14_ASRC_MASK_SFT (0x1 << 10) +#define PDN_GENERAL15_ASRC_SFT 9 +#define PDN_GENERAL15_ASRC_MASK 0x1 +#define PDN_GENERAL15_ASRC_MASK_SFT (0x1 << 9) + +/* AUDIO_TOP_CON4 */ +#define PDN_APLL_TUNER1_SFT 13 +#define PDN_APLL_TUNER1_MASK 0x1 +#define PDN_APLL_TUNER1_MASK_SFT (0x1 << 13) +#define PDN_APLL_TUNER2_SFT 12 +#define PDN_APLL_TUNER2_MASK 0x1 +#define PDN_APLL_TUNER2_MASK_SFT (0x1 << 12) +#define CG_H208M_CK_SFT 4 +#define CG_H208M_CK_MASK 0x1 +#define CG_H208M_CK_MASK_SFT (0x1 << 4) +#define CG_APLL2_CK_SFT 3 +#define CG_APLL2_CK_MASK 0x1 +#define CG_APLL2_CK_MASK_SFT (0x1 << 3) +#define CG_APLL1_CK_SFT 2 +#define CG_APLL1_CK_MASK 0x1 +#define CG_APLL1_CK_MASK_SFT (0x1 << 2) +#define CG_AUDIO_F26M_CK_SFT 1 +#define CG_AUDIO_F26M_CK_MASK 0x1 +#define CG_AUDIO_F26M_CK_MASK_SFT (0x1 << 1) +#define CG_AUDIO_HOPPING_CK_SFT 0 +#define CG_AUDIO_HOPPING_CK_MASK 0x1 +#define CG_AUDIO_HOPPING_CK_MASK_SFT (0x1 << 0) + +/* AUDIO_ENGEN_CON0 */ +/* AUDIO_ENGEN_CON0_USER1 */ +/* AUDIO_ENGEN_CON0_USER1 */ +#define MULTI_USER_BYPASS_SFT 17 +#define MULTI_USER_BYPASS_MASK 0x1 +#define MULTI_USER_BYPASS_MASK_SFT (0x1 << 17) +#define MULTI_USER_RST_SFT 16 +#define MULTI_USER_RST_MASK 0x1 +#define MULTI_USER_RST_MASK_SFT (0x1 << 16) +#define AUDIO_F26M_EN_RST_SFT 8 +#define AUDIO_F26M_EN_RST_MASK 0x1 +#define AUDIO_F26M_EN_RST_MASK_SFT (0x1 << 8) +#define AUDIO_APLL2_EN_ON_SFT 3 +#define AUDIO_APLL2_EN_ON_MASK 0x1 +#define AUDIO_APLL2_EN_ON_MASK_SFT (0x1 << 3) +#define AUDIO_APLL1_EN_ON_SFT 2 +#define AUDIO_APLL1_EN_ON_MASK 0x1 +#define AUDIO_APLL1_EN_ON_MASK_SFT (0x1 << 2) +#define AUDIO_F3P25M_EN_ON_SFT 1 +#define AUDIO_F3P25M_EN_ON_MASK 0x1 +#define AUDIO_F3P25M_EN_ON_MASK_SFT (0x1 << 1) +#define AUDIO_26M_EN_ON_SFT 0 +#define AUDIO_26M_EN_ON_MASK 0x1 +#define AUDIO_26M_EN_ON_MASK_SFT (0x1 << 0) + +/* AFE_SINEGEN_CON0 */ +#define DAC_EN_SFT 26 +#define DAC_EN_MASK 0x1 +#define DAC_EN_MASK_SFT (0x1 << 26) +#define TIE_SW_CH2_SFT 25 +#define TIE_SW_CH2_MASK 0x1 +#define TIE_SW_CH2_MASK_SFT (0x1 << 25) +#define TIE_SW_CH1_SFT 24 +#define TIE_SW_CH1_MASK 0x1 +#define TIE_SW_CH1_MASK_SFT (0x1 << 24) +#define AMP_DIV_CH2_SFT 20 +#define AMP_DIV_CH2_MASK 0xf +#define AMP_DIV_CH2_MASK_SFT (0xf << 20) +#define FREQ_DIV_CH2_SFT 12 +#define FREQ_DIV_CH2_MASK 0x1f +#define FREQ_DIV_CH2_MASK_SFT (0x1f << 12) +#define AMP_DIV_CH1_SFT 8 +#define AMP_DIV_CH1_MASK 0xf +#define AMP_DIV_CH1_MASK_SFT (0xf << 8) +#define FREQ_DIV_CH1_SFT 0 +#define FREQ_DIV_CH1_MASK 0x1f +#define FREQ_DIV_CH1_MASK_SFT (0x1f << 0) + +/* AFE_SINEGEN_CON1 */ +#define SINE_DOMAIN_SFT 20 +#define SINE_DOMAIN_MASK 0x7 +#define SINE_DOMAIN_MASK_SFT (0x7 << 20) +#define SINE_MODE_SFT 12 +#define SINE_MODE_MASK 0x1f +#define SINE_MODE_MASK_SFT (0x1f << 12) +#define INNER_LOOP_BACKI_SEL_SFT 8 +#define INNER_LOOP_BACKI_SEL_MASK 0x1 +#define INNER_LOOP_BACKI_SEL_MASK_SFT (0x1 << 8) +#define INNER_LOOP_BACK_MODE_SFT 0 +#define INNER_LOOP_BACK_MODE_MASK 0xff +#define INNER_LOOP_BACK_MODE_MASK_SFT (0xff << 0) + +/* AFE_SINEGEN_CON2 */ +#define TIE_CH1_CONSTANT_SFT 0 +#define TIE_CH1_CONSTANT_MASK 0xffffffff +#define TIE_CH1_CONSTANT_MASK_SFT (0xffffffff << 0) + +/* AFE_SINEGEN_CON3 */ +#define TIE_CH2_CONSTANT_SFT 0 +#define TIE_CH2_CONSTANT_MASK 0xffffffff +#define TIE_CH2_CONSTANT_MASK_SFT (0xffffffff << 0) + +/* AFE_APLL1_TUNER_CFG */ +/* AFE_APLL2_TUNER_CFG */ +#define UPPER_BOUND_SFT 8 +#define UPPER_BOUND_MASK 0xff +#define UPPER_BOUND_MASK_SFT (0xff << 8) +#define APLL_DIV_SFT 4 +#define APLL_DIV_MASK 0xf +#define APLL_DIV_MASK_SFT (0xf << 4) +#define XTAL_EN_128FS_SEL_SFT 1 +#define XTAL_EN_128FS_SEL_MASK 0x3 +#define XTAL_EN_128FS_SEL_MASK_SFT (0x3 << 1) +#define FREQ_TUNER_EN_SFT 0 +#define FREQ_TUNER_EN_MASK 0x1 +#define FREQ_TUNER_EN_MASK_SFT (0x1 << 0) + +/* AFE_APLL1_TUNER_MON0 */ +/* AFE_APLL2_TUNER_MON0 */ +#define TUNER_MON_SFT 0 +#define TUNER_MON_MASK 0xffffffff +#define TUNER_MON_MASK_SFT (0xffffffff << 0) + +/* AUDIO_TOP_RG0 */ +/* AUDIO_TOP_RG1 */ +/* AUDIO_TOP_RG2 */ +/* AUDIO_TOP_RG3 */ +/* AUDIO_TOP_RG4 */ +#define RESERVE_RG_SFT 0 +#define RESERVE_RG_MASK 0xffffffff +#define RESERVE_RG_MASK_SFT (0xffffffff << 0) + +/* AFE_SPM_CONTROL_REQ */ +#define AFE_DDREN_REQ_SFT 4 +#define AFE_DDREN_REQ_MASK 0x1 +#define AFE_DDREN_REQ_MASK_SFT (0x1 << 4) +#define AFE_INFRA_REQ_SFT 3 +#define AFE_INFRA_REQ_MASK 0x1 +#define AFE_INFRA_REQ_MASK_SFT (0x1 << 3) +#define AFE_VRF18_REQ_SFT 2 +#define AFE_VRF18_REQ_MASK 0x1 +#define AFE_VRF18_REQ_MASK_SFT (0x1 << 2) +#define AFE_APSRC_REQ_SFT 1 +#define AFE_APSRC_REQ_MASK 0x1 +#define AFE_APSRC_REQ_MASK_SFT (0x1 << 1) +#define AFE_SRCCLKENA_REQ_SFT 0 +#define AFE_SRCCLKENA_REQ_MASK 0x1 +#define AFE_SRCCLKENA_REQ_MASK_SFT (0x1 << 0) + +/* AFE_SPM_CONTROL_ACK */ +#define SPM_RESOURCE_CONTROL_ACK_SFT 0 +#define SPM_RESOURCE_CONTROL_ACK_MASK 0xffffffff +#define SPM_RESOURCE_CONTROL_ACK_MASK_SFT (0xffffffff << 0) + +/* AUD_TOP_CFG_VCORE_RG */ +#define AUD_TOP_CFG_SFT 0 +#define AUD_TOP_CFG_MASK 0xffffffff +#define AUD_TOP_CFG_MASK_SFT (0xffffffff << 0) + +/* AUDIO_TOP_IP_VERSION */ +#define AUDIO_TOP_IP_VERSION_SFT 0 +#define AUDIO_TOP_IP_VERSION_MASK 0xffffffff +#define AUDIO_TOP_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AUDIO_ENGEN_CON0_MON */ +#define AUDIO_ENGEN_MON_SFT 0 +#define AUDIO_ENGEN_MON_MASK 0xffffffff +#define AUDIO_ENGEN_MON_MASK_SFT (0xffffffff << 0) + +/* AUD_TOP_CFG_VLP_RG */ +#define I2SIN1_DAT_SEL_SFT 31 +#define I2SIN1_DAT_SEL_MASK 0x1 +#define I2SIN1_DAT_SEL_MASK_SFT (0x1 << 31) +#define FMI2S_IN_SEL_SFT 30 +#define FMI2S_IN_SEL_MASK 0x1 +#define FMI2S_IN_SEL_MASK_SFT (0x1 << 30) +#define RG_I2S4_IN_BCK_NEG_EG_LATCH_SFT 21 +#define RG_I2S4_IN_BCK_NEG_EG_LATCH_MASK 0x1 +#define RG_I2S4_IN_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 21) +#define RG_I2S4_OUT_BCK_NEG_EG_LATCH_SFT 20 +#define RG_I2S4_OUT_BCK_NEG_EG_LATCH_MASK 0x1 +#define RG_I2S4_OUT_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 20) +#define RG_I2S4_IN_SLV_LRCK_LATCH_EDGE_SFT 19 +#define RG_I2S4_IN_SLV_LRCK_LATCH_EDGE_MASK 0x1 +#define RG_I2S4_IN_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 19) +#define RG_I2S4_IN_SLV_BCK_INV_SEL_SFT 18 +#define RG_I2S4_IN_SLV_BCK_INV_SEL_MASK 0x1 +#define RG_I2S4_IN_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 18) +#define RG_I2S4_OUT_SLV_LRCK_LATCH_EDGE_SFT 17 +#define RG_I2S4_OUT_SLV_LRCK_LATCH_EDGE_MASK 0x1 +#define RG_I2S4_OUT_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 17) +#define RG_I2S4_OUT_SLV_BCK_INV_SEL_SFT 16 +#define RG_I2S4_OUT_SLV_BCK_INV_SEL_MASK 0x1 +#define RG_I2S4_OUT_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 16) +#define RG_I2S5_IN_BCK_NEG_EG_LATCH_SFT 13 +#define RG_I2S5_IN_BCK_NEG_EG_LATCH_MASK 0x1 +#define RG_I2S5_IN_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 13) +#define RG_I2S5_OUT_BCK_NEG_EG_LATCH_SFT 12 +#define RG_I2S5_OUT_BCK_NEG_EG_LATCH_MASK 0x1 +#define RG_I2S5_OUT_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 12) +#define RG_I2S5_IN_SLV_LRCK_LATCH_EDGE_SFT 11 +#define RG_I2S5_IN_SLV_LRCK_LATCH_EDGE_MASK 0x1 +#define RG_I2S5_IN_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 11) +#define RG_I2S5_IN_SLV_BCK_INV_SEL_SFT 10 +#define RG_I2S5_IN_SLV_BCK_INV_SEL_MASK 0x1 +#define RG_I2S5_IN_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 10) +#define RG_I2S5_OUT_SLV_LRCK_LATCH_EDGE_SFT 9 +#define RG_I2S5_OUT_SLV_LRCK_LATCH_EDGE_MASK 0x1 +#define RG_I2S5_OUT_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 9) +#define RG_I2S5_OUT_SLV_BCK_INV_SEL_SFT 8 +#define RG_I2S5_OUT_SLV_BCK_INV_SEL_MASK 0x1 +#define RG_I2S5_OUT_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 8) +#define RG_I2S4_PAD_TOP_CK_EN_SFT 5 +#define RG_I2S4_PAD_TOP_CK_EN_MASK 0x1 +#define RG_I2S4_PAD_TOP_CK_EN_MASK_SFT (0x1 << 5) +#define RG_I2S5_PAD_TOP_CK_EN_SFT 4 +#define RG_I2S5_PAD_TOP_CK_EN_MASK 0x1 +#define RG_I2S5_PAD_TOP_CK_EN_MASK_SFT (0x1 << 4) +#define RG_TEST_TYPE_SFT 2 +#define RG_TEST_TYPE_MASK 0x1 +#define RG_TEST_TYPE_MASK_SFT (0x1 << 2) +#define RG_SW_RESET_SFT 1 +#define RG_SW_RESET_MASK 0x1 +#define RG_SW_RESET_MASK_SFT (0x1 << 1) +#define RG_TEST_ON_SFT 0 +#define RG_TEST_ON_MASK 0x1 +#define RG_TEST_ON_MASK_SFT (0x1 << 0) + +/* AUD_TOP_MON_RG */ +#define AUD_TOP_MON_SFT 0 +#define AUD_TOP_MON_MASK 0xffffffff +#define AUD_TOP_MON_MASK_SFT (0xffffffff << 0) + +/* AUDIO_USE_DEFAULT_DELSEL0 */ +#define USE_DEFAULT_DELSEL_RG_SFT 0 +#define USE_DEFAULT_DELSEL_RG_MASK 0xffffffff +#define USE_DEFAULT_DELSEL_RG_MASK_SFT (0xffffffff << 0) + +/* AUDIO_USE_DEFAULT_DELSEL1 */ +#define USE_DEFAULT_DELSEL_RG_SFT 0 +#define USE_DEFAULT_DELSEL_RG_MASK 0xffffffff +#define USE_DEFAULT_DELSEL_RG_MASK_SFT (0xffffffff << 0) + +/* AUDIO_USE_DEFAULT_DELSEL2 */ +#define USE_DEFAULT_DELSEL_RG_SFT 0 +#define USE_DEFAULT_DELSEL_RG_MASK 0xffffffff +#define USE_DEFAULT_DELSEL_RG_MASK_SFT (0xffffffff << 0) + +/* AFE_CONNSYS_I2S_IPM_VER_MON */ +#define RG_CONNSYS_I2S_IPM_VER_MON_SFT 0 +#define RG_CONNSYS_I2S_IPM_VER_MON_MASK 0xffffffff +#define RG_CONNSYS_I2S_IPM_VER_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_CONNSYS_I2S_MON_SEL */ +#define RG_CONNSYS_I2S_MON_SEL_SFT 0 +#define RG_CONNSYS_I2S_MON_SEL_MASK 0xff +#define RG_CONNSYS_I2S_MON_SEL_MASK_SFT (0xff << 0) + +/* AFE_CONNSYS_I2S_MON */ +#define RG_CONNSYS_I2S_MON_SFT 0 +#define RG_CONNSYS_I2S_MON_MASK 0xffffffff +#define RG_CONNSYS_I2S_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_CONNSYS_I2S_CON */ +#define I2S_SOFT_RST_SFT 31 +#define I2S_SOFT_RST_MASK 0x1 +#define I2S_SOFT_RST_MASK_SFT (0x1 << 31) +#define BCK_NEG_EG_LATCH_SFT 30 +#define BCK_NEG_EG_LATCH_MASK 0x1 +#define BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 30) +#define BCK_INV_SFT 29 +#define BCK_INV_MASK 0x1 +#define BCK_INV_MASK_SFT (0x1 << 29) +#define I2SIN_PAD_SEL_SFT 28 +#define I2SIN_PAD_SEL_MASK 0x1 +#define I2SIN_PAD_SEL_MASK_SFT (0x1 << 28) +#define I2S_LOOPBACK_SFT 20 +#define I2S_LOOPBACK_MASK 0x1 +#define I2S_LOOPBACK_MASK_SFT (0x1 << 20) +#define I2S_HDEN_SFT 12 +#define I2S_HDEN_MASK 0x1 +#define I2S_HDEN_MASK_SFT (0x1 << 12) +#define I2S_MODE_SFT 8 +#define I2S_MODE_MASK 0xf +#define I2S_MODE_MASK_SFT (0xf << 8) +#define I2S_BYPSRC_SFT 6 +#define I2S_BYPSRC_MASK 0x1 +#define I2S_BYPSRC_MASK_SFT (0x1 << 6) +#define INV_LRCK_SFT 5 +#define INV_LRCK_MASK 0x1 +#define INV_LRCK_MASK_SFT (0x1 << 5) +#define I2S_FMT_SFT 3 +#define I2S_FMT_MASK 0x1 +#define I2S_FMT_MASK_SFT (0x1 << 3) +#define I2S_SRC_SFT 2 +#define I2S_SRC_MASK 0x1 +#define I2S_SRC_MASK_SFT (0x1 << 2) +#define I2S_WLEN_SFT 1 +#define I2S_WLEN_MASK 0x1 +#define I2S_WLEN_MASK_SFT (0x1 << 1) +#define I2S_EN_SFT 0 +#define I2S_EN_MASK 0x1 +#define I2S_EN_MASK_SFT (0x1 << 0) + +/* AFE_PCM0_INTF_CON0 */ +#define PCM0_HDEN_SFT 26 +#define PCM0_HDEN_MASK 0x1 +#define PCM0_HDEN_MASK_SFT (0x1 << 26) +#define PCM0_SYNC_DELSEL_SFT 25 +#define PCM0_SYNC_DELSEL_MASK 0x1 +#define PCM0_SYNC_DELSEL_MASK_SFT (0x1 << 25) +#define PCM0_TX_LR_SWAP_SFT 24 +#define PCM0_TX_LR_SWAP_MASK 0x1 +#define PCM0_TX_LR_SWAP_MASK_SFT (0x1 << 24) +#define PCM0_SYNC_OUT_INV_SFT 23 +#define PCM0_SYNC_OUT_INV_MASK 0x1 +#define PCM0_SYNC_OUT_INV_MASK_SFT (0x1 << 23) +#define PCM0_BCLK_OUT_INV_SFT 22 +#define PCM0_BCLK_OUT_INV_MASK 0x1 +#define PCM0_BCLK_OUT_INV_MASK_SFT (0x1 << 22) +#define PCM0_SYNC_IN_INV_SFT 21 +#define PCM0_SYNC_IN_INV_MASK 0x1 +#define PCM0_SYNC_IN_INV_MASK_SFT (0x1 << 21) +#define PCM0_BCLK_IN_INV_SFT 20 +#define PCM0_BCLK_IN_INV_MASK 0x1 +#define PCM0_BCLK_IN_INV_MASK_SFT (0x1 << 20) +#define PCM0_TX_LCH_RPT_SFT 19 +#define PCM0_TX_LCH_RPT_MASK 0x1 +#define PCM0_TX_LCH_RPT_MASK_SFT (0x1 << 19) +#define PCM0_VBT_16K_MODE_SFT 18 +#define PCM0_VBT_16K_MODE_MASK 0x1 +#define PCM0_VBT_16K_MODE_MASK_SFT (0x1 << 18) +#define PCM0_BIT_LENGTH_SFT 16 +#define PCM0_BIT_LENGTH_MASK 0x3 +#define PCM0_BIT_LENGTH_MASK_SFT (0x3 << 16) +#define PCM0_WLEN_SFT 14 +#define PCM0_WLEN_MASK 0x3 +#define PCM0_WLEN_MASK_SFT (0x3 << 14) +#define PCM0_SYNC_LENGTH_SFT 9 +#define PCM0_SYNC_LENGTH_MASK 0x1f +#define PCM0_SYNC_LENGTH_MASK_SFT (0x1f << 9) +#define PCM0_SYNC_TYPE_SFT 8 +#define PCM0_SYNC_TYPE_MASK 0x1 +#define PCM0_SYNC_TYPE_MASK_SFT (0x1 << 8) +#define PCM0_BYP_ASRC_SFT 7 +#define PCM0_BYP_ASRC_MASK 0x1 +#define PCM0_BYP_ASRC_MASK_SFT (0x1 << 7) +#define PCM0_SLAVE_SFT 6 +#define PCM0_SLAVE_MASK 0x1 +#define PCM0_SLAVE_MASK_SFT (0x1 << 6) +#define PCM0_MODE_SFT 3 +#define PCM0_MODE_MASK 0x7 +#define PCM0_MODE_MASK_SFT (0x7 << 3) +#define PCM0_FMT_SFT 1 +#define PCM0_FMT_MASK 0x3 +#define PCM0_FMT_MASK_SFT (0x3 << 1) +#define PCM0_EN_SFT 0 +#define PCM0_EN_MASK 0x1 +#define PCM0_EN_MASK_SFT (0x1 << 0) + +/* AFE_PCM0_INTF_CON1 */ +#define PCM0_TX_RX_LOOPBACK_SFT 31 +#define PCM0_TX_RX_LOOPBACK_MASK 0x1 +#define PCM0_TX_RX_LOOPBACK_MASK_SFT (0x1 << 31) +#define PCM0_BUFFER_LOOPBACK_SFT 30 +#define PCM0_BUFFER_LOOPBACK_MASK 0x1 +#define PCM0_BUFFER_LOOPBACK_MASK_SFT (0x1 << 30) +#define PCM0_PARALLEL_LOOPBACK_SFT 29 +#define PCM0_PARALLEL_LOOPBACK_MASK 0x1 +#define PCM0_PARALLEL_LOOPBACK_MASK_SFT (0x1 << 29) +#define PCM0_SERIAL_LOOPBACK_SFT 28 +#define PCM0_SERIAL_LOOPBACK_MASK 0x1 +#define PCM0_SERIAL_LOOPBACK_MASK_SFT (0x1 << 28) +#define PCM0_DAI_LOOPBACK_SFT 27 +#define PCM0_DAI_LOOPBACK_MASK 0x1 +#define PCM0_DAI_LOOPBACK_MASK_SFT (0x1 << 27) +#define PCM0_I2S_LOOPBACK_SFT 26 +#define PCM0_I2S_LOOPBACK_MASK 0x1 +#define PCM0_I2S_LOOPBACK_MASK_SFT (0x1 << 26) +#define PCM0_1X_EN_DOMAIN_SFT 23 +#define PCM0_1X_EN_DOMAIN_MASK 0x7 +#define PCM0_1X_EN_DOMAIN_MASK_SFT (0x7 << 23) +#define PCM0_1X_EN_MODE_SFT 18 +#define PCM0_1X_EN_MODE_MASK 0x1f +#define PCM0_1X_EN_MODE_MASK_SFT (0x1f << 18) +#define PCM0_TX3_RCH_DBG_MODE_SFT 17 +#define PCM0_TX3_RCH_DBG_MODE_MASK 0x1 +#define PCM0_TX3_RCH_DBG_MODE_MASK_SFT (0x1 << 17) +#define PCM0_PCM1_LOOPBACK_SFT 16 +#define PCM0_PCM1_LOOPBACK_MASK 0x1 +#define PCM0_PCM1_LOOPBACK_MASK_SFT (0x1 << 16) +#define PCM0_LOOPBACK_CH_SEL_SFT 12 +#define PCM0_LOOPBACK_CH_SEL_MASK 0x3 +#define PCM0_LOOPBACK_CH_SEL_MASK_SFT (0x3 << 12) +#define PCM0_BT_MODE_SFT 11 +#define PCM0_BT_MODE_MASK 0x1 +#define PCM0_BT_MODE_MASK_SFT (0x1 << 11) +#define PCM0_EXT_MODEM_SFT 10 +#define PCM0_EXT_MODEM_MASK 0x1 +#define PCM0_EXT_MODEM_MASK_SFT (0x1 << 10) +#define PCM0_USE_MD3_SFT 9 +#define PCM0_USE_MD3_MASK 0x1 +#define PCM0_USE_MD3_MASK_SFT (0x1 << 9) +#define PCM0_FIX_VALUE_SEL_SFT 8 +#define PCM0_FIX_VALUE_SEL_MASK 0x1 +#define PCM0_FIX_VALUE_SEL_MASK_SFT (0x1 << 8) +#define PCM0_TX_FIX_VALUE_SFT 0 +#define PCM0_TX_FIX_VALUE_MASK 0xff +#define PCM0_TX_FIX_VALUE_MASK_SFT (0xff << 0) + +/* AFE_PCM_INTF_MON */ +#define PCM0_TX_FIFO_OV_SFT 5 +#define PCM0_TX_FIFO_OV_MASK 0x1 +#define PCM0_TX_FIFO_OV_MASK_SFT (0x1 << 5) +#define PCM0_RX_FIFO_OV_SFT 4 +#define PCM0_RX_FIFO_OV_MASK 0x1 +#define PCM0_RX_FIFO_OV_MASK_SFT (0x1 << 4) +#define PCM1_TX_FIFO_OV_SFT 3 +#define PCM1_TX_FIFO_OV_MASK 0x1 +#define PCM1_TX_FIFO_OV_MASK_SFT (0x1 << 3) +#define PCM1_RX_FIFO_OV_SFT 2 +#define PCM1_RX_FIFO_OV_MASK 0x1 +#define PCM1_RX_FIFO_OV_MASK_SFT (0x1 << 2) +#define PCM0_SYNC_GLITCH_SFT 1 +#define PCM0_SYNC_GLITCH_MASK 0x1 +#define PCM0_SYNC_GLITCH_MASK_SFT (0x1 << 1) +#define PCM1_SYNC_GLITCH_SFT 0 +#define PCM1_SYNC_GLITCH_MASK 0x1 +#define PCM1_SYNC_GLITCH_MASK_SFT (0x1 << 0) + +/* AFE_PCM1_INTF_CON0 */ +#define PCM1_TX_FIX_VALUE_SFT 24 +#define PCM1_TX_FIX_VALUE_MASK 0xff +#define PCM1_TX_FIX_VALUE_MASK_SFT (0xff << 24) +#define PCM1_FIX_VALUE_SEL_SFT 23 +#define PCM1_FIX_VALUE_SEL_MASK 0x1 +#define PCM1_FIX_VALUE_SEL_MASK_SFT (0x1 << 23) +#define PCM1_BUFFER_LOOPBACK_SFT 22 +#define PCM1_BUFFER_LOOPBACK_MASK 0x1 +#define PCM1_BUFFER_LOOPBACK_MASK_SFT (0x1 << 22) +#define PCM1_PARALLEL_LOOPBACK_SFT 21 +#define PCM1_PARALLEL_LOOPBACK_MASK 0x1 +#define PCM1_PARALLEL_LOOPBACK_MASK_SFT (0x1 << 21) +#define PCM1_SERIAL_LOOPBACK_SFT 20 +#define PCM1_SERIAL_LOOPBACK_MASK 0x1 +#define PCM1_SERIAL_LOOPBACK_MASK_SFT (0x1 << 20) +#define PCM1_DAI_PCM1_LOOPBACK_SFT 19 +#define PCM1_DAI_PCM1_LOOPBACK_MASK 0x1 +#define PCM1_DAI_PCM1_LOOPBACK_MASK_SFT (0x1 << 19) +#define PCM1_I2S_PCM1_LOOPBACK_SFT 18 +#define PCM1_I2S_PCM1_LOOPBACK_MASK 0x1 +#define PCM1_I2S_PCM1_LOOPBACK_MASK_SFT (0x1 << 18) +#define PCM1_SYNC_DELSEL_SFT 17 +#define PCM1_SYNC_DELSEL_MASK 0x1 +#define PCM1_SYNC_DELSEL_MASK_SFT (0x1 << 17) +#define PCM1_TX_LR_SWAP_SFT 16 +#define PCM1_TX_LR_SWAP_MASK 0x1 +#define PCM1_TX_LR_SWAP_MASK_SFT (0x1 << 16) +#define PCM1_SYNC_IN_INV_SFT 15 +#define PCM1_SYNC_IN_INV_MASK 0x1 +#define PCM1_SYNC_IN_INV_MASK_SFT (0x1 << 15) +#define PCM1_BCLK_IN_INV_SFT 14 +#define PCM1_BCLK_IN_INV_MASK 0x1 +#define PCM1_BCLK_IN_INV_MASK_SFT (0x1 << 14) +#define PCM1_TX_LCH_RPT_SFT 13 +#define PCM1_TX_LCH_RPT_MASK 0x1 +#define PCM1_TX_LCH_RPT_MASK_SFT (0x1 << 13) +#define PCM1_VBT_16K_MODE_SFT 12 +#define PCM1_VBT_16K_MODE_MASK 0x1 +#define PCM1_VBT_16K_MODE_MASK_SFT (0x1 << 12) +#define PCM1_LOOPBACK_CH_SEL_SFT 10 +#define PCM1_LOOPBACK_CH_SEL_MASK 0x3 +#define PCM1_LOOPBACK_CH_SEL_MASK_SFT (0x3 << 10) +#define PCM1_TX2_BT_MODE_SFT 8 +#define PCM1_TX2_BT_MODE_MASK 0x1 +#define PCM1_TX2_BT_MODE_MASK_SFT (0x1 << 8) +#define PCM1_BT_MODE_SFT 7 +#define PCM1_BT_MODE_MASK 0x1 +#define PCM1_BT_MODE_MASK_SFT (0x1 << 7) +#define PCM1_AFIFO_SFT 6 +#define PCM1_AFIFO_MASK 0x1 +#define PCM1_AFIFO_MASK_SFT (0x1 << 6) +#define PCM1_WLEN_SFT 5 +#define PCM1_WLEN_MASK 0x1 +#define PCM1_WLEN_MASK_SFT (0x1 << 5) +#define PCM1_MODE_SFT 3 +#define PCM1_MODE_MASK 0x3 +#define PCM1_MODE_MASK_SFT (0x3 << 3) +#define PCM1_FMT_SFT 1 +#define PCM1_FMT_MASK 0x3 +#define PCM1_FMT_MASK_SFT (0x3 << 1) +#define PCM1_EN_SFT 0 +#define PCM1_EN_MASK 0x1 +#define PCM1_EN_MASK_SFT (0x1 << 0) + +/* AFE_PCM1_INTF_CON1 */ +#define PCM1_1X_EN_DOMAIN_SFT 23 +#define PCM1_1X_EN_DOMAIN_MASK 0x7 +#define PCM1_1X_EN_DOMAIN_MASK_SFT (0x7 << 23) +#define PCM1_1X_EN_MODE_SFT 18 +#define PCM1_1X_EN_MODE_MASK 0x1f +#define PCM1_1X_EN_MODE_MASK_SFT (0x1f << 18) + +/* AFE_PCM_TOP_IP_VERSION */ +#define AFE_PCM_TOP_IP_VERSION_SFT 0 +#define AFE_PCM_TOP_IP_VERSION_MASK 0xffffffff +#define AFE_PCM_TOP_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_IRQ_MCU_EN */ +#define AFE_IRQ_MCU_EN_SFT 0 +#define AFE_IRQ_MCU_EN_MASK 0xffffffff +#define AFE_IRQ_MCU_EN_MASK_SFT (0xffffffff << 0) + +/* AFE_IRQ_MCU_DSP_EN */ +#define AFE_IRQ_DSP_EN_SFT 0 +#define AFE_IRQ_DSP_EN_MASK 0xffffffff +#define AFE_IRQ_DSP_EN_MASK_SFT (0xffffffff << 0) + +/* AFE_IRQ_MCU_DSP2_EN */ +#define AFE_IRQ_DSP2_EN_SFT 0 +#define AFE_IRQ_DSP2_EN_MASK 0xffffffff +#define AFE_IRQ_DSP2_EN_MASK_SFT (0xffffffff << 0) + +/* AFE_IRQ_MCU_SCP_EN */ +#define IRQ31_MCU_SCP_EN_SFT 31 +#define IRQ30_MCU_SCP_EN_SFT 30 +#define IRQ29_MCU_SCP_EN_SFT 29 +#define IRQ28_MCU_SCP_EN_SFT 28 +#define IRQ27_MCU_SCP_EN_SFT 27 +#define IRQ26_MCU_SCP_EN_SFT 26 +#define IRQ25_MCU_SCP_EN_SFT 25 +#define IRQ24_MCU_SCP_EN_SFT 24 +#define IRQ23_MCU_SCP_EN_SFT 23 +#define IRQ22_MCU_SCP_EN_SFT 22 +#define IRQ21_MCU_SCP_EN_SFT 21 +#define IRQ20_MCU_SCP_EN_SFT 20 +#define IRQ19_MCU_SCP_EN_SFT 19 +#define IRQ18_MCU_SCP_EN_SFT 18 +#define IRQ17_MCU_SCP_EN_SFT 17 +#define IRQ16_MCU_SCP_EN_SFT 16 +#define IRQ15_MCU_SCP_EN_SFT 15 +#define IRQ14_MCU_SCP_EN_SFT 14 +#define IRQ13_MCU_SCP_EN_SFT 13 +#define IRQ12_MCU_SCP_EN_SFT 12 +#define IRQ11_MCU_SCP_EN_SFT 11 +#define IRQ10_MCU_SCP_EN_SFT 10 +#define IRQ9_MCU_SCP_EN_SFT 9 +#define IRQ8_MCU_SCP_EN_SFT 8 +#define IRQ7_MCU_SCP_EN_SFT 7 +#define IRQ6_MCU_SCP_EN_SFT 6 +#define IRQ5_MCU_SCP_EN_SFT 5 +#define IRQ4_MCU_SCP_EN_SFT 4 +#define IRQ3_MCU_SCP_EN_SFT 3 +#define IRQ2_MCU_SCP_EN_SFT 2 +#define IRQ1_MCU_SCP_EN_SFT 1 +#define IRQ0_MCU_SCP_EN_SFT 0 + +/* AFE_CUSTOM_IRQ_MCU_EN */ +#define AFE_CUSTOM_IRQ_MCU_EN_SFT 0 +#define AFE_CUSTOM_IRQ_MCU_EN_MASK 0xffffffff +#define AFE_CUSTOM_IRQ_MCU_EN_MASK_SFT (0xffffffff << 0) + +/* AFE_CUSTOM_IRQ_MCU_DSP_EN */ +#define AFE_CUSTOM_IRQ_DSP_EN_SFT 0 +#define AFE_CUSTOM_IRQ_DSP_EN_MASK 0xffffffff +#define AFE_CUSTOM_IRQ_DSP_EN_MASK_SFT (0xffffffff << 0) + +/* AFE_CUSTOM_IRQ_MCU_DSP2_EN */ +#define AFE_CUSTOM_IRQ_DSP2_EN_SFT 0 +#define AFE_CUSTOM_IRQ_DSP2_EN_MASK 0xffffffff +#define AFE_CUSTOM_IRQ_DSP2_EN_MASK_SFT (0xffffffff << 0) + +/* AFE_CUSTOM_IRQ_MCU_SCP_EN */ +#define AFE_CUSTOM_IRQ_SCP_EN_SFT 0 +#define AFE_CUSTOM_IRQ_SCP_EN_MASK 0xffffffff +#define AFE_CUSTOM_IRQ_SCP_EN_MASK_SFT (0xffffffff << 0) + +/* AFE_IRQ_MCU_STATUS */ +#define IRQ26_MCU_SFT 26 +#define IRQ26_MCU_MASK 0x1 +#define IRQ26_MCU_MASK_SFT (0x1 << 26) +#define IRQ25_MCU_SFT 25 +#define IRQ25_MCU_MASK 0x1 +#define IRQ25_MCU_MASK_SFT (0x1 << 25) +#define IRQ24_MCU_SFT 24 +#define IRQ24_MCU_MASK 0x1 +#define IRQ24_MCU_MASK_SFT (0x1 << 24) +#define IRQ23_MCU_SFT 23 +#define IRQ23_MCU_MASK 0x1 +#define IRQ23_MCU_MASK_SFT (0x1 << 23) +#define IRQ22_MCU_SFT 22 +#define IRQ22_MCU_MASK 0x1 +#define IRQ22_MCU_MASK_SFT (0x1 << 22) +#define IRQ21_MCU_SFT 21 +#define IRQ21_MCU_MASK 0x1 +#define IRQ21_MCU_MASK_SFT (0x1 << 21) +#define IRQ20_MCU_SFT 20 +#define IRQ20_MCU_MASK 0x1 +#define IRQ20_MCU_MASK_SFT (0x1 << 20) +#define IRQ19_MCU_SFT 19 +#define IRQ19_MCU_MASK 0x1 +#define IRQ19_MCU_MASK_SFT (0x1 << 19) +#define IRQ18_MCU_SFT 18 +#define IRQ18_MCU_MASK 0x1 +#define IRQ18_MCU_MASK_SFT (0x1 << 18) +#define IRQ17_MCU_SFT 17 +#define IRQ17_MCU_MASK 0x1 +#define IRQ17_MCU_MASK_SFT (0x1 << 17) +#define IRQ16_MCU_SFT 16 +#define IRQ16_MCU_MASK 0x1 +#define IRQ16_MCU_MASK_SFT (0x1 << 16) +#define IRQ15_MCU_SFT 15 +#define IRQ15_MCU_MASK 0x1 +#define IRQ15_MCU_MASK_SFT (0x1 << 15) +#define IRQ14_MCU_SFT 14 +#define IRQ14_MCU_MASK 0x1 +#define IRQ14_MCU_MASK_SFT (0x1 << 14) +#define IRQ13_MCU_SFT 13 +#define IRQ13_MCU_MASK 0x1 +#define IRQ13_MCU_MASK_SFT (0x1 << 13) +#define IRQ12_MCU_SFT 12 +#define IRQ12_MCU_MASK 0x1 +#define IRQ12_MCU_MASK_SFT (0x1 << 12) +#define IRQ11_MCU_SFT 11 +#define IRQ11_MCU_MASK 0x1 +#define IRQ11_MCU_MASK_SFT (0x1 << 11) +#define IRQ10_MCU_SFT 10 +#define IRQ10_MCU_MASK 0x1 +#define IRQ10_MCU_MASK_SFT (0x1 << 10) +#define IRQ9_MCU_SFT 9 +#define IRQ9_MCU_MASK 0x1 +#define IRQ9_MCU_MASK_SFT (0x1 << 9) +#define IRQ8_MCU_SFT 8 +#define IRQ8_MCU_MASK 0x1 +#define IRQ8_MCU_MASK_SFT (0x1 << 8) +#define IRQ7_MCU_SFT 7 +#define IRQ7_MCU_MASK 0x1 +#define IRQ7_MCU_MASK_SFT (0x1 << 7) +#define IRQ6_MCU_SFT 6 +#define IRQ6_MCU_MASK 0x1 +#define IRQ6_MCU_MASK_SFT (0x1 << 6) +#define IRQ5_MCU_SFT 5 +#define IRQ5_MCU_MASK 0x1 +#define IRQ5_MCU_MASK_SFT (0x1 << 5) +#define IRQ4_MCU_SFT 4 +#define IRQ4_MCU_MASK 0x1 +#define IRQ4_MCU_MASK_SFT (0x1 << 4) +#define IRQ3_MCU_SFT 3 +#define IRQ3_MCU_MASK 0x1 +#define IRQ3_MCU_MASK_SFT (0x1 << 3) +#define IRQ2_MCU_SFT 2 +#define IRQ2_MCU_MASK 0x1 +#define IRQ2_MCU_MASK_SFT (0x1 << 2) +#define IRQ1_MCU_SFT 1 +#define IRQ1_MCU_MASK 0x1 +#define IRQ1_MCU_MASK_SFT (0x1 << 1) +#define IRQ0_MCU_SFT 0 +#define IRQ0_MCU_MASK 0x1 +#define IRQ0_MCU_MASK_SFT (0x1 << 0) + +/* AFE_CUSTOM_IRQ_MCU_STATUS */ +#define CUSTOM_IRQ21_MCU_SFT 21 +#define CUSTOM_IRQ21_MCU_MASK 0x1 +#define CUSTOM_IRQ21_MCU_MASK_SFT (0x1 << 21) +#define CUSTOM_IRQ20_MCU_SFT 20 +#define CUSTOM_IRQ20_MCU_MASK 0x1 +#define CUSTOM_IRQ20_MCU_MASK_SFT (0x1 << 20) +#define CUSTOM_IRQ19_MCU_SFT 19 +#define CUSTOM_IRQ19_MCU_MASK 0x1 +#define CUSTOM_IRQ19_MCU_MASK_SFT (0x1 << 19) +#define CUSTOM_IRQ18_MCU_SFT 18 +#define CUSTOM_IRQ18_MCU_MASK 0x1 +#define CUSTOM_IRQ18_MCU_MASK_SFT (0x1 << 18) +#define CUSTOM_IRQ17_MCU_SFT 17 +#define CUSTOM_IRQ17_MCU_MASK 0x1 +#define CUSTOM_IRQ17_MCU_MASK_SFT (0x1 << 17) +#define CUSTOM_IRQ16_MCU_SFT 16 +#define CUSTOM_IRQ16_MCU_MASK 0x1 +#define CUSTOM_IRQ16_MCU_MASK_SFT (0x1 << 16) +#define CUSTOM_IRQ9_MCU_SFT 9 +#define CUSTOM_IRQ9_MCU_MASK 0x1 +#define CUSTOM_IRQ9_MCU_MASK_SFT (0x1 << 9) +#define CUSTOM_IRQ8_MCU_SFT 8 +#define CUSTOM_IRQ8_MCU_MASK 0x1 +#define CUSTOM_IRQ8_MCU_MASK_SFT (0x1 << 8) +#define CUSTOM_IRQ7_MCU_SFT 7 +#define CUSTOM_IRQ7_MCU_MASK 0x1 +#define CUSTOM_IRQ7_MCU_MASK_SFT (0x1 << 7) +#define CUSTOM_IRQ6_MCU_SFT 6 +#define CUSTOM_IRQ6_MCU_MASK 0x1 +#define CUSTOM_IRQ6_MCU_MASK_SFT (0x1 << 6) +#define CUSTOM_IRQ5_MCU_SFT 5 +#define CUSTOM_IRQ5_MCU_MASK 0x1 +#define CUSTOM_IRQ5_MCU_MASK_SFT (0x1 << 5) +#define CUSTOM_IRQ4_MCU_SFT 4 +#define CUSTOM_IRQ4_MCU_MASK 0x1 +#define CUSTOM_IRQ4_MCU_MASK_SFT (0x1 << 4) +#define CUSTOM_IRQ3_MCU_SFT 3 +#define CUSTOM_IRQ3_MCU_MASK 0x1 +#define CUSTOM_IRQ3_MCU_MASK_SFT (0x1 << 3) +#define CUSTOM_IRQ2_MCU_SFT 2 +#define CUSTOM_IRQ2_MCU_MASK 0x1 +#define CUSTOM_IRQ2_MCU_MASK_SFT (0x1 << 2) +#define CUSTOM_IRQ1_MCU_SFT 1 +#define CUSTOM_IRQ1_MCU_MASK 0x1 +#define CUSTOM_IRQ1_MCU_MASK_SFT (0x1 << 1) +#define CUSTOM_IRQ0_MCU_SFT 0 +#define CUSTOM_IRQ0_MCU_MASK 0x1 +#define CUSTOM_IRQ0_MCU_MASK_SFT (0x1 << 0) + +/* AFE_IRQ_MCU_CFG */ +#define AFE_IRQ_CLR_CFG_SFT 31 +#define AFE_IRQ_CLR_CFG_MASK 0x1 +#define AFE_IRQ_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ_MCU_CNT_SFT 0 +#define AFE_IRQ_MCU_CNT_MASK 0xffffff +#define AFE_IRQ_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ0_MCU_CFG0 */ +#define AFE_IRQ0_MCU_DOMAIN_SFT 9 +#define AFE_IRQ0_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ0_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ0_MCU_FS_SFT 4 +#define AFE_IRQ0_MCU_FS_MASK 0x1f +#define AFE_IRQ0_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ0_MCU_ON_SFT 0 +#define AFE_IRQ0_MCU_ON_MASK 0x1 +#define AFE_IRQ0_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ0_MCU_CFG1 */ +#define AFE_IRQ0_CLR_CFG_SFT 31 +#define AFE_IRQ0_CLR_CFG_MASK 0x1 +#define AFE_IRQ0_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ0_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ0_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ0_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ0_MCU_CNT_SFT 0 +#define AFE_IRQ0_MCU_CNT_MASK 0xffffff +#define AFE_IRQ0_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ1_MCU_CFG0 */ +#define AFE_IRQ1_MCU_DOMAIN_SFT 9 +#define AFE_IRQ1_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ1_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ1_MCU_FS_SFT 4 +#define AFE_IRQ1_MCU_FS_MASK 0x1f +#define AFE_IRQ1_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ1_MCU_ON_SFT 0 +#define AFE_IRQ1_MCU_ON_MASK 0x1 +#define AFE_IRQ1_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ1_MCU_CFG1 */ +#define AFE_IRQ1_CLR_CFG_SFT 31 +#define AFE_IRQ1_CLR_CFG_MASK 0x1 +#define AFE_IRQ1_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ1_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ1_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ1_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ1_MCU_CNT_SFT 0 +#define AFE_IRQ1_MCU_CNT_MASK 0xffffff +#define AFE_IRQ1_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ2_MCU_CFG0 */ +#define AFE_IRQ2_MCU_DOMAIN_SFT 9 +#define AFE_IRQ2_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ2_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ2_MCU_FS_SFT 4 +#define AFE_IRQ2_MCU_FS_MASK 0x1f +#define AFE_IRQ2_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ2_MCU_ON_SFT 0 +#define AFE_IRQ2_MCU_ON_MASK 0x1 +#define AFE_IRQ2_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ2_MCU_CFG1 */ +#define AFE_IRQ2_CLR_CFG_SFT 31 +#define AFE_IRQ2_CLR_CFG_MASK 0x1 +#define AFE_IRQ2_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ2_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ2_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ2_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ2_MCU_CNT_SFT 0 +#define AFE_IRQ2_MCU_CNT_MASK 0xffffff +#define AFE_IRQ2_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ3_MCU_CFG0 */ +#define AFE_IRQ3_MCU_DOMAIN_SFT 9 +#define AFE_IRQ3_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ3_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ3_MCU_FS_SFT 4 +#define AFE_IRQ3_MCU_FS_MASK 0x1f +#define AFE_IRQ3_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ3_MCU_ON_SFT 0 +#define AFE_IRQ3_MCU_ON_MASK 0x1 +#define AFE_IRQ3_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ3_MCU_CFG1 */ +#define AFE_IRQ3_CLR_CFG_SFT 31 +#define AFE_IRQ3_CLR_CFG_MASK 0x1 +#define AFE_IRQ3_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ3_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ3_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ3_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ3_MCU_CNT_SFT 0 +#define AFE_IRQ3_MCU_CNT_MASK 0xffffff +#define AFE_IRQ3_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ4_MCU_CFG0 */ +#define AFE_IRQ4_MCU_DOMAIN_SFT 9 +#define AFE_IRQ4_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ4_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ4_MCU_FS_SFT 4 +#define AFE_IRQ4_MCU_FS_MASK 0x1f +#define AFE_IRQ4_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ4_MCU_ON_SFT 0 +#define AFE_IRQ4_MCU_ON_MASK 0x1 +#define AFE_IRQ4_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ4_MCU_CFG1 */ +#define AFE_IRQ4_CLR_CFG_SFT 31 +#define AFE_IRQ4_CLR_CFG_MASK 0x1 +#define AFE_IRQ4_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ4_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ4_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ4_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ4_MCU_CNT_SFT 0 +#define AFE_IRQ4_MCU_CNT_MASK 0xffffff +#define AFE_IRQ4_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ5_MCU_CFG0 */ +#define AFE_IRQ5_MCU_DOMAIN_SFT 9 +#define AFE_IRQ5_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ5_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ5_MCU_FS_SFT 4 +#define AFE_IRQ5_MCU_FS_MASK 0x1f +#define AFE_IRQ5_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ5_MCU_ON_SFT 0 +#define AFE_IRQ5_MCU_ON_MASK 0x1 +#define AFE_IRQ5_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ5_MCU_CFG1 */ +#define AFE_IRQ5_CLR_CFG_SFT 31 +#define AFE_IRQ5_CLR_CFG_MASK 0x1 +#define AFE_IRQ5_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ5_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ5_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ5_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ5_MCU_CNT_SFT 0 +#define AFE_IRQ5_MCU_CNT_MASK 0xffffff +#define AFE_IRQ5_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ6_MCU_CFG0 */ +#define AFE_IRQ6_MCU_DOMAIN_SFT 9 +#define AFE_IRQ6_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ6_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ6_MCU_FS_SFT 4 +#define AFE_IRQ6_MCU_FS_MASK 0x1f +#define AFE_IRQ6_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ6_MCU_ON_SFT 0 +#define AFE_IRQ6_MCU_ON_MASK 0x1 +#define AFE_IRQ6_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ6_MCU_CFG1 */ +#define AFE_IRQ6_CLR_CFG_SFT 31 +#define AFE_IRQ6_CLR_CFG_MASK 0x1 +#define AFE_IRQ6_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ6_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ6_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ6_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ6_MCU_CNT_SFT 0 +#define AFE_IRQ6_MCU_CNT_MASK 0xffffff +#define AFE_IRQ6_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ7_MCU_CFG0 */ +#define AFE_IRQ7_MCU_DOMAIN_SFT 9 +#define AFE_IRQ7_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ7_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ7_MCU_FS_SFT 4 +#define AFE_IRQ7_MCU_FS_MASK 0x1f +#define AFE_IRQ7_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ7_MCU_ON_SFT 0 +#define AFE_IRQ7_MCU_ON_MASK 0x1 +#define AFE_IRQ7_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ7_MCU_CFG1 */ +#define AFE_IRQ7_CLR_CFG_SFT 31 +#define AFE_IRQ7_CLR_CFG_MASK 0x1 +#define AFE_IRQ7_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ7_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ7_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ7_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ7_MCU_CNT_SFT 0 +#define AFE_IRQ7_MCU_CNT_MASK 0xffffff +#define AFE_IRQ7_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ8_MCU_CFG0 */ +#define AFE_IRQ8_MCU_DOMAIN_SFT 9 +#define AFE_IRQ8_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ8_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ8_MCU_FS_SFT 4 +#define AFE_IRQ8_MCU_FS_MASK 0x1f +#define AFE_IRQ8_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ8_MCU_ON_SFT 0 +#define AFE_IRQ8_MCU_ON_MASK 0x1 +#define AFE_IRQ8_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ8_MCU_CFG1 */ +#define AFE_IRQ8_CLR_CFG_SFT 31 +#define AFE_IRQ8_CLR_CFG_MASK 0x1 +#define AFE_IRQ8_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ8_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ8_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ8_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ8_MCU_CNT_SFT 0 +#define AFE_IRQ8_MCU_CNT_MASK 0xffffff +#define AFE_IRQ8_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ9_MCU_CFG0 */ +#define AFE_IRQ9_MCU_DOMAIN_SFT 9 +#define AFE_IRQ9_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ9_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ9_MCU_FS_SFT 4 +#define AFE_IRQ9_MCU_FS_MASK 0x1f +#define AFE_IRQ9_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ9_MCU_ON_SFT 0 +#define AFE_IRQ9_MCU_ON_MASK 0x1 +#define AFE_IRQ9_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ9_MCU_CFG1 */ +#define AFE_IRQ9_CLR_CFG_SFT 31 +#define AFE_IRQ9_CLR_CFG_MASK 0x1 +#define AFE_IRQ9_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ9_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ9_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ9_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ9_MCU_CNT_SFT 0 +#define AFE_IRQ9_MCU_CNT_MASK 0xffffff +#define AFE_IRQ9_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ10_MCU_CFG0 */ +#define AFE_IRQ10_MCU_DOMAIN_SFT 9 +#define AFE_IRQ10_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ10_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ10_MCU_FS_SFT 4 +#define AFE_IRQ10_MCU_FS_MASK 0x1f +#define AFE_IRQ10_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ10_MCU_ON_SFT 0 +#define AFE_IRQ10_MCU_ON_MASK 0x1 +#define AFE_IRQ10_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ10_MCU_CFG1 */ +#define AFE_IRQ10_CLR_CFG_SFT 31 +#define AFE_IRQ10_CLR_CFG_MASK 0x1 +#define AFE_IRQ10_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ10_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ10_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ10_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ10_MCU_CNT_SFT 0 +#define AFE_IRQ10_MCU_CNT_MASK 0xffffff +#define AFE_IRQ10_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ11_MCU_CFG0 */ +#define AFE_IRQ11_MCU_DOMAIN_SFT 9 +#define AFE_IRQ11_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ11_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ11_MCU_FS_SFT 4 +#define AFE_IRQ11_MCU_FS_MASK 0x1f +#define AFE_IRQ11_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ11_MCU_ON_SFT 0 +#define AFE_IRQ11_MCU_ON_MASK 0x1 +#define AFE_IRQ11_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ11_MCU_CFG1 */ +#define AFE_IRQ11_CLR_CFG_SFT 31 +#define AFE_IRQ11_CLR_CFG_MASK 0x1 +#define AFE_IRQ11_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ11_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ11_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ11_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ11_MCU_CNT_SFT 0 +#define AFE_IRQ11_MCU_CNT_MASK 0xffffff +#define AFE_IRQ11_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ12_MCU_CFG0 */ +#define AFE_IRQ12_MCU_DOMAIN_SFT 9 +#define AFE_IRQ12_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ12_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ12_MCU_FS_SFT 4 +#define AFE_IRQ12_MCU_FS_MASK 0x1f +#define AFE_IRQ12_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ12_MCU_ON_SFT 0 +#define AFE_IRQ12_MCU_ON_MASK 0x1 +#define AFE_IRQ12_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ12_MCU_CFG1 */ +#define AFE_IRQ12_CLR_CFG_SFT 31 +#define AFE_IRQ12_CLR_CFG_MASK 0x1 +#define AFE_IRQ12_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ12_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ12_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ12_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ12_MCU_CNT_SFT 0 +#define AFE_IRQ12_MCU_CNT_MASK 0xffffff +#define AFE_IRQ12_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ13_MCU_CFG0 */ +#define AFE_IRQ13_MCU_DOMAIN_SFT 9 +#define AFE_IRQ13_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ13_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ13_MCU_FS_SFT 4 +#define AFE_IRQ13_MCU_FS_MASK 0x1f +#define AFE_IRQ13_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ13_MCU_ON_SFT 0 +#define AFE_IRQ13_MCU_ON_MASK 0x1 +#define AFE_IRQ13_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ13_MCU_CFG1 */ +#define AFE_IRQ13_CLR_CFG_SFT 31 +#define AFE_IRQ13_CLR_CFG_MASK 0x1 +#define AFE_IRQ13_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ13_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ13_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ13_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ13_MCU_CNT_SFT 0 +#define AFE_IRQ13_MCU_CNT_MASK 0xffffff +#define AFE_IRQ13_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ14_MCU_CFG0 */ +#define AFE_IRQ14_MCU_DOMAIN_SFT 9 +#define AFE_IRQ14_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ14_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ14_MCU_FS_SFT 4 +#define AFE_IRQ14_MCU_FS_MASK 0x1f +#define AFE_IRQ14_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ14_MCU_ON_SFT 0 +#define AFE_IRQ14_MCU_ON_MASK 0x1 +#define AFE_IRQ14_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ14_MCU_CFG1 */ +#define AFE_IRQ14_CLR_CFG_SFT 31 +#define AFE_IRQ14_CLR_CFG_MASK 0x1 +#define AFE_IRQ14_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ14_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ14_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ14_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ14_MCU_CNT_SFT 0 +#define AFE_IRQ14_MCU_CNT_MASK 0xffffff +#define AFE_IRQ14_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ15_MCU_CFG0 */ +#define AFE_IRQ15_MCU_DOMAIN_SFT 9 +#define AFE_IRQ15_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ15_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ15_MCU_FS_SFT 4 +#define AFE_IRQ15_MCU_FS_MASK 0x1f +#define AFE_IRQ15_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ15_MCU_ON_SFT 0 +#define AFE_IRQ15_MCU_ON_MASK 0x1 +#define AFE_IRQ15_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ15_MCU_CFG1 */ +#define AFE_IRQ15_CLR_CFG_SFT 31 +#define AFE_IRQ15_CLR_CFG_MASK 0x1 +#define AFE_IRQ15_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ15_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ15_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ15_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ15_MCU_CNT_SFT 0 +#define AFE_IRQ15_MCU_CNT_MASK 0xffffff +#define AFE_IRQ15_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ16_MCU_CFG0 */ +#define AFE_IRQ16_MCU_DOMAIN_SFT 9 +#define AFE_IRQ16_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ16_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ16_MCU_FS_SFT 4 +#define AFE_IRQ16_MCU_FS_MASK 0x1f +#define AFE_IRQ16_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ16_MCU_ON_SFT 0 +#define AFE_IRQ16_MCU_ON_MASK 0x1 +#define AFE_IRQ16_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ16_MCU_CFG1 */ +#define AFE_IRQ16_CLR_CFG_SFT 31 +#define AFE_IRQ16_CLR_CFG_MASK 0x1 +#define AFE_IRQ16_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ16_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ16_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ16_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ16_MCU_CNT_SFT 0 +#define AFE_IRQ16_MCU_CNT_MASK 0xffffff +#define AFE_IRQ16_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ17_MCU_CFG0 */ +#define AFE_IRQ17_MCU_DOMAIN_SFT 9 +#define AFE_IRQ17_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ17_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ17_MCU_FS_SFT 4 +#define AFE_IRQ17_MCU_FS_MASK 0x1f +#define AFE_IRQ17_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ17_MCU_ON_SFT 0 +#define AFE_IRQ17_MCU_ON_MASK 0x1 +#define AFE_IRQ17_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ17_MCU_CFG1 */ +#define AFE_IRQ17_CLR_CFG_SFT 31 +#define AFE_IRQ17_CLR_CFG_MASK 0x1 +#define AFE_IRQ17_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ17_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ17_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ17_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ17_MCU_CNT_SFT 0 +#define AFE_IRQ17_MCU_CNT_MASK 0xffffff +#define AFE_IRQ17_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ18_MCU_CFG0 */ +#define AFE_IRQ18_MCU_DOMAIN_SFT 9 +#define AFE_IRQ18_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ18_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ18_MCU_FS_SFT 4 +#define AFE_IRQ18_MCU_FS_MASK 0x1f +#define AFE_IRQ18_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ18_MCU_ON_SFT 0 +#define AFE_IRQ18_MCU_ON_MASK 0x1 +#define AFE_IRQ18_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ18_MCU_CFG1 */ +#define AFE_IRQ18_CLR_CFG_SFT 31 +#define AFE_IRQ18_CLR_CFG_MASK 0x1 +#define AFE_IRQ18_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ18_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ18_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ18_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ18_MCU_CNT_SFT 0 +#define AFE_IRQ18_MCU_CNT_MASK 0xffffff +#define AFE_IRQ18_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ19_MCU_CFG0 */ +#define AFE_IRQ19_MCU_DOMAIN_SFT 9 +#define AFE_IRQ19_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ19_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ19_MCU_FS_SFT 4 +#define AFE_IRQ19_MCU_FS_MASK 0x1f +#define AFE_IRQ19_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ19_MCU_ON_SFT 0 +#define AFE_IRQ19_MCU_ON_MASK 0x1 +#define AFE_IRQ19_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ19_MCU_CFG1 */ +#define AFE_IRQ19_CLR_CFG_SFT 31 +#define AFE_IRQ19_CLR_CFG_MASK 0x1 +#define AFE_IRQ19_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ19_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ19_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ19_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ19_MCU_CNT_SFT 0 +#define AFE_IRQ19_MCU_CNT_MASK 0xffffff +#define AFE_IRQ19_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ20_MCU_CFG0 */ +#define AFE_IRQ20_MCU_DOMAIN_SFT 9 +#define AFE_IRQ20_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ20_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ20_MCU_FS_SFT 4 +#define AFE_IRQ20_MCU_FS_MASK 0x1f +#define AFE_IRQ20_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ20_MCU_ON_SFT 0 +#define AFE_IRQ20_MCU_ON_MASK 0x1 +#define AFE_IRQ20_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ20_MCU_CFG1 */ +#define AFE_IRQ20_CLR_CFG_SFT 31 +#define AFE_IRQ20_CLR_CFG_MASK 0x1 +#define AFE_IRQ20_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ20_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ20_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ20_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ20_MCU_CNT_SFT 0 +#define AFE_IRQ20_MCU_CNT_MASK 0xffffff +#define AFE_IRQ20_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ21_MCU_CFG0 */ +#define AFE_IRQ21_MCU_DOMAIN_SFT 9 +#define AFE_IRQ21_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ21_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ21_MCU_FS_SFT 4 +#define AFE_IRQ21_MCU_FS_MASK 0x1f +#define AFE_IRQ21_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ21_MCU_ON_SFT 0 +#define AFE_IRQ21_MCU_ON_MASK 0x1 +#define AFE_IRQ21_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ21_MCU_CFG1 */ +#define AFE_IRQ21_CLR_CFG_SFT 31 +#define AFE_IRQ21_CLR_CFG_MASK 0x1 +#define AFE_IRQ21_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ21_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ21_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ21_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ21_MCU_CNT_SFT 0 +#define AFE_IRQ21_MCU_CNT_MASK 0xffffff +#define AFE_IRQ21_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ22_MCU_CFG0 */ +#define AFE_IRQ22_MCU_DOMAIN_SFT 9 +#define AFE_IRQ22_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ22_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ22_MCU_FS_SFT 4 +#define AFE_IRQ22_MCU_FS_MASK 0x1f +#define AFE_IRQ22_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ22_MCU_ON_SFT 0 +#define AFE_IRQ22_MCU_ON_MASK 0x1 +#define AFE_IRQ22_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ22_MCU_CFG1 */ +#define AFE_IRQ22_CLR_CFG_SFT 31 +#define AFE_IRQ22_CLR_CFG_MASK 0x1 +#define AFE_IRQ22_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ22_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ22_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ22_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ22_MCU_CNT_SFT 0 +#define AFE_IRQ22_MCU_CNT_MASK 0xffffff +#define AFE_IRQ22_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ23_MCU_CFG0 */ +#define AFE_IRQ23_MCU_DOMAIN_SFT 9 +#define AFE_IRQ23_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ23_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ23_MCU_FS_SFT 4 +#define AFE_IRQ23_MCU_FS_MASK 0x1f +#define AFE_IRQ23_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ23_MCU_ON_SFT 0 +#define AFE_IRQ23_MCU_ON_MASK 0x1 +#define AFE_IRQ23_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ23_MCU_CFG1 */ +#define AFE_IRQ23_CLR_CFG_SFT 31 +#define AFE_IRQ23_CLR_CFG_MASK 0x1 +#define AFE_IRQ23_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ23_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ23_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ23_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ23_MCU_CNT_SFT 0 +#define AFE_IRQ23_MCU_CNT_MASK 0xffffff +#define AFE_IRQ23_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ24_MCU_CFG0 */ +#define AFE_IRQ24_MCU_DOMAIN_SFT 9 +#define AFE_IRQ24_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ24_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ24_MCU_FS_SFT 4 +#define AFE_IRQ24_MCU_FS_MASK 0x1f +#define AFE_IRQ24_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ24_MCU_ON_SFT 0 +#define AFE_IRQ24_MCU_ON_MASK 0x1 +#define AFE_IRQ24_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ24_MCU_CFG1 */ +#define AFE_IRQ24_CLR_CFG_SFT 31 +#define AFE_IRQ24_CLR_CFG_MASK 0x1 +#define AFE_IRQ24_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ24_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ24_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ24_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ24_MCU_CNT_SFT 0 +#define AFE_IRQ24_MCU_CNT_MASK 0xffffff +#define AFE_IRQ24_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ25_MCU_CFG0 */ +#define AFE_IRQ25_MCU_DOMAIN_SFT 9 +#define AFE_IRQ25_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ25_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ25_MCU_FS_SFT 4 +#define AFE_IRQ25_MCU_FS_MASK 0x1f +#define AFE_IRQ25_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ25_MCU_ON_SFT 0 +#define AFE_IRQ25_MCU_ON_MASK 0x1 +#define AFE_IRQ25_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ25_MCU_CFG1 */ +#define AFE_IRQ25_CLR_CFG_SFT 31 +#define AFE_IRQ25_CLR_CFG_MASK 0x1 +#define AFE_IRQ25_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ25_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ25_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ25_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ25_MCU_CNT_SFT 0 +#define AFE_IRQ25_MCU_CNT_MASK 0xffffff +#define AFE_IRQ25_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ26_MCU_CFG0 */ +#define AFE_IRQ26_MCU_DOMAIN_SFT 9 +#define AFE_IRQ26_MCU_DOMAIN_MASK 0x7 +#define AFE_IRQ26_MCU_DOMAIN_MASK_SFT (0x7 << 9) +#define AFE_IRQ26_MCU_FS_SFT 4 +#define AFE_IRQ26_MCU_FS_MASK 0x1f +#define AFE_IRQ26_MCU_FS_MASK_SFT (0x1f << 4) +#define AFE_IRQ26_MCU_ON_SFT 0 +#define AFE_IRQ26_MCU_ON_MASK 0x1 +#define AFE_IRQ26_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ26_MCU_CFG1 */ +#define AFE_IRQ26_CLR_CFG_SFT 31 +#define AFE_IRQ26_CLR_CFG_MASK 0x1 +#define AFE_IRQ26_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_IRQ26_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_IRQ26_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_IRQ26_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_IRQ26_MCU_CNT_SFT 0 +#define AFE_IRQ26_MCU_CNT_MASK 0xffffff +#define AFE_IRQ26_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_CUSTOM_IRQ0_MCU_CFG0 */ +#define AFE_CUSTOM_IRQ0_MCU_ON_SFT 0 +#define AFE_CUSTOM_IRQ0_MCU_ON_MASK 0x1 +#define AFE_CUSTOM_IRQ0_MCU_ON_MASK_SFT (0x1 << 0) + +/* AFE_IRQ_MCU_MON0 */ +#define AFE_IRQ26_MISS_FLAG_SFT 26 +#define AFE_IRQ26_MISS_FLAG_MASK 0x1 +#define AFE_IRQ26_MISS_FLAG_MASK_SFT (0x1 << 26) +#define AFE_IRQ25_MISS_FLAG_SFT 25 +#define AFE_IRQ25_MISS_FLAG_MASK 0x1 +#define AFE_IRQ25_MISS_FLAG_MASK_SFT (0x1 << 25) +#define AFE_IRQ24_MISS_FLAG_SFT 24 +#define AFE_IRQ24_MISS_FLAG_MASK 0x1 +#define AFE_IRQ24_MISS_FLAG_MASK_SFT (0x1 << 24) +#define AFE_IRQ23_MISS_FLAG_SFT 23 +#define AFE_IRQ23_MISS_FLAG_MASK 0x1 +#define AFE_IRQ23_MISS_FLAG_MASK_SFT (0x1 << 23) +#define AFE_IRQ22_MISS_FLAG_SFT 22 +#define AFE_IRQ22_MISS_FLAG_MASK 0x1 +#define AFE_IRQ22_MISS_FLAG_MASK_SFT (0x1 << 22) +#define AFE_IRQ21_MISS_FLAG_SFT 21 +#define AFE_IRQ21_MISS_FLAG_MASK 0x1 +#define AFE_IRQ21_MISS_FLAG_MASK_SFT (0x1 << 21) +#define AFE_IRQ20_MISS_FLAG_SFT 20 +#define AFE_IRQ20_MISS_FLAG_MASK 0x1 +#define AFE_IRQ20_MISS_FLAG_MASK_SFT (0x1 << 20) +#define AFE_IRQ19_MISS_FLAG_SFT 19 +#define AFE_IRQ19_MISS_FLAG_MASK 0x1 +#define AFE_IRQ19_MISS_FLAG_MASK_SFT (0x1 << 19) +#define AFE_IRQ18_MISS_FLAG_SFT 18 +#define AFE_IRQ18_MISS_FLAG_MASK 0x1 +#define AFE_IRQ18_MISS_FLAG_MASK_SFT (0x1 << 18) +#define AFE_IRQ17_MISS_FLAG_SFT 17 +#define AFE_IRQ17_MISS_FLAG_MASK 0x1 +#define AFE_IRQ17_MISS_FLAG_MASK_SFT (0x1 << 17) +#define AFE_IRQ16_MISS_FLAG_SFT 16 +#define AFE_IRQ16_MISS_FLAG_MASK 0x1 +#define AFE_IRQ16_MISS_FLAG_MASK_SFT (0x1 << 16) +#define AFE_IRQ15_MISS_FLAG_SFT 15 +#define AFE_IRQ15_MISS_FLAG_MASK 0x1 +#define AFE_IRQ15_MISS_FLAG_MASK_SFT (0x1 << 15) +#define AFE_IRQ14_MISS_FLAG_SFT 14 +#define AFE_IRQ14_MISS_FLAG_MASK 0x1 +#define AFE_IRQ14_MISS_FLAG_MASK_SFT (0x1 << 14) +#define AFE_IRQ13_MISS_FLAG_SFT 13 +#define AFE_IRQ13_MISS_FLAG_MASK 0x1 +#define AFE_IRQ13_MISS_FLAG_MASK_SFT (0x1 << 13) +#define AFE_IRQ12_MISS_FLAG_SFT 12 +#define AFE_IRQ12_MISS_FLAG_MASK 0x1 +#define AFE_IRQ12_MISS_FLAG_MASK_SFT (0x1 << 12) +#define AFE_IRQ11_MISS_FLAG_SFT 11 +#define AFE_IRQ11_MISS_FLAG_MASK 0x1 +#define AFE_IRQ11_MISS_FLAG_MASK_SFT (0x1 << 11) +#define AFE_IRQ10_MISS_FLAG_SFT 10 +#define AFE_IRQ10_MISS_FLAG_MASK 0x1 +#define AFE_IRQ10_MISS_FLAG_MASK_SFT (0x1 << 10) +#define AFE_IRQ9_MISS_FLAG_SFT 9 +#define AFE_IRQ9_MISS_FLAG_MASK 0x1 +#define AFE_IRQ9_MISS_FLAG_MASK_SFT (0x1 << 9) +#define AFE_IRQ8_MISS_FLAG_SFT 8 +#define AFE_IRQ8_MISS_FLAG_MASK 0x1 +#define AFE_IRQ8_MISS_FLAG_MASK_SFT (0x1 << 8) +#define AFE_IRQ7_MISS_FLAG_SFT 7 +#define AFE_IRQ7_MISS_FLAG_MASK 0x1 +#define AFE_IRQ7_MISS_FLAG_MASK_SFT (0x1 << 7) +#define AFE_IRQ6_MISS_FLAG_SFT 6 +#define AFE_IRQ6_MISS_FLAG_MASK 0x1 +#define AFE_IRQ6_MISS_FLAG_MASK_SFT (0x1 << 6) +#define AFE_IRQ5_MISS_FLAG_SFT 5 +#define AFE_IRQ5_MISS_FLAG_MASK 0x1 +#define AFE_IRQ5_MISS_FLAG_MASK_SFT (0x1 << 5) +#define AFE_IRQ4_MISS_FLAG_SFT 4 +#define AFE_IRQ4_MISS_FLAG_MASK 0x1 +#define AFE_IRQ4_MISS_FLAG_MASK_SFT (0x1 << 4) +#define AFE_IRQ3_MISS_FLAG_SFT 3 +#define AFE_IRQ3_MISS_FLAG_MASK 0x1 +#define AFE_IRQ3_MISS_FLAG_MASK_SFT (0x1 << 3) +#define AFE_IRQ2_MISS_FLAG_SFT 2 +#define AFE_IRQ2_MISS_FLAG_MASK 0x1 +#define AFE_IRQ2_MISS_FLAG_MASK_SFT (0x1 << 2) +#define AFE_IRQ1_MISS_FLAG_SFT 1 +#define AFE_IRQ1_MISS_FLAG_MASK 0x1 +#define AFE_IRQ1_MISS_FLAG_MASK_SFT (0x1 << 1) +#define AFE_IRQ0_MISS_FLAG_SFT 0 +#define AFE_IRQ0_MISS_FLAG_MASK 0x1 +#define AFE_IRQ0_MISS_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_IRQ_MCU_MON1 */ +#define AFE_CUSTOM_IRQ21_MISS_FLAG_SFT 21 +#define AFE_CUSTOM_IRQ21_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ21_MISS_FLAG_MASK_SFT (0x1 << 21) +#define AFE_CUSTOM_IRQ20_MISS_FLAG_SFT 20 +#define AFE_CUSTOM_IRQ20_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ20_MISS_FLAG_MASK_SFT (0x1 << 20) +#define AFE_CUSTOM_IRQ19_MISS_FLAG_SFT 19 +#define AFE_CUSTOM_IRQ19_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ19_MISS_FLAG_MASK_SFT (0x1 << 19) +#define AFE_CUSTOM_IRQ18_MISS_FLAG_SFT 18 +#define AFE_CUSTOM_IRQ18_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ18_MISS_FLAG_MASK_SFT (0x1 << 18) +#define AFE_CUSTOM_IRQ17_MISS_FLAG_SFT 17 +#define AFE_CUSTOM_IRQ17_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ17_MISS_FLAG_MASK_SFT (0x1 << 17) +#define AFE_CUSTOM_IRQ16_MISS_FLAG_SFT 16 +#define AFE_CUSTOM_IRQ16_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ16_MISS_FLAG_MASK_SFT (0x1 << 16) +#define AFE_CUSTOM_IRQ9_MISS_FLAG_SFT 9 +#define AFE_CUSTOM_IRQ9_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ9_MISS_FLAG_MASK_SFT (0x1 << 9) +#define AFE_CUSTOM_IRQ8_MISS_FLAG_SFT 8 +#define AFE_CUSTOM_IRQ8_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ8_MISS_FLAG_MASK_SFT (0x1 << 8) +#define AFE_CUSTOM_IRQ7_MISS_FLAG_SFT 7 +#define AFE_CUSTOM_IRQ7_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ7_MISS_FLAG_MASK_SFT (0x1 << 7) +#define AFE_CUSTOM_IRQ6_MISS_FLAG_SFT 6 +#define AFE_CUSTOM_IRQ6_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ6_MISS_FLAG_MASK_SFT (0x1 << 6) +#define AFE_CUSTOM_IRQ5_MISS_FLAG_SFT 5 +#define AFE_CUSTOM_IRQ5_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ5_MISS_FLAG_MASK_SFT (0x1 << 5) +#define AFE_CUSTOM_IRQ4_MISS_FLAG_SFT 4 +#define AFE_CUSTOM_IRQ4_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ4_MISS_FLAG_MASK_SFT (0x1 << 4) +#define AFE_CUSTOM_IRQ3_MISS_FLAG_SFT 3 +#define AFE_CUSTOM_IRQ3_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ3_MISS_FLAG_MASK_SFT (0x1 << 3) +#define AFE_CUSTOM_IRQ2_MISS_FLAG_SFT 2 +#define AFE_CUSTOM_IRQ2_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ2_MISS_FLAG_MASK_SFT (0x1 << 2) +#define AFE_CUSTOM_IRQ1_MISS_FLAG_SFT 1 +#define AFE_CUSTOM_IRQ1_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ1_MISS_FLAG_MASK_SFT (0x1 << 1) +#define AFE_CUSTOM_IRQ0_MISS_FLAG_SFT 0 +#define AFE_CUSTOM_IRQ0_MISS_FLAG_MASK 0x1 +#define AFE_CUSTOM_IRQ0_MISS_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_IRQ_MCU_MON2 */ +#define AFE_IRQ_B_R_CNT_SFT 8 +#define AFE_IRQ_B_R_CNT_MASK 0xff +#define AFE_IRQ_B_R_CNT_MASK_SFT (0xff << 8) +#define AFE_IRQ_B_F_CNT_SFT 0 +#define AFE_IRQ_B_F_CNT_MASK 0xff +#define AFE_IRQ_B_F_CNT_MASK_SFT (0xff << 0) + +/* AFE_IRQ0_CNT_MON */ +#define AFE_IRQ0_CNT_MON_SFT 0 +#define AFE_IRQ0_CNT_MON_MASK 0xffffff +#define AFE_IRQ0_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ1_CNT_MON */ +#define AFE_IRQ1_CNT_MON_SFT 0 +#define AFE_IRQ1_CNT_MON_MASK 0xffffff +#define AFE_IRQ1_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ2_CNT_MON */ +#define AFE_IRQ2_CNT_MON_SFT 0 +#define AFE_IRQ2_CNT_MON_MASK 0xffffff +#define AFE_IRQ2_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ3_CNT_MON */ +#define AFE_IRQ3_CNT_MON_SFT 0 +#define AFE_IRQ3_CNT_MON_MASK 0xffffff +#define AFE_IRQ3_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ4_CNT_MON */ +#define AFE_IRQ4_CNT_MON_SFT 0 +#define AFE_IRQ4_CNT_MON_MASK 0xffffff +#define AFE_IRQ4_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ5_CNT_MON */ +#define AFE_IRQ5_CNT_MON_SFT 0 +#define AFE_IRQ5_CNT_MON_MASK 0xffffff +#define AFE_IRQ5_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ6_CNT_MON */ +#define AFE_IRQ6_CNT_MON_SFT 0 +#define AFE_IRQ6_CNT_MON_MASK 0xffffff +#define AFE_IRQ6_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ7_CNT_MON */ +#define AFE_IRQ7_CNT_MON_SFT 0 +#define AFE_IRQ7_CNT_MON_MASK 0xffffff +#define AFE_IRQ7_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ8_CNT_MON */ +#define AFE_IRQ8_CNT_MON_SFT 0 +#define AFE_IRQ8_CNT_MON_MASK 0xffffff +#define AFE_IRQ8_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ9_CNT_MON */ +#define AFE_IRQ9_CNT_MON_SFT 0 +#define AFE_IRQ9_CNT_MON_MASK 0xffffff +#define AFE_IRQ9_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ10_CNT_MON */ +#define AFE_IRQ10_CNT_MON_SFT 0 +#define AFE_IRQ10_CNT_MON_MASK 0xffffff +#define AFE_IRQ10_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ11_CNT_MON */ +#define AFE_IRQ11_CNT_MON_SFT 0 +#define AFE_IRQ11_CNT_MON_MASK 0xffffff +#define AFE_IRQ11_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ12_CNT_MON */ +#define AFE_IRQ12_CNT_MON_SFT 0 +#define AFE_IRQ12_CNT_MON_MASK 0xffffff +#define AFE_IRQ12_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ13_CNT_MON */ +#define AFE_IRQ13_CNT_MON_SFT 0 +#define AFE_IRQ13_CNT_MON_MASK 0xffffff +#define AFE_IRQ13_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ14_CNT_MON */ +#define AFE_IRQ14_CNT_MON_SFT 0 +#define AFE_IRQ14_CNT_MON_MASK 0xffffff +#define AFE_IRQ14_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ15_CNT_MON */ +#define AFE_IRQ15_CNT_MON_SFT 0 +#define AFE_IRQ15_CNT_MON_MASK 0xffffff +#define AFE_IRQ15_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ16_CNT_MON */ +#define AFE_IRQ16_CNT_MON_SFT 0 +#define AFE_IRQ16_CNT_MON_MASK 0xffffff +#define AFE_IRQ16_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ17_CNT_MON */ +#define AFE_IRQ17_CNT_MON_SFT 0 +#define AFE_IRQ17_CNT_MON_MASK 0xffffff +#define AFE_IRQ17_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ18_CNT_MON */ +#define AFE_IRQ18_CNT_MON_SFT 0 +#define AFE_IRQ18_CNT_MON_MASK 0xffffff +#define AFE_IRQ18_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ19_CNT_MON */ +#define AFE_IRQ19_CNT_MON_SFT 0 +#define AFE_IRQ19_CNT_MON_MASK 0xffffff +#define AFE_IRQ19_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ20_CNT_MON */ +#define AFE_IRQ20_CNT_MON_SFT 0 +#define AFE_IRQ20_CNT_MON_MASK 0xffffff +#define AFE_IRQ20_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ21_CNT_MON */ +#define AFE_IRQ21_CNT_MON_SFT 0 +#define AFE_IRQ21_CNT_MON_MASK 0xffffff +#define AFE_IRQ21_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ22_CNT_MON */ +#define AFE_IRQ22_CNT_MON_SFT 0 +#define AFE_IRQ22_CNT_MON_MASK 0xffffff +#define AFE_IRQ22_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ23_CNT_MON */ +#define AFE_IRQ23_CNT_MON_SFT 0 +#define AFE_IRQ23_CNT_MON_MASK 0xffffff +#define AFE_IRQ23_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ24_CNT_MON */ +#define AFE_IRQ24_CNT_MON_SFT 0 +#define AFE_IRQ24_CNT_MON_MASK 0xffffff +#define AFE_IRQ24_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ25_CNT_MON */ +#define AFE_IRQ25_CNT_MON_SFT 0 +#define AFE_IRQ25_CNT_MON_MASK 0xffffff +#define AFE_IRQ25_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_IRQ26_CNT_MON */ +#define AFE_IRQ26_CNT_MON_SFT 0 +#define AFE_IRQ26_CNT_MON_MASK 0xffffff +#define AFE_IRQ26_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_CUSTOM_IRQ0_CNT_MON */ +#define AFE_CUSTOM_IRQ0_CNT_MON_SFT 0 +#define AFE_CUSTOM_IRQ0_CNT_MON_MASK 0xffffff +#define AFE_CUSTOM_IRQ0_CNT_MON_MASK_SFT (0xffffff << 0) + +/* AFE_CUSTOM_IRQ0_MCU_CFG1 */ +#define AFE_CUSTOM_IRQ0_CLR_CFG_SFT 31 +#define AFE_CUSTOM_IRQ0_CLR_CFG_MASK 0x1 +#define AFE_CUSTOM_IRQ0_CLR_CFG_MASK_SFT (0x1 << 31) +#define AFE_CUSTOM_IRQ0_MISS_FLAG_CLR_CFG_SFT 30 +#define AFE_CUSTOM_IRQ0_MISS_FLAG_CLR_CFG_MASK 0x1 +#define AFE_CUSTOM_IRQ0_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30) +#define AFE_CUSTOM_IRQ0_MCU_CNT_SFT 0 +#define AFE_CUSTOM_IRQ0_MCU_CNT_MASK 0xffffff +#define AFE_CUSTOM_IRQ0_MCU_CNT_MASK_SFT (0xffffff << 0) + +/* AFE_GAIN0_CON1_R */ +/* AFE_GAIN1_CON1_R */ +/* AFE_GAIN2_CON1_R */ +/* AFE_GAIN3_CON1_R */ +#define GAIN_TARGET_R_SFT 0 +#define GAIN_TARGET_R_MASK 0xffffffff +#define GAIN_TARGET_R_MASK_SFT (0xffffffff << 0) + +/* AFE_GAIN0_CON1_L */ +/* AFE_GAIN1_CON1_L */ +/* AFE_GAIN2_CON1_L */ +/* AFE_GAIN3_CON1_L */ +#define GAIN_TARGET_L_SFT 0 +#define GAIN_TARGET_L_MASK 0xffffffff +#define GAIN_TARGET_L_MASK_SFT (0xffffffff << 0) + +/* AFE_GAIN0_CON2 */ +#define GAIN0_DOWN_STEP_SFT 0 +#define GAIN0_DOWN_STEP_MASK 0x3fffff +#define GAIN0_DOWN_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_GAIN0_CON3 */ +#define GAIN0_UP_STEP_SFT 0 +#define GAIN0_UP_STEP_MASK 0x3fffff +#define GAIN0_UP_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_GAIN0_CUR_R */ +/* AFE_GAIN1_CUR_R */ +/* AFE_GAIN2_CUR_R */ +/* AFE_GAIN3_CUR_R */ +#define AFE_GAIN_CUR_R_SFT 0 +#define AFE_GAIN_CUR_R_MASK 0xffffffff +#define AFE_GAIN_CUR_R_MASK_SFT (0xffffffff << 0) + +/* AFE_GAIN0_CUR_L */ +/* AFE_GAIN1_CUR_L */ +/* AFE_GAIN2_CUR_L */ +/* AFE_GAIN3_CUR_L */ +#define AFE_GAIN_CUR_L_SFT 0 +#define AFE_GAIN_CUR_L_MASK 0xffffffff +#define AFE_GAIN_CUR_L_MASK_SFT (0xffffffff << 0) + +/* AFE_GAIN0_CON0 */ +/* AFE_GAIN1_CON0 */ +/* AFE_GAIN2_CON0 */ +/* AFE_GAIN3_CON0 */ +#define GAIN_TARGET_SYNC_ON_SFT 24 +#define GAIN_TARGET_SYNC_ON_MASK 0x1 +#define GAIN_TARGET_SYNC_ON_MASK_SFT (0x1 << 24) +#define GAIN_TIMEOUT_SFT 18 +#define GAIN_TIMEOUT_MASK 0x3f +#define GAIN_TIMEOUT_MASK_SFT (0x3f << 18) +#define GAIN_TRIG_SFT 17 +#define GAIN_TRIG_MASK 0x1 +#define GAIN_TRIG_MASK_SFT (0x1 << 17) +#define GAIN_ON_SFT 16 +#define GAIN_ON_MASK 0x1 +#define GAIN_ON_MASK_SFT (0x1 << 16) +#define GAIN_SAMPLE_PER_STEP_SFT 8 +#define GAIN_SAMPLE_PER_STEP_MASK 0xff +#define GAIN_SAMPLE_PER_STEP_MASK_SFT (0xff << 8) +#define GAIN_SEL_DOMAIN_SFT 5 +#define GAIN_SEL_DOMAIN_MASK 0x7 +#define GAIN_SEL_DOMAIN_MASK_SFT (0x7 << 5) +#define GAIN_SEL_FS_SFT 0 +#define GAIN_SEL_FS_MASK 0x1f +#define GAIN_SEL_FS_MASK_SFT (0x1f << 0) + +/* AFE_GAIN1_CON2 */ +#define GAIN1_DOWN_STEP_SFT 0 +#define GAIN1_DOWN_STEP_MASK 0x3fffff +#define GAIN1_DOWN_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_GAIN1_CON3 */ +#define GAIN1_UP_STEP_SFT 0 +#define GAIN1_UP_STEP_MASK 0x3fffff +#define GAIN1_UP_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_GAIN2_CON2 */ +#define GAIN2_DOWN_STEP_SFT 0 +#define GAIN2_DOWN_STEP_MASK 0x3fffff +#define GAIN2_DOWN_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_GAIN2_CON3 */ +#define GAIN2_UP_STEP_SFT 0 +#define GAIN2_UP_STEP_MASK 0x3fffff +#define GAIN2_UP_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_GAIN3_CON2 */ +#define GAIN3_DOWN_STEP_SFT 0 +#define GAIN3_DOWN_STEP_MASK 0x3fffff +#define GAIN3_DOWN_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_GAIN3_CON3 */ +#define GAIN3_UP_STEP_SFT 0 +#define GAIN3_UP_STEP_MASK 0x3fffff +#define GAIN3_UP_STEP_MASK_SFT (0x3fffff << 0) + +/* AFE_STF_CON0 */ +#define SLT_CNT_FLAG_RESET_SFT 28 +#define SLT_CNT_FLAG_RESET_MASK 0x1 +#define SLT_CNT_FLAG_RESET_MASK_SFT (0x1 << 28) +#define SLT_CNT_THD_SFT 16 +#define SLT_CNT_THD_MASK 0xfff +#define SLT_CNT_THD_MASK_SFT (0xfff << 16) +#define SIDE_TONE_HALF_TAP_NUM_SFT 4 +#define SIDE_TONE_HALF_TAP_NUM_MASK 0x7f +#define SIDE_TONE_HALF_TAP_NUM_MASK_SFT (0x7f << 4) +#define SIDE_TONE_ODD_MODE_SFT 1 +#define SIDE_TONE_ODD_MODE_MASK 0x1 +#define SIDE_TONE_ODD_MODE_MASK_SFT (0x1 << 1) +#define SIDE_TONE_ON_SFT 0 +#define SIDE_TONE_ON_MASK 0x1 +#define SIDE_TONE_ON_MASK_SFT (0x1 << 0) + +/* AFE_STF_CON1 */ +#define SIDE_TONE_IN_EN_SEL_DOMAIN_SFT 5 +#define SIDE_TONE_IN_EN_SEL_DOMAIN_MASK 0x7 +#define SIDE_TONE_IN_EN_SEL_DOMAIN_MASK_SFT (0x7 << 5) +#define SIDE_TONE_IN_EN_SEL_FS_SFT 0 +#define SIDE_TONE_IN_EN_SEL_FS_MASK 0x1f +#define SIDE_TONE_IN_EN_SEL_FS_MASK_SFT (0x1f << 0) + +/* AFE_STF_COEFF */ +#define SIDE_TONE_COEFFICIENT_R_W_SEL_SFT 24 +#define SIDE_TONE_COEFFICIENT_R_W_SEL_MASK 0x1 +#define SIDE_TONE_COEFFICIENT_R_W_SEL_MASK_SFT (0x1 << 24) +#define SIDE_TONE_COEFFICIENT_ADDR_SFT 16 +#define SIDE_TONE_COEFFICIENT_ADDR_MASK 0x1f +#define SIDE_TONE_COEFFICIENT_ADDR_MASK_SFT (0x1f << 16) +#define SIDE_TONE_COEFFICIENT_SFT 0 +#define SIDE_TONE_COEFFICIENT_MASK 0xffff +#define SIDE_TONE_COEFFICIENT_MASK_SFT (0xffff << 0) + +/* AFE_STF_GAIN */ +#define SIDE_TONE_POSITIVE_GAIN_SFT 16 +#define SIDE_TONE_POSITIVE_GAIN_MASK 0x7 +#define SIDE_TONE_POSITIVE_GAIN_MASK_SFT (0x7 << 16) +#define SIDE_TONE_GAIN_SFT 0 +#define SIDE_TONE_GAIN_MASK 0xffff +#define SIDE_TONE_GAIN_MASK_SFT (0xffff << 0) + +/* AFE_STF_MON */ +#define SIDE_TONE_R_RDY_SFT 30 +#define SIDE_TONE_R_RDY_MASK 0x1 +#define SIDE_TONE_R_RDY_MASK_SFT (0x1 << 30) +#define SIDE_TONE_W_RDY_SFT 29 +#define SIDE_TONE_W_RDY_MASK 0x1 +#define SIDE_TONE_W_RDY_MASK_SFT (0x1 << 29) +#define SLT_CNT_FLAG_SFT 28 +#define SLT_CNT_FLAG_MASK 0x1 +#define SLT_CNT_FLAG_MASK_SFT (0x1 << 28) +#define SLT_CNT_SFT 16 +#define SLT_CNT_MASK 0xfff +#define SLT_CNT_MASK_SFT (0xfff << 16) +#define SIDE_TONE_COEFF_SFT 0 +#define SIDE_TONE_COEFF_MASK 0xffff +#define SIDE_TONE_COEFF_MASK_SFT (0xffff << 0) + +/* AFE_STF_IP_VERSION */ +#define SIDE_TONE_IP_VERSION_SFT 0 +#define SIDE_TONE_IP_VERSION_MASK 0xffffffff +#define SIDE_TONE_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_CM_REG */ +#define AFE_CM_UPDATE_CNT_SFT 16 +#define AFE_CM_UPDATE_CNT_MASK 0x7fff +#define AFE_CM_UPDATE_CNT_MASK_SFT (0x7fff << 16) +#define AFE_CM_1X_EN_SEL_FS_SFT 8 +#define AFE_CM_1X_EN_SEL_FS_MASK 0x1f +#define AFE_CM_1X_EN_SEL_FS_MASK_SFT (0x1f << 8) +#define AFE_CM_CH_NUM_SFT 2 +#define AFE_CM_CH_NUM_MASK 0x1f +#define AFE_CM_CH_NUM_MASK_SFT (0x1f << 2) +#define AFE_CM_BYTE_SWAP_SFT 1 +#define AFE_CM_BYTE_SWAP_MASK 0x1 +#define AFE_CM_BYTE_SWAP_MASK_SFT (0x1 << 1) +#define AFE_CM_BYPASS_MODE_SFT 31 +#define AFE_CM_BYPASS_MODE_MASK 0x1 +#define AFE_CM_BYPASS_MODE_MASK_SFT (0x1 << 31) + +/* AFE_CM0_CON0 */ +#define AFE_CM0_BYPASS_MODE_SFT 31 +#define AFE_CM0_BYPASS_MODE_MASK 0x1 +#define AFE_CM0_BYPASS_MODE_MASK_SFT (0x1 << 31) +#define AFE_CM0_UPDATE_CNT_SFT 16 +#define AFE_CM0_UPDATE_CNT_MASK 0x7fff +#define AFE_CM0_UPDATE_CNT_MASK_SFT (0x7fff << 16) +#define AFE_CM0_1X_EN_SEL_DOMAIN_SFT 13 +#define AFE_CM0_1X_EN_SEL_DOMAIN_MASK 0x7 +#define AFE_CM0_1X_EN_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define AFE_CM0_1X_EN_SEL_FS_SFT 8 +#define AFE_CM0_1X_EN_SEL_FS_MASK 0x1f +#define AFE_CM0_1X_EN_SEL_FS_MASK_SFT (0x1f << 8) +#define AFE_CM0_OUTPUT_MUX_SFT 7 +#define AFE_CM0_OUTPUT_MUX_MASK 0x1 +#define AFE_CM0_OUTPUT_MUX_MASK_SFT (0x1 << 7) +#define AFE_CM0_CH_NUM_SFT 2 +#define AFE_CM0_CH_NUM_MASK 0x1f +#define AFE_CM0_CH_NUM_MASK_SFT (0x1f << 2) +#define AFE_CM0_BYTE_SWAP_SFT 1 +#define AFE_CM0_BYTE_SWAP_MASK 0x1 +#define AFE_CM0_BYTE_SWAP_MASK_SFT (0x1 << 1) +#define AFE_CM0_ON_SFT 0 +#define AFE_CM0_ON_MASK 0x1 +#define AFE_CM0_ON_MASK_SFT (0x1 << 0) + +/* AFE_CM0_MON */ +#define AFE_CM0_BYPASS_MODE_MON_SFT 31 +#define AFE_CM0_BYPASS_MODE_MON_MASK 0x1 +#define AFE_CM0_BYPASS_MODE_MON_MASK_SFT (0x1 << 31) +#define AFE_CM0_OUTPUT_CNT_MON_SFT 16 +#define AFE_CM0_OUTPUT_CNT_MON_MASK 0x7fff +#define AFE_CM0_OUTPUT_CNT_MON_MASK_SFT (0x7fff << 16) +#define AFE_CM0_CUR_CHSET_MON_SFT 5 +#define AFE_CM0_CUR_CHSET_MON_MASK 0xf +#define AFE_CM0_CUR_CHSET_MON_MASK_SFT (0xf << 5) +#define AFE_CM0_ODD_FLAG_MON_SFT 4 +#define AFE_CM0_ODD_FLAG_MON_MASK 0x1 +#define AFE_CM0_ODD_FLAG_MON_MASK_SFT (0x1 << 4) +#define AFE_CM0_BYTE_SWAP_MON_SFT 1 +#define AFE_CM0_BYTE_SWAP_MON_MASK 0x1 +#define AFE_CM0_BYTE_SWAP_MON_MASK_SFT (0x1 << 1) +#define AFE_CM0_ON_MON_SFT 0 +#define AFE_CM0_ON_MON_MASK 0x1 +#define AFE_CM0_ON_MON_MASK_SFT (0x1 << 0) + +/* AFE_CM0_IP_VERSION */ +#define AFE_CM0_IP_VERSION_SFT 0 +#define AFE_CM0_IP_VERSION_MASK 0xffffffff +#define AFE_CM0_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_CM1_CON0 */ +#define AFE_CM1_BYPASS_MODE_SFT 31 +#define AFE_CM1_BYPASS_MODE_MASK 0x1 +#define AFE_CM1_BYPASS_MODE_MASK_SFT (0x1 << 31) +#define AFE_CM1_UPDATE_CNT_SFT 16 +#define AFE_CM1_UPDATE_CNT_MASK 0x7fff +#define AFE_CM1_UPDATE_CNT_MASK_SFT (0x7fff << 16) +#define AFE_CM1_1X_EN_SEL_DOMAIN_SFT 13 +#define AFE_CM1_1X_EN_SEL_DOMAIN_MASK 0x7 +#define AFE_CM1_1X_EN_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define AFE_CM1_1X_EN_SEL_FS_SFT 8 +#define AFE_CM1_1X_EN_SEL_FS_MASK 0x1f +#define AFE_CM1_1X_EN_SEL_FS_MASK_SFT (0x1f << 8) +#define AFE_CM1_OUTPUT_MUX_SFT 7 +#define AFE_CM1_OUTPUT_MUX_MASK 0x1 +#define AFE_CM1_OUTPUT_MUX_MASK_SFT (0x1 << 7) +#define AFE_CM1_CH_NUM_SFT 2 +#define AFE_CM1_CH_NUM_MASK 0x1f +#define AFE_CM1_CH_NUM_MASK_SFT (0x1f << 2) +#define AFE_CM1_BYTE_SWAP_SFT 1 +#define AFE_CM1_BYTE_SWAP_MASK 0x1 +#define AFE_CM1_BYTE_SWAP_MASK_SFT (0x1 << 1) +#define AFE_CM1_ON_SFT 0 +#define AFE_CM1_ON_MASK 0x1 +#define AFE_CM1_ON_MASK_SFT (0x1 << 0) + +/* AFE_CM1_MON */ +#define AFE_CM1_BYPASS_MODE_MON_SFT 31 +#define AFE_CM1_BYPASS_MODE_MON_MASK 0x1 +#define AFE_CM1_BYPASS_MODE_MON_MASK_SFT (0x1 << 31) +#define AFE_CM1_OUTPUT_CNT_MON_SFT 16 +#define AFE_CM1_OUTPUT_CNT_MON_MASK 0x7fff +#define AFE_CM1_OUTPUT_CNT_MON_MASK_SFT (0x7fff << 16) +#define AFE_CM1_CUR_CHSET_MON_SFT 5 +#define AFE_CM1_CUR_CHSET_MON_MASK 0xf +#define AFE_CM1_CUR_CHSET_MON_MASK_SFT (0xf << 5) +#define AFE_CM1_ODD_FLAG_MON_SFT 4 +#define AFE_CM1_ODD_FLAG_MON_MASK 0x1 +#define AFE_CM1_ODD_FLAG_MON_MASK_SFT (0x1 << 4) +#define AFE_CM1_BYTE_SWAP_MON_SFT 1 +#define AFE_CM1_BYTE_SWAP_MON_MASK 0x1 +#define AFE_CM1_BYTE_SWAP_MON_MASK_SFT (0x1 << 1) +#define AFE_CM1_ON_MON_SFT 0 +#define AFE_CM1_ON_MON_MASK 0x1 +#define AFE_CM1_ON_MON_MASK_SFT (0x1 << 0) + +/* AFE_CM1_IP_VERSION */ +#define AFE_CM1_IP_VERSION_SFT 0 +#define AFE_CM1_IP_VERSION_MASK 0xffffffff +#define AFE_CM1_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_CM2_CON0 */ +#define AFE_CM2_BYPASS_MODE_SFT 31 +#define AFE_CM2_BYPASS_MODE_MASK 0x1 +#define AFE_CM2_BYPASS_MODE_MASK_SFT (0x1 << 31) +#define AFE_CM2_UPDATE_CNT_SFT 16 +#define AFE_CM2_UPDATE_CNT_MASK 0x7fff +#define AFE_CM2_UPDATE_CNT_MASK_SFT (0x7fff << 16) +#define AFE_CM2_1X_EN_SEL_DOMAIN_SFT 13 +#define AFE_CM2_1X_EN_SEL_DOMAIN_MASK 0x7 +#define AFE_CM2_1X_EN_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define AFE_CM2_1X_EN_SEL_FS_SFT 8 +#define AFE_CM2_1X_EN_SEL_FS_MASK 0x1f +#define AFE_CM2_1X_EN_SEL_FS_MASK_SFT (0x1f << 8) +#define AFE_CM2_OUTPUT_MUX_SFT 7 +#define AFE_CM2_OUTPUT_MUX_MASK 0x1 +#define AFE_CM2_OUTPUT_MUX_MASK_SFT (0x1 << 7) +#define AFE_CM2_CH_NUM_SFT 2 +#define AFE_CM2_CH_NUM_MASK 0x1f +#define AFE_CM2_CH_NUM_MASK_SFT (0x1f << 2) +#define AFE_CM2_BYTE_SWAP_SFT 1 +#define AFE_CM2_BYTE_SWAP_MASK 0x1 +#define AFE_CM2_BYTE_SWAP_MASK_SFT (0x1 << 1) +#define AFE_CM2_ON_SFT 0 +#define AFE_CM2_ON_MASK 0x1 +#define AFE_CM2_ON_MASK_SFT (0x1 << 0) + +/* AFE_CM2_MON */ +#define AFE_CM2_BYPASS_MODE_MON_SFT 31 +#define AFE_CM2_BYPASS_MODE_MON_MASK 0x1 +#define AFE_CM2_BYPASS_MODE_MON_MASK_SFT (0x1 << 31) +#define AFE_CM2_OUTPUT_CNT_MON_SFT 16 +#define AFE_CM2_OUTPUT_CNT_MON_MASK 0x7fff +#define AFE_CM2_OUTPUT_CNT_MON_MASK_SFT (0x7fff << 16) +#define AFE_CM2_CUR_CHSET_MON_SFT 5 +#define AFE_CM2_CUR_CHSET_MON_MASK 0xf +#define AFE_CM2_CUR_CHSET_MON_MASK_SFT (0xf << 5) +#define AFE_CM2_ODD_FLAG_MON_SFT 4 +#define AFE_CM2_ODD_FLAG_MON_MASK 0x1 +#define AFE_CM2_ODD_FLAG_MON_MASK_SFT (0x1 << 4) +#define AFE_CM2_BYTE_SWAP_MON_SFT 1 +#define AFE_CM2_BYTE_SWAP_MON_MASK 0x1 +#define AFE_CM2_BYTE_SWAP_MON_MASK_SFT (0x1 << 1) +#define AFE_CM2_ON_MON_SFT 0 +#define AFE_CM2_ON_MON_MASK 0x1 +#define AFE_CM2_ON_MON_MASK_SFT (0x1 << 0) + +/* AFE_CM2_IP_VERSION */ +#define AFE_CM2_IP_VERSION_SFT 0 +#define AFE_CM2_IP_VERSION_MASK 0xffffffff +#define AFE_CM2_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_SRC_CON0 */ +#define ULCF_CFG_EN_CTL_SFT 31 +#define ULCF_CFG_EN_CTL_MASK 0x1 +#define ULCF_CFG_EN_CTL_MASK_SFT (0x1 << 31) +#define UL_DMIC_PHASE_SEL_CH1_SFT 27 +#define UL_DMIC_PHASE_SEL_CH1_MASK 0x7 +#define UL_DMIC_PHASE_SEL_CH1_MASK_SFT (0x7 << 27) +#define UL_DMIC_PHASE_SEL_CH2_SFT 24 +#define UL_DMIC_PHASE_SEL_CH2_MASK 0x7 +#define UL_DMIC_PHASE_SEL_CH2_MASK_SFT (0x7 << 24) +#define UL_DMIC_TWO_WIRE_CTL_SFT 23 +#define UL_DMIC_TWO_WIRE_CTL_MASK 0x1 +#define UL_DMIC_TWO_WIRE_CTL_MASK_SFT (0x1 << 23) +#define UL_MODE_3P25M_CH2_CTL_SFT 22 +#define UL_MODE_3P25M_CH2_CTL_MASK 0x1 +#define UL_MODE_3P25M_CH2_CTL_MASK_SFT (0x1 << 22) +#define UL_MODE_3P25M_CH1_CTL_SFT 21 +#define UL_MODE_3P25M_CH1_CTL_MASK 0x1 +#define UL_MODE_3P25M_CH1_CTL_MASK_SFT (0x1 << 21) +#define UL_VOICE_MODE_CH1_CH2_CTL_SFT 17 +#define UL_VOICE_MODE_CH1_CH2_CTL_MASK 0x7 +#define UL_VOICE_MODE_CH1_CH2_CTL_MASK_SFT (0x7 << 17) +#define UL_AP_DMIC_ON_SFT 16 +#define UL_AP_DMIC_ON_MASK 0x1 +#define UL_AP_DMIC_ON_MASK_SFT (0x1 << 16) +#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 UL_DISABLE_HW_CG_CTL_SFT 12 +#define UL_DISABLE_HW_CG_CTL_MASK 0x1 +#define UL_DISABLE_HW_CG_CTL_MASK_SFT (0x1 << 12) +#define AMIC_26M_SEL_CTL_SFT 11 +#define AMIC_26M_SEL_CTL_MASK 0x1 +#define AMIC_26M_SEL_CTL_MASK_SFT (0x1 << 11) +#define UL_IIR_ON_TMP_CTL_SFT 10 +#define UL_IIR_ON_TMP_CTL_MASK 0x1 +#define UL_IIR_ON_TMP_CTL_MASK_SFT (0x1 << 10) +#define UL_IIRMODE_CTL_SFT 7 +#define UL_IIRMODE_CTL_MASK 0x7 +#define UL_IIRMODE_CTL_MASK_SFT (0x7 << 7) +#define DIGMIC_4P33M_SEL_SFT 6 +#define DIGMIC_4P33M_SEL_MASK 0x1 +#define DIGMIC_4P33M_SEL_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 AMIC_6P5M_SEL_CTL_SFT 4 +#define AMIC_6P5M_SEL_CTL_MASK 0x1 +#define AMIC_6P5M_SEL_CTL_MASK_SFT (0x1 << 4) +#define AMIC_1P625M_SEL_CTL_SFT 3 +#define AMIC_1P625M_SEL_CTL_MASK 0x1 +#define AMIC_1P625M_SEL_CTL_MASK_SFT (0x1 << 3) +#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_ADDA_UL0_SRC_CON1 */ +#define ADDA_UL_GAIN_VALUE_SFT 16 +#define ADDA_UL_GAIN_VALUE_MASK 0xffff +#define ADDA_UL_GAIN_VALUE_MASK_SFT (0xffff << 16) +#define ADDA_UL_POSTIVEGAIN_SFT 12 +#define ADDA_UL_POSTIVEGAIN_MASK 0x7 +#define ADDA_UL_POSTIVEGAIN_MASK_SFT (0x7 << 12) +#define ADDA_UL_ODDTAP_MODE_SFT 11 +#define ADDA_UL_ODDTAP_MODE_MASK 0x1 +#define ADDA_UL_ODDTAP_MODE_MASK_SFT (0x1 << 11) +#define ADDA_UL_HALF_TAP_NUM_SFT 5 +#define ADDA_UL_HALF_TAP_NUM_MASK 0x3f +#define ADDA_UL_HALF_TAP_NUM_MASK_SFT (0x3f << 5) +#define FIFO_SOFT_RST_SFT 4 +#define FIFO_SOFT_RST_MASK 0x1 +#define FIFO_SOFT_RST_MASK_SFT (0x1 << 4) +#define FIFO_SOFT_RST_EN_SFT 3 +#define FIFO_SOFT_RST_EN_MASK 0x1 +#define FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 3) +#define LR_SWAP_SFT 2 +#define LR_SWAP_MASK 0x1 +#define LR_SWAP_MASK_SFT (0x1 << 2) +#define GAIN_MODE_SFT 0 +#define GAIN_MODE_MASK 0x3 +#define GAIN_MODE_MASK_SFT (0x3 << 0) + +/* AFE_ADDA_UL0_SRC_CON2 */ +#define C_DAC_EN_CTL_SFT 27 +#define C_DAC_EN_CTL_MASK 0x1 +#define C_DAC_EN_CTL_MASK_SFT (0x1 << 27) +#define C_MUTE_SW_CTL_SFT 26 +#define C_MUTE_SW_CTL_MASK 0x1 +#define C_MUTE_SW_CTL_MASK_SFT (0x1 << 26) +#define C_AMP_DIV_CH2_CTL_SFT 21 +#define C_AMP_DIV_CH2_CTL_MASK 0x7 +#define C_AMP_DIV_CH2_CTL_MASK_SFT (0x7 << 21) +#define C_FREQ_DIV_CH2_CTL_SFT 16 +#define C_FREQ_DIV_CH2_CTL_MASK 0x1f +#define C_FREQ_DIV_CH2_CTL_MASK_SFT (0x1f << 16) +#define C_SINE_MODE_CH2_CTL_SFT 12 +#define C_SINE_MODE_CH2_CTL_MASK 0xf +#define C_SINE_MODE_CH2_CTL_MASK_SFT (0xf << 12) +#define C_AMP_DIV_CH1_CTL_SFT 9 +#define C_AMP_DIV_CH1_CTL_MASK 0x7 +#define C_AMP_DIV_CH1_CTL_MASK_SFT (0x7 << 9) +#define C_FREQ_DIV_CH1_CTL_SFT 4 +#define C_FREQ_DIV_CH1_CTL_MASK 0x1f +#define C_FREQ_DIV_CH1_CTL_MASK_SFT (0x1f << 4) +#define C_SINE_MODE_CH1_CTL_SFT 0 +#define C_SINE_MODE_CH1_CTL_MASK 0xf +#define C_SINE_MODE_CH1_CTL_MASK_SFT (0xf << 0) + +/* AFE_ADDA_UL0_SRC_DEBUG */ +#define UL_SLT_CNT_FLAG_RESET_CTL_SFT 16 +#define UL_SLT_CNT_FLAG_RESET_CTL_MASK 0x1 +#define UL_SLT_CNT_FLAG_RESET_CTL_MASK_SFT (0x1 << 16) +#define FIFO_DIGMIC_TESTIN_SFT 12 +#define FIFO_DIGMIC_TESTIN_MASK 0x3 +#define FIFO_DIGMIC_TESTIN_MASK_SFT (0x3 << 12) +#define FIFO_DIGMIC_WDATA_TESTEN_SFT 11 +#define FIFO_DIGMIC_WDATA_TESTEN_MASK 0x1 +#define FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT (0x1 << 11) +#define SLT_CNT_THD_CTL_SFT 0 +#define SLT_CNT_THD_CTL_MASK 0x7ff +#define SLT_CNT_THD_CTL_MASK_SFT (0x7ff << 0) + +/* AFE_ADDA_UL0_SRC_DEBUG_MON0 */ +#define SLT_CNT_FLAG_CTL_SFT 16 +#define SLT_CNT_FLAG_CTL_MASK 0x1 +#define SLT_CNT_FLAG_CTL_MASK_SFT (0x1 << 16) +#define SLT_COUNTER_CTL_SFT 0 +#define SLT_COUNTER_CTL_MASK 0x7ff +#define SLT_COUNTER_CTL_MASK_SFT (0x7ff << 0) + +/* AFE_ADDA_UL0_IIR_COEF_02_01 */ +#define ADDA_IIR_COEF_02_01_SFT 0 +#define ADDA_IIR_COEF_02_01_MASK 0xffffffff +#define ADDA_IIR_COEF_02_01_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_IIR_COEF_04_03 */ +#define ADDA_IIR_COEF_04_03_SFT 0 +#define ADDA_IIR_COEF_04_03_MASK 0xffffffff +#define ADDA_IIR_COEF_04_03_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_IIR_COEF_06_05 */ +#define ADDA_IIR_COEF_06_05_SFT 0 +#define ADDA_IIR_COEF_06_05_MASK 0xffffffff +#define ADDA_IIR_COEF_06_05_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_IIR_COEF_08_07 */ +#define ADDA_IIR_COEF_08_07_SFT 0 +#define ADDA_IIR_COEF_08_07_MASK 0xffffffff +#define ADDA_IIR_COEF_08_07_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_IIR_COEF_10_09 */ +#define ADDA_IIR_COEF_10_09_SFT 0 +#define ADDA_IIR_COEF_10_09_MASK 0xffffffff +#define ADDA_IIR_COEF_10_09_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_02_01 */ +#define ADDA_ULCF_CFG_02_01_SFT 0 +#define ADDA_ULCF_CFG_02_01_MASK 0xffffffff +#define ADDA_ULCF_CFG_02_01_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_04_03 */ +#define ADDA_ULCF_CFG_04_03_SFT 0 +#define ADDA_ULCF_CFG_04_03_MASK 0xffffffff +#define ADDA_ULCF_CFG_04_03_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_06_05 */ +#define ADDA_ULCF_CFG_06_05_SFT 0 +#define ADDA_ULCF_CFG_06_05_MASK 0xffffffff +#define ADDA_ULCF_CFG_06_05_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_08_07 */ +#define ADDA_ULCF_CFG_08_07_SFT 0 +#define ADDA_ULCF_CFG_08_07_MASK 0xffffffff +#define ADDA_ULCF_CFG_08_07_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_10_09 */ +#define ADDA_ULCF_CFG_10_09_SFT 0 +#define ADDA_ULCF_CFG_10_09_MASK 0xffffffff +#define ADDA_ULCF_CFG_10_09_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_12_11 */ +#define ADDA_ULCF_CFG_12_11_SFT 0 +#define ADDA_ULCF_CFG_12_11_MASK 0xffffffff +#define ADDA_ULCF_CFG_12_11_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_14_13 */ +#define ADDA_ULCF_CFG_14_13_SFT 0 +#define ADDA_ULCF_CFG_14_13_MASK 0xffffffff +#define ADDA_ULCF_CFG_14_13_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_16_15 */ +#define ADDA_ULCF_CFG_16_15_SFT 0 +#define ADDA_ULCF_CFG_16_15_MASK 0xffffffff +#define ADDA_ULCF_CFG_16_15_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_18_17 */ +#define ADDA_ULCF_CFG_18_17_SFT 0 +#define ADDA_ULCF_CFG_18_17_MASK 0xffffffff +#define ADDA_ULCF_CFG_18_17_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_20_19 */ +#define ADDA_ULCF_CFG_20_19_SFT 0 +#define ADDA_ULCF_CFG_20_19_MASK 0xffffffff +#define ADDA_ULCF_CFG_20_19_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_22_21 */ +#define ADDA_ULCF_CFG_22_21_SFT 0 +#define ADDA_ULCF_CFG_22_21_MASK 0xffffffff +#define ADDA_ULCF_CFG_22_21_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_24_23 */ +#define ADDA_ULCF_CFG_24_23_SFT 0 +#define ADDA_ULCF_CFG_24_23_MASK 0xffffffff +#define ADDA_ULCF_CFG_24_23_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_26_25 */ +#define ADDA_ULCF_CFG_26_25_SFT 0 +#define ADDA_ULCF_CFG_26_25_MASK 0xffffffff +#define ADDA_ULCF_CFG_26_25_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_28_27 */ +#define ADDA_ULCF_CFG_28_27_SFT 0 +#define ADDA_ULCF_CFG_28_27_MASK 0xffffffff +#define ADDA_ULCF_CFG_28_27_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_30_29 */ +#define ADDA_ULCF_CFG_30_29_SFT 0 +#define ADDA_ULCF_CFG_30_29_MASK 0xffffffff +#define ADDA_ULCF_CFG_30_29_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_ULCF_CFG_32_31 */ +#define ADDA_ULCF_CFG_32_31_SFT 0 +#define ADDA_ULCF_CFG_32_31_MASK 0xffffffff +#define ADDA_ULCF_CFG_32_31_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_IP_VERSION */ +#define ADDA_ULCF_IP_VERSION_SFT 0 +#define ADDA_ULCF_IP_VERSION_MASK 0xffffffff +#define ADDA_ULCF_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_SRC_CON0 */ +#define ULCF_CFG_EN_CTL_SFT 31 +#define ULCF_CFG_EN_CTL_MASK 0x1 +#define ULCF_CFG_EN_CTL_MASK_SFT (0x1 << 31) +#define UL_DMIC_PHASE_SEL_CH1_SFT 27 +#define UL_DMIC_PHASE_SEL_CH1_MASK 0x7 +#define UL_DMIC_PHASE_SEL_CH1_MASK_SFT (0x7 << 27) +#define UL_DMIC_PHASE_SEL_CH2_SFT 24 +#define UL_DMIC_PHASE_SEL_CH2_MASK 0x7 +#define UL_DMIC_PHASE_SEL_CH2_MASK_SFT (0x7 << 24) +#define UL_DMIC_TWO_WIRE_CTL_SFT 23 +#define UL_DMIC_TWO_WIRE_CTL_MASK 0x1 +#define UL_DMIC_TWO_WIRE_CTL_MASK_SFT (0x1 << 23) +#define UL_MODE_3P25M_CH2_CTL_SFT 22 +#define UL_MODE_3P25M_CH2_CTL_MASK 0x1 +#define UL_MODE_3P25M_CH2_CTL_MASK_SFT (0x1 << 22) +#define UL_MODE_3P25M_CH1_CTL_SFT 21 +#define UL_MODE_3P25M_CH1_CTL_MASK 0x1 +#define UL_MODE_3P25M_CH1_CTL_MASK_SFT (0x1 << 21) +#define UL_VOICE_MODE_CH1_CH2_CTL_SFT 17 +#define UL_VOICE_MODE_CH1_CH2_CTL_MASK 0x7 +#define UL_VOICE_MODE_CH1_CH2_CTL_MASK_SFT (0x7 << 17) +#define UL_AP_DMIC_ON_SFT 16 +#define UL_AP_DMIC_ON_MASK 0x1 +#define UL_AP_DMIC_ON_MASK_SFT (0x1 << 16) +#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 UL_DISABLE_HW_CG_CTL_SFT 12 +#define UL_DISABLE_HW_CG_CTL_MASK 0x1 +#define UL_DISABLE_HW_CG_CTL_MASK_SFT (0x1 << 12) +#define AMIC_26M_SEL_CTL_SFT 11 +#define AMIC_26M_SEL_CTL_MASK 0x1 +#define AMIC_26M_SEL_CTL_MASK_SFT (0x1 << 11) +#define UL_IIR_ON_TMP_CTL_SFT 10 +#define UL_IIR_ON_TMP_CTL_MASK 0x1 +#define UL_IIR_ON_TMP_CTL_MASK_SFT (0x1 << 10) +#define UL_IIRMODE_CTL_SFT 7 +#define UL_IIRMODE_CTL_MASK 0x7 +#define UL_IIRMODE_CTL_MASK_SFT (0x7 << 7) +#define DIGMIC_4P33M_SEL_SFT 6 +#define DIGMIC_4P33M_SEL_MASK 0x1 +#define DIGMIC_4P33M_SEL_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 AMIC_6P5M_SEL_CTL_SFT 4 +#define AMIC_6P5M_SEL_CTL_MASK 0x1 +#define AMIC_6P5M_SEL_CTL_MASK_SFT (0x1 << 4) +#define AMIC_1P625M_SEL_CTL_SFT 3 +#define AMIC_1P625M_SEL_CTL_MASK 0x1 +#define AMIC_1P625M_SEL_CTL_MASK_SFT (0x1 << 3) +#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_ADDA_UL1_SRC_CON1 */ +#define ADDA_UL_GAIN_VALUE_SFT 16 +#define ADDA_UL_GAIN_VALUE_MASK 0xffff +#define ADDA_UL_GAIN_VALUE_MASK_SFT (0xffff << 16) +#define ADDA_UL_POSTIVEGAIN_SFT 12 +#define ADDA_UL_POSTIVEGAIN_MASK 0x7 +#define ADDA_UL_POSTIVEGAIN_MASK_SFT (0x7 << 12) +#define ADDA_UL_ODDTAP_MODE_SFT 11 +#define ADDA_UL_ODDTAP_MODE_MASK 0x1 +#define ADDA_UL_ODDTAP_MODE_MASK_SFT (0x1 << 11) +#define ADDA_UL_HALF_TAP_NUM_SFT 5 +#define ADDA_UL_HALF_TAP_NUM_MASK 0x3f +#define ADDA_UL_HALF_TAP_NUM_MASK_SFT (0x3f << 5) +#define FIFO_SOFT_RST_SFT 4 +#define FIFO_SOFT_RST_MASK 0x1 +#define FIFO_SOFT_RST_MASK_SFT (0x1 << 4) +#define FIFO_SOFT_RST_EN_SFT 3 +#define FIFO_SOFT_RST_EN_MASK 0x1 +#define FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 3) +#define LR_SWAP_SFT 2 +#define LR_SWAP_MASK 0x1 +#define LR_SWAP_MASK_SFT (0x1 << 2) +#define GAIN_MODE_SFT 0 +#define GAIN_MODE_MASK 0x3 +#define GAIN_MODE_MASK_SFT (0x3 << 0) + +/* AFE_ADDA_UL1_SRC_CON2 */ +#define C_DAC_EN_CTL_SFT 27 +#define C_DAC_EN_CTL_MASK 0x1 +#define C_DAC_EN_CTL_MASK_SFT (0x1 << 27) +#define C_MUTE_SW_CTL_SFT 26 +#define C_MUTE_SW_CTL_MASK 0x1 +#define C_MUTE_SW_CTL_MASK_SFT (0x1 << 26) +#define C_AMP_DIV_CH2_CTL_SFT 21 +#define C_AMP_DIV_CH2_CTL_MASK 0x7 +#define C_AMP_DIV_CH2_CTL_MASK_SFT (0x7 << 21) +#define C_FREQ_DIV_CH2_CTL_SFT 16 +#define C_FREQ_DIV_CH2_CTL_MASK 0x1f +#define C_FREQ_DIV_CH2_CTL_MASK_SFT (0x1f << 16) +#define C_SINE_MODE_CH2_CTL_SFT 12 +#define C_SINE_MODE_CH2_CTL_MASK 0xf +#define C_SINE_MODE_CH2_CTL_MASK_SFT (0xf << 12) +#define C_AMP_DIV_CH1_CTL_SFT 9 +#define C_AMP_DIV_CH1_CTL_MASK 0x7 +#define C_AMP_DIV_CH1_CTL_MASK_SFT (0x7 << 9) +#define C_FREQ_DIV_CH1_CTL_SFT 4 +#define C_FREQ_DIV_CH1_CTL_MASK 0x1f +#define C_FREQ_DIV_CH1_CTL_MASK_SFT (0x1f << 4) +#define C_SINE_MODE_CH1_CTL_SFT 0 +#define C_SINE_MODE_CH1_CTL_MASK 0xf +#define C_SINE_MODE_CH1_CTL_MASK_SFT (0xf << 0) + +/* AFE_ADDA_UL1_SRC_DEBUG */ +#define UL_SLT_CNT_FLAG_RESET_CTL_SFT 16 +#define UL_SLT_CNT_FLAG_RESET_CTL_MASK 0x1 +#define UL_SLT_CNT_FLAG_RESET_CTL_MASK_SFT (0x1 << 16) +#define FIFO_DIGMIC_TESTIN_SFT 12 +#define FIFO_DIGMIC_TESTIN_MASK 0x3 +#define FIFO_DIGMIC_TESTIN_MASK_SFT (0x3 << 12) +#define FIFO_DIGMIC_WDATA_TESTEN_SFT 11 +#define FIFO_DIGMIC_WDATA_TESTEN_MASK 0x1 +#define FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT (0x1 << 11) +#define SLT_CNT_THD_CTL_SFT 0 +#define SLT_CNT_THD_CTL_MASK 0x7ff +#define SLT_CNT_THD_CTL_MASK_SFT (0x7ff << 0) + +/* AFE_ADDA_UL1_SRC_DEBUG_MON0 */ +#define SLT_CNT_FLAG_CTL_SFT 16 +#define SLT_CNT_FLAG_CTL_MASK 0x1 +#define SLT_CNT_FLAG_CTL_MASK_SFT (0x1 << 16) +#define SLT_COUNTER_CTL_SFT 0 +#define SLT_COUNTER_CTL_MASK 0x7ff +#define SLT_COUNTER_CTL_MASK_SFT (0x7ff << 0) + +/* AFE_ADDA_UL1_IIR_COEF_02_01 */ +#define ADDA_IIR_COEF_02_01_SFT 0 +#define ADDA_IIR_COEF_02_01_MASK 0xffffffff +#define ADDA_IIR_COEF_02_01_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_IIR_COEF_04_03 */ +#define ADDA_IIR_COEF_04_03_SFT 0 +#define ADDA_IIR_COEF_04_03_MASK 0xffffffff +#define ADDA_IIR_COEF_04_03_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_IIR_COEF_06_05 */ +#define ADDA_IIR_COEF_06_05_SFT 0 +#define ADDA_IIR_COEF_06_05_MASK 0xffffffff +#define ADDA_IIR_COEF_06_05_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_IIR_COEF_08_07 */ +#define ADDA_IIR_COEF_08_07_SFT 0 +#define ADDA_IIR_COEF_08_07_MASK 0xffffffff +#define ADDA_IIR_COEF_08_07_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_IIR_COEF_10_09 */ +#define ADDA_IIR_COEF_10_09_SFT 0 +#define ADDA_IIR_COEF_10_09_MASK 0xffffffff +#define ADDA_IIR_COEF_10_09_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_02_01 */ +#define ADDA_ULCF_CFG_02_01_SFT 0 +#define ADDA_ULCF_CFG_02_01_MASK 0xffffffff +#define ADDA_ULCF_CFG_02_01_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_04_03 */ +#define ADDA_ULCF_CFG_04_03_SFT 0 +#define ADDA_ULCF_CFG_04_03_MASK 0xffffffff +#define ADDA_ULCF_CFG_04_03_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_06_05 */ +#define ADDA_ULCF_CFG_06_05_SFT 0 +#define ADDA_ULCF_CFG_06_05_MASK 0xffffffff +#define ADDA_ULCF_CFG_06_05_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_08_07 */ +#define ADDA_ULCF_CFG_08_07_SFT 0 +#define ADDA_ULCF_CFG_08_07_MASK 0xffffffff +#define ADDA_ULCF_CFG_08_07_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_10_09 */ +#define ADDA_ULCF_CFG_10_09_SFT 0 +#define ADDA_ULCF_CFG_10_09_MASK 0xffffffff +#define ADDA_ULCF_CFG_10_09_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_12_11 */ +#define ADDA_ULCF_CFG_12_11_SFT 0 +#define ADDA_ULCF_CFG_12_11_MASK 0xffffffff +#define ADDA_ULCF_CFG_12_11_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_14_13 */ +#define ADDA_ULCF_CFG_14_13_SFT 0 +#define ADDA_ULCF_CFG_14_13_MASK 0xffffffff +#define ADDA_ULCF_CFG_14_13_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_16_15 */ +#define ADDA_ULCF_CFG_16_15_SFT 0 +#define ADDA_ULCF_CFG_16_15_MASK 0xffffffff +#define ADDA_ULCF_CFG_16_15_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_18_17 */ +#define ADDA_ULCF_CFG_18_17_SFT 0 +#define ADDA_ULCF_CFG_18_17_MASK 0xffffffff +#define ADDA_ULCF_CFG_18_17_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_20_19 */ +#define ADDA_ULCF_CFG_20_19_SFT 0 +#define ADDA_ULCF_CFG_20_19_MASK 0xffffffff +#define ADDA_ULCF_CFG_20_19_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_22_21 */ +#define ADDA_ULCF_CFG_22_21_SFT 0 +#define ADDA_ULCF_CFG_22_21_MASK 0xffffffff +#define ADDA_ULCF_CFG_22_21_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_24_23 */ +#define ADDA_ULCF_CFG_24_23_SFT 0 +#define ADDA_ULCF_CFG_24_23_MASK 0xffffffff +#define ADDA_ULCF_CFG_24_23_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_26_25 */ +#define ADDA_ULCF_CFG_26_25_SFT 0 +#define ADDA_ULCF_CFG_26_25_MASK 0xffffffff +#define ADDA_ULCF_CFG_26_25_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_28_27 */ +#define ADDA_ULCF_CFG_28_27_SFT 0 +#define ADDA_ULCF_CFG_28_27_MASK 0xffffffff +#define ADDA_ULCF_CFG_28_27_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_30_29 */ +#define ADDA_ULCF_CFG_30_29_SFT 0 +#define ADDA_ULCF_CFG_30_29_MASK 0xffffffff +#define ADDA_ULCF_CFG_30_29_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_ULCF_CFG_32_31 */ +#define ADDA_ULCF_CFG_32_31_SFT 0 +#define ADDA_ULCF_CFG_32_31_MASK 0xffffffff +#define ADDA_ULCF_CFG_32_31_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_IP_VERSION */ +#define ADDA_ULCF_IP_VERSION_SFT 0 +#define ADDA_ULCF_IP_VERSION_MASK 0xffffffff +#define ADDA_ULCF_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_SRC_CON0 */ +#define ULCF_CFG_EN_CTL_SFT 31 +#define ULCF_CFG_EN_CTL_MASK 0x1 +#define ULCF_CFG_EN_CTL_MASK_SFT (0x1 << 31) +#define UL_DMIC_PHASE_SEL_CH1_SFT 27 +#define UL_DMIC_PHASE_SEL_CH1_MASK 0x7 +#define UL_DMIC_PHASE_SEL_CH1_MASK_SFT (0x7 << 27) +#define UL_DMIC_PHASE_SEL_CH2_SFT 24 +#define UL_DMIC_PHASE_SEL_CH2_MASK 0x7 +#define UL_DMIC_PHASE_SEL_CH2_MASK_SFT (0x7 << 24) +#define UL_DMIC_TWO_WIRE_CTL_SFT 23 +#define UL_DMIC_TWO_WIRE_CTL_MASK 0x1 +#define UL_DMIC_TWO_WIRE_CTL_MASK_SFT (0x1 << 23) +#define UL_MODE_3P25M_CH2_CTL_SFT 22 +#define UL_MODE_3P25M_CH2_CTL_MASK 0x1 +#define UL_MODE_3P25M_CH2_CTL_MASK_SFT (0x1 << 22) +#define UL_MODE_3P25M_CH1_CTL_SFT 21 +#define UL_MODE_3P25M_CH1_CTL_MASK 0x1 +#define UL_MODE_3P25M_CH1_CTL_MASK_SFT (0x1 << 21) +#define UL_VOICE_MODE_CH1_CH2_CTL_SFT 17 +#define UL_VOICE_MODE_CH1_CH2_CTL_MASK 0x7 +#define UL_VOICE_MODE_CH1_CH2_CTL_MASK_SFT (0x7 << 17) +#define UL_AP_DMIC_ON_SFT 16 +#define UL_AP_DMIC_ON_MASK 0x1 +#define UL_AP_DMIC_ON_MASK_SFT (0x1 << 16) +#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 UL_DISABLE_HW_CG_CTL_SFT 12 +#define UL_DISABLE_HW_CG_CTL_MASK 0x1 +#define UL_DISABLE_HW_CG_CTL_MASK_SFT (0x1 << 12) +#define AMIC_26M_SEL_CTL_SFT 11 +#define AMIC_26M_SEL_CTL_MASK 0x1 +#define AMIC_26M_SEL_CTL_MASK_SFT (0x1 << 11) +#define UL_IIR_ON_TMP_CTL_SFT 10 +#define UL_IIR_ON_TMP_CTL_MASK 0x1 +#define UL_IIR_ON_TMP_CTL_MASK_SFT (0x1 << 10) +#define UL_IIRMODE_CTL_SFT 7 +#define UL_IIRMODE_CTL_MASK 0x7 +#define UL_IIRMODE_CTL_MASK_SFT (0x7 << 7) +#define DIGMIC_4P33M_SEL_SFT 6 +#define DIGMIC_4P33M_SEL_MASK 0x1 +#define DIGMIC_4P33M_SEL_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 AMIC_6P5M_SEL_CTL_SFT 4 +#define AMIC_6P5M_SEL_CTL_MASK 0x1 +#define AMIC_6P5M_SEL_CTL_MASK_SFT (0x1 << 4) +#define AMIC_1P625M_SEL_CTL_SFT 3 +#define AMIC_1P625M_SEL_CTL_MASK 0x1 +#define AMIC_1P625M_SEL_CTL_MASK_SFT (0x1 << 3) +#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_ADDA_UL2_SRC_CON1 */ +#define ADDA_UL_GAIN_VALUE_SFT 16 +#define ADDA_UL_GAIN_VALUE_MASK 0xffff +#define ADDA_UL_GAIN_VALUE_MASK_SFT (0xffff << 16) +#define ADDA_UL_POSTIVEGAIN_SFT 12 +#define ADDA_UL_POSTIVEGAIN_MASK 0x7 +#define ADDA_UL_POSTIVEGAIN_MASK_SFT (0x7 << 12) +#define ADDA_UL_ODDTAP_MODE_SFT 11 +#define ADDA_UL_ODDTAP_MODE_MASK 0x1 +#define ADDA_UL_ODDTAP_MODE_MASK_SFT (0x1 << 11) +#define ADDA_UL_HALF_TAP_NUM_SFT 5 +#define ADDA_UL_HALF_TAP_NUM_MASK 0x3f +#define ADDA_UL_HALF_TAP_NUM_MASK_SFT (0x3f << 5) +#define FIFO_SOFT_RST_SFT 4 +#define FIFO_SOFT_RST_MASK 0x1 +#define FIFO_SOFT_RST_MASK_SFT (0x1 << 4) +#define FIFO_SOFT_RST_EN_SFT 3 +#define FIFO_SOFT_RST_EN_MASK 0x1 +#define FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 3) +#define LR_SWAP_SFT 2 +#define LR_SWAP_MASK 0x1 +#define LR_SWAP_MASK_SFT (0x1 << 2) +#define GAIN_MODE_SFT 0 +#define GAIN_MODE_MASK 0x3 +#define GAIN_MODE_MASK_SFT (0x3 << 0) + +/* AFE_ADDA_UL2_SRC_CON2 */ +#define C_DAC_EN_CTL_SFT 27 +#define C_DAC_EN_CTL_MASK 0x1 +#define C_DAC_EN_CTL_MASK_SFT (0x1 << 27) +#define C_MUTE_SW_CTL_SFT 26 +#define C_MUTE_SW_CTL_MASK 0x1 +#define C_MUTE_SW_CTL_MASK_SFT (0x1 << 26) +#define C_AMP_DIV_CH2_CTL_SFT 21 +#define C_AMP_DIV_CH2_CTL_MASK 0x7 +#define C_AMP_DIV_CH2_CTL_MASK_SFT (0x7 << 21) +#define C_FREQ_DIV_CH2_CTL_SFT 16 +#define C_FREQ_DIV_CH2_CTL_MASK 0x1f +#define C_FREQ_DIV_CH2_CTL_MASK_SFT (0x1f << 16) +#define C_SINE_MODE_CH2_CTL_SFT 12 +#define C_SINE_MODE_CH2_CTL_MASK 0xf +#define C_SINE_MODE_CH2_CTL_MASK_SFT (0xf << 12) +#define C_AMP_DIV_CH1_CTL_SFT 9 +#define C_AMP_DIV_CH1_CTL_MASK 0x7 +#define C_AMP_DIV_CH1_CTL_MASK_SFT (0x7 << 9) +#define C_FREQ_DIV_CH1_CTL_SFT 4 +#define C_FREQ_DIV_CH1_CTL_MASK 0x1f +#define C_FREQ_DIV_CH1_CTL_MASK_SFT (0x1f << 4) +#define C_SINE_MODE_CH1_CTL_SFT 0 +#define C_SINE_MODE_CH1_CTL_MASK 0xf +#define C_SINE_MODE_CH1_CTL_MASK_SFT (0xf << 0) + +/* AFE_ADDA_UL2_SRC_DEBUG */ +#define UL_SLT_CNT_FLAG_RESET_CTL_SFT 16 +#define UL_SLT_CNT_FLAG_RESET_CTL_MASK 0x1 +#define UL_SLT_CNT_FLAG_RESET_CTL_MASK_SFT (0x1 << 16) +#define FIFO_DIGMIC_TESTIN_SFT 12 +#define FIFO_DIGMIC_TESTIN_MASK 0x3 +#define FIFO_DIGMIC_TESTIN_MASK_SFT (0x3 << 12) +#define FIFO_DIGMIC_WDATA_TESTEN_SFT 11 +#define FIFO_DIGMIC_WDATA_TESTEN_MASK 0x1 +#define FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT (0x1 << 11) +#define SLT_CNT_THD_CTL_SFT 0 +#define SLT_CNT_THD_CTL_MASK 0x7ff +#define SLT_CNT_THD_CTL_MASK_SFT (0x7ff << 0) + +/* AFE_ADDA_UL2_SRC_DEBUG_MON0 */ +#define SLT_CNT_FLAG_CTL_SFT 16 +#define SLT_CNT_FLAG_CTL_MASK 0x1 +#define SLT_CNT_FLAG_CTL_MASK_SFT (0x1 << 16) +#define SLT_COUNTER_CTL_SFT 0 +#define SLT_COUNTER_CTL_MASK 0x7ff +#define SLT_COUNTER_CTL_MASK_SFT (0x7ff << 0) + +/* AFE_ADDA_UL2_IIR_COEF_02_01 */ +#define ADDA_IIR_COEF_02_01_SFT 0 +#define ADDA_IIR_COEF_02_01_MASK 0xffffffff +#define ADDA_IIR_COEF_02_01_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_IIR_COEF_04_03 */ +#define ADDA_IIR_COEF_04_03_SFT 0 +#define ADDA_IIR_COEF_04_03_MASK 0xffffffff +#define ADDA_IIR_COEF_04_03_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_IIR_COEF_06_05 */ +#define ADDA_IIR_COEF_06_05_SFT 0 +#define ADDA_IIR_COEF_06_05_MASK 0xffffffff +#define ADDA_IIR_COEF_06_05_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_IIR_COEF_08_07 */ +#define ADDA_IIR_COEF_08_07_SFT 0 +#define ADDA_IIR_COEF_08_07_MASK 0xffffffff +#define ADDA_IIR_COEF_08_07_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_IIR_COEF_10_09 */ +#define ADDA_IIR_COEF_10_09_SFT 0 +#define ADDA_IIR_COEF_10_09_MASK 0xffffffff +#define ADDA_IIR_COEF_10_09_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_02_01 */ +#define ADDA_ULCF_CFG_02_01_SFT 0 +#define ADDA_ULCF_CFG_02_01_MASK 0xffffffff +#define ADDA_ULCF_CFG_02_01_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_04_03 */ +#define ADDA_ULCF_CFG_04_03_SFT 0 +#define ADDA_ULCF_CFG_04_03_MASK 0xffffffff +#define ADDA_ULCF_CFG_04_03_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_06_05 */ +#define ADDA_ULCF_CFG_06_05_SFT 0 +#define ADDA_ULCF_CFG_06_05_MASK 0xffffffff +#define ADDA_ULCF_CFG_06_05_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_08_07 */ +#define ADDA_ULCF_CFG_08_07_SFT 0 +#define ADDA_ULCF_CFG_08_07_MASK 0xffffffff +#define ADDA_ULCF_CFG_08_07_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_10_09 */ +#define ADDA_ULCF_CFG_10_09_SFT 0 +#define ADDA_ULCF_CFG_10_09_MASK 0xffffffff +#define ADDA_ULCF_CFG_10_09_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_12_11 */ +#define ADDA_ULCF_CFG_12_11_SFT 0 +#define ADDA_ULCF_CFG_12_11_MASK 0xffffffff +#define ADDA_ULCF_CFG_12_11_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_14_13 */ +#define ADDA_ULCF_CFG_14_13_SFT 0 +#define ADDA_ULCF_CFG_14_13_MASK 0xffffffff +#define ADDA_ULCF_CFG_14_13_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_16_15 */ +#define ADDA_ULCF_CFG_16_15_SFT 0 +#define ADDA_ULCF_CFG_16_15_MASK 0xffffffff +#define ADDA_ULCF_CFG_16_15_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_18_17 */ +#define ADDA_ULCF_CFG_18_17_SFT 0 +#define ADDA_ULCF_CFG_18_17_MASK 0xffffffff +#define ADDA_ULCF_CFG_18_17_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_20_19 */ +#define ADDA_ULCF_CFG_20_19_SFT 0 +#define ADDA_ULCF_CFG_20_19_MASK 0xffffffff +#define ADDA_ULCF_CFG_20_19_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_22_21 */ +#define ADDA_ULCF_CFG_22_21_SFT 0 +#define ADDA_ULCF_CFG_22_21_MASK 0xffffffff +#define ADDA_ULCF_CFG_22_21_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_24_23 */ +#define ADDA_ULCF_CFG_24_23_SFT 0 +#define ADDA_ULCF_CFG_24_23_MASK 0xffffffff +#define ADDA_ULCF_CFG_24_23_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_26_25 */ +#define ADDA_ULCF_CFG_26_25_SFT 0 +#define ADDA_ULCF_CFG_26_25_MASK 0xffffffff +#define ADDA_ULCF_CFG_26_25_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_28_27 */ +#define ADDA_ULCF_CFG_28_27_SFT 0 +#define ADDA_ULCF_CFG_28_27_MASK 0xffffffff +#define ADDA_ULCF_CFG_28_27_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_30_29 */ +#define ADDA_ULCF_CFG_30_29_SFT 0 +#define ADDA_ULCF_CFG_30_29_MASK 0xffffffff +#define ADDA_ULCF_CFG_30_29_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_ULCF_CFG_32_31 */ +#define ADDA_ULCF_CFG_32_31_SFT 0 +#define ADDA_ULCF_CFG_32_31_MASK 0xffffffff +#define ADDA_ULCF_CFG_32_31_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_IP_VERSION */ +#define ADDA_ULCF_IP_VERSION_SFT 0 +#define ADDA_ULCF_IP_VERSION_MASK 0xffffffff +#define ADDA_ULCF_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_PROXIMITY_CON0 */ +#define PROXIMITY_CH1_ON_SFT 12 +#define PROXIMITY_CH1_ON_MASK 0x1 +#define PROXIMITY_CH1_ON_MASK_SFT (0x1 << 12) +#define PROXIMITY_CH1_SEL_SFT 8 +#define PROXIMITY_CH1_SEL_MASK 0xf +#define PROXIMITY_CH1_SEL_MASK_SFT (0xf << 8) +#define PROXIMITY_CH2_ON_SFT 4 +#define PROXIMITY_CH2_ON_MASK 0x1 +#define PROXIMITY_CH2_ON_MASK_SFT (0x1 << 4) +#define PROXIMITY_CH2_SEL_SFT 0 +#define PROXIMITY_CH2_SEL_MASK 0xf +#define PROXIMITY_CH2_SEL_MASK_SFT (0xf << 0) + +/* AFE_ADDA_ULSRC_PHASE_CON0 */ +#define DMIC1_PHASE_FCLK_SEL_SFT 30 +#define DMIC1_PHASE_FCLK_SEL_MASK 0x3 +#define DMIC1_PHASE_FCLK_SEL_MASK_SFT (0x3 << 30) +#define DMIC0_PHASE_FCLK_SEL_SFT 28 +#define DMIC0_PHASE_FCLK_SEL_MASK 0x3 +#define DMIC0_PHASE_FCLK_SEL_MASK_SFT (0x3 << 28) +#define UL3_PHASE_FCLK_SEL_SFT 26 +#define UL3_PHASE_FCLK_SEL_MASK 0x3 +#define UL3_PHASE_FCLK_SEL_MASK_SFT (0x3 << 26) +#define UL2_PHASE_FCLK_SEL_SFT 24 +#define UL2_PHASE_FCLK_SEL_MASK 0x3 +#define UL2_PHASE_FCLK_SEL_MASK_SFT (0x3 << 24) +#define UL1_PHASE_FCLK_SEL_SFT 22 +#define UL1_PHASE_FCLK_SEL_MASK 0x3 +#define UL1_PHASE_FCLK_SEL_MASK_SFT (0x3 << 22) +#define UL0_PHASE_FCLK_SEL_SFT 20 +#define UL0_PHASE_FCLK_SEL_MASK 0x3 +#define UL0_PHASE_FCLK_SEL_MASK_SFT (0x3 << 20) +#define UL_PHASE_SYNC_FCLK_2_ON_SFT 18 +#define UL_PHASE_SYNC_FCLK_2_ON_MASK 0x1 +#define UL_PHASE_SYNC_FCLK_2_ON_MASK_SFT (0x1 << 18) +#define UL_PHASE_SYNC_FCLK_1_ON_SFT 17 +#define UL_PHASE_SYNC_FCLK_1_ON_MASK 0x1 +#define UL_PHASE_SYNC_FCLK_1_ON_MASK_SFT (0x1 << 17) +#define UL_PHASE_SYNC_FCLK_0_ON_SFT 16 +#define UL_PHASE_SYNC_FCLK_0_ON_MASK 0x1 +#define UL_PHASE_SYNC_FCLK_0_ON_MASK_SFT (0x1 << 16) +#define DMIC1_PHASE_HCLK_SEL_SFT 14 +#define DMIC1_PHASE_HCLK_SEL_MASK 0x3 +#define DMIC1_PHASE_HCLK_SEL_MASK_SFT (0x3 << 14) +#define DMIC0_PHASE_HCLK_SEL_SFT 12 +#define DMIC0_PHASE_HCLK_SEL_MASK 0x3 +#define DMIC0_PHASE_HCLK_SEL_MASK_SFT (0x3 << 12) +#define UL3_PHASE_HCLK_SEL_SFT 10 +#define UL3_PHASE_HCLK_SEL_MASK 0x3 +#define UL3_PHASE_HCLK_SEL_MASK_SFT (0x3 << 10) +#define UL2_PHASE_HCLK_SEL_SFT 8 +#define UL2_PHASE_HCLK_SEL_MASK 0x3 +#define UL2_PHASE_HCLK_SEL_MASK_SFT (0x3 << 8) +#define UL1_PHASE_HCLK_SEL_SFT 6 +#define UL1_PHASE_HCLK_SEL_MASK 0x3 +#define UL1_PHASE_HCLK_SEL_MASK_SFT (0x3 << 6) +#define UL0_PHASE_HCLK_SEL_SFT 4 +#define UL0_PHASE_HCLK_SEL_MASK 0x3 +#define UL0_PHASE_HCLK_SEL_MASK_SFT (0x3 << 4) +#define UL_PHASE_SYNC_HCLK_2_ON_SFT 2 +#define UL_PHASE_SYNC_HCLK_2_ON_MASK 0x1 +#define UL_PHASE_SYNC_HCLK_2_ON_MASK_SFT (0x1 << 2) +#define UL_PHASE_SYNC_HCLK_1_ON_SFT 1 +#define UL_PHASE_SYNC_HCLK_1_ON_MASK 0x1 +#define UL_PHASE_SYNC_HCLK_1_ON_MASK_SFT (0x1 << 1) +#define UL_PHASE_SYNC_HCLK_0_ON_SFT 0 +#define UL_PHASE_SYNC_HCLK_0_ON_MASK 0x1 +#define UL_PHASE_SYNC_HCLK_0_ON_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_ULSRC_PHASE_CON1 */ +#define DMIC_CLK_PHASE_SYNC_SET_SFT 31 +#define DMIC_CLK_PHASE_SYNC_SET_MASK 0x1 +#define DMIC_CLK_PHASE_SYNC_SET_MASK_SFT (0x1 << 31) +#define DMIC1_PHASE_SYNC_FCLK_SET_SFT 11 +#define DMIC1_PHASE_SYNC_FCLK_SET_MASK 0x1 +#define DMIC1_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 11) +#define DMIC1_PHASE_SYNC_HCLK_SET_SFT 10 +#define DMIC1_PHASE_SYNC_HCLK_SET_MASK 0x1 +#define DMIC1_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 10) +#define DMIC0_PHASE_SYNC_FCLK_SET_SFT 9 +#define DMIC0_PHASE_SYNC_FCLK_SET_MASK 0x1 +#define DMIC0_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 9) +#define DMIC0_PHASE_SYNC_HCLK_SET_SFT 8 +#define DMIC0_PHASE_SYNC_HCLK_SET_MASK 0x1 +#define DMIC0_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 8) +#define UL3_PHASE_SYNC_FCLK_SET_SFT 7 +#define UL3_PHASE_SYNC_FCLK_SET_MASK 0x1 +#define UL3_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 7) +#define UL3_PHASE_SYNC_HCLK_SET_SFT 6 +#define UL3_PHASE_SYNC_HCLK_SET_MASK 0x1 +#define UL3_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 6) +#define UL2_PHASE_SYNC_FCLK_SET_SFT 5 +#define UL2_PHASE_SYNC_FCLK_SET_MASK 0x1 +#define UL2_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 5) +#define UL2_PHASE_SYNC_HCLK_SET_SFT 4 +#define UL2_PHASE_SYNC_HCLK_SET_MASK 0x1 +#define UL2_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 4) +#define UL1_PHASE_SYNC_FCLK_SET_SFT 3 +#define UL1_PHASE_SYNC_FCLK_SET_MASK 0x1 +#define UL1_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 3) +#define UL1_PHASE_SYNC_HCLK_SET_SFT 2 +#define UL1_PHASE_SYNC_HCLK_SET_MASK 0x1 +#define UL1_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 2) +#define UL0_PHASE_SYNC_FCLK_SET_SFT 1 +#define UL0_PHASE_SYNC_FCLK_SET_MASK 0x1 +#define UL0_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 1) +#define UL0_PHASE_SYNC_HCLK_SET_SFT 0 +#define UL0_PHASE_SYNC_HCLK_SET_MASK 0x1 +#define UL0_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_ULSRC_PHASE_CON2 */ +#define DMIC1_PHASE_SYNC_1X_EN_SEL_SFT 26 +#define DMIC1_PHASE_SYNC_1X_EN_SEL_MASK 0x3 +#define DMIC1_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 26) +#define DMIC0_PHASE_SYNC_1X_EN_SEL_SFT 24 +#define DMIC0_PHASE_SYNC_1X_EN_SEL_MASK 0x3 +#define DMIC0_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 24) +#define UL3_PHASE_SYNC_1X_EN_SEL_SFT 22 +#define UL3_PHASE_SYNC_1X_EN_SEL_MASK 0x3 +#define UL3_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 22) +#define UL2_PHASE_SYNC_1X_EN_SEL_SFT 20 +#define UL2_PHASE_SYNC_1X_EN_SEL_MASK 0x3 +#define UL2_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 20) +#define UL1_PHASE_SYNC_1X_EN_SEL_SFT 18 +#define UL1_PHASE_SYNC_1X_EN_SEL_MASK 0x3 +#define UL1_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 18) +#define UL0_PHASE_SYNC_1X_EN_SEL_SFT 16 +#define UL0_PHASE_SYNC_1X_EN_SEL_MASK 0x3 +#define UL0_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 16) +#define UL_PHASE_SYNC_FCLK_1X_EN_2_ON_SFT 5 +#define UL_PHASE_SYNC_FCLK_1X_EN_2_ON_MASK 0x1 +#define UL_PHASE_SYNC_FCLK_1X_EN_2_ON_MASK_SFT (0x1 << 5) +#define UL_PHASE_SYNC_FCLK_1X_EN_1_ON_SFT 4 +#define UL_PHASE_SYNC_FCLK_1X_EN_1_ON_MASK 0x1 +#define UL_PHASE_SYNC_FCLK_1X_EN_1_ON_MASK_SFT (0x1 << 4) +#define UL_PHASE_SYNC_FCLK_1X_EN_0_ON_SFT 3 +#define UL_PHASE_SYNC_FCLK_1X_EN_0_ON_MASK 0x1 +#define UL_PHASE_SYNC_FCLK_1X_EN_0_ON_MASK_SFT (0x1 << 3) +#define UL_PHASE_SYNC_HCLK_1X_EN_2_ON_SFT 2 +#define UL_PHASE_SYNC_HCLK_1X_EN_2_ON_MASK 0x1 +#define UL_PHASE_SYNC_HCLK_1X_EN_2_ON_MASK_SFT (0x1 << 2) +#define UL_PHASE_SYNC_HCLK_1X_EN_1_ON_SFT 1 +#define UL_PHASE_SYNC_HCLK_1X_EN_1_ON_MASK 0x1 +#define UL_PHASE_SYNC_HCLK_1X_EN_1_ON_MASK_SFT (0x1 << 1) +#define UL_PHASE_SYNC_HCLK_1X_EN_0_ON_SFT 0 +#define UL_PHASE_SYNC_HCLK_1X_EN_0_ON_MASK 0x1 +#define UL_PHASE_SYNC_HCLK_1X_EN_0_ON_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_ULSRC_PHASE_CON3 */ +#define DMIC1_PHASE_SYNC_SOFT_RST_SEL_SFT 26 +#define DMIC1_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3 +#define DMIC1_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 26) +#define DMIC0_PHASE_SYNC_SOFT_RST_SEL_SFT 24 +#define DMIC0_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3 +#define DMIC0_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 24) +#define UL3_PHASE_SYNC_SOFT_RST_SEL_SFT 22 +#define UL3_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3 +#define UL3_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 22) +#define UL2_PHASE_SYNC_SOFT_RST_SEL_SFT 20 +#define UL2_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3 +#define UL2_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 20) +#define UL1_PHASE_SYNC_SOFT_RST_SEL_SFT 18 +#define UL1_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3 +#define UL1_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 18) +#define UL0_PHASE_SYNC_SOFT_RST_SEL_SFT 16 +#define UL0_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3 +#define UL0_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 16) +#define DMIC1_PHASE_SYNC_CH1_FIFO_SEL_SFT 13 +#define DMIC1_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1 +#define DMIC1_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 13) +#define DMIC0_PHASE_SYNC_CH1_FIFO_SEL_SFT 12 +#define DMIC0_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1 +#define DMIC0_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 12) +#define UL3_PHASE_SYNC_CH1_FIFO_SEL_SFT 11 +#define UL3_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1 +#define UL3_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 11) +#define UL2_PHASE_SYNC_CH1_FIFO_SEL_SFT 10 +#define UL2_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1 +#define UL2_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 10) +#define UL1_PHASE_SYNC_CH1_FIFO_SEL_SFT 9 +#define UL1_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1 +#define UL1_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 9) +#define UL0_PHASE_SYNC_CH1_FIFO_SEL_SFT 8 +#define UL0_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1 +#define UL0_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 8) +#define UL_PHASE_SYNC_SOFT_RST_EN_2_ON_SFT 5 +#define UL_PHASE_SYNC_SOFT_RST_EN_2_ON_MASK 0x1 +#define UL_PHASE_SYNC_SOFT_RST_EN_2_ON_MASK_SFT (0x1 << 5) +#define UL_PHASE_SYNC_SOFT_RST_EN_1_ON_SFT 4 +#define UL_PHASE_SYNC_SOFT_RST_EN_1_ON_MASK 0x1 +#define UL_PHASE_SYNC_SOFT_RST_EN_1_ON_MASK_SFT (0x1 << 4) +#define UL_PHASE_SYNC_SOFT_RST_EN_0_ON_SFT 3 +#define UL_PHASE_SYNC_SOFT_RST_EN_0_ON_MASK 0x1 +#define UL_PHASE_SYNC_SOFT_RST_EN_0_ON_MASK_SFT (0x1 << 3) +#define UL_PHASE_SYNC_SOFT_RST_2_ON_SFT 2 +#define UL_PHASE_SYNC_SOFT_RST_2_ON_MASK 0x1 +#define UL_PHASE_SYNC_SOFT_RST_2_ON_MASK_SFT (0x1 << 2) +#define UL_PHASE_SYNC_SOFT_RST_1_ON_SFT 1 +#define UL_PHASE_SYNC_SOFT_RST_1_ON_MASK 0x1 +#define UL_PHASE_SYNC_SOFT_RST_1_ON_MASK_SFT (0x1 << 1) +#define UL_PHASE_SYNC_SOFT_RST_0_ON_SFT 0 +#define UL_PHASE_SYNC_SOFT_RST_0_ON_MASK 0x1 +#define UL_PHASE_SYNC_SOFT_RST_0_ON_MASK_SFT (0x1 << 0) + +/* AFE_MTKAIF_IPM_VER_MON */ +#define RG_MTKAIF_IPM_VER_MON_SFT 0 +#define RG_MTKAIF_IPM_VER_MON_MASK 0xffffffff +#define RG_MTKAIF_IPM_VER_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_MTKAIF_MON_SEL */ +#define RG_MTKAIF_MON_SEL_SFT 0 +#define RG_MTKAIF_MON_SEL_MASK 0xff +#define RG_MTKAIF_MON_SEL_MASK_SFT (0xff << 0) + +/* AFE_MTKAIF_MON */ +#define RG_MTKAIF_MON_SFT 0 +#define RG_MTKAIF_MON_MASK 0xffffffff +#define RG_MTKAIF_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_MTKAIF0_CFG0 */ +#define RG_MTKAIF0_RXIF_CLKINV_SFT 31 +#define RG_MTKAIF0_RXIF_CLKINV_MASK 0x1 +#define RG_MTKAIF0_RXIF_CLKINV_MASK_SFT (0x1 << 31) +#define RG_MTKAIF0_RXIF_BYPASS_SRC_SFT 17 +#define RG_MTKAIF0_RXIF_BYPASS_SRC_MASK 0x1 +#define RG_MTKAIF0_RXIF_BYPASS_SRC_MASK_SFT (0x1 << 17) +#define RG_MTKAIF0_RXIF_PROTOCOL2_SFT 16 +#define RG_MTKAIF0_RXIF_PROTOCOL2_MASK 0x1 +#define RG_MTKAIF0_RXIF_PROTOCOL2_MASK_SFT (0x1 << 16) +#define RG_MTKAIF0_TXIF_NLE_DEBUG_SFT 8 +#define RG_MTKAIF0_TXIF_NLE_DEBUG_MASK 0x1 +#define RG_MTKAIF0_TXIF_NLE_DEBUG_MASK_SFT (0x1 << 8) +#define RG_MTKAIF0_TXIF_BYPASS_SRC_SFT 5 +#define RG_MTKAIF0_TXIF_BYPASS_SRC_MASK 0x1 +#define RG_MTKAIF0_TXIF_BYPASS_SRC_MASK_SFT (0x1 << 5) +#define RG_MTKAIF0_TXIF_PROTOCOL2_SFT 4 +#define RG_MTKAIF0_TXIF_PROTOCOL2_MASK 0x1 +#define RG_MTKAIF0_TXIF_PROTOCOL2_MASK_SFT (0x1 << 4) +#define RG_MTKAIF0_TXIF_8TO5_SFT 2 +#define RG_MTKAIF0_TXIF_8TO5_MASK 0x1 +#define RG_MTKAIF0_TXIF_8TO5_MASK_SFT (0x1 << 2) +#define RG_MTKAIF0_RXIF_8TO5_SFT 1 +#define RG_MTKAIF0_RXIF_8TO5_MASK 0x1 +#define RG_MTKAIF0_RXIF_8TO5_MASK_SFT (0x1 << 1) +#define RG_MTKAIF0_TX2RX_LOOPBACK1_SFT 0 +#define RG_MTKAIF0_TX2RX_LOOPBACK1_MASK 0x1 +#define RG_MTKAIF0_TX2RX_LOOPBACK1_MASK_SFT (0x1 << 0) + +/* AFE_MTKAIF0_TX_CFG0 */ +#define RG_MTKAIF0_TXIF_NLE_FIFO_SWAP_SFT 23 +#define RG_MTKAIF0_TXIF_NLE_FIFO_SWAP_MASK 0x1 +#define RG_MTKAIF0_TXIF_NLE_FIFO_SWAP_MASK_SFT (0x1 << 23) +#define RG_MTKAIF0_TXIF_NLE_FIFO_RSP_SFT 20 +#define RG_MTKAIF0_TXIF_NLE_FIFO_RSP_MASK 0x7 +#define RG_MTKAIF0_TXIF_NLE_FIFO_RSP_MASK_SFT (0x7 << 20) +#define RG_MTKAIF0_TXIF_FIFO_SWAP_SFT 15 +#define RG_MTKAIF0_TXIF_FIFO_SWAP_MASK 0x1 +#define RG_MTKAIF0_TXIF_FIFO_SWAP_MASK_SFT (0x1 << 15) +#define RG_MTKAIF0_TXIF_FIFO_RSP_SFT 12 +#define RG_MTKAIF0_TXIF_FIFO_RSP_MASK 0x7 +#define RG_MTKAIF0_TXIF_FIFO_RSP_MASK_SFT (0x7 << 12) +#define RG_MTKAIF0_TXIF_SYNC_WORD1_SFT 4 +#define RG_MTKAIF0_TXIF_SYNC_WORD1_MASK 0x7 +#define RG_MTKAIF0_TXIF_SYNC_WORD1_MASK_SFT (0x7 << 4) +#define RG_MTKAIF0_TXIF_SYNC_WORD0_SFT 0 +#define RG_MTKAIF0_TXIF_SYNC_WORD0_MASK 0x7 +#define RG_MTKAIF0_TXIF_SYNC_WORD0_MASK_SFT (0x7 << 0) + +/* AFE_MTKAIF0_RX_CFG0 */ +#define RG_MTKAIF0_RXIF_VOICE_MODE_SFT 20 +#define RG_MTKAIF0_RXIF_VOICE_MODE_MASK 0xf +#define RG_MTKAIF0_RXIF_VOICE_MODE_MASK_SFT (0xf << 20) +#define RG_MTKAIF0_RXIF_DETECT_ON_SFT 16 +#define RG_MTKAIF0_RXIF_DETECT_ON_MASK 0x1 +#define RG_MTKAIF0_RXIF_DETECT_ON_MASK_SFT (0x1 << 16) +#define RG_MTKAIF0_RXIF_DATA_BIT_SFT 8 +#define RG_MTKAIF0_RXIF_DATA_BIT_MASK 0x7 +#define RG_MTKAIF0_RXIF_DATA_BIT_MASK_SFT (0x7 << 8) +#define RG_MTKAIF0_RXIF_FIFO_RSP_SFT 4 +#define RG_MTKAIF0_RXIF_FIFO_RSP_MASK 0x7 +#define RG_MTKAIF0_RXIF_FIFO_RSP_MASK_SFT (0x7 << 4) +#define RG_MTKAIF0_RXIF_DATA_MODE_SFT 0 +#define RG_MTKAIF0_RXIF_DATA_MODE_MASK 0x1 +#define RG_MTKAIF0_RXIF_DATA_MODE_MASK_SFT (0x1 << 0) + +/* AFE_MTKAIF0_RX_CFG1 */ +#define RG_MTKAIF0_RXIF_CLEAR_SYNC_FAIL_SFT 28 +#define RG_MTKAIF0_RXIF_CLEAR_SYNC_FAIL_MASK 0x1 +#define RG_MTKAIF0_RXIF_CLEAR_SYNC_FAIL_MASK_SFT (0x1 << 28) +#define RG_MTKAIF0_RXIF_SYNC_CNT_TABLE_SFT 16 +#define RG_MTKAIF0_RXIF_SYNC_CNT_TABLE_MASK 0xfff +#define RG_MTKAIF0_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 16) +#define RG_MTKAIF0_RXIF_SYNC_SEARCH_TABLE_SFT 12 +#define RG_MTKAIF0_RXIF_SYNC_SEARCH_TABLE_MASK 0xf +#define RG_MTKAIF0_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0xf << 12) +#define RG_MTKAIF0_RXIF_INVALID_SYNC_CHECK_ROUND_SFT 8 +#define RG_MTKAIF0_RXIF_INVALID_SYNC_CHECK_ROUND_MASK 0xf +#define RG_MTKAIF0_RXIF_INVALID_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8) +#define RG_MTKAIF0_RXIF_SYNC_CHECK_ROUND_SFT 4 +#define RG_MTKAIF0_RXIF_SYNC_CHECK_ROUND_MASK 0xf +#define RG_MTKAIF0_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4) + +/* AFE_MTKAIF0_RX_CFG2 */ +#define RG_MTKAIF0_RXIF_SYNC_WORD1_DISABLE_SFT 27 +#define RG_MTKAIF0_RXIF_SYNC_WORD1_DISABLE_MASK 0x1 +#define RG_MTKAIF0_RXIF_SYNC_WORD1_DISABLE_MASK_SFT (0x1 << 27) +#define RG_MTKAIF0_RXIF_SYNC_WORD1_SFT 24 +#define RG_MTKAIF0_RXIF_SYNC_WORD1_MASK 0x7 +#define RG_MTKAIF0_RXIF_SYNC_WORD1_MASK_SFT (0x7 << 24) +#define RG_MTKAIF0_RXIF_SYNC_WORD0_DISABLE_SFT 23 +#define RG_MTKAIF0_RXIF_SYNC_WORD0_DISABLE_MASK 0x1 +#define RG_MTKAIF0_RXIF_SYNC_WORD0_DISABLE_MASK_SFT (0x1 << 23) +#define RG_MTKAIF0_RXIF_SYNC_WORD0_SFT 20 +#define RG_MTKAIF0_RXIF_SYNC_WORD0_MASK 0x7 +#define RG_MTKAIF0_RXIF_SYNC_WORD0_MASK_SFT (0x7 << 20) +#define RG_MTKAIF0_RXIF_DELAY_CYCLE_SFT 12 +#define RG_MTKAIF0_RXIF_DELAY_CYCLE_MASK 0xf +#define RG_MTKAIF0_RXIF_DELAY_CYCLE_MASK_SFT (0xf << 12) +#define RG_MTKAIF0_RXIF_DELAY_DATA_SFT 8 +#define RG_MTKAIF0_RXIF_DELAY_DATA_MASK 0x1 +#define RG_MTKAIF0_RXIF_DELAY_DATA_MASK_SFT (0x1 << 8) + +/* AFE_MTKAIF1_CFG0 */ +#define RG_MTKAIF1_RXIF_CLKINV_ADC_SFT 31 +#define RG_MTKAIF1_RXIF_CLKINV_ADC_MASK 0x1 +#define RG_MTKAIF1_RXIF_CLKINV_ADC_MASK_SFT (0x1 << 31) +#define RG_MTKAIF1_RXIF_BYPASS_SRC_SFT 17 +#define RG_MTKAIF1_RXIF_BYPASS_SRC_MASK 0x1 +#define RG_MTKAIF1_RXIF_BYPASS_SRC_MASK_SFT (0x1 << 17) +#define RG_MTKAIF1_RXIF_PROTOCOL2_SFT 16 +#define RG_MTKAIF1_RXIF_PROTOCOL2_MASK 0x1 +#define RG_MTKAIF1_RXIF_PROTOCOL2_MASK_SFT (0x1 << 16) +#define RG_MTKAIF1_TXIF_NLE_DEBUG_SFT 8 +#define RG_MTKAIF1_TXIF_NLE_DEBUG_MASK 0x1 +#define RG_MTKAIF1_TXIF_NLE_DEBUG_MASK_SFT (0x1 << 8) +#define RG_MTKAIF1_TXIF_BYPASS_SRC_SFT 5 +#define RG_MTKAIF1_TXIF_BYPASS_SRC_MASK 0x1 +#define RG_MTKAIF1_TXIF_BYPASS_SRC_MASK_SFT (0x1 << 5) +#define RG_MTKAIF1_TXIF_PROTOCOL2_SFT 4 +#define RG_MTKAIF1_TXIF_PROTOCOL2_MASK 0x1 +#define RG_MTKAIF1_TXIF_PROTOCOL2_MASK_SFT (0x1 << 4) +#define RG_MTKAIF1_TXIF_8TO5_SFT 2 +#define RG_MTKAIF1_TXIF_8TO5_MASK 0x1 +#define RG_MTKAIF1_TXIF_8TO5_MASK_SFT (0x1 << 2) +#define RG_MTKAIF1_RXIF_8TO5_SFT 1 +#define RG_MTKAIF1_RXIF_8TO5_MASK 0x1 +#define RG_MTKAIF1_RXIF_8TO5_MASK_SFT (0x1 << 1) +#define RG_MTKAIF1_IF_LOOPBACK1_SFT 0 +#define RG_MTKAIF1_IF_LOOPBACK1_MASK 0x1 +#define RG_MTKAIF1_IF_LOOPBACK1_MASK_SFT (0x1 << 0) + +/* AFE_MTKAIF1_TX_CFG0 */ +#define RG_MTKAIF1_TXIF_NLE_FIFO_SWAP_SFT 23 +#define RG_MTKAIF1_TXIF_NLE_FIFO_SWAP_MASK 0x1 +#define RG_MTKAIF1_TXIF_NLE_FIFO_SWAP_MASK_SFT (0x1 << 23) +#define RG_MTKAIF1_TXIF_NLE_FIFO_RSP_SFT 20 +#define RG_MTKAIF1_TXIF_NLE_FIFO_RSP_MASK 0x7 +#define RG_MTKAIF1_TXIF_NLE_FIFO_RSP_MASK_SFT (0x7 << 20) +#define RG_MTKAIF1_TXIF_FIFO_SWAP_SFT 15 +#define RG_MTKAIF1_TXIF_FIFO_SWAP_MASK 0x1 +#define RG_MTKAIF1_TXIF_FIFO_SWAP_MASK_SFT (0x1 << 15) +#define RG_MTKAIF1_TXIF_FIFO_RSP_SFT 12 +#define RG_MTKAIF1_TXIF_FIFO_RSP_MASK 0x7 +#define RG_MTKAIF1_TXIF_FIFO_RSP_MASK_SFT (0x7 << 12) +#define RG_MTKAIF1_TXIF_SYNC_WORD1_SFT 4 +#define RG_MTKAIF1_TXIF_SYNC_WORD1_MASK 0x7 +#define RG_MTKAIF1_TXIF_SYNC_WORD1_MASK_SFT (0x7 << 4) +#define RG_MTKAIF1_TXIF_SYNC_WORD0_SFT 0 +#define RG_MTKAIF1_TXIF_SYNC_WORD0_MASK 0x7 +#define RG_MTKAIF1_TXIF_SYNC_WORD0_MASK_SFT (0x7 << 0) + +/* AFE_MTKAIF1_RX_CFG0 */ +#define RG_MTKAIF1_RXIF_VOICE_MODE_SFT 20 +#define RG_MTKAIF1_RXIF_VOICE_MODE_MASK 0xf +#define RG_MTKAIF1_RXIF_VOICE_MODE_MASK_SFT (0xf << 20) +#define RG_MTKAIF1_RXIF_DETECT_ON_SFT 16 +#define RG_MTKAIF1_RXIF_DETECT_ON_MASK 0x1 +#define RG_MTKAIF1_RXIF_DETECT_ON_MASK_SFT (0x1 << 16) +#define RG_MTKAIF1_RXIF_DATA_BIT_SFT 8 +#define RG_MTKAIF1_RXIF_DATA_BIT_MASK 0x7 +#define RG_MTKAIF1_RXIF_DATA_BIT_MASK_SFT (0x7 << 8) +#define RG_MTKAIF1_RXIF_FIFO_RSP_SFT 4 +#define RG_MTKAIF1_RXIF_FIFO_RSP_MASK 0x7 +#define RG_MTKAIF1_RXIF_FIFO_RSP_MASK_SFT (0x7 << 4) +#define RG_MTKAIF1_RXIF_DATA_MODE_SFT 0 +#define RG_MTKAIF1_RXIF_DATA_MODE_MASK 0x1 +#define RG_MTKAIF1_RXIF_DATA_MODE_MASK_SFT (0x1 << 0) + +/* AFE_MTKAIF1_RX_CFG1 */ +#define RG_MTKAIF1_RXIF_CLEAR_SYNC_FAIL_SFT 28 +#define RG_MTKAIF1_RXIF_CLEAR_SYNC_FAIL_MASK 0x1 +#define RG_MTKAIF1_RXIF_CLEAR_SYNC_FAIL_MASK_SFT (0x1 << 28) +#define RG_MTKAIF1_RXIF_SYNC_CNT_TABLE_SFT 16 +#define RG_MTKAIF1_RXIF_SYNC_CNT_TABLE_MASK 0xfff +#define RG_MTKAIF1_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 16) +#define RG_MTKAIF1_RXIF_SYNC_SEARCH_TABLE_SFT 12 +#define RG_MTKAIF1_RXIF_SYNC_SEARCH_TABLE_MASK 0xf +#define RG_MTKAIF1_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0xf << 12) +#define RG_MTKAIF1_RXIF_INVALID_SYNC_CHECK_ROUND_SFT 8 +#define RG_MTKAIF1_RXIF_INVALID_SYNC_CHECK_ROUND_MASK 0xf +#define RG_MTKAIF1_RXIF_INVALID_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8) +#define RG_MTKAIF1_RXIF_SYNC_CHECK_ROUND_SFT 4 +#define RG_MTKAIF1_RXIF_SYNC_CHECK_ROUND_MASK 0xf +#define RG_MTKAIF1_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4) + +/* AFE_MTKAIF1_RX_CFG2 */ +#define RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_SFT 27 +#define RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_MASK 0x1 +#define RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_MASK_SFT (0x1 << 27) +#define RG_MTKAIF1_RXIF_SYNC_WORD1_SFT 24 +#define RG_MTKAIF1_RXIF_SYNC_WORD1_MASK 0x7 +#define RG_MTKAIF1_RXIF_SYNC_WORD1_MASK_SFT (0x7 << 24) +#define RG_MTKAIF1_RXIF_SYNC_WORD0_DISABLE_SFT 23 +#define RG_MTKAIF1_RXIF_SYNC_WORD0_DISABLE_MASK 0x1 +#define RG_MTKAIF1_RXIF_SYNC_WORD0_DISABLE_MASK_SFT (0x1 << 23) +#define RG_MTKAIF1_RXIF_SYNC_WORD0_SFT 20 +#define RG_MTKAIF1_RXIF_SYNC_WORD0_MASK 0x7 +#define RG_MTKAIF1_RXIF_SYNC_WORD0_MASK_SFT (0x7 << 20) +#define RG_MTKAIF1_RXIF_DELAY_CYCLE_SFT 12 +#define RG_MTKAIF1_RXIF_DELAY_CYCLE_MASK 0xf +#define RG_MTKAIF1_RXIF_DELAY_CYCLE_MASK_SFT (0xf << 12) +#define RG_MTKAIF1_RXIF_DELAY_DATA_SFT 8 +#define RG_MTKAIF1_RXIF_DELAY_DATA_MASK 0x1 +#define RG_MTKAIF1_RXIF_DELAY_DATA_MASK_SFT (0x1 << 8) + +/* AFE_AUD_PAD_TOP_CFG0 */ +#define AUD_PAD_TOP_FIFO_RSP_SFT 4 +#define AUD_PAD_TOP_FIFO_RSP_MASK 0xf +#define AUD_PAD_TOP_FIFO_RSP_MASK_SFT (0xf << 4) +#define RG_RX_PROTOCOL2_SFT 3 +#define RG_RX_PROTOCOL2_MASK 0x1 +#define RG_RX_PROTOCOL2_MASK_SFT (0x1 << 3) +#define RG_RX_FIFO_ON_SFT 0 +#define RG_RX_FIFO_ON_MASK 0x1 +#define RG_RX_FIFO_ON_MASK_SFT (0x1 << 0) + +/* AFE_AUD_PAD_TOP_MON */ +#define AUD_PAD_TOP_MON_SFT 0 +#define AUD_PAD_TOP_MON_MASK 0xffff +#define AUD_PAD_TOP_MON_MASK_SFT (0xffff << 0) + +/* AFE_ADDA_MTKAIFV4_TX_CFG0 */ +#define MTKAIFV4_TXIF_EN_SEL_SFT 12 +#define MTKAIFV4_TXIF_EN_SEL_MASK 0x1 +#define MTKAIFV4_TXIF_EN_SEL_MASK_SFT (0x1 << 12) +#define MTKAIFV4_TXIF_V4_SFT 11 +#define MTKAIFV4_TXIF_V4_MASK 0x1 +#define MTKAIFV4_TXIF_V4_MASK_SFT (0x1 << 11) +#define MTKAIFV4_ADDA6_OUT_EN_SEL_SFT 10 +#define MTKAIFV4_ADDA6_OUT_EN_SEL_MASK 0x1 +#define MTKAIFV4_ADDA6_OUT_EN_SEL_MASK_SFT (0x1 << 10) +#define MTKAIFV4_ADDA_OUT_EN_SEL_SFT 9 +#define MTKAIFV4_ADDA_OUT_EN_SEL_MASK 0x1 +#define MTKAIFV4_ADDA_OUT_EN_SEL_MASK_SFT (0x1 << 9) +#define MTKAIFV4_TXIF_INPUT_MODE_SFT 4 +#define MTKAIFV4_TXIF_INPUT_MODE_MASK 0x1f +#define MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT (0x1f << 4) +#define MTKAIFV4_TXIF_FOUR_CHANNEL_SFT 1 +#define MTKAIFV4_TXIF_FOUR_CHANNEL_MASK 0x1 +#define MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1) +#define MTKAIFV4_TXIF_AFE_ON_SFT 0 +#define MTKAIFV4_TXIF_AFE_ON_MASK 0x1 +#define MTKAIFV4_TXIF_AFE_ON_MASK_SFT (0x1 << 0) + +/* AFE_ADDA6_MTKAIFV4_TX_CFG0 */ +#define ADDA6_MTKAIFV4_TXIF_EN_SEL_SFT 12 +#define ADDA6_MTKAIFV4_TXIF_EN_SEL_MASK 0x1 +#define ADDA6_MTKAIFV4_TXIF_EN_SEL_MASK_SFT (0x1 << 12) +#define ADDA6_MTKAIFV4_TXIF_INPUT_MODE_SFT 4 +#define ADDA6_MTKAIFV4_TXIF_INPUT_MODE_MASK 0x1f +#define ADDA6_MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT (0x1f << 4) +#define ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_SFT 1 +#define ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_MASK 0x1 +#define ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1) +#define ADDA6_MTKAIFV4_TXIF_AFE_ON_SFT 0 +#define ADDA6_MTKAIFV4_TXIF_AFE_ON_MASK 0x1 +#define ADDA6_MTKAIFV4_TXIF_AFE_ON_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_MTKAIFV4_RX_CFG0 */ +#define MTKAIFV4_RXIF_CLKINV_SFT 31 +#define MTKAIFV4_RXIF_CLKINV_MASK 0x1 +#define MTKAIFV4_RXIF_CLKINV_MASK_SFT (0x1 << 31) +#define MTKAIFV4_RXIF_LOOPBACK_MODE_SFT 28 +#define MTKAIFV4_RXIF_LOOPBACK_MODE_MASK 0x1 +#define MTKAIFV4_RXIF_LOOPBACK_MODE_MASK_SFT (0x1 << 28) +#define MTKAIFV4_UL_CH7CH8_IN_EN_SEL_SFT 19 +#define MTKAIFV4_UL_CH7CH8_IN_EN_SEL_MASK 0x1 +#define MTKAIFV4_UL_CH7CH8_IN_EN_SEL_MASK_SFT (0x1 << 19) +#define MTKAIFV4_UL_CH5CH6_IN_EN_SEL_SFT 18 +#define MTKAIFV4_UL_CH5CH6_IN_EN_SEL_MASK 0x1 +#define MTKAIFV4_UL_CH5CH6_IN_EN_SEL_MASK_SFT (0x1 << 18) +#define MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT 17 +#define MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK 0x1 +#define MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT (0x1 << 17) +#define MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT 16 +#define MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK 0x1 +#define MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT (0x1 << 16) +#define MTKAIFV4_RXIF_EN_SEL_SFT 12 +#define MTKAIFV4_RXIF_EN_SEL_MASK 0x1 +#define MTKAIFV4_RXIF_EN_SEL_MASK_SFT (0x1 << 12) +#define MTKAIFV4_RXIF_INPUT_MODE_SFT 4 +#define MTKAIFV4_RXIF_INPUT_MODE_MASK 0x1f +#define MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT (0x1f << 4) +#define MTKAIFV4_RXIF_FOUR_CHANNEL_SFT 1 +#define MTKAIFV4_RXIF_FOUR_CHANNEL_MASK 0x1 +#define MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1) +#define MTKAIFV4_RXIF_AFE_ON_SFT 0 +#define MTKAIFV4_RXIF_AFE_ON_MASK 0x1 +#define MTKAIFV4_RXIF_AFE_ON_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_MTKAIFV4_RX_CFG1 */ +#define MTKAIFV4_RXIF_SYNC_CNT_TABLE_SFT 17 +#define MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK 0xfff +#define MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 17) +#define MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_SFT 12 +#define MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK 0x1f +#define MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0x1f << 12) +#define MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_SFT 8 +#define MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK 0xf +#define MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8) +#define MTKAIFV4_RXIF_SYNC_CHECK_ROUND_SFT 4 +#define MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK 0xf +#define MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4) +#define MTKAIFV4_RXIF_FIFO_RSP_SFT 1 +#define MTKAIFV4_RXIF_FIFO_RSP_MASK 0x7 +#define MTKAIFV4_RXIF_FIFO_RSP_MASK_SFT (0x7 << 1) +#define MTKAIFV4_RXIF_SELF_DEFINE_TABLE_SFT 0 +#define MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK 0x1 +#define MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK_SFT (0x1 << 0) + +/* AFE_ADDA6_MTKAIFV4_RX_CFG0 */ +#define ADDA6_MTKAIFV4_RXIF_CLKINV_SFT 31 +#define ADDA6_MTKAIFV4_RXIF_CLKINV_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_CLKINV_MASK_SFT (0x1 << 31) +#define ADDA6_MTKAIFV4_RXIF_LOOPBACK_MODE_SFT 28 +#define ADDA6_MTKAIFV4_RXIF_LOOPBACK_MODE_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_LOOPBACK_MODE_MASK_SFT (0x1 << 28) +#define ADDA6_MTKAIFV4_RXIF_EN_SEL_SFT 12 +#define ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK_SFT (0x1 << 12) +#define ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT 4 +#define ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK 0x1f +#define ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT (0x1f << 4) +#define ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_SFT 1 +#define ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1) +#define ADDA6_MTKAIFV4_RXIF_AFE_ON_SFT 0 +#define ADDA6_MTKAIFV4_RXIF_AFE_ON_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_AFE_ON_MASK_SFT (0x1 << 0) + +/* AFE_ADDA6_MTKAIFV4_RX_CFG1 */ +#define ADDA6_MTKAIFV4_RXIF_SYNC_CNT_TABLE_SFT 17 +#define ADDA6_MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK 0xfff +#define ADDA6_MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 17) +#define ADDA6_MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_SFT 12 +#define ADDA6_MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK 0x1f +#define ADDA6_MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0x1f << 12) +#define ADDA6_MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_SFT 8 +#define ADDA6_MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK 0xf +#define ADDA6_MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8) +#define ADDA6_MTKAIFV4_RXIF_SYNC_CHECK_ROUND_SFT 4 +#define ADDA6_MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK 0xf +#define ADDA6_MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4) +#define ADDA6_MTKAIFV4_RXIF_FIFO_RSP_SFT 1 +#define ADDA6_MTKAIFV4_RXIF_FIFO_RSP_MASK 0x7 +#define ADDA6_MTKAIFV4_RXIF_FIFO_RSP_MASK_SFT (0x7 << 1) +#define ADDA6_MTKAIFV4_RXIF_SELF_DEFINE_TABLE_SFT 0 +#define ADDA6_MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK_SFT (0x1 << 0) + +/* AFE_ADDA_MTKAIFV4_TX_SYNCWORD_CFG */ +#define ADDA6_MTKAIFV4_TXIF_SYNCWORD_SFT 16 +#define ADDA6_MTKAIFV4_TXIF_SYNCWORD_MASK 0xffff +#define ADDA6_MTKAIFV4_TXIF_SYNCWORD_MASK_SFT (0xffff << 16) +#define ADDA_MTKAIFV4_TXIF_SYNCWORD_SFT 0 +#define ADDA_MTKAIFV4_TXIF_SYNCWORD_MASK 0xffff +#define ADDA_MTKAIFV4_TXIF_SYNCWORD_MASK_SFT (0xffff << 0) + +/* AFE_ADDA_MTKAIFV4_RX_SYNCWORD_CFG */ +#define ADDA6_MTKAIFV4_RXIF_SYNCWORD_SFT 16 +#define ADDA6_MTKAIFV4_RXIF_SYNCWORD_MASK 0xffff +#define ADDA6_MTKAIFV4_RXIF_SYNCWORD_MASK_SFT (0xffff << 16) +#define ADDA_MTKAIFV4_RXIF_SYNCWORD_SFT 0 +#define ADDA_MTKAIFV4_RXIF_SYNCWORD_MASK 0xffff +#define ADDA_MTKAIFV4_RXIF_SYNCWORD_MASK_SFT (0xffff << 0) + +/* AFE_ADDA_MTKAIFV4_MON0 */ +#define MTKAIFV4_TXIF_SDATA_OUT_SFT 23 +#define MTKAIFV4_TXIF_SDATA_OUT_MASK 0x1 +#define MTKAIFV4_TXIF_SDATA_OUT_MASK_SFT (0x1 << 23) +#define MTKAIFV4_RXIF_SDATA_IN_SFT 22 +#define MTKAIFV4_RXIF_SDATA_IN_MASK 0x1 +#define MTKAIFV4_RXIF_SDATA_IN_MASK_SFT (0x1 << 22) +#define MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_SFT 21 +#define MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK 0x1 +#define MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK_SFT (0x1 << 21) +#define MTKAIFV4_RXIF_ADC_FIFO_STATUS_SFT 0 +#define MTKAIFV4_RXIF_ADC_FIFO_STATUS_MASK 0xfff +#define MTKAIFV4_RXIF_ADC_FIFO_STATUS_MASK_SFT (0xfff << 0) + +/* AFE_ADDA_MTKAIFV4_MON1 */ +#define MTKAIFV4_RXIF_OUT_CH4_SFT 24 +#define MTKAIFV4_RXIF_OUT_CH4_MASK 0xff +#define MTKAIFV4_RXIF_OUT_CH4_MASK_SFT (0xff << 24) +#define MTKAIFV4_RXIF_OUT_CH3_SFT 16 +#define MTKAIFV4_RXIF_OUT_CH3_MASK 0xff +#define MTKAIFV4_RXIF_OUT_CH3_MASK_SFT (0xff << 16) +#define MTKAIFV4_RXIF_OUT_CH2_SFT 8 +#define MTKAIFV4_RXIF_OUT_CH2_MASK 0xff +#define MTKAIFV4_RXIF_OUT_CH2_MASK_SFT (0xff << 8) +#define MTKAIFV4_RXIF_OUT_CH1_SFT 0 +#define MTKAIFV4_RXIF_OUT_CH1_MASK 0xff +#define MTKAIFV4_RXIF_OUT_CH1_MASK_SFT (0xff << 0) + +/* AFE_ADDA6_MTKAIFV4_MON0 */ +#define ADDA6_MTKAIFV4_TXIF_SDATA_OUT_SFT 23 +#define ADDA6_MTKAIFV4_TXIF_SDATA_OUT_MASK 0x1 +#define ADDA6_MTKAIFV4_TXIF_SDATA_OUT_MASK_SFT (0x1 << 23) +#define ADDA6_MTKAIFV4_RXIF_SDATA_IN_SFT 22 +#define ADDA6_MTKAIFV4_RXIF_SDATA_IN_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_SDATA_IN_MASK_SFT (0x1 << 22) +#define ADDA6_MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_SFT 21 +#define ADDA6_MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK 0x1 +#define ADDA6_MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK_SFT (0x1 << 21) +#define ADDA6_MTKAIFV3P3_RXIF_ADC_FIFO_STATUS_SFT 0 +#define ADDA6_MTKAIFV3P3_RXIF_ADC_FIFO_STATUS_MASK 0xfff +#define ADDA6_MTKAIFV3P3_RXIF_ADC_FIFO_STATUS_MASK_SFT (0xfff << 0) + +/* ETDM_IN0_CON0 */ +#define REG_ETDM_IN_EN_SFT 0 +#define REG_ETDM_IN_EN_MASK 0x1 +#define REG_ETDM_IN_EN_MASK_SFT (0x1 << 0) +#define REG_SYNC_MODE_SFT 1 +#define REG_SYNC_MODE_MASK 0x1 +#define REG_SYNC_MODE_MASK_SFT (0x1 << 1) +#define REG_LSB_FIRST_SFT 3 +#define REG_LSB_FIRST_MASK 0x1 +#define REG_LSB_FIRST_MASK_SFT (0x1 << 3) +#define REG_SOFT_RST_SFT 4 +#define REG_SOFT_RST_MASK 0x1 +#define REG_SOFT_RST_MASK_SFT (0x1 << 4) +#define REG_SLAVE_MODE_SFT 5 +#define REG_SLAVE_MODE_MASK 0x1 +#define REG_SLAVE_MODE_MASK_SFT (0x1 << 5) +#define REG_FMT_SFT 6 +#define REG_FMT_MASK 0x7 +#define REG_FMT_MASK_SFT (0x7 << 6) +#define REG_LRCK_EDGE_SEL_SFT 10 +#define REG_LRCK_EDGE_SEL_MASK 0x1 +#define REG_LRCK_EDGE_SEL_MASK_SFT (0x1 << 10) +#define REG_BIT_LENGTH_SFT 11 +#define REG_BIT_LENGTH_MASK 0x1f +#define REG_BIT_LENGTH_MASK_SFT (0x1f << 11) +#define REG_WORD_LENGTH_SFT 16 +#define REG_WORD_LENGTH_MASK 0x1f +#define REG_WORD_LENGTH_MASK_SFT (0x1f << 16) +#define REG_CH_NUM_SFT 23 +#define REG_CH_NUM_MASK 0x1f +#define REG_CH_NUM_MASK_SFT (0x1f << 23) +#define REG_RELATCH_1X_EN_DOMAIN_SEL_SFT 28 +#define REG_RELATCH_1X_EN_DOMAIN_SEL_MASK 0x7 +#define REG_RELATCH_1X_EN_DOMAIN_SEL_MASK_SFT (0x7 << 28) +#define REG_VALID_TOGETHER_SFT 31 +#define REG_VALID_TOGETHER_MASK 0x1 +#define REG_VALID_TOGETHER_MASK_SFT (0x1 << 31) + +/* ETDM_IN0_CON1 */ +/* ETDM_IN1_CON1 */ +/* ETDM_IN2_CON1 */ +/* ETDM_IN3_CON1 */ +/* ETDM_IN4_CON1 */ +/* ETDM_IN5_CON1 */ +/* ETDM_IN6_CON1 */ +#define REG_INITIAL_COUNT_SFT 0 +#define REG_INITIAL_COUNT_MASK 0x1f +#define REG_INITIAL_COUNT_MASK_SFT (0x1f << 0) +#define REG_INITIAL_POINT_SFT 5 +#define REG_INITIAL_POINT_MASK 0x1f +#define REG_INITIAL_POINT_MASK_SFT (0x1f << 5) +#define REG_LRCK_AUTO_OFF_SFT 10 +#define REG_LRCK_AUTO_OFF_MASK 0x1 +#define REG_LRCK_AUTO_OFF_MASK_SFT (0x1 << 10) +#define REG_BCK_AUTO_OFF_SFT 11 +#define REG_BCK_AUTO_OFF_MASK 0x1 +#define REG_BCK_AUTO_OFF_MASK_SFT (0x1 << 11) +#define REG_INITIAL_LRCK_SFT 13 +#define REG_INITIAL_LRCK_MASK 0x1 +#define REG_INITIAL_LRCK_MASK_SFT (0x1 << 13) +#define REG_NO_ALIGN_1X_EN_SFT 14 +#define REG_NO_ALIGN_1X_EN_MASK 0x1 +#define REG_NO_ALIGN_1X_EN_MASK_SFT (0x1 << 14) +#define REG_LRCK_RESET_SFT 15 +#define REG_LRCK_RESET_MASK 0x1 +#define REG_LRCK_RESET_MASK_SFT (0x1 << 15) +#define PINMUX_MCLK_CTRL_OE_SFT 16 +#define PINMUX_MCLK_CTRL_OE_MASK 0x1 +#define PINMUX_MCLK_CTRL_OE_MASK_SFT (0x1 << 16) +#define REG_OUTPUT_CR_EN_SFT 18 +#define REG_OUTPUT_CR_EN_MASK 0x1 +#define REG_OUTPUT_CR_EN_MASK_SFT (0x1 << 18) +#define REG_LR_ALIGN_SFT 19 +#define REG_LR_ALIGN_MASK 0x1 +#define REG_LR_ALIGN_MASK_SFT (0x1 << 19) +#define REG_LRCK_WIDTH_SFT 20 +#define REG_LRCK_WIDTH_MASK 0x3ff +#define REG_LRCK_WIDTH_MASK_SFT (0x3ff << 20) +#define REG_DIRECT_INPUT_MASTER_BCK_SFT 30 +#define REG_DIRECT_INPUT_MASTER_BCK_MASK 0x1 +#define REG_DIRECT_INPUT_MASTER_BCK_MASK_SFT (0x1 << 30) +#define REG_LRCK_AUTO_MODE_SFT 31 +#define REG_LRCK_AUTO_MODE_MASK 0x1 +#define REG_LRCK_AUTO_MODE_MASK_SFT (0x1 << 31) + +/* ETDM_IN0_CON2 */ +/* ETDM_IN1_CON2 */ +/* ETDM_IN2_CON2 */ +/* ETDM_IN3_CON2 */ +/* ETDM_IN4_CON2 */ +/* ETDM_IN5_CON2 */ +/* ETDM_IN6_CON2 */ +#define REG_UPDATE_POINT_SFT 0 +#define REG_UPDATE_POINT_MASK 0x1f +#define REG_UPDATE_POINT_MASK_SFT (0x1f << 0) +#define REG_UPDATE_GAP_SFT 5 +#define REG_UPDATE_GAP_MASK 0x1f +#define REG_UPDATE_GAP_MASK_SFT (0x1f << 5) +#define REG_CLOCK_SOURCE_SEL_SFT 10 +#define REG_CLOCK_SOURCE_SEL_MASK 0x7 +#define REG_CLOCK_SOURCE_SEL_MASK_SFT (0x7 << 10) +#define REG_CK_EN_SEL_AUTO_SFT 14 +#define REG_CK_EN_SEL_AUTO_MASK 0x1 +#define REG_CK_EN_SEL_AUTO_MASK_SFT (0x1 << 14) +#define REG_MULTI_IP_TOTAL_CHNUM_SFT 15 +#define REG_MULTI_IP_TOTAL_CHNUM_MASK 0x1f +#define REG_MULTI_IP_TOTAL_CHNUM_MASK_SFT (0x1f << 15) +#define REG_MASK_AUTO_SFT 20 +#define REG_MASK_AUTO_MASK 0x1 +#define REG_MASK_AUTO_MASK_SFT (0x1 << 20) +#define REG_MASK_NUM_SFT 21 +#define REG_MASK_NUM_MASK 0x1f +#define REG_MASK_NUM_MASK_SFT (0x1f << 21) +#define REG_UPDATE_POINT_AUTO_SFT 26 +#define REG_UPDATE_POINT_AUTO_MASK 0x1 +#define REG_UPDATE_POINT_AUTO_MASK_SFT (0x1 << 26) +#define REG_SDATA_DELAY_0P5T_EN_SFT 27 +#define REG_SDATA_DELAY_0P5T_EN_MASK 0x1 +#define REG_SDATA_DELAY_0P5T_EN_MASK_SFT (0x1 << 27) +#define REG_SDATA_DELAY_BCK_INV_SFT 28 +#define REG_SDATA_DELAY_BCK_INV_MASK 0x1 +#define REG_SDATA_DELAY_BCK_INV_MASK_SFT (0x1 << 28) +#define REG_LRCK_DELAY_0P5T_EN_SFT 29 +#define REG_LRCK_DELAY_0P5T_EN_MASK 0x1 +#define REG_LRCK_DELAY_0P5T_EN_MASK_SFT (0x1 << 29) +#define REG_LRCK_DELAY_BCK_INV_SFT 30 +#define REG_LRCK_DELAY_BCK_INV_MASK 0x1 +#define REG_LRCK_DELAY_BCK_INV_MASK_SFT (0x1 << 30) +#define REG_MULTI_IP_MODE_SFT 31 +#define REG_MULTI_IP_MODE_MASK 0x1 +#define REG_MULTI_IP_MODE_MASK_SFT (0x1 << 31) + +/* ETDM_IN0_CON3 */ +/* ETDM_IN1_CON3 */ +/* ETDM_IN2_CON3 */ +/* ETDM_IN3_CON3 */ +/* ETDM_IN4_CON3 */ +/* ETDM_IN5_CON3 */ +/* ETDM_IN6_CON3 */ +#define REG_DISABLE_OUT_SFT 0 +#define REG_DISABLE_OUT_MASK 0xffff +#define REG_DISABLE_OUT_MASK_SFT (0xffff << 0) +#define REG_RJ_DATA_RIGHT_ALIGN_SFT 16 +#define REG_RJ_DATA_RIGHT_ALIGN_MASK 0x1 +#define REG_RJ_DATA_RIGHT_ALIGN_MASK_SFT (0x1 << 16) +#define REG_MONITOR_SEL_SFT 17 +#define REG_MONITOR_SEL_MASK 0x3 +#define REG_MONITOR_SEL_MASK_SFT (0x3 << 17) +#define REG_CNT_UPPER_LIMIT_SFT 19 +#define REG_CNT_UPPER_LIMIT_MASK 0x3f +#define REG_CNT_UPPER_LIMIT_MASK_SFT (0x3f << 19) +#define REG_COMPACT_SAMPLE_END_DIS_SFT 25 +#define REG_COMPACT_SAMPLE_END_DIS_MASK 0x1 +#define REG_COMPACT_SAMPLE_END_DIS_MASK_SFT (0x1 << 25) +#define REG_FS_TIMING_SEL_SFT 26 +#define REG_FS_TIMING_SEL_MASK 0x1f +#define REG_FS_TIMING_SEL_MASK_SFT (0x1f << 26) +#define REG_SAMPLE_END_MODE_SFT 31 +#define REG_SAMPLE_END_MODE_MASK 0x1 +#define REG_SAMPLE_END_MODE_MASK_SFT (0x1 << 31) + +/* ETDM_IN0_CON4 */ +/* ETDM_IN1_CON4 */ +/* ETDM_IN2_CON4 */ +/* ETDM_IN3_CON4 */ +/* ETDM_IN4_CON4 */ +/* ETDM_IN5_CON4 */ +/* ETDM_IN6_CON4 */ +#define REG_ALWAYS_OPEN_1X_EN_SFT 31 +#define REG_ALWAYS_OPEN_1X_EN_MASK 0x1 +#define REG_ALWAYS_OPEN_1X_EN_MASK_SFT (0x1 << 31) +#define REG_WAIT_LAST_SAMPLE_SFT 30 +#define REG_WAIT_LAST_SAMPLE_MASK 0x1 +#define REG_WAIT_LAST_SAMPLE_MASK_SFT (0x1 << 30) +#define REG_SAMPLE_END_POINT_SFT 25 +#define REG_SAMPLE_END_POINT_MASK 0x1f +#define REG_SAMPLE_END_POINT_MASK_SFT (0x1f << 25) +#define REG_RELATCH_1X_EN_SEL_SFT 20 +#define REG_RELATCH_1X_EN_SEL_MASK 0x1f +#define REG_RELATCH_1X_EN_SEL_MASK_SFT (0x1f << 20) +#define REG_MASTER_WS_INV_SFT 19 +#define REG_MASTER_WS_INV_MASK 0x1 +#define REG_MASTER_WS_INV_MASK_SFT (0x1 << 19) +#define REG_MASTER_BCK_INV_SFT 18 +#define REG_MASTER_BCK_INV_MASK 0x1 +#define REG_MASTER_BCK_INV_MASK_SFT (0x1 << 18) +#define REG_SLAVE_LRCK_INV_SFT 17 +#define REG_SLAVE_LRCK_INV_MASK 0x1 +#define REG_SLAVE_LRCK_INV_MASK_SFT (0x1 << 17) +#define REG_SLAVE_BCK_INV_SFT 16 +#define REG_SLAVE_BCK_INV_MASK 0x1 +#define REG_SLAVE_BCK_INV_MASK_SFT (0x1 << 16) +#define REG_REPACK_CHNUM_SFT 12 +#define REG_REPACK_CHNUM_MASK 0xf +#define REG_REPACK_CHNUM_MASK_SFT (0xf << 12) +#define REG_ASYNC_RESET_SFT 11 +#define REG_ASYNC_RESET_MASK 0x1 +#define REG_ASYNC_RESET_MASK_SFT (0x1 << 11) +#define REG_REPACK_WORD_LENGTH_SFT 9 +#define REG_REPACK_WORD_LENGTH_MASK 0x3 +#define REG_REPACK_WORD_LENGTH_MASK_SFT (0x3 << 9) +#define REG_REPACK_AUTO_MODE_SFT 8 +#define REG_REPACK_AUTO_MODE_MASK 0x1 +#define REG_REPACK_AUTO_MODE_MASK_SFT (0x1 << 8) +#define REG_REPACK_MODE_SFT 0 +#define REG_REPACK_MODE_MASK 0x3f +#define REG_REPACK_MODE_MASK_SFT (0x3f << 0) + +/* ETDM_IN0_CON5 */ +/* ETDM_IN1_CON5 */ +/* ETDM_IN2_CON5 */ +/* ETDM_IN3_CON5 */ +/* ETDM_IN4_CON5 */ +/* ETDM_IN5_CON5 */ +/* ETDM_IN6_CON5 */ +#define REG_LR_SWAP_SFT 16 +#define REG_LR_SWAP_MASK 0xffff +#define REG_LR_SWAP_MASK_SFT (0xffff << 16) +#define REG_ODD_FLAG_EN_SFT 0 +#define REG_ODD_FLAG_EN_MASK 0xffff +#define REG_ODD_FLAG_EN_MASK_SFT (0xffff << 0) + +/* ETDM_IN0_CON6 */ +/* ETDM_IN1_CON6 */ +/* ETDM_IN2_CON6 */ +/* ETDM_IN3_CON6 */ +/* ETDM_IN4_CON6 */ +/* ETDM_IN5_CON6 */ +/* ETDM_IN6_CON6 */ +#define LCH_DATA_REG_SFT 0 +#define LCH_DATA_REG_MASK 0xffffffff +#define LCH_DATA_REG_MASK_SFT (0xffffffff << 0) + +/* ETDM_IN0_CON7 */ +/* ETDM_IN1_CON7 */ +/* ETDM_IN2_CON7 */ +/* ETDM_IN3_CON7 */ +/* ETDM_IN4_CON7 */ +/* ETDM_IN5_CON7 */ +/* ETDM_IN6_CON7 */ +#define RCH_DATA_REG_SFT 0 +#define RCH_DATA_REG_MASK 0xffffffff +#define RCH_DATA_REG_MASK_SFT (0xffffffff << 0) + +/* ETDM_IN0_CON8 */ +/* ETDM_IN1_CON8 */ +/* ETDM_IN2_CON8 */ +/* ETDM_IN3_CON8 */ +/* ETDM_IN4_CON8 */ +/* ETDM_IN5_CON8 */ +/* ETDM_IN6_CON8 */ +#define REG_AFIFO_THRESHOLD_SFT 29 +#define REG_AFIFO_THRESHOLD_MASK 0x3 +#define REG_AFIFO_THRESHOLD_MASK_SFT (0x3 << 29) +#define REG_CK_EN_SEL_MANUAL_SFT 16 +#define REG_CK_EN_SEL_MANUAL_MASK 0x3ff +#define REG_CK_EN_SEL_MANUAL_MASK_SFT (0x3ff << 16) +#define REG_AFIFO_SW_RESET_SFT 15 +#define REG_AFIFO_SW_RESET_MASK 0x1 +#define REG_AFIFO_SW_RESET_MASK_SFT (0x1 << 15) +#define REG_AFIFO_RESET_SEL_SFT 14 +#define REG_AFIFO_RESET_SEL_MASK 0x1 +#define REG_AFIFO_RESET_SEL_MASK_SFT (0x1 << 14) +#define REG_AFIFO_AUTO_RESET_DIS_SFT 9 +#define REG_AFIFO_AUTO_RESET_DIS_MASK 0x1 +#define REG_AFIFO_AUTO_RESET_DIS_MASK_SFT (0x1 << 9) +#define REG_ETDM_USE_AFIFO_SFT 8 +#define REG_ETDM_USE_AFIFO_MASK 0x1 +#define REG_ETDM_USE_AFIFO_MASK_SFT (0x1 << 8) +#define REG_AFIFO_CLOCK_DOMAIN_SEL_SFT 5 +#define REG_AFIFO_CLOCK_DOMAIN_SEL_MASK 0x7 +#define REG_AFIFO_CLOCK_DOMAIN_SEL_MASK_SFT (0x7 << 5) +#define REG_AFIFO_MODE_SFT 0 +#define REG_AFIFO_MODE_MASK 0x1f +#define REG_AFIFO_MODE_MASK_SFT (0x1f << 0) + +/* ETDM_IN0_CON9 */ +/* ETDM_IN1_CON9 */ +/* ETDM_IN2_CON9 */ +/* ETDM_IN3_CON9 */ +/* ETDM_IN4_CON9 */ +/* ETDM_IN5_CON9 */ +/* ETDM_IN6_CON9 */ +#define REG_OUT2LATCH_TIME_SFT 10 +#define REG_OUT2LATCH_TIME_MASK 0x1f +#define REG_OUT2LATCH_TIME_MASK_SFT (0x1f << 10) +#define REG_ALMOST_END_BIT_COUNT_SFT 5 +#define REG_ALMOST_END_BIT_COUNT_MASK 0x1f +#define REG_ALMOST_END_BIT_COUNT_MASK_SFT (0x1f << 5) +#define REG_ALMOST_END_CH_COUNT_SFT 0 +#define REG_ALMOST_END_CH_COUNT_MASK 0x1f +#define REG_ALMOST_END_CH_COUNT_MASK_SFT (0x1f << 0) + +/* ETDM_IN0_MON */ +/* ETDM_IN1_MON */ +/* ETDM_IN2_MON */ +/* ETDM_IN3_MON */ +/* ETDM_IN4_MON */ +/* ETDM_IN5_MON */ +/* ETDM_IN6_MON */ +#define LRCK_INV_SFT 30 +#define LRCK_INV_MASK 0x1 +#define LRCK_INV_MASK_SFT (0x1 << 30) +#define EN_SYNC_OUT_SFT 29 +#define EN_SYNC_OUT_MASK 0x1 +#define EN_SYNC_OUT_MASK_SFT (0x1 << 29) +#define HOPPING_EN_SYNC_OUT_PRE_SFT 28 +#define HOPPING_EN_SYNC_OUT_PRE_MASK 0x1 +#define HOPPING_EN_SYNC_OUT_PRE_MASK_SFT (0x1 << 28) +#define WFULL_SFT 27 +#define WFULL_MASK 0x1 +#define WFULL_MASK_SFT (0x1 << 27) +#define REMPTY_SFT 26 +#define REMPTY_MASK 0x1 +#define REMPTY_MASK_SFT (0x1 << 26) +#define ETDM_2X_CK_EN_SFT 25 +#define ETDM_2X_CK_EN_MASK 0x1 +#define ETDM_2X_CK_EN_MASK_SFT (0x1 << 25) +#define ETDM_1X_CK_EN_SFT 24 +#define ETDM_1X_CK_EN_MASK 0x1 +#define ETDM_1X_CK_EN_MASK_SFT (0x1 << 24) +#define SDATA0_SFT 23 +#define SDATA0_MASK 0x1 +#define SDATA0_MASK_SFT (0x1 << 23) +#define CURRENT_STATUS_SFT 21 +#define CURRENT_STATUS_MASK 0x3 +#define CURRENT_STATUS_MASK_SFT (0x3 << 21) +#define BIT_POINT_SFT 16 +#define BIT_POINT_MASK 0x1f +#define BIT_POINT_MASK_SFT (0x1f << 16) +#define BIT_CH_COUNT_SFT 10 +#define BIT_CH_COUNT_MASK 0x3f +#define BIT_CH_COUNT_MASK_SFT (0x3f << 10) +#define BIT_COUNT_SFT 5 +#define BIT_COUNT_MASK 0x1f +#define BIT_COUNT_MASK_SFT (0x1f << 5) +#define CH_COUNT_SFT 0 +#define CH_COUNT_MASK 0x1f +#define CH_COUNT_MASK_SFT (0x1f << 0) + +/* ETDM_OUT0_CON0 */ +/* ETDM_OUT1_CON0 */ +/* ETDM_OUT2_CON0 */ +/* ETDM_OUT3_CON0 */ +/* ETDM_OUT4_CON0 */ +/* ETDM_OUT5_CON0 */ +/* ETDM_OUT6_CON0 */ +#define OUT_REG_ETDM_OUT_EN_SFT 0 +#define OUT_REG_ETDM_OUT_EN_MASK 0x1 +#define OUT_REG_ETDM_OUT_EN_MASK_SFT (0x1 << 0) +#define OUT_REG_SYNC_MODE_SFT 1 +#define OUT_REG_SYNC_MODE_MASK 0x1 +#define OUT_REG_SYNC_MODE_MASK_SFT (0x1 << 1) +#define OUT_REG_LSB_FIRST_SFT 3 +#define OUT_REG_LSB_FIRST_MASK 0x1 +#define OUT_REG_LSB_FIRST_MASK_SFT (0x1 << 3) +#define OUT_REG_SOFT_RST_SFT 4 +#define OUT_REG_SOFT_RST_MASK 0x1 +#define OUT_REG_SOFT_RST_MASK_SFT (0x1 << 4) +#define OUT_REG_SLAVE_MODE_SFT 5 +#define OUT_REG_SLAVE_MODE_MASK 0x1 +#define OUT_REG_SLAVE_MODE_MASK_SFT (0x1 << 5) +#define OUT_REG_FMT_SFT 6 +#define OUT_REG_FMT_MASK 0x7 +#define OUT_REG_FMT_MASK_SFT (0x7 << 6) +#define OUT_REG_LRCK_EDGE_SEL_SFT 10 +#define OUT_REG_LRCK_EDGE_SEL_MASK 0x1 +#define OUT_REG_LRCK_EDGE_SEL_MASK_SFT (0x1 << 10) +#define OUT_REG_BIT_LENGTH_SFT 11 +#define OUT_REG_BIT_LENGTH_MASK 0x1f +#define OUT_REG_BIT_LENGTH_MASK_SFT (0x1f << 11) +#define OUT_REG_WORD_LENGTH_SFT 16 +#define OUT_REG_WORD_LENGTH_MASK 0x1f +#define OUT_REG_WORD_LENGTH_MASK_SFT (0x1f << 16) +#define OUT_REG_CH_NUM_SFT 23 +#define OUT_REG_CH_NUM_MASK 0x1f +#define OUT_REG_CH_NUM_MASK_SFT (0x1f << 23) +#define OUT_REG_RELATCH_DOMAIN_SEL_SFT 28 +#define OUT_REG_RELATCH_DOMAIN_SEL_MASK 0x7 +#define OUT_REG_RELATCH_DOMAIN_SEL_MASK_SFT (0x7 << 28) +#define OUT_REG_VALID_TOGETHER_SFT 31 +#define OUT_REG_VALID_TOGETHER_MASK 0x1 +#define OUT_REG_VALID_TOGETHER_MASK_SFT (0x1 << 31) + +/* ETDM_OUT0_CON1 */ +/* ETDM_OUT1_CON1 */ +/* ETDM_OUT2_CON1 */ +/* ETDM_OUT3_CON1 */ +/* ETDM_OUT4_CON1 */ +/* ETDM_OUT5_CON1 */ +/* ETDM_OUT6_CON1 */ +#define OUT_REG_INITIAL_COUNT_SFT 0 +#define OUT_REG_INITIAL_COUNT_MASK 0x1f +#define OUT_REG_INITIAL_COUNT_MASK_SFT (0x1f << 0) +#define OUT_REG_INITIAL_POINT_SFT 5 +#define OUT_REG_INITIAL_POINT_MASK 0x1f +#define OUT_REG_INITIAL_POINT_MASK_SFT (0x1f << 5) +#define OUT_REG_LRCK_AUTO_OFF_SFT 10 +#define OUT_REG_LRCK_AUTO_OFF_MASK 0x1 +#define OUT_REG_LRCK_AUTO_OFF_MASK_SFT (0x1 << 10) +#define OUT_REG_BCK_AUTO_OFF_SFT 11 +#define OUT_REG_BCK_AUTO_OFF_MASK 0x1 +#define OUT_REG_BCK_AUTO_OFF_MASK_SFT (0x1 << 11) +#define OUT_REG_INITIAL_LRCK_SFT 13 +#define OUT_REG_INITIAL_LRCK_MASK 0x1 +#define OUT_REG_INITIAL_LRCK_MASK_SFT (0x1 << 13) +#define OUT_REG_NO_ALIGN_1X_EN_SFT 14 +#define OUT_REG_NO_ALIGN_1X_EN_MASK 0x1 +#define OUT_REG_NO_ALIGN_1X_EN_MASK_SFT (0x1 << 14) +#define OUT_REG_LRCK_RESET_SFT 15 +#define OUT_REG_LRCK_RESET_MASK 0x1 +#define OUT_REG_LRCK_RESET_MASK_SFT (0x1 << 15) +#define OUT_PINMUX_MCLK_CTRL_OE_SFT 16 +#define OUT_PINMUX_MCLK_CTRL_OE_MASK 0x1 +#define OUT_PINMUX_MCLK_CTRL_OE_MASK_SFT (0x1 << 16) +#define OUT_REG_OUTPUT_CR_EN_SFT 18 +#define OUT_REG_OUTPUT_CR_EN_MASK 0x1 +#define OUT_REG_OUTPUT_CR_EN_MASK_SFT (0x1 << 18) +#define OUT_REG_LRCK_WIDTH_SFT 19 +#define OUT_REG_LRCK_WIDTH_MASK 0x3ff +#define OUT_REG_LRCK_WIDTH_MASK_SFT (0x3ff << 19) +#define OUT_REG_LRCK_AUTO_MODE_SFT 29 +#define OUT_REG_LRCK_AUTO_MODE_MASK 0x1 +#define OUT_REG_LRCK_AUTO_MODE_MASK_SFT (0x1 << 29) +#define OUT_REG_DIRECT_INPUT_MASTER_BCK_SFT 30 +#define OUT_REG_DIRECT_INPUT_MASTER_BCK_MASK 0x1 +#define OUT_REG_DIRECT_INPUT_MASTER_BCK_MASK_SFT (0x1 << 30) +#define OUT_REG_16B_COMPACT_MODE_SFT 31 +#define OUT_REG_16B_COMPACT_MODE_MASK 0x1 +#define OUT_REG_16B_COMPACT_MODE_MASK_SFT (0x1 << 31) + +/* ETDM_OUT0_CON2 */ +/* ETDM_OUT1_CON2 */ +/* ETDM_OUT2_CON2 */ +/* ETDM_OUT3_CON2 */ +/* ETDM_OUT4_CON2 */ +/* ETDM_OUT5_CON2 */ +/* ETDM_OUT6_CON2 */ +#define OUT_REG_IN2LATCH_TIME_SFT 0 +#define OUT_REG_IN2LATCH_TIME_MASK 0x1f +#define OUT_REG_IN2LATCH_TIME_MASK_SFT (0x1f << 0) +#define OUT_REG_MASK_NUM_SFT 5 +#define OUT_REG_MASK_NUM_MASK 0x1f +#define OUT_REG_MASK_NUM_MASK_SFT (0x1f << 5) +#define OUT_REG_MASK_AUTO_SFT 10 +#define OUT_REG_MASK_AUTO_MASK 0x1 +#define OUT_REG_MASK_AUTO_MASK_SFT (0x1 << 10) +#define OUT_REG_SDATA_SHIFT_SFT 11 +#define OUT_REG_SDATA_SHIFT_MASK 0x3 +#define OUT_REG_SDATA_SHIFT_MASK_SFT (0x3 << 11) +#define OUT_REG_ALMOST_END_BIT_COUNT_SFT 13 +#define OUT_REG_ALMOST_END_BIT_COUNT_MASK 0x1f +#define OUT_REG_ALMOST_END_BIT_COUNT_MASK_SFT (0x1f << 13) +#define OUT_REG_SDATA_CON_SFT 18 +#define OUT_REG_SDATA_CON_MASK 0x3 +#define OUT_REG_SDATA_CON_MASK_SFT (0x3 << 18) +#define OUT_REG_REDUNDANT_0_SFT 20 +#define OUT_REG_REDUNDANT_0_MASK 0x1 +#define OUT_REG_REDUNDANT_0_MASK_SFT (0x1 << 20) +#define OUT_REG_SDATA_AUTO_OFF_SFT 21 +#define OUT_REG_SDATA_AUTO_OFF_MASK 0x1 +#define OUT_REG_SDATA_AUTO_OFF_MASK_SFT (0x1 << 21) +#define OUT_REG_BCK_OFF_TIME_SFT 22 +#define OUT_REG_BCK_OFF_TIME_MASK 0x3 +#define OUT_REG_BCK_OFF_TIME_MASK_SFT (0x3 << 22) +#define OUT_REG_MONITOR_SEL_SFT 24 +#define OUT_REG_MONITOR_SEL_MASK 0x3 +#define OUT_REG_MONITOR_SEL_MASK_SFT (0x3 << 24) +#define OUT_REG_SHIFT_AUTO_SFT 26 +#define OUT_REG_SHIFT_AUTO_MASK 0x1 +#define OUT_REG_SHIFT_AUTO_MASK_SFT (0x1 << 26) +#define OUT_REG_SDATA_DELAY_0P5T_EN_SFT 27 +#define OUT_REG_SDATA_DELAY_0P5T_EN_MASK 0x1 +#define OUT_REG_SDATA_DELAY_0P5T_EN_MASK_SFT (0x1 << 27) +#define OUT_REG_SDATA_DELAY_BCK_INV_SFT 28 +#define OUT_REG_SDATA_DELAY_BCK_INV_MASK 0x1 +#define OUT_REG_SDATA_DELAY_BCK_INV_MASK_SFT (0x1 << 28) +#define OUT_REG_LRCK_DELAY_0P5T_EN_SFT 29 +#define OUT_REG_LRCK_DELAY_0P5T_EN_MASK 0x1 +#define OUT_REG_LRCK_DELAY_0P5T_EN_MASK_SFT (0x1 << 29) +#define OUT_REG_LRCK_DELAY_BCK_INV_SFT 30 +#define OUT_REG_LRCK_DELAY_BCK_INV_MASK 0x1 +#define OUT_REG_LRCK_DELAY_BCK_INV_MASK_SFT (0x1 << 30) +#define OUT_REG_OFF_CR_EN_SFT 31 +#define OUT_REG_OFF_CR_EN_MASK 0x1 +#define OUT_REG_OFF_CR_EN_MASK_SFT (0x1 << 31) + +/* ETDM_OUT0_CON3 */ +/* ETDM_OUT1_CON3 */ +/* ETDM_OUT2_CON3 */ +/* ETDM_OUT3_CON3 */ +/* ETDM_OUT4_CON3 */ +/* ETDM_OUT5_CON3 */ +/* ETDM_OUT6_CON3 */ +#define OUT_REG_START_CH_PAIR0_SFT 0 +#define OUT_REG_START_CH_PAIR0_MASK 0xf +#define OUT_REG_START_CH_PAIR0_MASK_SFT (0xf << 0) +#define OUT_REG_START_CH_PAIR1_SFT 4 +#define OUT_REG_START_CH_PAIR1_MASK 0xf +#define OUT_REG_START_CH_PAIR1_MASK_SFT (0xf << 4) +#define OUT_REG_START_CH_PAIR2_SFT 8 +#define OUT_REG_START_CH_PAIR2_MASK 0xf +#define OUT_REG_START_CH_PAIR2_MASK_SFT (0xf << 8) +#define OUT_REG_START_CH_PAIR3_SFT 12 +#define OUT_REG_START_CH_PAIR3_MASK 0xf +#define OUT_REG_START_CH_PAIR3_MASK_SFT (0xf << 12) +#define OUT_REG_START_CH_PAIR4_SFT 16 +#define OUT_REG_START_CH_PAIR4_MASK 0xf +#define OUT_REG_START_CH_PAIR4_MASK_SFT (0xf << 16) +#define OUT_REG_START_CH_PAIR5_SFT 20 +#define OUT_REG_START_CH_PAIR5_MASK 0xf +#define OUT_REG_START_CH_PAIR5_MASK_SFT (0xf << 20) +#define OUT_REG_START_CH_PAIR6_SFT 24 +#define OUT_REG_START_CH_PAIR6_MASK 0xf +#define OUT_REG_START_CH_PAIR6_MASK_SFT (0xf << 24) +#define OUT_REG_START_CH_PAIR7_SFT 28 +#define OUT_REG_START_CH_PAIR7_MASK 0xf +#define OUT_REG_START_CH_PAIR7_MASK_SFT (0xf << 28) + +/* ETDM_OUT0_CON4 */ +/* ETDM_OUT1_CON4 */ +/* ETDM_OUT2_CON4 */ +/* ETDM_OUT3_CON4 */ +/* ETDM_OUT4_CON4 */ +/* ETDM_OUT5_CON4 */ +/* ETDM_OUT6_CON4 */ +#define OUT_REG_FS_TIMING_SEL_SFT 0 +#define OUT_REG_FS_TIMING_SEL_MASK 0x1f +#define OUT_REG_FS_TIMING_SEL_MASK_SFT (0x1f << 0) +#define OUT_REG_CLOCK_SOURCE_SEL_SFT 6 +#define OUT_REG_CLOCK_SOURCE_SEL_MASK 0x7 +#define OUT_REG_CLOCK_SOURCE_SEL_MASK_SFT (0x7 << 6) +#define OUT_REG_CK_EN_SEL_AUTO_SFT 10 +#define OUT_REG_CK_EN_SEL_AUTO_MASK 0x1 +#define OUT_REG_CK_EN_SEL_AUTO_MASK_SFT (0x1 << 10) +#define OUT_REG_ASYNC_RESET_SFT 11 +#define OUT_REG_ASYNC_RESET_MASK 0x1 +#define OUT_REG_ASYNC_RESET_MASK_SFT (0x1 << 11) +#define OUT_REG_CK_EN_SEL_MANUAL_SFT 14 +#define OUT_REG_CK_EN_SEL_MANUAL_MASK 0x3ff +#define OUT_REG_CK_EN_SEL_MANUAL_MASK_SFT (0x3ff << 14) +#define OUT_REG_RELATCH_EN_SEL_SFT 24 +#define OUT_REG_RELATCH_EN_SEL_MASK 0x1f +#define OUT_REG_RELATCH_EN_SEL_MASK_SFT (0x1f << 24) +#define OUT_REG_WAIT_LAST_SAMPLE_SFT 30 +#define OUT_REG_WAIT_LAST_SAMPLE_MASK 0x1 +#define OUT_REG_WAIT_LAST_SAMPLE_MASK_SFT (0x1 << 30) +#define OUT_REG_ALWAYS_OPEN_1X_EN_SFT 31 +#define OUT_REG_ALWAYS_OPEN_1X_EN_MASK 0x1 +#define OUT_REG_ALWAYS_OPEN_1X_EN_MASK_SFT (0x1 << 31) + +/* ETDM_OUT0_CON5 */ +/* ETDM_OUT1_CON5 */ +/* ETDM_OUT2_CON5 */ +/* ETDM_OUT3_CON5 */ +/* ETDM_OUT4_CON5 */ +/* ETDM_OUT5_CON5 */ +/* ETDM_OUT6_CON5 */ +#define OUT_REG_REPACK_BITNUM_SFT 0 +#define OUT_REG_REPACK_BITNUM_MASK 0x3 +#define OUT_REG_REPACK_BITNUM_MASK_SFT (0x3 << 0) +#define OUT_REG_REPACK_CHNUM_SFT 2 +#define OUT_REG_REPACK_CHNUM_MASK 0xf +#define OUT_REG_REPACK_CHNUM_MASK_SFT (0xf << 2) +#define OUT_REG_SLAVE_BCK_INV_SFT 7 +#define OUT_REG_SLAVE_BCK_INV_MASK 0x1 +#define OUT_REG_SLAVE_BCK_INV_MASK_SFT (0x1 << 7) +#define OUT_REG_SLAVE_LRCK_INV_SFT 8 +#define OUT_REG_SLAVE_LRCK_INV_MASK 0x1 +#define OUT_REG_SLAVE_LRCK_INV_MASK_SFT (0x1 << 8) +#define OUT_REG_MASTER_BCK_INV_SFT 9 +#define OUT_REG_MASTER_BCK_INV_MASK 0x1 +#define OUT_REG_MASTER_BCK_INV_MASK_SFT (0x1 << 9) +#define OUT_REG_MASTER_WS_INV_SFT 10 +#define OUT_REG_MASTER_WS_INV_MASK 0x1 +#define OUT_REG_MASTER_WS_INV_MASK_SFT (0x1 << 10) +#define OUT_REG_REPACK_24B_MSB_ALIGN_SFT 11 +#define OUT_REG_REPACK_24B_MSB_ALIGN_MASK 0x1 +#define OUT_REG_REPACK_24B_MSB_ALIGN_MASK_SFT (0x1 << 11) +#define OUT_REG_LR_SWAP_SFT 16 +#define OUT_REG_LR_SWAP_MASK 0xffff +#define OUT_REG_LR_SWAP_MASK_SFT (0xffff << 16) + +/* ETDM_OUT0_CON6 */ +/* ETDM_OUT1_CON6 */ +/* ETDM_OUT2_CON6 */ +/* ETDM_OUT3_CON6 */ +/* ETDM_OUT4_CON6 */ +/* ETDM_OUT5_CON6 */ +/* ETDM_OUT6_CON6 */ +#define OUT_LCH_DATA_REG_SFT 0 +#define OUT_LCH_DATA_REG_MASK 0xffffffff +#define OUT_LCH_DATA_REG_MASK_SFT (0xffffffff << 0) + +/* ETDM_OUT0_CON7 */ +/* ETDM_OUT1_CON7 */ +/* ETDM_OUT2_CON7 */ +/* ETDM_OUT3_CON7 */ +/* ETDM_OUT4_CON7 */ +/* ETDM_OUT5_CON7 */ +/* ETDM_OUT6_CON7 */ +#define OUT_RCH_DATA_REG_SFT 0 +#define OUT_RCH_DATA_REG_MASK 0xffffffff +#define OUT_RCH_DATA_REG_MASK_SFT (0xffffffff << 0) + +/* ETDM_OUT0_CON8 */ +/* ETDM_OUT1_CON8 */ +/* ETDM_OUT2_CON8 */ +/* ETDM_OUT3_CON8 */ +/* ETDM_OUT4_CON8 */ +/* ETDM_OUT5_CON8 */ +/* ETDM_OUT6_CON8 */ +#define OUT_REG_START_CH_PAIR8_SFT 0 +#define OUT_REG_START_CH_PAIR8_MASK 0xf +#define OUT_REG_START_CH_PAIR8_MASK_SFT (0xf << 0) +#define OUT_REG_START_CH_PAIR9_SFT 4 +#define OUT_REG_START_CH_PAIR9_MASK 0xf +#define OUT_REG_START_CH_PAIR9_MASK_SFT (0xf << 4) +#define OUT_REG_START_CH_PAIR10_SFT 8 +#define OUT_REG_START_CH_PAIR10_MASK 0xf +#define OUT_REG_START_CH_PAIR10_MASK_SFT (0xf << 8) +#define OUT_REG_START_CH_PAIR11_SFT 12 +#define OUT_REG_START_CH_PAIR11_MASK 0xf +#define OUT_REG_START_CH_PAIR11_MASK_SFT (0xf << 12) +#define OUT_REG_START_CH_PAIR12_SFT 16 +#define OUT_REG_START_CH_PAIR12_MASK 0xf +#define OUT_REG_START_CH_PAIR12_MASK_SFT (0xf << 16) +#define OUT_REG_START_CH_PAIR13_SFT 20 +#define OUT_REG_START_CH_PAIR13_MASK 0xf +#define OUT_REG_START_CH_PAIR13_MASK_SFT (0xf << 20) +#define OUT_REG_START_CH_PAIR14_SFT 24 +#define OUT_REG_START_CH_PAIR14_MASK 0xf +#define OUT_REG_START_CH_PAIR14_MASK_SFT (0xf << 24) +#define OUT_REG_START_CH_PAIR15_SFT 28 +#define OUT_REG_START_CH_PAIR15_MASK 0xf +#define OUT_REG_START_CH_PAIR15_MASK_SFT (0xf << 28) + +/* ETDM_OUT0_CON9 */ +/* ETDM_OUT1_CON9 */ +/* ETDM_OUT2_CON9 */ +/* ETDM_OUT3_CON9 */ +/* ETDM_OUT4_CON9 */ +/* ETDM_OUT5_CON9 */ +/* ETDM_OUT6_CON9 */ +#define OUT_REG_AFIFO_THRESHOLD_SFT 29 +#define OUT_REG_AFIFO_THRESHOLD_MASK 0x3 +#define OUT_REG_AFIFO_THRESHOLD_MASK_SFT (0x3 << 29) +#define OUT_REG_AFIFO_SW_RESET_SFT 15 +#define OUT_REG_AFIFO_SW_RESET_MASK 0x1 +#define OUT_REG_AFIFO_SW_RESET_MASK_SFT (0x1 << 15) +#define OUT_REG_AFIFO_RESET_SEL_SFT 14 +#define OUT_REG_AFIFO_RESET_SEL_MASK 0x1 +#define OUT_REG_AFIFO_RESET_SEL_MASK_SFT (0x1 << 14) +#define OUT_REG_AFIFO_AUTO_RESET_DIS_SFT 9 +#define OUT_REG_AFIFO_AUTO_RESET_DIS_MASK 0x1 +#define OUT_REG_AFIFO_AUTO_RESET_DIS_MASK_SFT (0x1 << 9) +#define OUT_REG_ETDM_USE_AFIFO_SFT 8 +#define OUT_REG_ETDM_USE_AFIFO_MASK 0x1 +#define OUT_REG_ETDM_USE_AFIFO_MASK_SFT (0x1 << 8) +#define OUT_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT 5 +#define OUT_REG_AFIFO_CLOCK_DOMAIN_SEL_MASK 0x7 +#define OUT_REG_AFIFO_CLOCK_DOMAIN_SEL_MASK_SFT (0x7 << 5) +#define OUT_REG_AFIFO_MODE_SFT 0 +#define OUT_REG_AFIFO_MODE_MASK 0x1f +#define OUT_REG_AFIFO_MODE_MASK_SFT (0x1f << 0) + +/* ETDM_OUT0_MON */ +/* ETDM_OUT1_MON */ +/* ETDM_OUT2_MON */ +/* ETDM_OUT3_MON */ +/* ETDM_OUT4_MON */ +/* ETDM_OUT5_MON */ +/* ETDM_OUT6_MON */ +#define LRCK_INV_SFT 30 +#define LRCK_INV_MASK 0x1 +#define LRCK_INV_MASK_SFT (0x1 << 30) +#define EN_SYNC_OUT_SFT 29 +#define EN_SYNC_OUT_MASK 0x1 +#define EN_SYNC_OUT_MASK_SFT (0x1 << 29) +#define HOPPING_EN_SYNC_OUT_PRE_SFT 28 +#define HOPPING_EN_SYNC_OUT_PRE_MASK 0x1 +#define HOPPING_EN_SYNC_OUT_PRE_MASK_SFT (0x1 << 28) +#define ETDM_2X_CK_EN_SFT 25 +#define ETDM_2X_CK_EN_MASK 0x1 +#define ETDM_2X_CK_EN_MASK_SFT (0x1 << 25) +#define ETDM_1X_CK_EN_SFT 24 +#define ETDM_1X_CK_EN_MASK 0x1 +#define ETDM_1X_CK_EN_MASK_SFT (0x1 << 24) +#define SDATA0_SFT 23 +#define SDATA0_MASK 0x1 +#define SDATA0_MASK_SFT (0x1 << 23) +#define CURRENT_STATUS_SFT 21 +#define CURRENT_STATUS_MASK 0x3 +#define CURRENT_STATUS_MASK_SFT (0x3 << 21) +#define BIT_POINT_SFT 16 +#define BIT_POINT_MASK 0x1f +#define BIT_POINT_MASK_SFT (0x1f << 16) +#define BIT_CH_COUNT_SFT 10 +#define BIT_CH_COUNT_MASK 0x3f +#define BIT_CH_COUNT_MASK_SFT (0x3f << 10) +#define BIT_COUNT_SFT 5 +#define BIT_COUNT_MASK 0x1f +#define BIT_COUNT_MASK_SFT (0x1f << 5) +#define CH_COUNT_SFT 0 +#define CH_COUNT_MASK 0x1f +#define CH_COUNT_MASK_SFT (0x1f << 0) + +/* ETDM_0_3_COWORK_CON0 */ +#define ETDM_OUT0_DATA_SEL_SFT 0 +#define ETDM_OUT0_DATA_SEL_MASK 0xf +#define ETDM_OUT0_DATA_SEL_MASK_SFT (0xf << 0) +#define ETDM_OUT0_SYNC_SEL_SFT 4 +#define ETDM_OUT0_SYNC_SEL_MASK 0xf +#define ETDM_OUT0_SYNC_SEL_MASK_SFT (0xf << 4) +#define ETDM_OUT0_SLAVE_SEL_SFT 8 +#define ETDM_OUT0_SLAVE_SEL_MASK 0xf +#define ETDM_OUT0_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_OUT1_DATA_SEL_SFT 12 +#define ETDM_OUT1_DATA_SEL_MASK 0xf +#define ETDM_OUT1_DATA_SEL_MASK_SFT (0xf << 12) +#define ETDM_OUT1_SYNC_SEL_SFT 16 +#define ETDM_OUT1_SYNC_SEL_MASK 0xf +#define ETDM_OUT1_SYNC_SEL_MASK_SFT (0xf << 16) +#define ETDM_OUT1_SLAVE_SEL_SFT 20 +#define ETDM_OUT1_SLAVE_SEL_MASK 0xf +#define ETDM_OUT1_SLAVE_SEL_MASK_SFT (0xf << 20) +#define ETDM_IN0_SLAVE_SEL_SFT 24 +#define ETDM_IN0_SLAVE_SEL_MASK 0xf +#define ETDM_IN0_SLAVE_SEL_MASK_SFT (0xf << 24) +#define ETDM_IN0_SYNC_SEL_SFT 28 +#define ETDM_IN0_SYNC_SEL_MASK 0xf +#define ETDM_IN0_SYNC_SEL_MASK_SFT (0xf << 28) + +/* ETDM_0_3_COWORK_CON1 */ +#define ETDM_IN0_SDATA0_SEL_SFT 0 +#define ETDM_IN0_SDATA0_SEL_MASK 0xf +#define ETDM_IN0_SDATA0_SEL_MASK_SFT (0xf << 0) +#define ETDM_IN0_SDATA1_15_SEL_SFT 4 +#define ETDM_IN0_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN0_SDATA1_15_SEL_MASK_SFT (0xf << 4) +#define ETDM_IN1_SLAVE_SEL_SFT 8 +#define ETDM_IN1_SLAVE_SEL_MASK 0xf +#define ETDM_IN1_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_IN1_SYNC_SEL_SFT 12 +#define ETDM_IN1_SYNC_SEL_MASK 0xf +#define ETDM_IN1_SYNC_SEL_MASK_SFT (0xf << 12) +#define ETDM_IN1_SDATA0_SEL_SFT 16 +#define ETDM_IN1_SDATA0_SEL_MASK 0xf +#define ETDM_IN1_SDATA0_SEL_MASK_SFT (0xf << 16) +#define ETDM_IN1_SDATA1_15_SEL_SFT 20 +#define ETDM_IN1_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN1_SDATA1_15_SEL_MASK_SFT (0xf << 20) + +/* ETDM_0_3_COWORK_CON2 */ +#define ETDM_OUT2_DATA_SEL_SFT 0 +#define ETDM_OUT2_DATA_SEL_MASK 0xf +#define ETDM_OUT2_DATA_SEL_MASK_SFT (0xf << 0) +#define ETDM_OUT2_SYNC_SEL_SFT 4 +#define ETDM_OUT2_SYNC_SEL_MASK 0xf +#define ETDM_OUT2_SYNC_SEL_MASK_SFT (0xf << 4) +#define ETDM_OUT2_SLAVE_SEL_SFT 8 +#define ETDM_OUT2_SLAVE_SEL_MASK 0xf +#define ETDM_OUT2_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_OUT3_DATA_SEL_SFT 12 +#define ETDM_OUT3_DATA_SEL_MASK 0xf +#define ETDM_OUT3_DATA_SEL_MASK_SFT (0xf << 12) +#define ETDM_OUT3_SYNC_SEL_SFT 16 +#define ETDM_OUT3_SYNC_SEL_MASK 0xf +#define ETDM_OUT3_SYNC_SEL_MASK_SFT (0xf << 16) +#define ETDM_OUT3_SLAVE_SEL_SFT 20 +#define ETDM_OUT3_SLAVE_SEL_MASK 0xf +#define ETDM_OUT3_SLAVE_SEL_MASK_SFT (0xf << 20) +#define ETDM_IN2_SLAVE_SEL_SFT 24 +#define ETDM_IN2_SLAVE_SEL_MASK 0xf +#define ETDM_IN2_SLAVE_SEL_MASK_SFT (0xf << 24) +#define ETDM_IN2_SYNC_SEL_SFT 28 +#define ETDM_IN2_SYNC_SEL_MASK 0xf +#define ETDM_IN2_SYNC_SEL_MASK_SFT (0xf << 28) + +/* ETDM_0_3_COWORK_CON3 */ +#define ETDM_IN2_SDATA0_SEL_SFT 0 +#define ETDM_IN2_SDATA0_SEL_MASK 0xf +#define ETDM_IN2_SDATA0_SEL_MASK_SFT (0xf << 0) +#define ETDM_IN2_SDATA1_15_SEL_SFT 4 +#define ETDM_IN2_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN2_SDATA1_15_SEL_MASK_SFT (0xf << 4) +#define ETDM_IN3_SLAVE_SEL_SFT 8 +#define ETDM_IN3_SLAVE_SEL_MASK 0xf +#define ETDM_IN3_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_IN3_SYNC_SEL_SFT 12 +#define ETDM_IN3_SYNC_SEL_MASK 0xf +#define ETDM_IN3_SYNC_SEL_MASK_SFT (0xf << 12) +#define ETDM_IN3_SDATA0_SEL_SFT 16 +#define ETDM_IN3_SDATA0_SEL_MASK 0xf +#define ETDM_IN3_SDATA0_SEL_MASK_SFT (0xf << 16) +#define ETDM_IN3_SDATA1_15_SEL_SFT 20 +#define ETDM_IN3_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN3_SDATA1_15_SEL_MASK_SFT (0xf << 20) + +/* ETDM_4_7_COWORK_CON0 */ +#define ETDM_OUT4_DATA_SEL_SFT 0 +#define ETDM_OUT4_DATA_SEL_MASK 0xf +#define ETDM_OUT4_DATA_SEL_MASK_SFT (0xf << 0) +#define ETDM_OUT4_SYNC_SEL_SFT 4 +#define ETDM_OUT4_SYNC_SEL_MASK 0xf +#define ETDM_OUT4_SYNC_SEL_MASK_SFT (0xf << 4) +#define ETDM_OUT4_SLAVE_SEL_SFT 8 +#define ETDM_OUT4_SLAVE_SEL_MASK 0xf +#define ETDM_OUT4_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_OUT5_DATA_SEL_SFT 12 +#define ETDM_OUT5_DATA_SEL_MASK 0xf +#define ETDM_OUT5_DATA_SEL_MASK_SFT (0xf << 12) +#define ETDM_OUT5_SYNC_SEL_SFT 16 +#define ETDM_OUT5_SYNC_SEL_MASK 0xf +#define ETDM_OUT5_SYNC_SEL_MASK_SFT (0xf << 16) +#define ETDM_OUT5_SLAVE_SEL_SFT 20 +#define ETDM_OUT5_SLAVE_SEL_MASK 0xf +#define ETDM_OUT5_SLAVE_SEL_MASK_SFT (0xf << 20) +#define ETDM_IN4_SLAVE_SEL_SFT 24 +#define ETDM_IN4_SLAVE_SEL_MASK 0xf +#define ETDM_IN4_SLAVE_SEL_MASK_SFT (0xf << 24) +#define ETDM_IN4_SYNC_SEL_SFT 28 +#define ETDM_IN4_SYNC_SEL_MASK 0xf +#define ETDM_IN4_SYNC_SEL_MASK_SFT (0xf << 28) + +/* ETDM_4_7_COWORK_CON1 */ +#define ETDM_IN4_SDATA0_SEL_SFT 0 +#define ETDM_IN4_SDATA0_SEL_MASK 0xf +#define ETDM_IN4_SDATA0_SEL_MASK_SFT (0xf << 0) +#define ETDM_IN4_SDATA1_15_SEL_SFT 4 +#define ETDM_IN4_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN4_SDATA1_15_SEL_MASK_SFT (0xf << 4) +#define ETDM_IN5_SLAVE_SEL_SFT 8 +#define ETDM_IN5_SLAVE_SEL_MASK 0xf +#define ETDM_IN5_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_IN5_SYNC_SEL_SFT 12 +#define ETDM_IN5_SYNC_SEL_MASK 0xf +#define ETDM_IN5_SYNC_SEL_MASK_SFT (0xf << 12) +#define ETDM_IN5_SDATA0_SEL_SFT 16 +#define ETDM_IN5_SDATA0_SEL_MASK 0xf +#define ETDM_IN5_SDATA0_SEL_MASK_SFT (0xf << 16) +#define ETDM_IN5_SDATA1_15_SEL_SFT 20 +#define ETDM_IN5_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN5_SDATA1_15_SEL_MASK_SFT (0xf << 20) + +/* ETDM_4_7_COWORK_CON2 */ +#define ETDM_OUT6_DATA_SEL_SFT 0 +#define ETDM_OUT6_DATA_SEL_MASK 0xf +#define ETDM_OUT6_DATA_SEL_MASK_SFT (0xf << 0) +#define ETDM_OUT6_SYNC_SEL_SFT 4 +#define ETDM_OUT6_SYNC_SEL_MASK 0xf +#define ETDM_OUT6_SYNC_SEL_MASK_SFT (0xf << 4) +#define ETDM_OUT6_SLAVE_SEL_SFT 8 +#define ETDM_OUT6_SLAVE_SEL_MASK 0xf +#define ETDM_OUT6_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_OUT7_DATA_SEL_SFT 12 +#define ETDM_OUT7_DATA_SEL_MASK 0xf +#define ETDM_OUT7_DATA_SEL_MASK_SFT (0xf << 12) +#define ETDM_OUT7_SYNC_SEL_SFT 16 +#define ETDM_OUT7_SYNC_SEL_MASK 0xf +#define ETDM_OUT7_SYNC_SEL_MASK_SFT (0xf << 16) +#define ETDM_OUT7_SLAVE_SEL_SFT 20 +#define ETDM_OUT7_SLAVE_SEL_MASK 0xf +#define ETDM_OUT7_SLAVE_SEL_MASK_SFT (0xf << 20) +#define ETDM_IN6_SLAVE_SEL_SFT 24 +#define ETDM_IN6_SLAVE_SEL_MASK 0xf +#define ETDM_IN6_SLAVE_SEL_MASK_SFT (0xf << 24) +#define ETDM_IN6_SYNC_SEL_SFT 28 +#define ETDM_IN6_SYNC_SEL_MASK 0xf +#define ETDM_IN6_SYNC_SEL_MASK_SFT (0xf << 28) + +/* ETDM_4_7_COWORK_CON3 */ +#define ETDM_IN6_SDATA0_SEL_SFT 0 +#define ETDM_IN6_SDATA0_SEL_MASK 0xf +#define ETDM_IN6_SDATA0_SEL_MASK_SFT (0xf << 0) +#define ETDM_IN6_SDATA1_15_SEL_SFT 4 +#define ETDM_IN6_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN6_SDATA1_15_SEL_MASK_SFT (0xf << 4) +#define ETDM_IN7_SLAVE_SEL_SFT 8 +#define ETDM_IN7_SLAVE_SEL_MASK 0xf +#define ETDM_IN7_SLAVE_SEL_MASK_SFT (0xf << 8) +#define ETDM_IN7_SYNC_SEL_SFT 12 +#define ETDM_IN7_SYNC_SEL_MASK 0xf +#define ETDM_IN7_SYNC_SEL_MASK_SFT (0xf << 12) +#define ETDM_IN7_SDATA0_SEL_SFT 16 +#define ETDM_IN7_SDATA0_SEL_MASK 0xf +#define ETDM_IN7_SDATA0_SEL_MASK_SFT (0xf << 16) +#define ETDM_IN7_SDATA1_15_SEL_SFT 20 +#define ETDM_IN7_SDATA1_15_SEL_MASK 0xf +#define ETDM_IN7_SDATA1_15_SEL_MASK_SFT (0xf << 20) + +/* AFE_DPTX_CON */ +#define DPTX_CHANNEL_ENABLE_SFT 8 +#define DPTX_CHANNEL_ENABLE_MASK 0xff +#define DPTX_CHANNEL_ENABLE_MASK_SFT (0xff << 8) +#define DPTX_REGISTER_MONITOR_SELECT_SFT 3 +#define DPTX_REGISTER_MONITOR_SELECT_MASK 0xf +#define DPTX_REGISTER_MONITOR_SELECT_MASK_SFT (0xf << 3) +#define DPTX_16BIT_SFT 2 +#define DPTX_16BIT_MASK 0x1 +#define DPTX_16BIT_MASK_SFT (0x1 << 2) +#define DPTX_CHANNEL_NUMBER_SFT 1 +#define DPTX_CHANNEL_NUMBER_MASK 0x1 +#define DPTX_CHANNEL_NUMBER_MASK_SFT (0x1 << 1) +#define DPTX_ON_SFT 0 +#define DPTX_ON_MASK 0x1 +#define DPTX_ON_MASK_SFT (0x1 << 0) + +/* AFE_DPTX_MON */ +#define AFE_DPTX_MON0_SFT 0 +#define AFE_DPTX_MON0_MASK 0xffffffff +#define AFE_DPTX_MON0_MASK_SFT (0xffffffff << 0) + +/* AFE_TDM_CON1 */ +#define TDM_EN_SFT 0 +#define TDM_EN_MASK 0x1 +#define TDM_EN_MASK_SFT (0x1 << 0) +#define BCK_INVERSE_SFT 1 +#define BCK_INVERSE_MASK 0x1 +#define BCK_INVERSE_MASK_SFT (0x1 << 1) +#define LRCK_INVERSE_SFT 2 +#define LRCK_INVERSE_MASK 0x1 +#define LRCK_INVERSE_MASK_SFT (0x1 << 2) +#define DELAY_DATA_SFT 3 +#define DELAY_DATA_MASK 0x1 +#define DELAY_DATA_MASK_SFT (0x1 << 3) +#define LEFT_ALIGN_SFT 4 +#define LEFT_ALIGN_MASK 0x1 +#define LEFT_ALIGN_MASK_SFT (0x1 << 4) +#define TDM_LRCK_D0P5T_SFT 5 +#define TDM_LRCK_D0P5T_MASK 0x1 +#define TDM_LRCK_D0P5T_MASK_SFT (0x1 << 5) +#define TDM_SDATA_D0P5T_SFT 6 +#define TDM_SDATA_D0P5T_MASK 0x1 +#define TDM_SDATA_D0P5T_MASK_SFT (0x1 << 6) +#define WLEN_SFT 8 +#define WLEN_MASK 0x3 +#define WLEN_MASK_SFT (0x3 << 8) +#define CHANNEL_NUM_SFT 10 +#define CHANNEL_NUM_MASK 0x3 +#define CHANNEL_NUM_MASK_SFT (0x3 << 10) +#define CHANNEL_BCK_CYCLES_SFT 12 +#define CHANNEL_BCK_CYCLES_MASK 0x3 +#define CHANNEL_BCK_CYCLES_MASK_SFT (0x3 << 12) +#define HDMI_CLK_INV_SEL_SFT 15 +#define HDMI_CLK_INV_SEL_MASK 0x1 +#define HDMI_CLK_INV_SEL_MASK_SFT (0x1 << 15) +#define DAC_BIT_NUM_SFT 16 +#define DAC_BIT_NUM_MASK 0x1f +#define DAC_BIT_NUM_MASK_SFT (0x1f << 16) +#define LRCK_TDM_WIDTH_SFT 24 +#define LRCK_TDM_WIDTH_MASK 0xff +#define LRCK_TDM_WIDTH_MASK_SFT (0xff << 24) + +/* AFE_TDM_CON2 */ +#define ST_CH_PAIR_SOUT0_SFT 0 +#define ST_CH_PAIR_SOUT0_MASK 0x7 +#define ST_CH_PAIR_SOUT0_MASK_SFT (0x7 << 0) +#define ST_CH_PAIR_SOUT1_SFT 4 +#define ST_CH_PAIR_SOUT1_MASK 0x7 +#define ST_CH_PAIR_SOUT1_MASK_SFT (0x7 << 4) +#define ST_CH_PAIR_SOUT2_SFT 8 +#define ST_CH_PAIR_SOUT2_MASK 0x7 +#define ST_CH_PAIR_SOUT2_MASK_SFT (0x7 << 8) +#define ST_CH_PAIR_SOUT3_SFT 12 +#define ST_CH_PAIR_SOUT3_MASK 0x7 +#define ST_CH_PAIR_SOUT3_MASK_SFT (0x7 << 12) +#define TDM_FIX_VALUE_SEL_SFT 16 +#define TDM_FIX_VALUE_SEL_MASK 0x1 +#define TDM_FIX_VALUE_SEL_MASK_SFT (0x1 << 16) +#define TDM_I2S_LOOPBACK_SFT 20 +#define TDM_I2S_LOOPBACK_MASK 0x1 +#define TDM_I2S_LOOPBACK_MASK_SFT (0x1 << 20) +#define TDM_I2S_LOOPBACK_CH_SFT 21 +#define TDM_I2S_LOOPBACK_CH_MASK 0x3 +#define TDM_I2S_LOOPBACK_CH_MASK_SFT (0x3 << 21) +#define TDM_USE_SINEGEN_INPUT_SFT 23 +#define TDM_USE_SINEGEN_INPUT_MASK 0x1 +#define TDM_USE_SINEGEN_INPUT_MASK_SFT (0x1 << 23) +#define TDM_FIX_VALUE_SFT 24 +#define TDM_FIX_VALUE_MASK 0xff +#define TDM_FIX_VALUE_MASK_SFT (0xff << 24) + +/* AFE_TDM_CON3 */ +#define TDM_OUT_SEL_DOMAIN_SFT 29 +#define TDM_OUT_SEL_DOMAIN_MASK 0x7 +#define TDM_OUT_SEL_DOMAIN_MASK_SFT (0x7 << 29) +#define TDM_OUT_SEL_FS_SFT 24 +#define TDM_OUT_SEL_FS_MASK 0x1f +#define TDM_OUT_SEL_FS_MASK_SFT (0x1f << 24) +#define TDM_OUT_MON_SEL_SFT 3 +#define TDM_OUT_MON_SEL_MASK 0x1 +#define TDM_OUT_MON_SEL_MASK_SFT (0x1 << 3) +#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_EN_SFT 2 +#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_EN_MASK 0x1 +#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 2) +#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_SFT 1 +#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_MASK 0x1 +#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_MASK_SFT (0x1 << 1) +#define TDM_UPDATE_EN_SEL_SFT 0 +#define TDM_UPDATE_EN_SEL_MASK 0x1 +#define TDM_UPDATE_EN_SEL_MASK_SFT (0x1 << 0) + +/* AFE_TDM_OUT_MON */ +#define AFE_TDM_OUT_MON_SFT 0 +#define AFE_TDM_OUT_MON_MASK 0xffffffff +#define AFE_TDM_OUT_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_HDMI_CONN0 */ +#define HDMI_O_7_SFT 21 +#define HDMI_O_7_MASK 0x7 +#define HDMI_O_7_MASK_SFT (0x7 << 21) +#define HDMI_O_6_SFT 18 +#define HDMI_O_6_MASK 0x7 +#define HDMI_O_6_MASK_SFT (0x7 << 18) +#define HDMI_O_5_SFT 15 +#define HDMI_O_5_MASK 0x7 +#define HDMI_O_5_MASK_SFT (0x7 << 15) +#define HDMI_O_4_SFT 12 +#define HDMI_O_4_MASK 0x7 +#define HDMI_O_4_MASK_SFT (0x7 << 12) +#define HDMI_O_3_SFT 9 +#define HDMI_O_3_MASK 0x7 +#define HDMI_O_3_MASK_SFT (0x7 << 9) +#define HDMI_O_2_SFT 6 +#define HDMI_O_2_MASK 0x7 +#define HDMI_O_2_MASK_SFT (0x7 << 6) +#define HDMI_O_1_SFT 3 +#define HDMI_O_1_MASK 0x7 +#define HDMI_O_1_MASK_SFT (0x7 << 3) +#define HDMI_O_0_SFT 0 +#define HDMI_O_0_MASK 0x7 +#define HDMI_O_0_MASK_SFT (0x7 << 0) + +/* AFE_TDM_TOP_IP_VERSION */ +#define AFE_TDM_TOP_IP_VERSION_SFT 0 +#define AFE_TDM_TOP_IP_VERSION_MASK 0xffffffff +#define AFE_TDM_TOP_IP_VERSION_MASK_SFT (0xffffffff << 0) + +/* AFE_CBIP_CFG0 */ +#define CBIP_TOP_SLV_MUX_WAY_EN_SFT 16 +#define CBIP_TOP_SLV_MUX_WAY_EN_MASK 0xffff +#define CBIP_TOP_SLV_MUX_WAY_EN_MASK_SFT (0xffff << 16) +#define RESERVED_04_SFT 15 +#define RESERVED_04_MASK 0x1 +#define RESERVED_04_MASK_SFT (0x1 << 15) +#define CBIP_ASYNC_MST_RG_FIFO_THRE_SFT 13 +#define CBIP_ASYNC_MST_RG_FIFO_THRE_MASK 0x3 +#define CBIP_ASYNC_MST_RG_FIFO_THRE_MASK_SFT (0x3 << 13) +#define CBIP_ASYNC_MST_POSTWRITE_DIS_SFT 12 +#define CBIP_ASYNC_MST_POSTWRITE_DIS_MASK 0x1 +#define CBIP_ASYNC_MST_POSTWRITE_DIS_MASK_SFT (0x1 << 12) +#define RESERVED_03_SFT 11 +#define RESERVED_03_MASK 0x1 +#define RESERVED_03_MASK_SFT (0x1 << 11) +#define CBIP_ASYNC_SLV_RG_FIFO_THRE_SFT 9 +#define CBIP_ASYNC_SLV_RG_FIFO_THRE_MASK 0x3 +#define CBIP_ASYNC_SLV_RG_FIFO_THRE_MASK_SFT (0x3 << 9) +#define CBIP_ASYNC_SLV_POSTWRITE_DIS_SFT 8 +#define CBIP_ASYNC_SLV_POSTWRITE_DIS_MASK 0x1 +#define CBIP_ASYNC_SLV_POSTWRITE_DIS_MASK_SFT (0x1 << 8) +#define AUDIOSYS_BUSY_SFT 7 +#define AUDIOSYS_BUSY_MASK 0x1 +#define AUDIOSYS_BUSY_MASK_SFT (0x1 << 7) +#define CBIP_SLV_DECODER_ERR_FLAG_EN_SFT 6 +#define CBIP_SLV_DECODER_ERR_FLAG_EN_MASK 0x1 +#define CBIP_SLV_DECODER_ERR_FLAG_EN_MASK_SFT (0x1 << 6) +#define CBIP_SLV_DECODER_SLAVE_WAY_EN_SFT 5 +#define CBIP_SLV_DECODER_SLAVE_WAY_EN_MASK 0x1 +#define CBIP_SLV_DECODER_SLAVE_WAY_EN_MASK_SFT (0x1 << 5) +#define APB_R2T_SFT 3 +#define APB_R2T_MASK 0x1 +#define APB_R2T_MASK_SFT (0x1 << 3) +#define APB_W2T_SFT 2 +#define APB_W2T_MASK 0x1 +#define APB_W2T_MASK_SFT (0x1 << 2) +#define AHB_IDLE_EN_INT_SFT 1 +#define AHB_IDLE_EN_INT_MASK 0x1 +#define AHB_IDLE_EN_INT_MASK_SFT (0x1 << 1) +#define AHB_IDLE_EN_EXT_SFT 0 +#define AHB_IDLE_EN_EXT_MASK 0x1 +#define AHB_IDLE_EN_EXT_MASK_SFT (0x1 << 0) + +/* AFE_CBIP_SLV_DECODER_MON0 */ +#define CBIP_SLV_DECODER_ERR_DOMAIN_SFT 4 +#define CBIP_SLV_DECODER_ERR_DOMAIN_MASK 0x1 +#define CBIP_SLV_DECODER_ERR_DOMAIN_MASK_SFT (0x1 << 4) +#define CBIP_SLV_DECODER_ERR_ID_SFT 3 +#define CBIP_SLV_DECODER_ERR_ID_MASK 0x1 +#define CBIP_SLV_DECODER_ERR_ID_MASK_SFT (0x1 << 3) +#define CBIP_SLV_DECODER_ERR_RW_SFT 2 +#define CBIP_SLV_DECODER_ERR_RW_MASK 0x1 +#define CBIP_SLV_DECODER_ERR_RW_MASK_SFT (0x1 << 2) +#define CBIP_SLV_DECODER_ERR_DECERR_SFT 1 +#define CBIP_SLV_DECODER_ERR_DECERR_MASK 0x1 +#define CBIP_SLV_DECODER_ERR_DECERR_MASK_SFT (0x1 << 1) +#define CBIP_SLV_DECODER_CTRL_UPDATE_STATUS_SFT 0 +#define CBIP_SLV_DECODER_CTRL_UPDATE_STATUS_MASK 0x1 +#define CBIP_SLV_DECODER_CTRL_UPDATE_STATUS_MASK_SFT (0x1 << 0) + +/* AFE_CBIP_SLV_DECODER_MON1 */ +#define CBIP_SLV_DECODER_ERR_ADDR_SFT 0 +#define CBIP_SLV_DECODER_ERR_ADDR_MASK 0xffffffff +#define CBIP_SLV_DECODER_ERR_ADDR_MASK_SFT (0xffffffff << 0) + +/* AFE_CBIP_SLV_MUX_MON_CFG */ +#define CBIP_SLV_MUX_ERR_FLAG_EN_SFT 3 +#define CBIP_SLV_MUX_ERR_FLAG_EN_MASK 0x1 +#define CBIP_SLV_MUX_ERR_FLAG_EN_MASK_SFT (0x1 << 3) +#define CBIP_SLV_MUX_REG_SLAVE_WAY_EN_SFT 2 +#define CBIP_SLV_MUX_REG_SLAVE_WAY_EN_MASK 0x1 +#define CBIP_SLV_MUX_REG_SLAVE_WAY_EN_MASK_SFT (0x1 << 2) +#define CBIP_SLV_MUX_REG_LAYER_WAY_EN_SFT 0 +#define CBIP_SLV_MUX_REG_LAYER_WAY_EN_MASK 0x3 +#define CBIP_SLV_MUX_REG_LAYER_WAY_EN_MASK_SFT (0x3 << 0) + +/* AFE_CBIP_SLV_MUX_MON0 */ +#define CBIP_SLV_MUX_ERR_DOMAIN_SFT 8 +#define CBIP_SLV_MUX_ERR_DOMAIN_MASK 0x1 +#define CBIP_SLV_MUX_ERR_DOMAIN_MASK_SFT (0x1 << 8) +#define CBIP_SLV_MUX_ERR_ID_SFT 7 +#define CBIP_SLV_MUX_ERR_ID_MASK 0x1 +#define CBIP_SLV_MUX_ERR_ID_MASK_SFT (0x1 << 7) +#define CBIP_SLV_MUX_ERR_RD_SFT 6 +#define CBIP_SLV_MUX_ERR_RD_MASK 0x1 +#define CBIP_SLV_MUX_ERR_RD_MASK_SFT (0x1 << 6) +#define CBIP_SLV_MUX_ERR_WR_SFT 5 +#define CBIP_SLV_MUX_ERR_WR_MASK 0x1 +#define CBIP_SLV_MUX_ERR_WR_MASK_SFT (0x1 << 5) +#define CBIP_SLV_MUX_ERR_EN_SLV_SFT 4 +#define CBIP_SLV_MUX_ERR_EN_SLV_MASK 0x1 +#define CBIP_SLV_MUX_ERR_EN_SLV_MASK_SFT (0x1 << 4) +#define CBIP_SLV_MUX_ERR_EN_MST_SFT 2 +#define CBIP_SLV_MUX_ERR_EN_MST_MASK 0x3 +#define CBIP_SLV_MUX_ERR_EN_MST_MASK_SFT (0x3 << 2) +#define CBIP_SLV_MUX_CTRL_UPDATE_STATUS_SFT 0 +#define CBIP_SLV_MUX_CTRL_UPDATE_STATUS_MASK 0x3 +#define CBIP_SLV_MUX_CTRL_UPDATE_STATUS_MASK_SFT (0x3 << 0) + +/* AFE_CBIP_SLV_MUX_MON1 */ +#define CBIP_SLV_MUX_ERR_ADDR_SFT 0 +#define CBIP_SLV_MUX_ERR_ADDR_MASK 0xffffffff +#define CBIP_SLV_MUX_ERR_ADDR_MASK_SFT (0xffffffff << 0) + +/* AFE_MEMIF_CON0 */ +#define CPU_COMPACT_MODE_SFT 2 +#define CPU_COMPACT_MODE_MASK 0x1 +#define CPU_COMPACT_MODE_MASK_SFT (0x1 << 2) +#define CPU_HD_ALIGN_SFT 1 +#define CPU_HD_ALIGN_MASK 0x1 +#define CPU_HD_ALIGN_MASK_SFT (0x1 << 1) +#define SYSRAM_SIGN_SFT 0 +#define SYSRAM_SIGN_MASK 0x1 +#define SYSRAM_SIGN_MASK_SFT (0x1 << 0) + +/* AFE_MEMIF_ONE_HEART */ +#define DL_ONE_HEART_ON_2_SFT 2 +#define DL_ONE_HEART_ON_2_MASK 0x1 +#define DL_ONE_HEART_ON_2_MASK_SFT (0x1 << 2) +#define DL_ONE_HEART_ON_1_SFT 1 +#define DL_ONE_HEART_ON_1_MASK 0x1 +#define DL_ONE_HEART_ON_1_MASK_SFT (0x1 << 1) +#define DL_ONE_HEART_ON_0_SFT 0 +#define DL_ONE_HEART_ON_0_MASK 0x1 +#define DL_ONE_HEART_ON_0_MASK_SFT (0x1 << 0) + +/* AFE_DL0_BASE_MSB */ +#define DL0_BASE_ADDR_MSB_SFT 0 +#define DL0_BASE_ADDR_MSB_MASK 0x1ff +#define DL0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL0_BASE */ +#define DL0_BASE_ADDR_SFT 4 +#define DL0_BASE_ADDR_MASK 0xfffffff +#define DL0_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL0_CUR_MSB */ +#define DL0_CUR_PTR_MSB_SFT 0 +#define DL0_CUR_PTR_MSB_MASK 0x1ff +#define DL0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL0_CUR */ +#define DL0_CUR_PTR_SFT 0 +#define DL0_CUR_PTR_MASK 0xffffffff +#define DL0_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL0_END_MSB */ +#define DL0_END_ADDR_MSB_SFT 0 +#define DL0_END_ADDR_MSB_MASK 0x1ff +#define DL0_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL0_END */ +#define DL0_END_ADDR_SFT 4 +#define DL0_END_ADDR_MASK 0xfffffff +#define DL0_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL0_RCH_MON */ +#define DL0_RCH_DATA_SFT 0 +#define DL0_RCH_DATA_MASK 0xffffffff +#define DL0_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL0_LCH_MON */ +#define DL0_LCH_DATA_SFT 0 +#define DL0_LCH_DATA_MASK 0xffffffff +#define DL0_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL0_CON0 */ +#define DL0_ON_SFT 28 +#define DL0_ON_MASK 0x1 +#define DL0_ON_MASK_SFT (0x1 << 28) +#define DL0_ONE_HEART_SEL_SFT 22 +#define DL0_ONE_HEART_SEL_MASK 0x3 +#define DL0_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL0_MINLEN_SFT 20 +#define DL0_MINLEN_MASK 0x3 +#define DL0_MINLEN_MASK_SFT (0x3 << 20) +#define DL0_MAXLEN_SFT 16 +#define DL0_MAXLEN_MASK 0x3 +#define DL0_MAXLEN_MASK_SFT (0x3 << 16) +#define DL0_SEL_DOMAIN_SFT 13 +#define DL0_SEL_DOMAIN_MASK 0x7 +#define DL0_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL0_SEL_FS_SFT 8 +#define DL0_SEL_FS_MASK 0x1f +#define DL0_SEL_FS_MASK_SFT (0x1f << 8) +#define DL0_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL0_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL0_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL0_PBUF_SIZE_SFT 5 +#define DL0_PBUF_SIZE_MASK 0x3 +#define DL0_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL0_MONO_SFT 4 +#define DL0_MONO_MASK 0x1 +#define DL0_MONO_MASK_SFT (0x1 << 4) +#define DL0_NORMAL_MODE_SFT 3 +#define DL0_NORMAL_MODE_MASK 0x1 +#define DL0_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL0_HALIGN_SFT 2 +#define DL0_HALIGN_MASK 0x1 +#define DL0_HALIGN_MASK_SFT (0x1 << 2) +#define DL0_HD_MODE_SFT 0 +#define DL0_HD_MODE_MASK 0x3 +#define DL0_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL1_BASE_MSB */ +#define DL1_BASE_ADDR_MSB_SFT 0 +#define DL1_BASE_ADDR_MSB_MASK 0x1ff +#define DL1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL1_BASE */ +#define DL1_BASE_ADDR_SFT 4 +#define DL1_BASE_ADDR_MASK 0xfffffff +#define DL1_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL1_CUR_MSB */ +#define DL1_CUR_PTR_MSB_SFT 0 +#define DL1_CUR_PTR_MSB_MASK 0x1ff +#define DL1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL1_CUR */ +#define DL1_CUR_PTR_SFT 0 +#define DL1_CUR_PTR_MASK 0xffffffff +#define DL1_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL1_END_MSB */ +#define DL1_END_ADDR_MSB_SFT 0 +#define DL1_END_ADDR_MSB_MASK 0x1ff +#define DL1_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL1_END */ +#define DL1_END_ADDR_SFT 4 +#define DL1_END_ADDR_MASK 0xfffffff +#define DL1_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL1_RCH_MON */ +#define DL1_RCH_DATA_SFT 0 +#define DL1_RCH_DATA_MASK 0xffffffff +#define DL1_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL1_LCH_MON */ +#define DL1_LCH_DATA_SFT 0 +#define DL1_LCH_DATA_MASK 0xffffffff +#define DL1_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL1_CON0 */ +#define DL1_ON_SFT 28 +#define DL1_ON_MASK 0x1 +#define DL1_ON_MASK_SFT (0x1 << 28) +#define DL1_ONE_HEART_SEL_SFT 22 +#define DL1_ONE_HEART_SEL_MASK 0x3 +#define DL1_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL1_MINLEN_SFT 20 +#define DL1_MINLEN_MASK 0x3 +#define DL1_MINLEN_MASK_SFT (0x3 << 20) +#define DL1_MAXLEN_SFT 16 +#define DL1_MAXLEN_MASK 0x3 +#define DL1_MAXLEN_MASK_SFT (0x3 << 16) +#define DL1_SEL_DOMAIN_SFT 13 +#define DL1_SEL_DOMAIN_MASK 0x7 +#define DL1_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL1_SEL_FS_SFT 8 +#define DL1_SEL_FS_MASK 0x1f +#define DL1_SEL_FS_MASK_SFT (0x1f << 8) +#define DL1_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL1_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL1_PBUF_SIZE_SFT 5 +#define DL1_PBUF_SIZE_MASK 0x3 +#define DL1_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL1_MONO_SFT 4 +#define DL1_MONO_MASK 0x1 +#define DL1_MONO_MASK_SFT (0x1 << 4) +#define DL1_NORMAL_MODE_SFT 3 +#define DL1_NORMAL_MODE_MASK 0x1 +#define DL1_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL1_HALIGN_SFT 2 +#define DL1_HALIGN_MASK 0x1 +#define DL1_HALIGN_MASK_SFT (0x1 << 2) +#define DL1_HD_MODE_SFT 0 +#define DL1_HD_MODE_MASK 0x3 +#define DL1_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL2_BASE_MSB */ +#define DL2_BASE__ADDR_MSB_SFT 0 +#define DL2_BASE__ADDR_MSB_MASK 0x1ff +#define DL2_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL2_BASE */ +#define DL2_BASE_ADDR_SFT 4 +#define DL2_BASE_ADDR_MASK 0xfffffff +#define DL2_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL2_CUR_MSB */ +#define DL2_CUR_PTR_MSB_SFT 0 +#define DL2_CUR_PTR_MSB_MASK 0x1ff +#define DL2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL2_CUR */ +#define DL2_CUR_PTR_SFT 0 +#define DL2_CUR_PTR_MASK 0xffffffff +#define DL2_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL2_END_MSB */ +#define DL2_END_ADDR_MSB_SFT 0 +#define DL2_END_ADDR_MSB_MASK 0x1ff +#define DL2_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL2_END */ +#define DL2_END_ADDR_SFT 4 +#define DL2_END_ADDR_MASK 0xfffffff +#define DL2_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL2_RCH_MON */ +#define DL2_RCH_DATA_SFT 0 +#define DL2_RCH_DATA_MASK 0xffffffff +#define DL2_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL2_LCH_MON */ +#define DL2_LCH_DATA_SFT 0 +#define DL2_LCH_DATA_MASK 0xffffffff +#define DL2_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL2_CON0 */ +#define DL2_ON_SFT 28 +#define DL2_ON_MASK 0x1 +#define DL2_ON_MASK_SFT (0x1 << 28) +#define DL2_ONE_HEART_SEL_SFT 22 +#define DL2_ONE_HEART_SEL_MASK 0x3 +#define DL2_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL2_MINLEN_SFT 20 +#define DL2_MINLEN_MASK 0x3 +#define DL2_MINLEN_MASK_SFT (0x3 << 20) +#define DL2_MAXLEN_SFT 16 +#define DL2_MAXLEN_MASK 0x3 +#define DL2_MAXLEN_MASK_SFT (0x3 << 16) +#define DL2_SEL_DOMAIN_SFT 13 +#define DL2_SEL_DOMAIN_MASK 0x7 +#define DL2_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL2_SEL_FS_SFT 8 +#define DL2_SEL_FS_MASK 0x1f +#define DL2_SEL_FS_MASK_SFT (0x1f << 8) +#define DL2_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL2_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL2_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL2_PBUF_SIZE_SFT 5 +#define DL2_PBUF_SIZE_MASK 0x3 +#define DL2_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL2_MONO_SFT 4 +#define DL2_MONO_MASK 0x1 +#define DL2_MONO_MASK_SFT (0x1 << 4) +#define DL2_NORMAL_MODE_SFT 3 +#define DL2_NORMAL_MODE_MASK 0x1 +#define DL2_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL2_HALIGN_SFT 2 +#define DL2_HALIGN_MASK 0x1 +#define DL2_HALIGN_MASK_SFT (0x1 << 2) +#define DL2_HD_MODE_SFT 0 +#define DL2_HD_MODE_MASK 0x3 +#define DL2_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL3_BASE_MSB */ +#define DL3_BASE__ADDR_MSB_SFT 0 +#define DL3_BASE__ADDR_MSB_MASK 0x1ff +#define DL3_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL3_BASE */ +#define DL3_BASE_ADDR_SFT 4 +#define DL3_BASE_ADDR_MASK 0xfffffff +#define DL3_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL3_CUR_MSB */ +#define DL3_CUR_PTR_MSB_SFT 0 +#define DL3_CUR_PTR_MSB_MASK 0x1ff +#define DL3_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL3_CUR */ +#define DL3_CUR_PTR_SFT 0 +#define DL3_CUR_PTR_MASK 0xffffffff +#define DL3_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL3_END_MSB */ +#define DL3_END_ADDR_MSB_SFT 0 +#define DL3_END_ADDR_MSB_MASK 0x1ff +#define DL3_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL3_END */ +#define DL3_END_ADDR_SFT 4 +#define DL3_END_ADDR_MASK 0xfffffff +#define DL3_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL3_RCH_MON */ +#define DL3_RCH_DATA_SFT 0 +#define DL3_RCH_DATA_MASK 0xffffffff +#define DL3_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL3_LCH_MON */ +#define DL3_LCH_DATA_SFT 0 +#define DL3_LCH_DATA_MASK 0xffffffff +#define DL3_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL3_CON0 */ +#define DL3_ON_SFT 28 +#define DL3_ON_MASK 0x1 +#define DL3_ON_MASK_SFT (0x1 << 28) +#define DL3_ONE_HEART_SEL_SFT 22 +#define DL3_ONE_HEART_SEL_MASK 0x3 +#define DL3_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL3_MINLEN_SFT 20 +#define DL3_MINLEN_MASK 0x3 +#define DL3_MINLEN_MASK_SFT (0x3 << 20) +#define DL3_MAXLEN_SFT 16 +#define DL3_MAXLEN_MASK 0x3 +#define DL3_MAXLEN_MASK_SFT (0x3 << 16) +#define DL3_SEL_DOMAIN_SFT 13 +#define DL3_SEL_DOMAIN_MASK 0x7 +#define DL3_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL3_SEL_FS_SFT 8 +#define DL3_SEL_FS_MASK 0x1f +#define DL3_SEL_FS_MASK_SFT (0x1f << 8) +#define DL3_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL3_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL3_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL3_PBUF_SIZE_SFT 5 +#define DL3_PBUF_SIZE_MASK 0x3 +#define DL3_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL3_MONO_SFT 4 +#define DL3_MONO_MASK 0x1 +#define DL3_MONO_MASK_SFT (0x1 << 4) +#define DL3_NORMAL_MODE_SFT 3 +#define DL3_NORMAL_MODE_MASK 0x1 +#define DL3_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL3_HALIGN_SFT 2 +#define DL3_HALIGN_MASK 0x1 +#define DL3_HALIGN_MASK_SFT (0x1 << 2) +#define DL3_HD_MODE_SFT 0 +#define DL3_HD_MODE_MASK 0x3 +#define DL3_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL4_BASE_MSB */ +#define DL4_BASE__ADDR_MSB_SFT 0 +#define DL4_BASE__ADDR_MSB_MASK 0x1ff +#define DL4_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL4_BASE */ +#define DL4_BASE_ADDR_SFT 4 +#define DL4_BASE_ADDR_MASK 0xfffffff +#define DL4_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL4_CUR_MSB */ +#define DL4_CUR_PTR_MSB_SFT 0 +#define DL4_CUR_PTR_MSB_MASK 0x1ff +#define DL4_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL4_CUR */ +#define DL4_CUR_PTR_SFT 0 +#define DL4_CUR_PTR_MASK 0xffffffff +#define DL4_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL4_END_MSB */ +#define DL4_END_ADDR_MSB_SFT 0 +#define DL4_END_ADDR_MSB_MASK 0x1ff +#define DL4_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL4_END */ +#define DL4_END_ADDR_SFT 4 +#define DL4_END_ADDR_MASK 0xfffffff +#define DL4_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL4_RCH_MON */ +#define DL4_RCH_DATA_SFT 0 +#define DL4_RCH_DATA_MASK 0xffffffff +#define DL4_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL4_LCH_MON */ +#define DL4_LCH_DATA_SFT 0 +#define DL4_LCH_DATA_MASK 0xffffffff +#define DL4_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL4_CON0 */ +#define DL4_ON_SFT 28 +#define DL4_ON_MASK 0x1 +#define DL4_ON_MASK_SFT (0x1 << 28) +#define DL4_ONE_HEART_SEL_SFT 22 +#define DL4_ONE_HEART_SEL_MASK 0x3 +#define DL4_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL4_MINLEN_SFT 20 +#define DL4_MINLEN_MASK 0x3 +#define DL4_MINLEN_MASK_SFT (0x3 << 20) +#define DL4_MAXLEN_SFT 16 +#define DL4_MAXLEN_MASK 0x3 +#define DL4_MAXLEN_MASK_SFT (0x3 << 16) +#define DL4_SEL_DOMAIN_SFT 13 +#define DL4_SEL_DOMAIN_MASK 0x7 +#define DL4_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL4_SEL_FS_SFT 8 +#define DL4_SEL_FS_MASK 0x1f +#define DL4_SEL_FS_MASK_SFT (0x1f << 8) +#define DL4_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL4_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL4_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL4_PBUF_SIZE_SFT 5 +#define DL4_PBUF_SIZE_MASK 0x3 +#define DL4_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL4_MONO_SFT 4 +#define DL4_MONO_MASK 0x1 +#define DL4_MONO_MASK_SFT (0x1 << 4) +#define DL4_NORMAL_MODE_SFT 3 +#define DL4_NORMAL_MODE_MASK 0x1 +#define DL4_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL4_HALIGN_SFT 2 +#define DL4_HALIGN_MASK 0x1 +#define DL4_HALIGN_MASK_SFT (0x1 << 2) +#define DL4_HD_MODE_SFT 0 +#define DL4_HD_MODE_MASK 0x3 +#define DL4_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL5_BASE_MSB */ +#define DL5_BASE__ADDR_MSB_SFT 0 +#define DL5_BASE__ADDR_MSB_MASK 0x1ff +#define DL5_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL5_BASE */ +#define DL5_BASE_ADDR_SFT 4 +#define DL5_BASE_ADDR_MASK 0xfffffff +#define DL5_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL5_CUR_MSB */ +#define DL5_CUR_PTR_MSB_SFT 0 +#define DL5_CUR_PTR_MSB_MASK 0x1ff +#define DL5_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL5_CUR */ +#define DL5_CUR_PTR_SFT 0 +#define DL5_CUR_PTR_MASK 0xffffffff +#define DL5_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL5_END_MSB */ +#define DL5_END_ADDR_MSB_SFT 0 +#define DL5_END_ADDR_MSB_MASK 0x1ff +#define DL5_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL5_END */ +#define DL5_END_ADDR_SFT 4 +#define DL5_END_ADDR_MASK 0xfffffff +#define DL5_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL5_RCH_MON */ +#define DL5_RCH_DATA_SFT 0 +#define DL5_RCH_DATA_MASK 0xffffffff +#define DL5_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL5_LCH_MON */ +#define DL5_LCH_DATA_SFT 0 +#define DL5_LCH_DATA_MASK 0xffffffff +#define DL5_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL5_CON0 */ +#define DL5_ON_SFT 28 +#define DL5_ON_MASK 0x1 +#define DL5_ON_MASK_SFT (0x1 << 28) +#define DL5_ONE_HEART_SEL_SFT 22 +#define DL5_ONE_HEART_SEL_MASK 0x3 +#define DL5_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL5_MINLEN_SFT 20 +#define DL5_MINLEN_MASK 0x3 +#define DL5_MINLEN_MASK_SFT (0x3 << 20) +#define DL5_MAXLEN_SFT 16 +#define DL5_MAXLEN_MASK 0x3 +#define DL5_MAXLEN_MASK_SFT (0x3 << 16) +#define DL5_SEL_DOMAIN_SFT 13 +#define DL5_SEL_DOMAIN_MASK 0x7 +#define DL5_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL5_SEL_FS_SFT 8 +#define DL5_SEL_FS_MASK 0x1f +#define DL5_SEL_FS_MASK_SFT (0x1f << 8) +#define DL5_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL5_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL5_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL5_PBUF_SIZE_SFT 5 +#define DL5_PBUF_SIZE_MASK 0x3 +#define DL5_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL5_MONO_SFT 4 +#define DL5_MONO_MASK 0x1 +#define DL5_MONO_MASK_SFT (0x1 << 4) +#define DL5_NORMAL_MODE_SFT 3 +#define DL5_NORMAL_MODE_MASK 0x1 +#define DL5_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL5_HALIGN_SFT 2 +#define DL5_HALIGN_MASK 0x1 +#define DL5_HALIGN_MASK_SFT (0x1 << 2) +#define DL5_HD_MODE_SFT 0 +#define DL5_HD_MODE_MASK 0x3 +#define DL5_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL6_BASE_MSB */ +#define DL6_BASE__ADDR_MSB_SFT 0 +#define DL6_BASE__ADDR_MSB_MASK 0x1ff +#define DL6_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL6_BASE */ +#define DL6_BASE_ADDR_SFT 4 +#define DL6_BASE_ADDR_MASK 0xfffffff +#define DL6_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL6_CUR_MSB */ +#define DL6_CUR_PTR_MSB_SFT 0 +#define DL6_CUR_PTR_MSB_MASK 0x1ff +#define DL6_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL6_CUR */ +#define DL6_CUR_PTR_SFT 0 +#define DL6_CUR_PTR_MASK 0xffffffff +#define DL6_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL6_END_MSB */ +#define DL6_END_ADDR_MSB_SFT 0 +#define DL6_END_ADDR_MSB_MASK 0x1ff +#define DL6_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL6_END */ +#define DL6_END_ADDR_SFT 4 +#define DL6_END_ADDR_MASK 0xfffffff +#define DL6_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL6_RCH_MON */ +#define DL6_RCH_DATA_SFT 0 +#define DL6_RCH_DATA_MASK 0xffffffff +#define DL6_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL6_LCH_MON */ +#define DL6_LCH_DATA_SFT 0 +#define DL6_LCH_DATA_MASK 0xffffffff +#define DL6_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL6_CON0 */ +#define DL6_ON_SFT 28 +#define DL6_ON_MASK 0x1 +#define DL6_ON_MASK_SFT (0x1 << 28) +#define DL6_ONE_HEART_SEL_SFT 22 +#define DL6_ONE_HEART_SEL_MASK 0x3 +#define DL6_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL6_MINLEN_SFT 20 +#define DL6_MINLEN_MASK 0x3 +#define DL6_MINLEN_MASK_SFT (0x3 << 20) +#define DL6_MAXLEN_SFT 16 +#define DL6_MAXLEN_MASK 0x3 +#define DL6_MAXLEN_MASK_SFT (0x3 << 16) +#define DL6_SEL_DOMAIN_SFT 13 +#define DL6_SEL_DOMAIN_MASK 0x7 +#define DL6_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL6_SEL_FS_SFT 8 +#define DL6_SEL_FS_MASK 0x1f +#define DL6_SEL_FS_MASK_SFT (0x1f << 8) +#define DL6_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL6_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL6_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL6_PBUF_SIZE_SFT 5 +#define DL6_PBUF_SIZE_MASK 0x3 +#define DL6_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL6_MONO_SFT 4 +#define DL6_MONO_MASK 0x1 +#define DL6_MONO_MASK_SFT (0x1 << 4) +#define DL6_NORMAL_MODE_SFT 3 +#define DL6_NORMAL_MODE_MASK 0x1 +#define DL6_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL6_HALIGN_SFT 2 +#define DL6_HALIGN_MASK 0x1 +#define DL6_HALIGN_MASK_SFT (0x1 << 2) +#define DL6_HD_MODE_SFT 0 +#define DL6_HD_MODE_MASK 0x3 +#define DL6_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL7_BASE_MSB */ +#define DL7_BASE__ADDR_MSB_SFT 0 +#define DL7_BASE__ADDR_MSB_MASK 0x1ff +#define DL7_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL7_BASE */ +#define DL7_BASE_ADDR_SFT 4 +#define DL7_BASE_ADDR_MASK 0xfffffff +#define DL7_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL7_CUR_MSB */ +#define DL7_CUR_PTR_MSB_SFT 0 +#define DL7_CUR_PTR_MSB_MASK 0x1ff +#define DL7_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL7_CUR */ +#define DL7_CUR_PTR_SFT 0 +#define DL7_CUR_PTR_MASK 0xffffffff +#define DL7_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL7_END_MSB */ +#define DL7_END_ADDR_MSB_SFT 0 +#define DL7_END_ADDR_MSB_MASK 0x1ff +#define DL7_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL7_END */ +#define DL7_END_ADDR_SFT 4 +#define DL7_END_ADDR_MASK 0xfffffff +#define DL7_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL7_RCH_MON */ +#define DL7_RCH_DATA_SFT 0 +#define DL7_RCH_DATA_MASK 0xffffffff +#define DL7_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL7_LCH_MON */ +#define DL7_LCH_DATA_SFT 0 +#define DL7_LCH_DATA_MASK 0xffffffff +#define DL7_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL7_CON0 */ +#define DL7_ON_SFT 28 +#define DL7_ON_MASK 0x1 +#define DL7_ON_MASK_SFT (0x1 << 28) +#define DL7_ONE_HEART_SEL_SFT 22 +#define DL7_ONE_HEART_SEL_MASK 0x3 +#define DL7_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL7_MINLEN_SFT 20 +#define DL7_MINLEN_MASK 0x3 +#define DL7_MINLEN_MASK_SFT (0x3 << 20) +#define DL7_MAXLEN_SFT 16 +#define DL7_MAXLEN_MASK 0x3 +#define DL7_MAXLEN_MASK_SFT (0x3 << 16) +#define DL7_SEL_DOMAIN_SFT 13 +#define DL7_SEL_DOMAIN_MASK 0x7 +#define DL7_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL7_SEL_FS_SFT 8 +#define DL7_SEL_FS_MASK 0x1f +#define DL7_SEL_FS_MASK_SFT (0x1f << 8) +#define DL7_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL7_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL7_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL7_PBUF_SIZE_SFT 5 +#define DL7_PBUF_SIZE_MASK 0x3 +#define DL7_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL7_MONO_SFT 4 +#define DL7_MONO_MASK 0x1 +#define DL7_MONO_MASK_SFT (0x1 << 4) +#define DL7_NORMAL_MODE_SFT 3 +#define DL7_NORMAL_MODE_MASK 0x1 +#define DL7_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL7_HALIGN_SFT 2 +#define DL7_HALIGN_MASK 0x1 +#define DL7_HALIGN_MASK_SFT (0x1 << 2) +#define DL7_HD_MODE_SFT 0 +#define DL7_HD_MODE_MASK 0x3 +#define DL7_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL8_BASE_MSB */ +#define DL8_BASE__ADDR_MSB_SFT 0 +#define DL8_BASE__ADDR_MSB_MASK 0x1ff +#define DL8_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL8_BASE */ +#define DL8_BASE_ADDR_SFT 4 +#define DL8_BASE_ADDR_MASK 0xfffffff +#define DL8_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL8_CUR_MSB */ +#define DL8_CUR_PTR_MSB_SFT 0 +#define DL8_CUR_PTR_MSB_MASK 0x1ff +#define DL8_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL8_CUR */ +#define DL8_CUR_PTR_SFT 0 +#define DL8_CUR_PTR_MASK 0xffffffff +#define DL8_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL8_END_MSB */ +#define DL8_END_ADDR_MSB_SFT 0 +#define DL8_END_ADDR_MSB_MASK 0x1ff +#define DL8_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL8_END */ +#define DL8_END_ADDR_SFT 4 +#define DL8_END_ADDR_MASK 0xfffffff +#define DL8_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL8_RCH_MON */ +#define DL8_RCH_DATA_SFT 0 +#define DL8_RCH_DATA_MASK 0xffffffff +#define DL8_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL8_LCH_MON */ +#define DL8_LCH_DATA_SFT 0 +#define DL8_LCH_DATA_MASK 0xffffffff +#define DL8_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL8_CON0 */ +#define DL8_ON_SFT 28 +#define DL8_ON_MASK 0x1 +#define DL8_ON_MASK_SFT (0x1 << 28) +#define DL8_ONE_HEART_SEL_SFT 22 +#define DL8_ONE_HEART_SEL_MASK 0x3 +#define DL8_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL8_MINLEN_SFT 20 +#define DL8_MINLEN_MASK 0x3 +#define DL8_MINLEN_MASK_SFT (0x3 << 20) +#define DL8_MAXLEN_SFT 16 +#define DL8_MAXLEN_MASK 0x3 +#define DL8_MAXLEN_MASK_SFT (0x3 << 16) +#define DL8_SEL_DOMAIN_SFT 13 +#define DL8_SEL_DOMAIN_MASK 0x7 +#define DL8_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL8_SEL_FS_SFT 8 +#define DL8_SEL_FS_MASK 0x1f +#define DL8_SEL_FS_MASK_SFT (0x1f << 8) +#define DL8_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL8_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL8_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL8_PBUF_SIZE_SFT 5 +#define DL8_PBUF_SIZE_MASK 0x3 +#define DL8_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL8_MONO_SFT 4 +#define DL8_MONO_MASK 0x1 +#define DL8_MONO_MASK_SFT (0x1 << 4) +#define DL8_NORMAL_MODE_SFT 3 +#define DL8_NORMAL_MODE_MASK 0x1 +#define DL8_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL8_HALIGN_SFT 2 +#define DL8_HALIGN_MASK 0x1 +#define DL8_HALIGN_MASK_SFT (0x1 << 2) +#define DL8_HD_MODE_SFT 0 +#define DL8_HD_MODE_MASK 0x3 +#define DL8_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL_4CH_BASE_MSB */ +#define DL_4CH_BASE__ADDR_MSB_SFT 0 +#define DL_4CH_BASE__ADDR_MSB_MASK 0x1ff +#define DL_4CH_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_4CH_BASE */ +#define DL_4CH_BASE_ADDR_SFT 4 +#define DL_4CH_BASE_ADDR_MASK 0xfffffff +#define DL_4CH_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL_4CH_CUR_MSB */ +#define DL_4CH_CUR_PTR_MSB_SFT 0 +#define DL_4CH_CUR_PTR_MSB_MASK 0x1ff +#define DL_4CH_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_4CH_CUR */ +#define DL_4CH_CUR_PTR_SFT 0 +#define DL_4CH_CUR_PTR_MASK 0xffffffff +#define DL_4CH_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_4CH_END_MSB */ +#define DL_4CH_END_ADDR_MSB_SFT 0 +#define DL_4CH_END_ADDR_MSB_MASK 0x1ff +#define DL_4CH_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_4CH_END */ +#define DL_4CH_END_ADDR_SFT 4 +#define DL_4CH_END_ADDR_MASK 0xfffffff +#define DL_4CH_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL_4CH_CON0 */ +#define DL_4CH_ON_SFT 31 +#define DL_4CH_ON_MASK 0x1 +#define DL_4CH_ON_MASK_SFT (0x1 << 31) +#define DL_4CH_NUM_SFT 24 +#define DL_4CH_NUM_MASK 0x1f +#define DL_4CH_NUM_MASK_SFT (0x1f << 24) +#define DL_4CH_ONE_HEART_SEL_SFT 22 +#define DL_4CH_ONE_HEART_SEL_MASK 0x3 +#define DL_4CH_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL_4CH_MINLEN_SFT 20 +#define DL_4CH_MINLEN_MASK 0x3 +#define DL_4CH_MINLEN_MASK_SFT (0x3 << 20) +#define DL_4CH_MAXLEN_SFT 16 +#define DL_4CH_MAXLEN_MASK 0x3 +#define DL_4CH_MAXLEN_MASK_SFT (0x3 << 16) +#define DL_4CH_SEL_DOMAIN_SFT 13 +#define DL_4CH_SEL_DOMAIN_MASK 0x7 +#define DL_4CH_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL_4CH_SEL_FS_SFT 8 +#define DL_4CH_SEL_FS_MASK 0x1f +#define DL_4CH_SEL_FS_MASK_SFT (0x1f << 8) +#define DL_4CH_BUF_EMPTY_CLR_SFT 7 +#define DL_4CH_BUF_EMPTY_CLR_MASK 0x1 +#define DL_4CH_BUF_EMPTY_CLR_MASK_SFT (0x1 << 7) +#define DL_4CH_PBUF_SIZE_SFT 5 +#define DL_4CH_PBUF_SIZE_MASK 0x3 +#define DL_4CH_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL_4CH_HANG_CLR_SFT 4 +#define DL_4CH_HANG_CLR_MASK 0x1 +#define DL_4CH_HANG_CLR_MASK_SFT (0x1 << 4) +#define DL_4CH_NORMAL_MODE_SFT 3 +#define DL_4CH_NORMAL_MODE_MASK 0x1 +#define DL_4CH_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL_4CH_HALIGN_SFT 2 +#define DL_4CH_HALIGN_MASK 0x1 +#define DL_4CH_HALIGN_MASK_SFT (0x1 << 2) +#define DL_4CH_HD_MODE_SFT 0 +#define DL_4CH_HD_MODE_MASK 0x3 +#define DL_4CH_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL_24CH_BASE_MSB */ +#define DL_24CH_BASE__ADDR_MSB_SFT 0 +#define DL_24CH_BASE__ADDR_MSB_MASK 0x1ff +#define DL_24CH_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_24CH_BASE */ +#define DL_24CH_BASE_ADDR_SFT 4 +#define DL_24CH_BASE_ADDR_MASK 0xfffffff +#define DL_24CH_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL_24CH_CUR_MSB */ +#define DL_24CH_CUR_PTR_MSB_SFT 0 +#define DL_24CH_CUR_PTR_MSB_MASK 0x1ff +#define DL_24CH_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_24CH_CUR */ +#define DL_24CH_CUR_PTR_SFT 0 +#define DL_24CH_CUR_PTR_MASK 0xffffffff +#define DL_24CH_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_END_MSB */ +#define DL_24CH_END_ADDR_MSB_SFT 0 +#define DL_24CH_END_ADDR_MSB_MASK 0x1ff +#define DL_24CH_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL_24CH_END */ +#define DL_24CH_END_ADDR_SFT 4 +#define DL_24CH_END_ADDR_MASK 0xfffffff +#define DL_24CH_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL_24CH_CON0 */ +#define DL_24CH_ON_SFT 31 +#define DL_24CH_ON_MASK 0x1 +#define DL_24CH_ON_MASK_SFT (0x1 << 31) +#define DL_24CH_NUM_SFT 24 +#define DL_24CH_NUM_MASK 0x3f +#define DL_24CH_NUM_MASK_SFT (0x3f << 24) +#define DL_24CH_ONE_HEART_SEL_SFT 22 +#define DL_24CH_ONE_HEART_SEL_MASK 0x3 +#define DL_24CH_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL_24CH_MINLEN_SFT 20 +#define DL_24CH_MINLEN_MASK 0x3 +#define DL_24CH_MINLEN_MASK_SFT (0x3 << 20) +#define DL_24CH_MAXLEN_SFT 16 +#define DL_24CH_MAXLEN_MASK 0x3 +#define DL_24CH_MAXLEN_MASK_SFT (0x3 << 16) +#define DL_24CH_SEL_DOMAIN_SFT 13 +#define DL_24CH_SEL_DOMAIN_MASK 0x7 +#define DL_24CH_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL_24CH_SEL_FS_SFT 8 +#define DL_24CH_SEL_FS_MASK 0x1f +#define DL_24CH_SEL_FS_MASK_SFT (0x1f << 8) +#define DL_24CH_BUF_EMPTY_CLR_SFT 7 +#define DL_24CH_BUF_EMPTY_CLR_MASK 0x1 +#define DL_24CH_BUF_EMPTY_CLR_MASK_SFT (0x1 << 7) +#define DL_24CH_PBUF_SIZE_SFT 5 +#define DL_24CH_PBUF_SIZE_MASK 0x3 +#define DL_24CH_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL_24CH_HANG_CLR_SFT 4 +#define DL_24CH_HANG_CLR_MASK 0x1 +#define DL_24CH_HANG_CLR_MASK_SFT (0x1 << 4) +#define DL_24CH_NORMAL_MODE_SFT 3 +#define DL_24CH_NORMAL_MODE_MASK 0x1 +#define DL_24CH_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL_24CH_HALIGN_SFT 2 +#define DL_24CH_HALIGN_MASK 0x1 +#define DL_24CH_HALIGN_MASK_SFT (0x1 << 2) +#define DL_24CH_HD_MODE_SFT 0 +#define DL_24CH_HD_MODE_MASK 0x3 +#define DL_24CH_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL23_BASE_MSB */ +#define DL23_BASE__ADDR_MSB_SFT 0 +#define DL23_BASE__ADDR_MSB_MASK 0x1ff +#define DL23_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL23_BASE */ +#define DL23_BASE_ADDR_SFT 4 +#define DL23_BASE_ADDR_MASK 0xfffffff +#define DL23_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL23_CUR_MSB */ +#define DL23_CUR_PTR_MSB_SFT 0 +#define DL23_CUR_PTR_MSB_MASK 0x1ff +#define DL23_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL23_CUR */ +#define DL23_CUR_PTR_SFT 0 +#define DL23_CUR_PTR_MASK 0xffffffff +#define DL23_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL23_END_MSB */ +#define DL23_END_ADDR_MSB_SFT 0 +#define DL23_END_ADDR_MSB_MASK 0x1ff +#define DL23_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL23_END */ +#define DL23_END_ADDR_SFT 4 +#define DL23_END_ADDR_MASK 0xfffffff +#define DL23_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL23_RCH_MON */ +#define DL23_RCH_DATA_SFT 0 +#define DL23_RCH_DATA_MASK 0xffffffff +#define DL23_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL23_LCH_MON */ +#define DL23_LCH_DATA_SFT 0 +#define DL23_LCH_DATA_MASK 0xffffffff +#define DL23_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL23_CON0 */ +#define DL23_ON_SFT 28 +#define DL23_ON_MASK 0x1 +#define DL23_ON_MASK_SFT (0x1 << 28) +#define DL23_ONE_HEART_SEL_SFT 22 +#define DL23_ONE_HEART_SEL_MASK 0x3 +#define DL23_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL23_MINLEN_SFT 20 +#define DL23_MINLEN_MASK 0x3 +#define DL23_MINLEN_MASK_SFT (0x3 << 20) +#define DL23_MAXLEN_SFT 16 +#define DL23_MAXLEN_MASK 0x3 +#define DL23_MAXLEN_MASK_SFT (0x3 << 16) +#define DL23_SEL_DOMAIN_SFT 13 +#define DL23_SEL_DOMAIN_MASK 0x7 +#define DL23_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL23_SEL_FS_SFT 8 +#define DL23_SEL_FS_MASK 0x1f +#define DL23_SEL_FS_MASK_SFT (0x1f << 8) +#define DL23_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL23_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL23_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL23_PBUF_SIZE_SFT 5 +#define DL23_PBUF_SIZE_MASK 0x3 +#define DL23_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL23_MONO_SFT 4 +#define DL23_MONO_MASK 0x1 +#define DL23_MONO_MASK_SFT (0x1 << 4) +#define DL23_NORMAL_MODE_SFT 3 +#define DL23_NORMAL_MODE_MASK 0x1 +#define DL23_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL23_HALIGN_SFT 2 +#define DL23_HALIGN_MASK 0x1 +#define DL23_HALIGN_MASK_SFT (0x1 << 2) +#define DL23_HD_MODE_SFT 0 +#define DL23_HD_MODE_MASK 0x3 +#define DL23_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL24_BASE_MSB */ +#define DL24_BASE__ADDR_MSB_SFT 0 +#define DL24_BASE__ADDR_MSB_MASK 0x1ff +#define DL24_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL24_BASE */ +#define DL24_BASE_ADDR_SFT 4 +#define DL24_BASE_ADDR_MASK 0xfffffff +#define DL24_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL24_CUR_MSB */ +#define DL24_CUR_PTR_MSB_SFT 0 +#define DL24_CUR_PTR_MSB_MASK 0x1ff +#define DL24_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL24_CUR */ +#define DL24_CUR_PTR_SFT 0 +#define DL24_CUR_PTR_MASK 0xffffffff +#define DL24_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL24_END_MSB */ +#define DL24_END_ADDR_MSB_SFT 0 +#define DL24_END_ADDR_MSB_MASK 0x1ff +#define DL24_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL24_END */ +#define DL24_END_ADDR_SFT 4 +#define DL24_END_ADDR_MASK 0xfffffff +#define DL24_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL24_RCH_MON */ +#define DL24_RCH_DATA_SFT 0 +#define DL24_RCH_DATA_MASK 0xffffffff +#define DL24_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL24_LCH_MON */ +#define DL24_LCH_DATA_SFT 0 +#define DL24_LCH_DATA_MASK 0xffffffff +#define DL24_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL24_CON0 */ +#define DL24_ON_SFT 28 +#define DL24_ON_MASK 0x1 +#define DL24_ON_MASK_SFT (0x1 << 28) +#define DL24_ONE_HEART_SEL_SFT 22 +#define DL24_ONE_HEART_SEL_MASK 0x3 +#define DL24_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL24_MINLEN_SFT 20 +#define DL24_MINLEN_MASK 0x3 +#define DL24_MINLEN_MASK_SFT (0x3 << 20) +#define DL24_MAXLEN_SFT 16 +#define DL24_MAXLEN_MASK 0x3 +#define DL24_MAXLEN_MASK_SFT (0x3 << 16) +#define DL24_SEL_DOMAIN_SFT 13 +#define DL24_SEL_DOMAIN_MASK 0x7 +#define DL24_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL24_SEL_FS_SFT 8 +#define DL24_SEL_FS_MASK 0x1f +#define DL24_SEL_FS_MASK_SFT (0x1f << 8) +#define DL24_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL24_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL24_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL24_PBUF_SIZE_SFT 5 +#define DL24_PBUF_SIZE_MASK 0x3 +#define DL24_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL24_MONO_SFT 4 +#define DL24_MONO_MASK 0x1 +#define DL24_MONO_MASK_SFT (0x1 << 4) +#define DL24_NORMAL_MODE_SFT 3 +#define DL24_NORMAL_MODE_MASK 0x1 +#define DL24_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL24_HALIGN_SFT 2 +#define DL24_HALIGN_MASK 0x1 +#define DL24_HALIGN_MASK_SFT (0x1 << 2) +#define DL24_HD_MODE_SFT 0 +#define DL24_HD_MODE_MASK 0x3 +#define DL24_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL25_BASE_MSB */ +#define DL25_BASE__ADDR_MSB_SFT 0 +#define DL25_BASE__ADDR_MSB_MASK 0x1ff +#define DL25_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL25_BASE */ +#define DL25_BASE_ADDR_SFT 4 +#define DL25_BASE_ADDR_MASK 0xfffffff +#define DL25_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL25_CUR_MSB */ +#define DL25_CUR_PTR_MSB_SFT 0 +#define DL25_CUR_PTR_MSB_MASK 0x1ff +#define DL25_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL25_CUR */ +#define DL25_CUR_PTR_SFT 0 +#define DL25_CUR_PTR_MASK 0xffffffff +#define DL25_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL25_END_MSB */ +#define DL25_END_ADDR_MSB_SFT 0 +#define DL25_END_ADDR_MSB_MASK 0x1ff +#define DL25_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL25_END */ +#define DL25_END_ADDR_SFT 4 +#define DL25_END_ADDR_MASK 0xfffffff +#define DL25_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL25_RCH_MON */ +#define DL25_RCH_DATA_SFT 0 +#define DL25_RCH_DATA_MASK 0xffffffff +#define DL25_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL25_LCH_MON */ +#define DL25_LCH_DATA_SFT 0 +#define DL25_LCH_DATA_MASK 0xffffffff +#define DL25_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL25_CON0 */ +#define DL25_ON_SFT 28 +#define DL25_ON_MASK 0x1 +#define DL25_ON_MASK_SFT (0x1 << 28) +#define DL25_ONE_HEART_SEL_SFT 22 +#define DL25_ONE_HEART_SEL_MASK 0x3 +#define DL25_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL25_MINLEN_SFT 20 +#define DL25_MINLEN_MASK 0x3 +#define DL25_MINLEN_MASK_SFT (0x3 << 20) +#define DL25_MAXLEN_SFT 16 +#define DL25_MAXLEN_MASK 0x3 +#define DL25_MAXLEN_MASK_SFT (0x3 << 16) +#define DL25_SEL_DOMAIN_SFT 13 +#define DL25_SEL_DOMAIN_MASK 0x7 +#define DL25_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL25_SEL_FS_SFT 8 +#define DL25_SEL_FS_MASK 0x1f +#define DL25_SEL_FS_MASK_SFT (0x1f << 8) +#define DL25_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL25_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL25_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL25_PBUF_SIZE_SFT 5 +#define DL25_PBUF_SIZE_MASK 0x3 +#define DL25_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL25_MONO_SFT 4 +#define DL25_MONO_MASK 0x1 +#define DL25_MONO_MASK_SFT (0x1 << 4) +#define DL25_NORMAL_MODE_SFT 3 +#define DL25_NORMAL_MODE_MASK 0x1 +#define DL25_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL25_HALIGN_SFT 2 +#define DL25_HALIGN_MASK 0x1 +#define DL25_HALIGN_MASK_SFT (0x1 << 2) +#define DL25_HD_MODE_SFT 0 +#define DL25_HD_MODE_MASK 0x3 +#define DL25_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_DL26_BASE_MSB */ +#define DL26_BASE__ADDR_MSB_SFT 0 +#define DL26_BASE__ADDR_MSB_MASK 0x1ff +#define DL26_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL26_BASE */ +#define DL26_BASE_ADDR_SFT 4 +#define DL26_BASE_ADDR_MASK 0xfffffff +#define DL26_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL26_CUR_MSB */ +#define DL26_CUR_PTR_MSB_SFT 0 +#define DL26_CUR_PTR_MSB_MASK 0x1ff +#define DL26_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL26_CUR */ +#define DL26_CUR_PTR_SFT 0 +#define DL26_CUR_PTR_MASK 0xffffffff +#define DL26_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_DL26_END_MSB */ +#define DL26_END_ADDR_MSB_SFT 0 +#define DL26_END_ADDR_MSB_MASK 0x1ff +#define DL26_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_DL26_END */ +#define DL26_END_ADDR_SFT 4 +#define DL26_END_ADDR_MASK 0xfffffff +#define DL26_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_DL26_RCH_MON */ +#define DL26_RCH_DATA_SFT 0 +#define DL26_RCH_DATA_MASK 0xffffffff +#define DL26_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL26_LCH_MON */ +#define DL26_LCH_DATA_SFT 0 +#define DL26_LCH_DATA_MASK 0xffffffff +#define DL26_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL26_CON0 */ +#define DL26_ON_SFT 28 +#define DL26_ON_MASK 0x1 +#define DL26_ON_MASK_SFT (0x1 << 28) +#define DL26_ONE_HEART_SEL_SFT 22 +#define DL26_ONE_HEART_SEL_MASK 0x3 +#define DL26_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define DL26_MINLEN_SFT 20 +#define DL26_MINLEN_MASK 0x3 +#define DL26_MINLEN_MASK_SFT (0x3 << 20) +#define DL26_MAXLEN_SFT 16 +#define DL26_MAXLEN_MASK 0x3 +#define DL26_MAXLEN_MASK_SFT (0x3 << 16) +#define DL26_SEL_DOMAIN_SFT 13 +#define DL26_SEL_DOMAIN_MASK 0x7 +#define DL26_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define DL26_SEL_FS_SFT 8 +#define DL26_SEL_FS_MASK 0x1f +#define DL26_SEL_FS_MASK_SFT (0x1f << 8) +#define DL26_SW_CLEAR_BUF_EMPTY_SFT 7 +#define DL26_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define DL26_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define DL26_PBUF_SIZE_SFT 5 +#define DL26_PBUF_SIZE_MASK 0x3 +#define DL26_PBUF_SIZE_MASK_SFT (0x3 << 5) +#define DL26_MONO_SFT 4 +#define DL26_MONO_MASK 0x1 +#define DL26_MONO_MASK_SFT (0x1 << 4) +#define DL26_NORMAL_MODE_SFT 3 +#define DL26_NORMAL_MODE_MASK 0x1 +#define DL26_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define DL26_HALIGN_SFT 2 +#define DL26_HALIGN_MASK 0x1 +#define DL26_HALIGN_MASK_SFT (0x1 << 2) +#define DL26_HD_MODE_SFT 0 +#define DL26_HD_MODE_MASK 0x3 +#define DL26_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL0_BASE_MSB */ +#define VUL0_BASE_ADDR_MSB_SFT 0 +#define VUL0_BASE_ADDR_MSB_MASK 0x1ff +#define VUL0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL0_BASE */ +#define VUL0_BASE_ADDR_SFT 4 +#define VUL0_BASE_ADDR_MASK 0xfffffff +#define VUL0_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL0_CUR_MSB */ +#define VUL0_CUR_PTR_MSB_SFT 0 +#define VUL0_CUR_PTR_MSB_MASK 0x1ff +#define VUL0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL0_CUR */ +#define VUL0_CUR_PTR_SFT 0 +#define VUL0_CUR_PTR_MASK 0xffffffff +#define VUL0_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL0_END_MSB */ +#define VUL0_END_ADDR_MSB_SFT 0 +#define VUL0_END_ADDR_MSB_MASK 0x1ff +#define VUL0_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL0_END */ +#define VUL0_END_ADDR_SFT 4 +#define VUL0_END_ADDR_MASK 0xfffffff +#define VUL0_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL0_RCH_MON */ +#define VUL0_RCH_DATA_SFT 0 +#define VUL0_RCH_DATA_MASK 0xffffffff +#define VUL0_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL0_LCH_MON */ +#define VUL0_LCH_DATA_SFT 0 +#define VUL0_LCH_DATA_MASK 0xffffffff +#define VUL0_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL0_CON0 */ +#define VUL0_ON_SFT 28 +#define VUL0_ON_MASK 0x1 +#define VUL0_ON_MASK_SFT (0x1 << 28) +#define VUL0_MINLEN_SFT 20 +#define VUL0_MINLEN_MASK 0x3 +#define VUL0_MINLEN_MASK_SFT (0x3 << 20) +#define VUL0_MAXLEN_SFT 16 +#define VUL0_MAXLEN_MASK 0x3 +#define VUL0_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL0_SEL_DOMAIN_SFT 13 +#define VUL0_SEL_DOMAIN_MASK 0x7 +#define VUL0_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL0_SEL_FS_SFT 8 +#define VUL0_SEL_FS_MASK 0x1f +#define VUL0_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL0_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL0_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL0_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL0_WR_SIGN_SFT 6 +#define VUL0_WR_SIGN_MASK 0x1 +#define VUL0_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL0_R_MONO_SFT 5 +#define VUL0_R_MONO_MASK 0x1 +#define VUL0_R_MONO_MASK_SFT (0x1 << 5) +#define VUL0_MONO_SFT 4 +#define VUL0_MONO_MASK 0x1 +#define VUL0_MONO_MASK_SFT (0x1 << 4) +#define VUL0_NORMAL_MODE_SFT 3 +#define VUL0_NORMAL_MODE_MASK 0x1 +#define VUL0_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL0_HALIGN_SFT 2 +#define VUL0_HALIGN_MASK 0x1 +#define VUL0_HALIGN_MASK_SFT (0x1 << 2) +#define VUL0_HD_MODE_SFT 0 +#define VUL0_HD_MODE_MASK 0x3 +#define VUL0_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL1_BASE_MSB */ +#define VUL1_BASE_ADDR_MSB_SFT 0 +#define VUL1_BASE_ADDR_MSB_MASK 0x1ff +#define VUL1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL1_BASE */ +#define VUL1_BASE_ADDR_SFT 4 +#define VUL1_BASE_ADDR_MASK 0xfffffff +#define VUL1_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL1_CUR_MSB */ +#define VUL1_CUR_PTR_MSB_SFT 0 +#define VUL1_CUR_PTR_MSB_MASK 0x1ff +#define VUL1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL1_CUR */ +#define VUL1_CUR_PTR_SFT 0 +#define VUL1_CUR_PTR_MASK 0xffffffff +#define VUL1_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL1_END_MSB */ +#define VUL1_END_ADDR_MSB_SFT 0 +#define VUL1_END_ADDR_MSB_MASK 0x1ff +#define VUL1_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL1_END */ +#define VUL1_END_ADDR_SFT 4 +#define VUL1_END_ADDR_MASK 0xfffffff +#define VUL1_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL1_RCH_MON */ +#define VUL1_RCH_DATA_SFT 0 +#define VUL1_RCH_DATA_MASK 0xffffffff +#define VUL1_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL1_LCH_MON */ +#define VUL1_LCH_DATA_SFT 0 +#define VUL1_LCH_DATA_MASK 0xffffffff +#define VUL1_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL1_CON0 */ +#define VUL1_ON_SFT 28 +#define VUL1_ON_MASK 0x1 +#define VUL1_ON_MASK_SFT (0x1 << 28) +#define VUL1_MINLEN_SFT 20 +#define VUL1_MINLEN_MASK 0x3 +#define VUL1_MINLEN_MASK_SFT (0x3 << 20) +#define VUL1_MAXLEN_SFT 16 +#define VUL1_MAXLEN_MASK 0x3 +#define VUL1_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL1_SEL_DOMAIN_SFT 13 +#define VUL1_SEL_DOMAIN_MASK 0x7 +#define VUL1_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL1_SEL_FS_SFT 8 +#define VUL1_SEL_FS_MASK 0x1f +#define VUL1_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL1_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL1_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL1_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL1_WR_SIGN_SFT 6 +#define VUL1_WR_SIGN_MASK 0x1 +#define VUL1_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL1_R_MONO_SFT 5 +#define VUL1_R_MONO_MASK 0x1 +#define VUL1_R_MONO_MASK_SFT (0x1 << 5) +#define VUL1_MONO_SFT 4 +#define VUL1_MONO_MASK 0x1 +#define VUL1_MONO_MASK_SFT (0x1 << 4) +#define VUL1_NORMAL_MODE_SFT 3 +#define VUL1_NORMAL_MODE_MASK 0x1 +#define VUL1_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL1_HALIGN_SFT 2 +#define VUL1_HALIGN_MASK 0x1 +#define VUL1_HALIGN_MASK_SFT (0x1 << 2) +#define VUL1_HD_MODE_SFT 0 +#define VUL1_HD_MODE_MASK 0x3 +#define VUL1_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL2_BASE_MSB */ +#define VUL2_BASE_ADDR_MSB_SFT 0 +#define VUL2_BASE_ADDR_MSB_MASK 0x1ff +#define VUL2_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL2_BASE */ +#define VUL2_BASE_ADDR_SFT 4 +#define VUL2_BASE_ADDR_MASK 0xfffffff +#define VUL2_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL2_CUR_MSB */ +#define VUL2_CUR_PTR_MSB_SFT 0 +#define VUL2_CUR_PTR_MSB_MASK 0x1ff +#define VUL2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL2_CUR */ +#define VUL2_CUR_PTR_SFT 0 +#define VUL2_CUR_PTR_MASK 0xffffffff +#define VUL2_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL2_END_MSB */ +#define VUL2_END_ADDR_MSB_SFT 0 +#define VUL2_END_ADDR_MSB_MASK 0x1ff +#define VUL2_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL2_END */ +#define VUL2_END_ADDR_SFT 4 +#define VUL2_END_ADDR_MASK 0xfffffff +#define VUL2_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL2_RCH_MON */ +#define VUL2_RCH_DATA_SFT 0 +#define VUL2_RCH_DATA_MASK 0xffffffff +#define VUL2_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL2_LCH_MON */ +#define VUL2_LCH_DATA_SFT 0 +#define VUL2_LCH_DATA_MASK 0xffffffff +#define VUL2_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL2_CON0 */ +#define VUL2_ON_SFT 28 +#define VUL2_ON_MASK 0x1 +#define VUL2_ON_MASK_SFT (0x1 << 28) +#define VUL2_MINLEN_SFT 20 +#define VUL2_MINLEN_MASK 0x3 +#define VUL2_MINLEN_MASK_SFT (0x3 << 20) +#define VUL2_MAXLEN_SFT 16 +#define VUL2_MAXLEN_MASK 0x3 +#define VUL2_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL2_SEL_DOMAIN_SFT 13 +#define VUL2_SEL_DOMAIN_MASK 0x7 +#define VUL2_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL2_SEL_FS_SFT 8 +#define VUL2_SEL_FS_MASK 0x1f +#define VUL2_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL2_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL2_WR_SIGN_SFT 6 +#define VUL2_WR_SIGN_MASK 0x1 +#define VUL2_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL2_R_MONO_SFT 5 +#define VUL2_R_MONO_MASK 0x1 +#define VUL2_R_MONO_MASK_SFT (0x1 << 5) +#define VUL2_MONO_SFT 4 +#define VUL2_MONO_MASK 0x1 +#define VUL2_MONO_MASK_SFT (0x1 << 4) +#define VUL2_NORMAL_MODE_SFT 3 +#define VUL2_NORMAL_MODE_MASK 0x1 +#define VUL2_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL2_HALIGN_SFT 2 +#define VUL2_HALIGN_MASK 0x1 +#define VUL2_HALIGN_MASK_SFT (0x1 << 2) +#define VUL2_HD_MODE_SFT 0 +#define VUL2_HD_MODE_MASK 0x3 +#define VUL2_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL3_BASE_MSB */ +#define VUL3_BASE_ADDR_MSB_SFT 0 +#define VUL3_BASE_ADDR_MSB_MASK 0x1ff +#define VUL3_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL3_BASE */ +#define VUL3_BASE_ADDR_SFT 4 +#define VUL3_BASE_ADDR_MASK 0xfffffff +#define VUL3_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL3_CUR_MSB */ +#define VUL3_CUR_PTR_MSB_SFT 0 +#define VUL3_CUR_PTR_MSB_MASK 0x1ff +#define VUL3_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL3_CUR */ +#define VUL3_CUR_PTR_SFT 0 +#define VUL3_CUR_PTR_MASK 0xffffffff +#define VUL3_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL3_END_MSB */ +#define VUL3_END_ADDR_MSB_SFT 0 +#define VUL3_END_ADDR_MSB_MASK 0x1ff +#define VUL3_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL3_END */ +#define VUL3_END_ADDR_SFT 4 +#define VUL3_END_ADDR_MASK 0xfffffff +#define VUL3_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL3_RCH_MON */ +#define VUL3_RCH_DATA_SFT 0 +#define VUL3_RCH_DATA_MASK 0xffffffff +#define VUL3_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL3_LCH_MON */ +#define VUL3_LCH_DATA_SFT 0 +#define VUL3_LCH_DATA_MASK 0xffffffff +#define VUL3_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL3_CON0 */ +#define VUL3_ON_SFT 28 +#define VUL3_ON_MASK 0x1 +#define VUL3_ON_MASK_SFT (0x1 << 28) +#define VUL3_MINLEN_SFT 20 +#define VUL3_MINLEN_MASK 0x3 +#define VUL3_MINLEN_MASK_SFT (0x3 << 20) +#define VUL3_MAXLEN_SFT 16 +#define VUL3_MAXLEN_MASK 0x3 +#define VUL3_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL3_SEL_DOMAIN_SFT 13 +#define VUL3_SEL_DOMAIN_MASK 0x7 +#define VUL3_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL3_SEL_FS_SFT 8 +#define VUL3_SEL_FS_MASK 0x1f +#define VUL3_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL3_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL3_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL3_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL3_WR_SIGN_SFT 6 +#define VUL3_WR_SIGN_MASK 0x1 +#define VUL3_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL3_R_MONO_SFT 5 +#define VUL3_R_MONO_MASK 0x1 +#define VUL3_R_MONO_MASK_SFT (0x1 << 5) +#define VUL3_MONO_SFT 4 +#define VUL3_MONO_MASK 0x1 +#define VUL3_MONO_MASK_SFT (0x1 << 4) +#define VUL3_NORMAL_MODE_SFT 3 +#define VUL3_NORMAL_MODE_MASK 0x1 +#define VUL3_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL3_HALIGN_SFT 2 +#define VUL3_HALIGN_MASK 0x1 +#define VUL3_HALIGN_MASK_SFT (0x1 << 2) +#define VUL3_HD_MODE_SFT 0 +#define VUL3_HD_MODE_MASK 0x3 +#define VUL3_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL4_BASE_MSB */ +#define VUL4_BASE_ADDR_MSB_SFT 0 +#define VUL4_BASE_ADDR_MSB_MASK 0x1ff +#define VUL4_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL4_BASE */ +#define VUL4_BASE_ADDR_SFT 4 +#define VUL4_BASE_ADDR_MASK 0xfffffff +#define VUL4_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL4_CUR_MSB */ +#define VUL4_CUR_PTR_MSB_SFT 0 +#define VUL4_CUR_PTR_MSB_MASK 0x1ff +#define VUL4_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL4_CUR */ +#define VUL4_CUR_PTR_SFT 0 +#define VUL4_CUR_PTR_MASK 0xffffffff +#define VUL4_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL4_END_MSB */ +#define VUL4_END_ADDR_MSB_SFT 0 +#define VUL4_END_ADDR_MSB_MASK 0x1ff +#define VUL4_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL4_END */ +#define VUL4_END_ADDR_SFT 4 +#define VUL4_END_ADDR_MASK 0xfffffff +#define VUL4_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL4_RCH_MON */ +#define VUL4_RCH_DATA_SFT 0 +#define VUL4_RCH_DATA_MASK 0xffffffff +#define VUL4_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL4_LCH_MON */ +#define VUL4_LCH_DATA_SFT 0 +#define VUL4_LCH_DATA_MASK 0xffffffff +#define VUL4_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL4_CON0 */ +#define VUL4_ON_SFT 28 +#define VUL4_ON_MASK 0x1 +#define VUL4_ON_MASK_SFT (0x1 << 28) +#define VUL4_MINLEN_SFT 20 +#define VUL4_MINLEN_MASK 0x3 +#define VUL4_MINLEN_MASK_SFT (0x3 << 20) +#define VUL4_MAXLEN_SFT 16 +#define VUL4_MAXLEN_MASK 0x3 +#define VUL4_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL4_SEL_DOMAIN_SFT 13 +#define VUL4_SEL_DOMAIN_MASK 0x7 +#define VUL4_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL4_SEL_FS_SFT 8 +#define VUL4_SEL_FS_MASK 0x1f +#define VUL4_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL4_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL4_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL4_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL4_WR_SIGN_SFT 6 +#define VUL4_WR_SIGN_MASK 0x1 +#define VUL4_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL4_R_MONO_SFT 5 +#define VUL4_R_MONO_MASK 0x1 +#define VUL4_R_MONO_MASK_SFT (0x1 << 5) +#define VUL4_MONO_SFT 4 +#define VUL4_MONO_MASK 0x1 +#define VUL4_MONO_MASK_SFT (0x1 << 4) +#define VUL4_NORMAL_MODE_SFT 3 +#define VUL4_NORMAL_MODE_MASK 0x1 +#define VUL4_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL4_HALIGN_SFT 2 +#define VUL4_HALIGN_MASK 0x1 +#define VUL4_HALIGN_MASK_SFT (0x1 << 2) +#define VUL4_HD_MODE_SFT 0 +#define VUL4_HD_MODE_MASK 0x3 +#define VUL4_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL5_BASE_MSB */ +#define VUL5_BASE_ADDR_MSB_SFT 0 +#define VUL5_BASE_ADDR_MSB_MASK 0x1ff +#define VUL5_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL5_BASE */ +#define VUL5_BASE_ADDR_SFT 4 +#define VUL5_BASE_ADDR_MASK 0xfffffff +#define VUL5_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL5_CUR_MSB */ +#define VUL5_CUR_PTR_MSB_SFT 0 +#define VUL5_CUR_PTR_MSB_MASK 0x1ff +#define VUL5_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL5_CUR */ +#define VUL5_CUR_PTR_SFT 0 +#define VUL5_CUR_PTR_MASK 0xffffffff +#define VUL5_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL5_END_MSB */ +#define VUL5_END_ADDR_MSB_SFT 0 +#define VUL5_END_ADDR_MSB_MASK 0x1ff +#define VUL5_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL5_END */ +#define VUL5_END_ADDR_SFT 4 +#define VUL5_END_ADDR_MASK 0xfffffff +#define VUL5_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL5_RCH_MON */ +#define VUL5_RCH_DATA_SFT 0 +#define VUL5_RCH_DATA_MASK 0xffffffff +#define VUL5_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL5_LCH_MON */ +#define VUL5_LCH_DATA_SFT 0 +#define VUL5_LCH_DATA_MASK 0xffffffff +#define VUL5_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL5_CON0 */ +#define VUL5_ON_SFT 28 +#define VUL5_ON_MASK 0x1 +#define VUL5_ON_MASK_SFT (0x1 << 28) +#define VUL5_MINLEN_SFT 20 +#define VUL5_MINLEN_MASK 0x3 +#define VUL5_MINLEN_MASK_SFT (0x3 << 20) +#define VUL5_MAXLEN_SFT 16 +#define VUL5_MAXLEN_MASK 0x3 +#define VUL5_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL5_SEL_DOMAIN_SFT 13 +#define VUL5_SEL_DOMAIN_MASK 0x7 +#define VUL5_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL5_SEL_FS_SFT 8 +#define VUL5_SEL_FS_MASK 0x1f +#define VUL5_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL5_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL5_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL5_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL5_WR_SIGN_SFT 6 +#define VUL5_WR_SIGN_MASK 0x1 +#define VUL5_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL5_R_MONO_SFT 5 +#define VUL5_R_MONO_MASK 0x1 +#define VUL5_R_MONO_MASK_SFT (0x1 << 5) +#define VUL5_MONO_SFT 4 +#define VUL5_MONO_MASK 0x1 +#define VUL5_MONO_MASK_SFT (0x1 << 4) +#define VUL5_NORMAL_MODE_SFT 3 +#define VUL5_NORMAL_MODE_MASK 0x1 +#define VUL5_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL5_HALIGN_SFT 2 +#define VUL5_HALIGN_MASK 0x1 +#define VUL5_HALIGN_MASK_SFT (0x1 << 2) +#define VUL5_HD_MODE_SFT 0 +#define VUL5_HD_MODE_MASK 0x3 +#define VUL5_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL6_BASE_MSB */ +#define VUL6_BASE_ADDR_MSB_SFT 0 +#define VUL6_BASE_ADDR_MSB_MASK 0x1ff +#define VUL6_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL6_BASE */ +#define VUL6_BASE_ADDR_SFT 4 +#define VUL6_BASE_ADDR_MASK 0xfffffff +#define VUL6_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL6_CUR_MSB */ +#define VUL6_CUR_PTR_MSB_SFT 0 +#define VUL6_CUR_PTR_MSB_MASK 0x1ff +#define VUL6_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL6_CUR */ +#define VUL6_CUR_PTR_SFT 0 +#define VUL6_CUR_PTR_MASK 0xffffffff +#define VUL6_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL6_END_MSB */ +#define VUL6_END_ADDR_MSB_SFT 0 +#define VUL6_END_ADDR_MSB_MASK 0x1ff +#define VUL6_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL6_END */ +#define VUL6_END_ADDR_SFT 4 +#define VUL6_END_ADDR_MASK 0xfffffff +#define VUL6_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL6_RCH_MON */ +#define VUL6_RCH_DATA_SFT 0 +#define VUL6_RCH_DATA_MASK 0xffffffff +#define VUL6_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL6_LCH_MON */ +#define VUL6_LCH_DATA_SFT 0 +#define VUL6_LCH_DATA_MASK 0xffffffff +#define VUL6_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL6_CON0 */ +#define VUL6_ON_SFT 28 +#define VUL6_ON_MASK 0x1 +#define VUL6_ON_MASK_SFT (0x1 << 28) +#define VUL6_MINLEN_SFT 20 +#define VUL6_MINLEN_MASK 0x3 +#define VUL6_MINLEN_MASK_SFT (0x3 << 20) +#define VUL6_MAXLEN_SFT 16 +#define VUL6_MAXLEN_MASK 0x3 +#define VUL6_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL6_SEL_DOMAIN_SFT 13 +#define VUL6_SEL_DOMAIN_MASK 0x7 +#define VUL6_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL6_SEL_FS_SFT 8 +#define VUL6_SEL_FS_MASK 0x1f +#define VUL6_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL6_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL6_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL6_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL6_WR_SIGN_SFT 6 +#define VUL6_WR_SIGN_MASK 0x1 +#define VUL6_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL6_R_MONO_SFT 5 +#define VUL6_R_MONO_MASK 0x1 +#define VUL6_R_MONO_MASK_SFT (0x1 << 5) +#define VUL6_MONO_SFT 4 +#define VUL6_MONO_MASK 0x1 +#define VUL6_MONO_MASK_SFT (0x1 << 4) +#define VUL6_NORMAL_MODE_SFT 3 +#define VUL6_NORMAL_MODE_MASK 0x1 +#define VUL6_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL6_HALIGN_SFT 2 +#define VUL6_HALIGN_MASK 0x1 +#define VUL6_HALIGN_MASK_SFT (0x1 << 2) +#define VUL6_HD_MODE_SFT 0 +#define VUL6_HD_MODE_MASK 0x3 +#define VUL6_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL7_BASE_MSB */ +#define VUL7_BASE_ADDR_MSB_SFT 0 +#define VUL7_BASE_ADDR_MSB_MASK 0x1ff +#define VUL7_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL7_BASE */ +#define VUL7_BASE_ADDR_SFT 4 +#define VUL7_BASE_ADDR_MASK 0xfffffff +#define VUL7_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL7_CUR_MSB */ +#define VUL7_CUR_PTR_MSB_SFT 0 +#define VUL7_CUR_PTR_MSB_MASK 0x1ff +#define VUL7_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL7_CUR */ +#define VUL7_CUR_PTR_SFT 0 +#define VUL7_CUR_PTR_MASK 0xffffffff +#define VUL7_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL7_END_MSB */ +#define VUL7_END_ADDR_MSB_SFT 0 +#define VUL7_END_ADDR_MSB_MASK 0x1ff +#define VUL7_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL7_END */ +#define VUL7_END_ADDR_SFT 4 +#define VUL7_END_ADDR_MASK 0xfffffff +#define VUL7_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL7_RCH_MON */ +#define VUL7_RCH_DATA_SFT 0 +#define VUL7_RCH_DATA_MASK 0xffffffff +#define VUL7_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL7_LCH_MON */ +#define VUL7_LCH_DATA_SFT 0 +#define VUL7_LCH_DATA_MASK 0xffffffff +#define VUL7_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL7_CON0 */ +#define VUL7_ON_SFT 28 +#define VUL7_ON_MASK 0x1 +#define VUL7_ON_MASK_SFT (0x1 << 28) +#define VUL7_MINLEN_SFT 20 +#define VUL7_MINLEN_MASK 0x3 +#define VUL7_MINLEN_MASK_SFT (0x3 << 20) +#define VUL7_MAXLEN_SFT 16 +#define VUL7_MAXLEN_MASK 0x3 +#define VUL7_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL7_SEL_DOMAIN_SFT 13 +#define VUL7_SEL_DOMAIN_MASK 0x7 +#define VUL7_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL7_SEL_FS_SFT 8 +#define VUL7_SEL_FS_MASK 0x1f +#define VUL7_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL7_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL7_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL7_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL7_WR_SIGN_SFT 6 +#define VUL7_WR_SIGN_MASK 0x1 +#define VUL7_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL7_R_MONO_SFT 5 +#define VUL7_R_MONO_MASK 0x1 +#define VUL7_R_MONO_MASK_SFT (0x1 << 5) +#define VUL7_MONO_SFT 4 +#define VUL7_MONO_MASK 0x1 +#define VUL7_MONO_MASK_SFT (0x1 << 4) +#define VUL7_NORMAL_MODE_SFT 3 +#define VUL7_NORMAL_MODE_MASK 0x1 +#define VUL7_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL7_HALIGN_SFT 2 +#define VUL7_HALIGN_MASK 0x1 +#define VUL7_HALIGN_MASK_SFT (0x1 << 2) +#define VUL7_HD_MODE_SFT 0 +#define VUL7_HD_MODE_MASK 0x3 +#define VUL7_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL8_BASE_MSB */ +#define VUL8_BASE_ADDR_MSB_SFT 0 +#define VUL8_BASE_ADDR_MSB_MASK 0x1ff +#define VUL8_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL8_BASE */ +#define VUL8_BASE_ADDR_SFT 4 +#define VUL8_BASE_ADDR_MASK 0xfffffff +#define VUL8_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL8_CUR_MSB */ +#define VUL8_CUR_PTR_MSB_SFT 0 +#define VUL8_CUR_PTR_MSB_MASK 0x1ff +#define VUL8_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL8_CUR */ +#define VUL8_CUR_PTR_SFT 0 +#define VUL8_CUR_PTR_MASK 0xffffffff +#define VUL8_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL8_END_MSB */ +#define VUL8_END_ADDR_MSB_SFT 0 +#define VUL8_END_ADDR_MSB_MASK 0x1ff +#define VUL8_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL8_END */ +#define VUL8_END_ADDR_SFT 4 +#define VUL8_END_ADDR_MASK 0xfffffff +#define VUL8_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL8_RCH_MON */ +#define VUL8_RCH_DATA_SFT 0 +#define VUL8_RCH_DATA_MASK 0xffffffff +#define VUL8_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL8_LCH_MON */ +#define VUL8_LCH_DATA_SFT 0 +#define VUL8_LCH_DATA_MASK 0xffffffff +#define VUL8_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL8_CON0 */ +#define VUL8_ON_SFT 28 +#define VUL8_ON_MASK 0x1 +#define VUL8_ON_MASK_SFT (0x1 << 28) +#define VUL8_MINLEN_SFT 20 +#define VUL8_MINLEN_MASK 0x3 +#define VUL8_MINLEN_MASK_SFT (0x3 << 20) +#define VUL8_MAXLEN_SFT 16 +#define VUL8_MAXLEN_MASK 0x3 +#define VUL8_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL8_SEL_DOMAIN_SFT 13 +#define VUL8_SEL_DOMAIN_MASK 0x7 +#define VUL8_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL8_SEL_FS_SFT 8 +#define VUL8_SEL_FS_MASK 0x1f +#define VUL8_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL8_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL8_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL8_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL8_WR_SIGN_SFT 6 +#define VUL8_WR_SIGN_MASK 0x1 +#define VUL8_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL8_R_MONO_SFT 5 +#define VUL8_R_MONO_MASK 0x1 +#define VUL8_R_MONO_MASK_SFT (0x1 << 5) +#define VUL8_MONO_SFT 4 +#define VUL8_MONO_MASK 0x1 +#define VUL8_MONO_MASK_SFT (0x1 << 4) +#define VUL8_NORMAL_MODE_SFT 3 +#define VUL8_NORMAL_MODE_MASK 0x1 +#define VUL8_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL8_HALIGN_SFT 2 +#define VUL8_HALIGN_MASK 0x1 +#define VUL8_HALIGN_MASK_SFT (0x1 << 2) +#define VUL8_HD_MODE_SFT 0 +#define VUL8_HD_MODE_MASK 0x3 +#define VUL8_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL9_BASE_MSB */ +#define VUL9_BASE_ADDR_MSB_SFT 0 +#define VUL9_BASE_ADDR_MSB_MASK 0x1ff +#define VUL9_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL9_BASE */ +#define VUL9_BASE_ADDR_SFT 4 +#define VUL9_BASE_ADDR_MASK 0xfffffff +#define VUL9_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL9_CUR_MSB */ +#define VUL9_CUR_PTR_MSB_SFT 0 +#define VUL9_CUR_PTR_MSB_MASK 0x1ff +#define VUL9_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL9_CUR */ +#define VUL9_CUR_PTR_SFT 0 +#define VUL9_CUR_PTR_MASK 0xffffffff +#define VUL9_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL9_END_MSB */ +#define VUL9_END_ADDR_MSB_SFT 0 +#define VUL9_END_ADDR_MSB_MASK 0x1ff +#define VUL9_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL9_END */ +#define VUL9_END_ADDR_SFT 4 +#define VUL9_END_ADDR_MASK 0xfffffff +#define VUL9_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL9_RCH_MON */ +#define VUL9_RCH_DATA_SFT 0 +#define VUL9_RCH_DATA_MASK 0xffffffff +#define VUL9_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL9_LCH_MON */ +#define VUL9_LCH_DATA_SFT 0 +#define VUL9_LCH_DATA_MASK 0xffffffff +#define VUL9_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL9_CON0 */ +#define VUL9_ON_SFT 28 +#define VUL9_ON_MASK 0x1 +#define VUL9_ON_MASK_SFT (0x1 << 28) +#define VUL9_MINLEN_SFT 20 +#define VUL9_MINLEN_MASK 0x3 +#define VUL9_MINLEN_MASK_SFT (0x3 << 20) +#define VUL9_MAXLEN_SFT 16 +#define VUL9_MAXLEN_MASK 0x3 +#define VUL9_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL9_SEL_DOMAIN_SFT 13 +#define VUL9_SEL_DOMAIN_MASK 0x7 +#define VUL9_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL9_SEL_FS_SFT 8 +#define VUL9_SEL_FS_MASK 0x1f +#define VUL9_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL9_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL9_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL9_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL9_WR_SIGN_SFT 6 +#define VUL9_WR_SIGN_MASK 0x1 +#define VUL9_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL9_R_MONO_SFT 5 +#define VUL9_R_MONO_MASK 0x1 +#define VUL9_R_MONO_MASK_SFT (0x1 << 5) +#define VUL9_MONO_SFT 4 +#define VUL9_MONO_MASK 0x1 +#define VUL9_MONO_MASK_SFT (0x1 << 4) +#define VUL9_NORMAL_MODE_SFT 3 +#define VUL9_NORMAL_MODE_MASK 0x1 +#define VUL9_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL9_HALIGN_SFT 2 +#define VUL9_HALIGN_MASK 0x1 +#define VUL9_HALIGN_MASK_SFT (0x1 << 2) +#define VUL9_HD_MODE_SFT 0 +#define VUL9_HD_MODE_MASK 0x3 +#define VUL9_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL10_BASE_MSB */ +#define VUL10_BASE_ADDR_MSB_SFT 0 +#define VUL10_BASE_ADDR_MSB_MASK 0x1ff +#define VUL10_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL10_BASE */ +#define VUL10_BASE_ADDR_SFT 4 +#define VUL10_BASE_ADDR_MASK 0xfffffff +#define VUL10_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL10_CUR_MSB */ +#define VUL10_CUR_PTR_MSB_SFT 0 +#define VUL10_CUR_PTR_MSB_MASK 0x1ff +#define VUL10_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL10_CUR */ +#define VUL10_CUR_PTR_SFT 0 +#define VUL10_CUR_PTR_MASK 0xffffffff +#define VUL10_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL10_END_MSB */ +#define VUL10_END_ADDR_MSB_SFT 0 +#define VUL10_END_ADDR_MSB_MASK 0x1ff +#define VUL10_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL10_END */ +#define VUL10_END_ADDR_SFT 4 +#define VUL10_END_ADDR_MASK 0xfffffff +#define VUL10_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL10_RCH_MON */ +#define VUL10_RCH_DATA_SFT 0 +#define VUL10_RCH_DATA_MASK 0xffffffff +#define VUL10_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL10_LCH_MON */ +#define VUL10_LCH_DATA_SFT 0 +#define VUL10_LCH_DATA_MASK 0xffffffff +#define VUL10_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL10_CON0 */ +#define VUL10_ON_SFT 28 +#define VUL10_ON_MASK 0x1 +#define VUL10_ON_MASK_SFT (0x1 << 28) +#define VUL10_MINLEN_SFT 20 +#define VUL10_MINLEN_MASK 0x3 +#define VUL10_MINLEN_MASK_SFT (0x3 << 20) +#define VUL10_MAXLEN_SFT 16 +#define VUL10_MAXLEN_MASK 0x3 +#define VUL10_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL10_SEL_DOMAIN_SFT 13 +#define VUL10_SEL_DOMAIN_MASK 0x7 +#define VUL10_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL10_SEL_FS_SFT 8 +#define VUL10_SEL_FS_MASK 0x1f +#define VUL10_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL10_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL10_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL10_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL10_WR_SIGN_SFT 6 +#define VUL10_WR_SIGN_MASK 0x1 +#define VUL10_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL10_R_MONO_SFT 5 +#define VUL10_R_MONO_MASK 0x1 +#define VUL10_R_MONO_MASK_SFT (0x1 << 5) +#define VUL10_MONO_SFT 4 +#define VUL10_MONO_MASK 0x1 +#define VUL10_MONO_MASK_SFT (0x1 << 4) +#define VUL10_NORMAL_MODE_SFT 3 +#define VUL10_NORMAL_MODE_MASK 0x1 +#define VUL10_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL10_HALIGN_SFT 2 +#define VUL10_HALIGN_MASK 0x1 +#define VUL10_HALIGN_MASK_SFT (0x1 << 2) +#define VUL10_HD_MODE_SFT 0 +#define VUL10_HD_MODE_MASK 0x3 +#define VUL10_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL24_BASE_MSB */ +#define VUL24_BASE_ADDR_MSB_SFT 0 +#define VUL24_BASE_ADDR_MSB_MASK 0x1ff +#define VUL24_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL24_BASE */ +#define VUL24_BASE_ADDR_SFT 4 +#define VUL24_BASE_ADDR_MASK 0xfffffff +#define VUL24_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL24_CUR_MSB */ +#define VUL24_CUR_PTR_MSB_SFT 0 +#define VUL24_CUR_PTR_MSB_MASK 0x1ff +#define VUL24_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL24_CUR */ +#define VUL24_CUR_PTR_SFT 0 +#define VUL24_CUR_PTR_MASK 0xffffffff +#define VUL24_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL24_END_MSB */ +#define VUL24_END_ADDR_MSB_SFT 0 +#define VUL24_END_ADDR_MSB_MASK 0x1ff +#define VUL24_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL24_END */ +#define VUL24_END_ADDR_SFT 4 +#define VUL24_END_ADDR_MASK 0xfffffff +#define VUL24_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL24_CON0 */ +#define OUT_ON_USE_VUL24_SFT 29 +#define OUT_ON_USE_VUL24_MASK 0x1 +#define OUT_ON_USE_VUL24_MASK_SFT (0x1 << 29) +#define VUL24_ON_SFT 28 +#define VUL24_ON_MASK 0x1 +#define VUL24_ON_MASK_SFT (0x1 << 28) +#define VUL24_MINLEN_SFT 20 +#define VUL24_MINLEN_MASK 0x3 +#define VUL24_MINLEN_MASK_SFT (0x3 << 20) +#define VUL24_MAXLEN_SFT 16 +#define VUL24_MAXLEN_MASK 0x3 +#define VUL24_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL24_SEL_DOMAIN_SFT 13 +#define VUL24_SEL_DOMAIN_MASK 0x7 +#define VUL24_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL24_SEL_FS_SFT 8 +#define VUL24_SEL_FS_MASK 0x1f +#define VUL24_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL24_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL24_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL24_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL24_WR_SIGN_SFT 6 +#define VUL24_WR_SIGN_MASK 0x1 +#define VUL24_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL24_R_MONO_SFT 5 +#define VUL24_R_MONO_MASK 0x1 +#define VUL24_R_MONO_MASK_SFT (0x1 << 5) +#define VUL24_MONO_SFT 4 +#define VUL24_MONO_MASK 0x1 +#define VUL24_MONO_MASK_SFT (0x1 << 4) +#define VUL24_NORMAL_MODE_SFT 3 +#define VUL24_NORMAL_MODE_MASK 0x1 +#define VUL24_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL24_HALIGN_SFT 2 +#define VUL24_HALIGN_MASK 0x1 +#define VUL24_HALIGN_MASK_SFT (0x1 << 2) +#define VUL24_HD_MODE_SFT 0 +#define VUL24_HD_MODE_MASK 0x3 +#define VUL24_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL25_BASE_MSB */ +#define VUL25_BASE_ADDR_MSB_SFT 0 +#define VUL25_BASE_ADDR_MSB_MASK 0x1ff +#define VUL25_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL25_BASE */ +#define VUL25_BASE_ADDR_SFT 4 +#define VUL25_BASE_ADDR_MASK 0xfffffff +#define VUL25_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL25_CUR_MSB */ +#define VUL25_CUR_PTR_MSB_SFT 0 +#define VUL25_CUR_PTR_MSB_MASK 0x1ff +#define VUL25_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL25_CUR */ +#define VUL25_CUR_PTR_SFT 0 +#define VUL25_CUR_PTR_MASK 0xffffffff +#define VUL25_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL25_END_MSB */ +#define VUL25_END_ADDR_MSB_SFT 0 +#define VUL25_END_ADDR_MSB_MASK 0x1ff +#define VUL25_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL25_END */ +#define VUL25_END_ADDR_SFT 4 +#define VUL25_END_ADDR_MASK 0xfffffff +#define VUL25_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL25_CON0 */ +#define OUT_ON_USE_VUL25_SFT 29 +#define OUT_ON_USE_VUL25_MASK 0x1 +#define OUT_ON_USE_VUL25_MASK_SFT (0x1 << 29) +#define VUL25_ON_SFT 28 +#define VUL25_ON_MASK 0x1 +#define VUL25_ON_MASK_SFT (0x1 << 28) +#define VUL25_MINLEN_SFT 20 +#define VUL25_MINLEN_MASK 0x3 +#define VUL25_MINLEN_MASK_SFT (0x3 << 20) +#define VUL25_MAXLEN_SFT 16 +#define VUL25_MAXLEN_MASK 0x3 +#define VUL25_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL25_SEL_DOMAIN_SFT 13 +#define VUL25_SEL_DOMAIN_MASK 0x7 +#define VUL25_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL25_SEL_FS_SFT 8 +#define VUL25_SEL_FS_MASK 0x1f +#define VUL25_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL25_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL25_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL25_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL25_WR_SIGN_SFT 6 +#define VUL25_WR_SIGN_MASK 0x1 +#define VUL25_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL25_R_MONO_SFT 5 +#define VUL25_R_MONO_MASK 0x1 +#define VUL25_R_MONO_MASK_SFT (0x1 << 5) +#define VUL25_MONO_SFT 4 +#define VUL25_MONO_MASK 0x1 +#define VUL25_MONO_MASK_SFT (0x1 << 4) +#define VUL25_NORMAL_MODE_SFT 3 +#define VUL25_NORMAL_MODE_MASK 0x1 +#define VUL25_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL25_HALIGN_SFT 2 +#define VUL25_HALIGN_MASK 0x1 +#define VUL25_HALIGN_MASK_SFT (0x1 << 2) +#define VUL25_HD_MODE_SFT 0 +#define VUL25_HD_MODE_MASK 0x3 +#define VUL25_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL26_BASE_MSB */ +#define VUL26_BASE_ADDR_MSB_SFT 0 +#define VUL26_BASE_ADDR_MSB_MASK 0x1ff +#define VUL26_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL26_BASE */ +#define VUL26_BASE_ADDR_SFT 4 +#define VUL26_BASE_ADDR_MASK 0xfffffff +#define VUL26_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL26_CUR_MSB */ +#define VUL26_CUR_PTR_MSB_SFT 0 +#define VUL26_CUR_PTR_MSB_MASK 0x1ff +#define VUL26_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL26_CUR */ +#define VUL26_CUR_PTR_SFT 0 +#define VUL26_CUR_PTR_MASK 0xffffffff +#define VUL26_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL26_END_MSB */ +#define VUL26_END_ADDR_MSB_SFT 0 +#define VUL26_END_ADDR_MSB_MASK 0x1ff +#define VUL26_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL26_END */ +#define VUL26_END_ADDR_SFT 4 +#define VUL26_END_ADDR_MASK 0xfffffff +#define VUL26_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL26_CON0 */ +#define OUT_ON_USE_VUL26_SFT 29 +#define OUT_ON_USE_VUL26_MASK 0x1 +#define OUT_ON_USE_VUL26_MASK_SFT (0x1 << 29) +#define VUL26_ON_SFT 28 +#define VUL26_ON_MASK 0x1 +#define VUL26_ON_MASK_SFT (0x1 << 28) +#define VUL26_MINLEN_SFT 20 +#define VUL26_MINLEN_MASK 0x3 +#define VUL26_MINLEN_MASK_SFT (0x3 << 20) +#define VUL26_MAXLEN_SFT 16 +#define VUL26_MAXLEN_MASK 0x3 +#define VUL26_MAXLEN_MASK_SFT (0x3 << 16) +#define VUL26_SEL_DOMAIN_SFT 13 +#define VUL26_SEL_DOMAIN_MASK 0x7 +#define VUL26_SEL_DOMAIN_MASK_SFT (0x7 << 13) +#define VUL26_SEL_FS_SFT 8 +#define VUL26_SEL_FS_MASK 0x1f +#define VUL26_SEL_FS_MASK_SFT (0x1f << 8) +#define VUL26_SW_CLEAR_BUF_FULL_SFT 7 +#define VUL26_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL26_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7) +#define VUL26_WR_SIGN_SFT 6 +#define VUL26_WR_SIGN_MASK 0x1 +#define VUL26_WR_SIGN_MASK_SFT (0x1 << 6) +#define VUL26_R_MONO_SFT 5 +#define VUL26_R_MONO_MASK 0x1 +#define VUL26_R_MONO_MASK_SFT (0x1 << 5) +#define VUL26_MONO_SFT 4 +#define VUL26_MONO_MASK 0x1 +#define VUL26_MONO_MASK_SFT (0x1 << 4) +#define VUL26_NORMAL_MODE_SFT 3 +#define VUL26_NORMAL_MODE_MASK 0x1 +#define VUL26_NORMAL_MODE_MASK_SFT (0x1 << 3) +#define VUL26_HALIGN_SFT 2 +#define VUL26_HALIGN_MASK 0x1 +#define VUL26_HALIGN_MASK_SFT (0x1 << 2) +#define VUL26_HD_MODE_SFT 0 +#define VUL26_HD_MODE_MASK 0x3 +#define VUL26_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL_CM0_BASE_MSB */ +#define VUL_CM0_BASE_ADDR_MSB_SFT 0 +#define VUL_CM0_BASE_ADDR_MSB_MASK 0x1ff +#define VUL_CM0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM0_BASE */ +#define VUL_CM0_BASE_ADDR_SFT 4 +#define VUL_CM0_BASE_ADDR_MASK 0xfffffff +#define VUL_CM0_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL_CM0_CUR_MSB */ +#define VUL_CM0_CUR_PTR_MSB_SFT 0 +#define VUL_CM0_CUR_PTR_MSB_MASK 0x1ff +#define VUL_CM0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM0_CUR */ +#define VUL_CM0_CUR_PTR_SFT 0 +#define VUL_CM0_CUR_PTR_MASK 0xffffffff +#define VUL_CM0_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM0_END_MSB */ +#define VUL_CM0_END_ADDR_MSB_SFT 0 +#define VUL_CM0_END_ADDR_MSB_MASK 0x1ff +#define VUL_CM0_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM0_END */ +#define VUL_CM0_END_ADDR_SFT 4 +#define VUL_CM0_END_ADDR_MASK 0xfffffff +#define VUL_CM0_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL_CM0_CON0 */ +#define VUL_CM0_ON_SFT 28 +#define VUL_CM0_ON_MASK 0x1 +#define VUL_CM0_ON_MASK_SFT (0x1 << 28) +#define VUL_CM0_REG_CH_SHIFT_MODE_SFT 26 +#define VUL_CM0_REG_CH_SHIFT_MODE_MASK 0x1 +#define VUL_CM0_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define VUL_CM0_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define VUL_CM0_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define VUL_CM0_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define VUL_CM0_SW_CLEAR_BUF_FULL_SFT 24 +#define VUL_CM0_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL_CM0_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define VUL_CM0_ULTRA_TH_SFT 20 +#define VUL_CM0_ULTRA_TH_MASK 0xf +#define VUL_CM0_ULTRA_TH_MASK_SFT (0xf << 20) +#define VUL_CM0_NORMAL_MODE_SFT 17 +#define VUL_CM0_NORMAL_MODE_MASK 0x1 +#define VUL_CM0_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define VUL_CM0_ODD_USE_EVEN_SFT 16 +#define VUL_CM0_ODD_USE_EVEN_MASK 0x1 +#define VUL_CM0_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define VUL_CM0_AXI_REQ_MAXLEN_SFT 12 +#define VUL_CM0_AXI_REQ_MAXLEN_MASK 0x3 +#define VUL_CM0_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define VUL_CM0_AXI_REQ_MINLEN_SFT 8 +#define VUL_CM0_AXI_REQ_MINLEN_MASK 0x3 +#define VUL_CM0_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define VUL_CM0_HALIGN_SFT 7 +#define VUL_CM0_HALIGN_MASK 0x1 +#define VUL_CM0_HALIGN_MASK_SFT (0x1 << 7) +#define VUL_CM0_SIGN_EXT_SFT 6 +#define VUL_CM0_SIGN_EXT_MASK 0x1 +#define VUL_CM0_SIGN_EXT_MASK_SFT (0x1 << 6) +#define VUL_CM0_HD_MODE_SFT 4 +#define VUL_CM0_HD_MODE_MASK 0x3 +#define VUL_CM0_HD_MODE_MASK_SFT (0x3 << 4) +#define VUL_CM0_MAKE_EXTRA_UPDATE_SFT 3 +#define VUL_CM0_MAKE_EXTRA_UPDATE_MASK 0x1 +#define VUL_CM0_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define VUL_CM0_AGENT_FREE_RUN_SFT 2 +#define VUL_CM0_AGENT_FREE_RUN_MASK 0x1 +#define VUL_CM0_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define VUL_CM0_USE_INT_ODD_SFT 1 +#define VUL_CM0_USE_INT_ODD_MASK 0x1 +#define VUL_CM0_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define VUL_CM0_INT_ODD_FLAG_SFT 0 +#define VUL_CM0_INT_ODD_FLAG_MASK 0x1 +#define VUL_CM0_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_VUL_CM1_BASE_MSB */ +#define VUL_CM1_BASE_ADDR_MSB_SFT 0 +#define VUL_CM1_BASE_ADDR_MSB_MASK 0x1ff +#define VUL_CM1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM1_BASE */ +#define VUL_CM1_BASE_ADDR_SFT 4 +#define VUL_CM1_BASE_ADDR_MASK 0xfffffff +#define VUL_CM1_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL_CM1_CUR_MSB */ +#define VUL_CM1_CUR_PTR_MSB_SFT 0 +#define VUL_CM1_CUR_PTR_MSB_MASK 0x1ff +#define VUL_CM1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM1_CUR */ +#define VUL_CM1_CUR_PTR_SFT 0 +#define VUL_CM1_CUR_PTR_MASK 0xffffffff +#define VUL_CM1_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM1_END_MSB */ +#define VUL_CM1_END_ADDR_MSB_SFT 0 +#define VUL_CM1_END_ADDR_MSB_MASK 0x1ff +#define VUL_CM1_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM1_END */ +#define VUL_CM1_END_ADDR_SFT 4 +#define VUL_CM1_END_ADDR_MASK 0xfffffff +#define VUL_CM1_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL_CM1_CON0 */ +#define VUL_CM1_ON_SFT 28 +#define VUL_CM1_ON_MASK 0x1 +#define VUL_CM1_ON_MASK_SFT (0x1 << 28) +#define VUL_CM1_REG_CH_SHIFT_MODE_SFT 26 +#define VUL_CM1_REG_CH_SHIFT_MODE_MASK 0x1 +#define VUL_CM1_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define VUL_CM1_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define VUL_CM1_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define VUL_CM1_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define VUL_CM1_SW_CLEAR_BUF_FULL_SFT 24 +#define VUL_CM1_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL_CM1_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define VUL_CM1_ULTRA_TH_SFT 20 +#define VUL_CM1_ULTRA_TH_MASK 0xf +#define VUL_CM1_ULTRA_TH_MASK_SFT (0xf << 20) +#define VUL_CM1_NORMAL_MODE_SFT 17 +#define VUL_CM1_NORMAL_MODE_MASK 0x1 +#define VUL_CM1_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define VUL_CM1_ODD_USE_EVEN_SFT 16 +#define VUL_CM1_ODD_USE_EVEN_MASK 0x1 +#define VUL_CM1_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define VUL_CM1_AXI_REQ_MAXLEN_SFT 12 +#define VUL_CM1_AXI_REQ_MAXLEN_MASK 0x3 +#define VUL_CM1_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define VUL_CM1_AXI_REQ_MINLEN_SFT 8 +#define VUL_CM1_AXI_REQ_MINLEN_MASK 0x3 +#define VUL_CM1_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define VUL_CM1_HALIGN_SFT 7 +#define VUL_CM1_HALIGN_MASK 0x1 +#define VUL_CM1_HALIGN_MASK_SFT (0x1 << 7) +#define VUL_CM1_SIGN_EXT_SFT 6 +#define VUL_CM1_SIGN_EXT_MASK 0x1 +#define VUL_CM1_SIGN_EXT_MASK_SFT (0x1 << 6) +#define VUL_CM1_HD_MODE_SFT 4 +#define VUL_CM1_HD_MODE_MASK 0x3 +#define VUL_CM1_HD_MODE_MASK_SFT (0x3 << 4) +#define VUL_CM1_MAKE_EXTRA_UPDATE_SFT 3 +#define VUL_CM1_MAKE_EXTRA_UPDATE_MASK 0x1 +#define VUL_CM1_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define VUL_CM1_AGENT_FREE_RUN_SFT 2 +#define VUL_CM1_AGENT_FREE_RUN_MASK 0x1 +#define VUL_CM1_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define VUL_CM1_USE_INT_ODD_SFT 1 +#define VUL_CM1_USE_INT_ODD_MASK 0x1 +#define VUL_CM1_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define VUL_CM1_INT_ODD_FLAG_SFT 0 +#define VUL_CM1_INT_ODD_FLAG_MASK 0x1 +#define VUL_CM1_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_VUL_CM2_BASE_MSB */ +#define VUL_CM2_BASE_ADDR_MSB_SFT 0 +#define VUL_CM2_BASE_ADDR_MSB_MASK 0x1ff +#define VUL_CM2_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM2_BASE */ +#define VUL_CM2_BASE_ADDR_SFT 4 +#define VUL_CM2_BASE_ADDR_MASK 0xfffffff +#define VUL_CM2_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL_CM2_CUR_MSB */ +#define VUL_CM2_CUR_PTR_MSB_SFT 0 +#define VUL_CM2_CUR_PTR_MSB_MASK 0x1ff +#define VUL_CM2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM2_CUR */ +#define VUL_CM2_CUR_PTR_SFT 0 +#define VUL_CM2_CUR_PTR_MASK 0xffffffff +#define VUL_CM2_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM2_END_MSB */ +#define VUL_CM2_END_ADDR_MSB_SFT 0 +#define VUL_CM2_END_ADDR_MSB_MASK 0x1ff +#define VUL_CM2_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_VUL_CM2_END */ +#define VUL_CM2_END_ADDR_SFT 4 +#define VUL_CM2_END_ADDR_MASK 0xfffffff +#define VUL_CM2_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_VUL_CM2_CON0 */ +#define VUL_CM2_ON_SFT 28 +#define VUL_CM2_ON_MASK 0x1 +#define VUL_CM2_ON_MASK_SFT (0x1 << 28) +#define VUL_CM2_REG_CH_SHIFT_MODE_SFT 26 +#define VUL_CM2_REG_CH_SHIFT_MODE_MASK 0x1 +#define VUL_CM2_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define VUL_CM2_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define VUL_CM2_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define VUL_CM2_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define VUL_CM2_SW_CLEAR_BUF_FULL_SFT 24 +#define VUL_CM2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define VUL_CM2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define VUL_CM2_ULTRA_TH_SFT 20 +#define VUL_CM2_ULTRA_TH_MASK 0xf +#define VUL_CM2_ULTRA_TH_MASK_SFT (0xf << 20) +#define VUL_CM2_NORMAL_MODE_SFT 17 +#define VUL_CM2_NORMAL_MODE_MASK 0x1 +#define VUL_CM2_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define VUL_CM2_ODD_USE_EVEN_SFT 16 +#define VUL_CM2_ODD_USE_EVEN_MASK 0x1 +#define VUL_CM2_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define VUL_CM2_AXI_REQ_MAXLEN_SFT 12 +#define VUL_CM2_AXI_REQ_MAXLEN_MASK 0x3 +#define VUL_CM2_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define VUL_CM2_AXI_REQ_MINLEN_SFT 8 +#define VUL_CM2_AXI_REQ_MINLEN_MASK 0x3 +#define VUL_CM2_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define VUL_CM2_HALIGN_SFT 7 +#define VUL_CM2_HALIGN_MASK 0x1 +#define VUL_CM2_HALIGN_MASK_SFT (0x1 << 7) +#define VUL_CM2_SIGN_EXT_SFT 6 +#define VUL_CM2_SIGN_EXT_MASK 0x1 +#define VUL_CM2_SIGN_EXT_MASK_SFT (0x1 << 6) +#define VUL_CM2_HD_MODE_SFT 4 +#define VUL_CM2_HD_MODE_MASK 0x3 +#define VUL_CM2_HD_MODE_MASK_SFT (0x3 << 4) +#define VUL_CM2_MAKE_EXTRA_UPDATE_SFT 3 +#define VUL_CM2_MAKE_EXTRA_UPDATE_MASK 0x1 +#define VUL_CM2_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define VUL_CM2_AGENT_FREE_RUN_SFT 2 +#define VUL_CM2_AGENT_FREE_RUN_MASK 0x1 +#define VUL_CM2_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define VUL_CM2_USE_INT_ODD_SFT 1 +#define VUL_CM2_USE_INT_ODD_MASK 0x1 +#define VUL_CM2_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define VUL_CM2_INT_ODD_FLAG_SFT 0 +#define VUL_CM2_INT_ODD_FLAG_MASK 0x1 +#define VUL_CM2_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_ETDM_IN0_BASE_MSB */ +#define ETDM_IN0_BASE_ADDR_MSB_SFT 0 +#define ETDM_IN0_BASE_ADDR_MSB_MASK 0x1ff +#define ETDM_IN0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN0_BASE */ +#define ETDM_IN0_BASE_ADDR_SFT 4 +#define ETDM_IN0_BASE_ADDR_MASK 0xfffffff +#define ETDM_IN0_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN0_CUR_MSB */ +#define ETDM_IN0_CUR_PTR_MSB_SFT 0 +#define ETDM_IN0_CUR_PTR_MSB_MASK 0x1ff +#define ETDM_IN0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN0_CUR */ +#define ETDM_IN0_CUR_PTR_SFT 0 +#define ETDM_IN0_CUR_PTR_MASK 0xffffffff +#define ETDM_IN0_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_ETDM_IN0_END_MSB */ +#define ETDM_IN0_END_ADDR_MSB_SFT 0 +#define ETDM_IN0_END_ADDR_MSB_MASK 0x1ff +#define ETDM_IN0_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN0_END */ +#define ETDM_IN0_END_ADDR_SFT 4 +#define ETDM_IN0_END_ADDR_MASK 0xfffffff +#define ETDM_IN0_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN0_CON0 */ +#define ETDM_IN0_CH_NUM_SFT 28 +#define ETDM_IN0_CH_NUM_MASK 0xf +#define ETDM_IN0_CH_NUM_MASK_SFT (0xf << 28) +#define ETDM_IN0_ON_SFT 27 +#define ETDM_IN0_ON_MASK 0x1 +#define ETDM_IN0_ON_MASK_SFT (0x1 << 27) +#define ETDM_IN0_REG_CH_SHIFT_MODE_SFT 26 +#define ETDM_IN0_REG_CH_SHIFT_MODE_MASK 0x1 +#define ETDM_IN0_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define ETDM_IN0_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define ETDM_IN0_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define ETDM_IN0_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define ETDM_IN0_SW_CLEAR_BUF_FULL_SFT 24 +#define ETDM_IN0_SW_CLEAR_BUF_FULL_MASK 0x1 +#define ETDM_IN0_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define ETDM_IN0_ULTRA_TH_SFT 20 +#define ETDM_IN0_ULTRA_TH_MASK 0xf +#define ETDM_IN0_ULTRA_TH_MASK_SFT (0xf << 20) +#define ETDM_IN0_NORMAL_MODE_SFT 17 +#define ETDM_IN0_NORMAL_MODE_MASK 0x1 +#define ETDM_IN0_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define ETDM_IN0_ODD_USE_EVEN_SFT 16 +#define ETDM_IN0_ODD_USE_EVEN_MASK 0x1 +#define ETDM_IN0_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define ETDM_IN0_AXI_REQ_MAXLEN_SFT 12 +#define ETDM_IN0_AXI_REQ_MAXLEN_MASK 0x3 +#define ETDM_IN0_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define ETDM_IN0_AXI_REQ_MINLEN_SFT 8 +#define ETDM_IN0_AXI_REQ_MINLEN_MASK 0x3 +#define ETDM_IN0_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define ETDM_IN0_HALIGN_SFT 7 +#define ETDM_IN0_HALIGN_MASK 0x1 +#define ETDM_IN0_HALIGN_MASK_SFT (0x1 << 7) +#define ETDM_IN0_SIGN_EXT_SFT 6 +#define ETDM_IN0_SIGN_EXT_MASK 0x1 +#define ETDM_IN0_SIGN_EXT_MASK_SFT (0x1 << 6) +#define ETDM_IN0_HD_MODE_SFT 4 +#define ETDM_IN0_HD_MODE_MASK 0x3 +#define ETDM_IN0_HD_MODE_MASK_SFT (0x3 << 4) +#define ETDM_IN0_MAKE_EXTRA_UPDATE_SFT 3 +#define ETDM_IN0_MAKE_EXTRA_UPDATE_MASK 0x1 +#define ETDM_IN0_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define ETDM_IN0_AGENT_FREE_RUN_SFT 2 +#define ETDM_IN0_AGENT_FREE_RUN_MASK 0x1 +#define ETDM_IN0_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define ETDM_IN0_USE_INT_ODD_SFT 1 +#define ETDM_IN0_USE_INT_ODD_MASK 0x1 +#define ETDM_IN0_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define ETDM_IN0_INT_ODD_FLAG_SFT 0 +#define ETDM_IN0_INT_ODD_FLAG_MASK 0x1 +#define ETDM_IN0_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_ETDM_IN1_BASE_MSB */ +#define ETDM_IN1_BASE_ADDR_MSB_SFT 0 +#define ETDM_IN1_BASE_ADDR_MSB_MASK 0x1ff +#define ETDM_IN1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN1_BASE */ +#define ETDM_IN1_BASE_ADDR_SFT 4 +#define ETDM_IN1_BASE_ADDR_MASK 0xfffffff +#define ETDM_IN1_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN1_CUR_MSB */ +#define ETDM_IN1_CUR_PTR_MSB_SFT 0 +#define ETDM_IN1_CUR_PTR_MSB_MASK 0x1ff +#define ETDM_IN1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN1_CUR */ +#define ETDM_IN1_CUR_PTR_SFT 0 +#define ETDM_IN1_CUR_PTR_MASK 0xffffffff +#define ETDM_IN1_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_ETDM_IN1_END_MSB */ +#define ETDM_IN1_END_ADDR_MSB_SFT 0 +#define ETDM_IN1_END_ADDR_MSB_MASK 0x1ff +#define ETDM_IN1_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN1_END */ +#define ETDM_IN1_END_ADDR_SFT 4 +#define ETDM_IN1_END_ADDR_MASK 0xfffffff +#define ETDM_IN1_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN1_CON0 */ +#define ETDM_IN1_CH_NUM_SFT 28 +#define ETDM_IN1_CH_NUM_MASK 0xf +#define ETDM_IN1_CH_NUM_MASK_SFT (0xf << 28) +#define ETDM_IN1_ON_SFT 27 +#define ETDM_IN1_ON_MASK 0x1 +#define ETDM_IN1_ON_MASK_SFT (0x1 << 27) +#define ETDM_IN1_REG_CH_SHIFT_MODE_SFT 26 +#define ETDM_IN1_REG_CH_SHIFT_MODE_MASK 0x1 +#define ETDM_IN1_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define ETDM_IN1_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define ETDM_IN1_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define ETDM_IN1_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define ETDM_IN1_SW_CLEAR_BUF_FULL_SFT 24 +#define ETDM_IN1_SW_CLEAR_BUF_FULL_MASK 0x1 +#define ETDM_IN1_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define ETDM_IN1_ULTRA_TH_SFT 20 +#define ETDM_IN1_ULTRA_TH_MASK 0xf +#define ETDM_IN1_ULTRA_TH_MASK_SFT (0xf << 20) +#define ETDM_IN1_NORMAL_MODE_SFT 17 +#define ETDM_IN1_NORMAL_MODE_MASK 0x1 +#define ETDM_IN1_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define ETDM_IN1_ODD_USE_EVEN_SFT 16 +#define ETDM_IN1_ODD_USE_EVEN_MASK 0x1 +#define ETDM_IN1_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define ETDM_IN1_AXI_REQ_MAXLEN_SFT 12 +#define ETDM_IN1_AXI_REQ_MAXLEN_MASK 0x3 +#define ETDM_IN1_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define ETDM_IN1_AXI_REQ_MINLEN_SFT 8 +#define ETDM_IN1_AXI_REQ_MINLEN_MASK 0x3 +#define ETDM_IN1_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define ETDM_IN1_HALIGN_SFT 7 +#define ETDM_IN1_HALIGN_MASK 0x1 +#define ETDM_IN1_HALIGN_MASK_SFT (0x1 << 7) +#define ETDM_IN1_SIGN_EXT_SFT 6 +#define ETDM_IN1_SIGN_EXT_MASK 0x1 +#define ETDM_IN1_SIGN_EXT_MASK_SFT (0x1 << 6) +#define ETDM_IN1_HD_MODE_SFT 4 +#define ETDM_IN1_HD_MODE_MASK 0x3 +#define ETDM_IN1_HD_MODE_MASK_SFT (0x3 << 4) +#define ETDM_IN1_MAKE_EXTRA_UPDATE_SFT 3 +#define ETDM_IN1_MAKE_EXTRA_UPDATE_MASK 0x1 +#define ETDM_IN1_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define ETDM_IN1_AGENT_FREE_RUN_SFT 2 +#define ETDM_IN1_AGENT_FREE_RUN_MASK 0x1 +#define ETDM_IN1_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define ETDM_IN1_USE_INT_ODD_SFT 1 +#define ETDM_IN1_USE_INT_ODD_MASK 0x1 +#define ETDM_IN1_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define ETDM_IN1_INT_ODD_FLAG_SFT 0 +#define ETDM_IN1_INT_ODD_FLAG_MASK 0x1 +#define ETDM_IN1_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_ETDM_IN2_BASE_MSB */ +#define ETDM_IN2_BASE_ADDR_MSB_SFT 0 +#define ETDM_IN2_BASE_ADDR_MSB_MASK 0x1ff +#define ETDM_IN2_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN2_BASE */ +#define ETDM_IN2_BASE_ADDR_SFT 4 +#define ETDM_IN2_BASE_ADDR_MASK 0xfffffff +#define ETDM_IN2_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN2_CUR_MSB */ +#define ETDM_IN2_CUR_PTR_MSB_SFT 0 +#define ETDM_IN2_CUR_PTR_MSB_MASK 0x1ff +#define ETDM_IN2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN2_CUR */ +#define ETDM_IN2_CUR_PTR_SFT 0 +#define ETDM_IN2_CUR_PTR_MASK 0xffffffff +#define ETDM_IN2_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_ETDM_IN2_END_MSB */ +#define ETDM_IN2_END_ADDR_MSB_SFT 0 +#define ETDM_IN2_END_ADDR_MSB_MASK 0x1ff +#define ETDM_IN2_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN2_END */ +#define ETDM_IN2_END_ADDR_SFT 4 +#define ETDM_IN2_END_ADDR_MASK 0xfffffff +#define ETDM_IN2_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN2_CON0 */ +#define ETDM_IN2_CH_NUM_SFT 28 +#define ETDM_IN2_CH_NUM_MASK 0xf +#define ETDM_IN2_CH_NUM_MASK_SFT (0xf << 28) +#define ETDM_IN2_ON_SFT 27 +#define ETDM_IN2_ON_MASK 0x1 +#define ETDM_IN2_ON_MASK_SFT (0x1 << 27) +#define ETDM_IN2_REG_CH_SHIFT_MODE_SFT 26 +#define ETDM_IN2_REG_CH_SHIFT_MODE_MASK 0x1 +#define ETDM_IN2_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define ETDM_IN2_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define ETDM_IN2_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define ETDM_IN2_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define ETDM_IN2_SW_CLEAR_BUF_FULL_SFT 24 +#define ETDM_IN2_SW_CLEAR_BUF_FULL_MASK 0x1 +#define ETDM_IN2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define ETDM_IN2_ULTRA_TH_SFT 20 +#define ETDM_IN2_ULTRA_TH_MASK 0xf +#define ETDM_IN2_ULTRA_TH_MASK_SFT (0xf << 20) +#define ETDM_IN2_NORMAL_MODE_SFT 17 +#define ETDM_IN2_NORMAL_MODE_MASK 0x1 +#define ETDM_IN2_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define ETDM_IN2_ODD_USE_EVEN_SFT 16 +#define ETDM_IN2_ODD_USE_EVEN_MASK 0x1 +#define ETDM_IN2_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define ETDM_IN2_AXI_REQ_MAXLEN_SFT 12 +#define ETDM_IN2_AXI_REQ_MAXLEN_MASK 0x3 +#define ETDM_IN2_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define ETDM_IN2_AXI_REQ_MINLEN_SFT 8 +#define ETDM_IN2_AXI_REQ_MINLEN_MASK 0x3 +#define ETDM_IN2_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define ETDM_IN2_HALIGN_SFT 7 +#define ETDM_IN2_HALIGN_MASK 0x1 +#define ETDM_IN2_HALIGN_MASK_SFT (0x1 << 7) +#define ETDM_IN2_SIGN_EXT_SFT 6 +#define ETDM_IN2_SIGN_EXT_MASK 0x1 +#define ETDM_IN2_SIGN_EXT_MASK_SFT (0x1 << 6) +#define ETDM_IN2_HD_MODE_SFT 4 +#define ETDM_IN2_HD_MODE_MASK 0x3 +#define ETDM_IN2_HD_MODE_MASK_SFT (0x3 << 4) +#define ETDM_IN2_MAKE_EXTRA_UPDATE_SFT 3 +#define ETDM_IN2_MAKE_EXTRA_UPDATE_MASK 0x1 +#define ETDM_IN2_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define ETDM_IN2_AGENT_FREE_RUN_SFT 2 +#define ETDM_IN2_AGENT_FREE_RUN_MASK 0x1 +#define ETDM_IN2_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define ETDM_IN2_USE_INT_ODD_SFT 1 +#define ETDM_IN2_USE_INT_ODD_MASK 0x1 +#define ETDM_IN2_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define ETDM_IN2_INT_ODD_FLAG_SFT 0 +#define ETDM_IN2_INT_ODD_FLAG_MASK 0x1 +#define ETDM_IN2_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_ETDM_IN3_BASE_MSB */ +#define ETDM_IN3_BASE_ADDR_MSB_SFT 0 +#define ETDM_IN3_BASE_ADDR_MSB_MASK 0x1ff +#define ETDM_IN3_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN3_BASE */ +#define ETDM_IN3_BASE_ADDR_SFT 4 +#define ETDM_IN3_BASE_ADDR_MASK 0xfffffff +#define ETDM_IN3_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN3_CUR_MSB */ +#define ETDM_IN3_CUR_PTR_MSB_SFT 0 +#define ETDM_IN3_CUR_PTR_MSB_MASK 0x1ff +#define ETDM_IN3_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN3_CUR */ +#define ETDM_IN3_CUR_PTR_SFT 0 +#define ETDM_IN3_CUR_PTR_MASK 0xffffffff +#define ETDM_IN3_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_ETDM_IN3_END_MSB */ +#define ETDM_IN3_END_ADDR_MSB_SFT 0 +#define ETDM_IN3_END_ADDR_MSB_MASK 0x1ff +#define ETDM_IN3_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN3_END */ +#define ETDM_IN3_END_ADDR_SFT 4 +#define ETDM_IN3_END_ADDR_MASK 0xfffffff +#define ETDM_IN3_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN3_CON0 */ +#define ETDM_IN3_CH_NUM_SFT 28 +#define ETDM_IN3_CH_NUM_MASK 0xf +#define ETDM_IN3_CH_NUM_MASK_SFT (0xf << 28) +#define ETDM_IN3_ON_SFT 27 +#define ETDM_IN3_ON_MASK 0x1 +#define ETDM_IN3_ON_MASK_SFT (0x1 << 27) +#define ETDM_IN3_REG_CH_SHIFT_MODE_SFT 26 +#define ETDM_IN3_REG_CH_SHIFT_MODE_MASK 0x1 +#define ETDM_IN3_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define ETDM_IN3_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define ETDM_IN3_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define ETDM_IN3_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define ETDM_IN3_SW_CLEAR_BUF_FULL_SFT 24 +#define ETDM_IN3_SW_CLEAR_BUF_FULL_MASK 0x1 +#define ETDM_IN3_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define ETDM_IN3_ULTRA_TH_SFT 20 +#define ETDM_IN3_ULTRA_TH_MASK 0xf +#define ETDM_IN3_ULTRA_TH_MASK_SFT (0xf << 20) +#define ETDM_IN3_NORMAL_MODE_SFT 17 +#define ETDM_IN3_NORMAL_MODE_MASK 0x1 +#define ETDM_IN3_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define ETDM_IN3_ODD_USE_EVEN_SFT 16 +#define ETDM_IN3_ODD_USE_EVEN_MASK 0x1 +#define ETDM_IN3_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define ETDM_IN3_AXI_REQ_MAXLEN_SFT 12 +#define ETDM_IN3_AXI_REQ_MAXLEN_MASK 0x3 +#define ETDM_IN3_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define ETDM_IN3_AXI_REQ_MINLEN_SFT 8 +#define ETDM_IN3_AXI_REQ_MINLEN_MASK 0x3 +#define ETDM_IN3_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define ETDM_IN3_HALIGN_SFT 7 +#define ETDM_IN3_HALIGN_MASK 0x1 +#define ETDM_IN3_HALIGN_MASK_SFT (0x1 << 7) +#define ETDM_IN3_SIGN_EXT_SFT 6 +#define ETDM_IN3_SIGN_EXT_MASK 0x1 +#define ETDM_IN3_SIGN_EXT_MASK_SFT (0x1 << 6) +#define ETDM_IN3_HD_MODE_SFT 4 +#define ETDM_IN3_HD_MODE_MASK 0x3 +#define ETDM_IN3_HD_MODE_MASK_SFT (0x3 << 4) +#define ETDM_IN3_MAKE_EXTRA_UPDATE_SFT 3 +#define ETDM_IN3_MAKE_EXTRA_UPDATE_MASK 0x1 +#define ETDM_IN3_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define ETDM_IN3_AGENT_FREE_RUN_SFT 2 +#define ETDM_IN3_AGENT_FREE_RUN_MASK 0x1 +#define ETDM_IN3_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define ETDM_IN3_USE_INT_ODD_SFT 1 +#define ETDM_IN3_USE_INT_ODD_MASK 0x1 +#define ETDM_IN3_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define ETDM_IN3_INT_ODD_FLAG_SFT 0 +#define ETDM_IN3_INT_ODD_FLAG_MASK 0x1 +#define ETDM_IN3_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_ETDM_IN4_BASE_MSB */ +#define ETDM_IN4_BASE_ADDR_MSB_SFT 0 +#define ETDM_IN4_BASE_ADDR_MSB_MASK 0x1ff +#define ETDM_IN4_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN4_BASE */ +#define ETDM_IN4_BASE_ADDR_SFT 4 +#define ETDM_IN4_BASE_ADDR_MASK 0xfffffff +#define ETDM_IN4_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN4_CUR_MSB */ +#define ETDM_IN4_CUR_PTR_MSB_SFT 0 +#define ETDM_IN4_CUR_PTR_MSB_MASK 0x1ff +#define ETDM_IN4_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN4_CUR */ +#define ETDM_IN4_CUR_PTR_SFT 0 +#define ETDM_IN4_CUR_PTR_MASK 0xffffffff +#define ETDM_IN4_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_ETDM_IN4_END_MSB */ +#define ETDM_IN4_END_ADDR_MSB_SFT 0 +#define ETDM_IN4_END_ADDR_MSB_MASK 0x1ff +#define ETDM_IN4_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN4_END */ +#define ETDM_IN4_END_ADDR_SFT 4 +#define ETDM_IN4_END_ADDR_MASK 0xfffffff +#define ETDM_IN4_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN4_CON0 */ +#define ETDM_IN4_CH_NUM_SFT 28 +#define ETDM_IN4_CH_NUM_MASK 0xf +#define ETDM_IN4_CH_NUM_MASK_SFT (0xf << 28) +#define ETDM_IN4_ON_SFT 27 +#define ETDM_IN4_ON_MASK 0x1 +#define ETDM_IN4_ON_MASK_SFT (0x1 << 27) +#define ETDM_IN4_REG_CH_SHIFT_MODE_SFT 26 +#define ETDM_IN4_REG_CH_SHIFT_MODE_MASK 0x1 +#define ETDM_IN4_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define ETDM_IN4_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define ETDM_IN4_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define ETDM_IN4_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define ETDM_IN4_SW_CLEAR_BUF_FULL_SFT 24 +#define ETDM_IN4_SW_CLEAR_BUF_FULL_MASK 0x1 +#define ETDM_IN4_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define ETDM_IN4_ULTRA_TH_SFT 20 +#define ETDM_IN4_ULTRA_TH_MASK 0xf +#define ETDM_IN4_ULTRA_TH_MASK_SFT (0xf << 20) +#define ETDM_IN4_NORMAL_MODE_SFT 17 +#define ETDM_IN4_NORMAL_MODE_MASK 0x1 +#define ETDM_IN4_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define ETDM_IN4_ODD_USE_EVEN_SFT 16 +#define ETDM_IN4_ODD_USE_EVEN_MASK 0x1 +#define ETDM_IN4_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define ETDM_IN4_AXI_REQ_MAXLEN_SFT 12 +#define ETDM_IN4_AXI_REQ_MAXLEN_MASK 0x3 +#define ETDM_IN4_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define ETDM_IN4_AXI_REQ_MINLEN_SFT 8 +#define ETDM_IN4_AXI_REQ_MINLEN_MASK 0x3 +#define ETDM_IN4_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define ETDM_IN4_HALIGN_SFT 7 +#define ETDM_IN4_HALIGN_MASK 0x1 +#define ETDM_IN4_HALIGN_MASK_SFT (0x1 << 7) +#define ETDM_IN4_SIGN_EXT_SFT 6 +#define ETDM_IN4_SIGN_EXT_MASK 0x1 +#define ETDM_IN4_SIGN_EXT_MASK_SFT (0x1 << 6) +#define ETDM_IN4_HD_MODE_SFT 4 +#define ETDM_IN4_HD_MODE_MASK 0x3 +#define ETDM_IN4_HD_MODE_MASK_SFT (0x3 << 4) +#define ETDM_IN4_MAKE_EXTRA_UPDATE_SFT 3 +#define ETDM_IN4_MAKE_EXTRA_UPDATE_MASK 0x1 +#define ETDM_IN4_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define ETDM_IN4_AGENT_FREE_RUN_SFT 2 +#define ETDM_IN4_AGENT_FREE_RUN_MASK 0x1 +#define ETDM_IN4_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define ETDM_IN4_USE_INT_ODD_SFT 1 +#define ETDM_IN4_USE_INT_ODD_MASK 0x1 +#define ETDM_IN4_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define ETDM_IN4_INT_ODD_FLAG_SFT 0 +#define ETDM_IN4_INT_ODD_FLAG_MASK 0x1 +#define ETDM_IN4_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_ETDM_IN5_BASE_MSB */ +#define ETDM_IN5_BASE_ADDR_MSB_SFT 0 +#define ETDM_IN5_BASE_ADDR_MSB_MASK 0x1ff +#define ETDM_IN5_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN5_BASE */ +#define ETDM_IN5_BASE_ADDR_SFT 4 +#define ETDM_IN5_BASE_ADDR_MASK 0xfffffff +#define ETDM_IN5_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN5_CUR_MSB */ +#define ETDM_IN5_CUR_PTR_MSB_SFT 0 +#define ETDM_IN5_CUR_PTR_MSB_MASK 0x1ff +#define ETDM_IN5_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN5_CUR */ +#define ETDM_IN5_CUR_PTR_SFT 0 +#define ETDM_IN5_CUR_PTR_MASK 0xffffffff +#define ETDM_IN5_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_ETDM_IN5_END_MSB */ +#define ETDM_IN5_END_ADDR_MSB_SFT 0 +#define ETDM_IN5_END_ADDR_MSB_MASK 0x1ff +#define ETDM_IN5_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN5_END */ +#define ETDM_IN5_END_ADDR_SFT 4 +#define ETDM_IN5_END_ADDR_MASK 0xfffffff +#define ETDM_IN5_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN5_CON0 */ +#define ETDM_IN5_CH_NUM_SFT 28 +#define ETDM_IN5_CH_NUM_MASK 0xf +#define ETDM_IN5_CH_NUM_MASK_SFT (0xf << 28) +#define ETDM_IN5_ON_SFT 27 +#define ETDM_IN5_ON_MASK 0x1 +#define ETDM_IN5_ON_MASK_SFT (0x1 << 27) +#define ETDM_IN5_REG_CH_SHIFT_MODE_SFT 26 +#define ETDM_IN5_REG_CH_SHIFT_MODE_MASK 0x1 +#define ETDM_IN5_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define ETDM_IN5_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define ETDM_IN5_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define ETDM_IN5_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define ETDM_IN5_SW_CLEAR_BUF_FULL_SFT 24 +#define ETDM_IN5_SW_CLEAR_BUF_FULL_MASK 0x1 +#define ETDM_IN5_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define ETDM_IN5_ULTRA_TH_SFT 20 +#define ETDM_IN5_ULTRA_TH_MASK 0xf +#define ETDM_IN5_ULTRA_TH_MASK_SFT (0xf << 20) +#define ETDM_IN5_NORMAL_MODE_SFT 17 +#define ETDM_IN5_NORMAL_MODE_MASK 0x1 +#define ETDM_IN5_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define ETDM_IN5_ODD_USE_EVEN_SFT 16 +#define ETDM_IN5_ODD_USE_EVEN_MASK 0x1 +#define ETDM_IN5_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define ETDM_IN5_AXI_REQ_MAXLEN_SFT 12 +#define ETDM_IN5_AXI_REQ_MAXLEN_MASK 0x3 +#define ETDM_IN5_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define ETDM_IN5_AXI_REQ_MINLEN_SFT 8 +#define ETDM_IN5_AXI_REQ_MINLEN_MASK 0x3 +#define ETDM_IN5_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define ETDM_IN5_HALIGN_SFT 7 +#define ETDM_IN5_HALIGN_MASK 0x1 +#define ETDM_IN5_HALIGN_MASK_SFT (0x1 << 7) +#define ETDM_IN5_SIGN_EXT_SFT 6 +#define ETDM_IN5_SIGN_EXT_MASK 0x1 +#define ETDM_IN5_SIGN_EXT_MASK_SFT (0x1 << 6) +#define ETDM_IN5_HD_MODE_SFT 4 +#define ETDM_IN5_HD_MODE_MASK 0x3 +#define ETDM_IN5_HD_MODE_MASK_SFT (0x3 << 4) +#define ETDM_IN5_MAKE_EXTRA_UPDATE_SFT 3 +#define ETDM_IN5_MAKE_EXTRA_UPDATE_MASK 0x1 +#define ETDM_IN5_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define ETDM_IN5_AGENT_FREE_RUN_SFT 2 +#define ETDM_IN5_AGENT_FREE_RUN_MASK 0x1 +#define ETDM_IN5_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define ETDM_IN5_USE_INT_ODD_SFT 1 +#define ETDM_IN5_USE_INT_ODD_MASK 0x1 +#define ETDM_IN5_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define ETDM_IN5_INT_ODD_FLAG_SFT 0 +#define ETDM_IN5_INT_ODD_FLAG_MASK 0x1 +#define ETDM_IN5_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_ETDM_IN6_BASE_MSB */ +#define ETDM_IN6_BASE_ADDR_MSB_SFT 0 +#define ETDM_IN6_BASE_ADDR_MSB_MASK 0x1ff +#define ETDM_IN6_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN6_BASE */ +#define ETDM_IN6_BASE_ADDR_SFT 4 +#define ETDM_IN6_BASE_ADDR_MASK 0xfffffff +#define ETDM_IN6_BASE_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN6_CUR_MSB */ +#define ETDM_IN6_CUR_PTR_MSB_SFT 0 +#define ETDM_IN6_CUR_PTR_MSB_MASK 0x1ff +#define ETDM_IN6_CUR_PTR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN6_CUR */ +#define ETDM_IN6_CUR_PTR_SFT 0 +#define ETDM_IN6_CUR_PTR_MASK 0xffffffff +#define ETDM_IN6_CUR_PTR_MASK_SFT (0xffffffff << 0) + +/* AFE_ETDM_IN6_END_MSB */ +#define ETDM_IN6_END_ADDR_MSB_SFT 0 +#define ETDM_IN6_END_ADDR_MSB_MASK 0x1ff +#define ETDM_IN6_END_ADDR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_ETDM_IN6_END */ +#define ETDM_IN6_END_ADDR_SFT 4 +#define ETDM_IN6_END_ADDR_MASK 0xfffffff +#define ETDM_IN6_END_ADDR_MASK_SFT (0xfffffff << 4) + +/* AFE_ETDM_IN6_CON0 */ +#define ETDM_IN6_CH_NUM_SFT 28 +#define ETDM_IN6_CH_NUM_MASK 0xf +#define ETDM_IN6_CH_NUM_MASK_SFT (0xf << 28) +#define ETDM_IN6_ON_SFT 27 +#define ETDM_IN6_ON_MASK 0x1 +#define ETDM_IN6_ON_MASK_SFT (0x1 << 27) +#define ETDM_IN6_REG_CH_SHIFT_MODE_SFT 26 +#define ETDM_IN6_REG_CH_SHIFT_MODE_MASK 0x1 +#define ETDM_IN6_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26) +#define ETDM_IN6_RG_FORCE_NO_MASK_EXTRA_SFT 25 +#define ETDM_IN6_RG_FORCE_NO_MASK_EXTRA_MASK 0x1 +#define ETDM_IN6_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25) +#define ETDM_IN6_SW_CLEAR_BUF_FULL_SFT 24 +#define ETDM_IN6_SW_CLEAR_BUF_FULL_MASK 0x1 +#define ETDM_IN6_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24) +#define ETDM_IN6_ULTRA_TH_SFT 20 +#define ETDM_IN6_ULTRA_TH_MASK 0xf +#define ETDM_IN6_ULTRA_TH_MASK_SFT (0xf << 20) +#define ETDM_IN6_NORMAL_MODE_SFT 17 +#define ETDM_IN6_NORMAL_MODE_MASK 0x1 +#define ETDM_IN6_NORMAL_MODE_MASK_SFT (0x1 << 17) +#define ETDM_IN6_ODD_USE_EVEN_SFT 16 +#define ETDM_IN6_ODD_USE_EVEN_MASK 0x1 +#define ETDM_IN6_ODD_USE_EVEN_MASK_SFT (0x1 << 16) +#define ETDM_IN6_AXI_REQ_MAXLEN_SFT 12 +#define ETDM_IN6_AXI_REQ_MAXLEN_MASK 0x3 +#define ETDM_IN6_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12) +#define ETDM_IN6_AXI_REQ_MINLEN_SFT 8 +#define ETDM_IN6_AXI_REQ_MINLEN_MASK 0x3 +#define ETDM_IN6_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8) +#define ETDM_IN6_HALIGN_SFT 7 +#define ETDM_IN6_HALIGN_MASK 0x1 +#define ETDM_IN6_HALIGN_MASK_SFT (0x1 << 7) +#define ETDM_IN6_SIGN_EXT_SFT 6 +#define ETDM_IN6_SIGN_EXT_MASK 0x1 +#define ETDM_IN6_SIGN_EXT_MASK_SFT (0x1 << 6) +#define ETDM_IN6_HD_MODE_SFT 4 +#define ETDM_IN6_HD_MODE_MASK 0x3 +#define ETDM_IN6_HD_MODE_MASK_SFT (0x3 << 4) +#define ETDM_IN6_MAKE_EXTRA_UPDATE_SFT 3 +#define ETDM_IN6_MAKE_EXTRA_UPDATE_MASK 0x1 +#define ETDM_IN6_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3) +#define ETDM_IN6_AGENT_FREE_RUN_SFT 2 +#define ETDM_IN6_AGENT_FREE_RUN_MASK 0x1 +#define ETDM_IN6_AGENT_FREE_RUN_MASK_SFT (0x1 << 2) +#define ETDM_IN6_USE_INT_ODD_SFT 1 +#define ETDM_IN6_USE_INT_ODD_MASK 0x1 +#define ETDM_IN6_USE_INT_ODD_MASK_SFT (0x1 << 1) +#define ETDM_IN6_INT_ODD_FLAG_SFT 0 +#define ETDM_IN6_INT_ODD_FLAG_MASK 0x1 +#define ETDM_IN6_INT_ODD_FLAG_MASK_SFT (0x1 << 0) + +/* AFE_HDMI_OUT_BASE_MSB */ +#define AFE_HDMI_OUT_BASE_MSB_SFT 0 +#define AFE_HDMI_OUT_BASE_MSB_MASK 0x1ff +#define AFE_HDMI_OUT_BASE_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_HDMI_OUT_BASE */ +#define AFE_HDMI_OUT_BASE_SFT 4 +#define AFE_HDMI_OUT_BASE_MASK 0xfffffff +#define AFE_HDMI_OUT_BASE_MASK_SFT (0xfffffff << 4) + +/* AFE_HDMI_OUT_CUR_MSB */ +#define AFE_HDMI_OUT_CUR_MSB_SFT 0 +#define AFE_HDMI_OUT_CUR_MSB_MASK 0x1ff +#define AFE_HDMI_OUT_CUR_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_HDMI_OUT_CUR */ +#define AFE_HDMI_OUT_CUR_SFT 0 +#define AFE_HDMI_OUT_CUR_MASK 0xffffffff +#define AFE_HDMI_OUT_CUR_MASK_SFT (0xffffffff << 0) + +/* AFE_HDMI_OUT_END_MSB */ +#define AFE_HDMI_OUT_END_MSB_SFT 0 +#define AFE_HDMI_OUT_END_MSB_MASK 0x1ff +#define AFE_HDMI_OUT_END_MSB_MASK_SFT (0x1ff << 0) + +/* AFE_HDMI_OUT_END */ +#define AFE_HDMI_OUT_END_SFT 4 +#define AFE_HDMI_OUT_END_MASK 0xfffffff +#define AFE_HDMI_OUT_END_MASK_SFT (0xfffffff << 4) +#define AFE_HDMI_OUT_END_LSB_SFT 0 +#define AFE_HDMI_OUT_END_LSB_MASK 0xf +#define AFE_HDMI_OUT_END_LSB_MASK_SFT (0xf << 0) + +/* AFE_HDMI_OUT_CON0 */ +#define HDMI_OUT_ON_SFT 28 +#define HDMI_OUT_ON_MASK 0x1 +#define HDMI_OUT_ON_MASK_SFT (0x1 << 28) +#define HDMI_CH_NUM_SFT 24 +#define HDMI_CH_NUM_MASK 0xf +#define HDMI_CH_NUM_MASK_SFT (0xf << 24) +#define HDMI_OUT_ONE_HEART_SEL_SFT 22 +#define HDMI_OUT_ONE_HEART_SEL_MASK 0x3 +#define HDMI_OUT_ONE_HEART_SEL_MASK_SFT (0x3 << 22) +#define HDMI_OUT_MINLEN_SFT 20 +#define HDMI_OUT_MINLEN_MASK 0x3 +#define HDMI_OUT_MINLEN_MASK_SFT (0x3 << 20) +#define HDMI_OUT_MAXLEN_SFT 16 +#define HDMI_OUT_MAXLEN_MASK 0x3 +#define HDMI_OUT_MAXLEN_MASK_SFT (0x3 << 16) +#define HDMI_OUT_SW_CLEAR_BUF_EMPTY_SFT 15 +#define HDMI_OUT_SW_CLEAR_BUF_EMPTY_MASK 0x1 +#define HDMI_OUT_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15) +#define HDMI_OUT_PBUF_SIZE_SFT 12 +#define HDMI_OUT_PBUF_SIZE_MASK 0x3 +#define HDMI_OUT_PBUF_SIZE_MASK_SFT (0x3 << 12) +#define HDMI_OUT_SW_CLEAR_HDMI_BUF_EMPTY_SFT 7 +#define HDMI_OUT_SW_CLEAR_HDMI_BUF_EMPTY_MASK 0x1 +#define HDMI_OUT_SW_CLEAR_HDMI_BUF_EMPTY_MASK_SFT (0x1 << 7) +#define HDMI_OUT_NORMAL_MODE_SFT 5 +#define HDMI_OUT_NORMAL_MODE_MASK 0x1 +#define HDMI_OUT_NORMAL_MODE_MASK_SFT (0x1 << 5) +#define HDMI_OUT_HALIGN_SFT 4 +#define HDMI_OUT_HALIGN_MASK 0x1 +#define HDMI_OUT_HALIGN_MASK_SFT (0x1 << 4) +#define HDMI_OUT_HD_MODE_SFT 0 +#define HDMI_OUT_HD_MODE_MASK 0x3 +#define HDMI_OUT_HD_MODE_MASK_SFT (0x3 << 0) + +/* AFE_VUL24_RCH_MON */ +#define VUL24_RCH_DATA_SFT 0 +#define VUL24_RCH_DATA_MASK 0xffffffff +#define VUL24_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL24_LCH_MON */ +#define VUL24_LCH_DATA_SFT 0 +#define VUL24_LCH_DATA_MASK 0xffffffff +#define VUL24_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL25_RCH_MON */ +#define VUL25_RCH_DATA_SFT 0 +#define VUL25_RCH_DATA_MASK 0xffffffff +#define VUL25_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL25_LCH_MON */ +#define VUL25_LCH_DATA_SFT 0 +#define VUL25_LCH_DATA_MASK 0xffffffff +#define VUL25_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL26_RCH_MON */ +#define VUL26_RCH_DATA_SFT 0 +#define VUL26_RCH_DATA_MASK 0xffffffff +#define VUL26_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL26_LCH_MON */ +#define VUL26_LCH_DATA_SFT 0 +#define VUL26_LCH_DATA_MASK 0xffffffff +#define VUL26_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM0_RCH_MON */ +#define VUL_CM0_RCH_DATA_SFT 0 +#define VUL_CM0_RCH_DATA_MASK 0xffffffff +#define VUL_CM0_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM0_LCH_MON */ +#define VUL_CM0_LCH_DATA_SFT 0 +#define VUL_CM0_LCH_DATA_MASK 0xffffffff +#define VUL_CM0_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM1_RCH_MON */ +#define VUL_CM1_RCH_DATA_SFT 0 +#define VUL_CM1_RCH_DATA_MASK 0xffffffff +#define VUL_CM1_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM1_LCH_MON */ +#define VUL_CM1_LCH_DATA_SFT 0 +#define VUL_CM1_LCH_DATA_MASK 0xffffffff +#define VUL_CM1_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM2_RCH_MON */ +#define VUL_CM2_RCH_DATA_SFT 0 +#define VUL_CM2_RCH_DATA_MASK 0xffffffff +#define VUL_CM2_RCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_VUL_CM2_LCH_MON */ +#define VUL_CM2_LCH_DATA_SFT 0 +#define VUL_CM2_LCH_DATA_MASK 0xffffffff +#define VUL_CM2_LCH_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_4CH_CH0_MON */ +#define DL_4CH_CH0_DATA_SFT 0 +#define DL_4CH_CH0_DATA_MASK 0xffffffff +#define DL_4CH_CH0_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_4CH_CH1_MON */ +#define DL_4CH_CH1_DATA_SFT 0 +#define DL_4CH_CH1_DATA_MASK 0xffffffff +#define DL_4CH_CH1_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_4CH_CH2_MON */ +#define DL_4CH_CH2_DATA_SFT 0 +#define DL_4CH_CH2_DATA_MASK 0xffffffff +#define DL_4CH_CH2_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_4CH_CH3_MON */ +#define DL_4CH_CH3_DATA_SFT 0 +#define DL_4CH_CH3_DATA_MASK 0xffffffff +#define DL_4CH_CH3_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH0_MON */ +#define DL_24CH_CH0_DATA_SFT 0 +#define DL_24CH_CH0_DATA_MASK 0xffffffff +#define DL_24CH_CH0_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH1_MON */ +#define DL_24CH_CH1_DATA_SFT 0 +#define DL_24CH_CH1_DATA_MASK 0xffffffff +#define DL_24CH_CH1_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH2_MON */ +#define DL_24CH_CH2_DATA_SFT 0 +#define DL_24CH_CH2_DATA_MASK 0xffffffff +#define DL_24CH_CH2_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH3_MON */ +#define DL_24CH_CH3_DATA_SFT 0 +#define DL_24CH_CH3_DATA_MASK 0xffffffff +#define DL_24CH_CH3_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH4_MON */ +#define DL_24CH_CH4_DATA_SFT 0 +#define DL_24CH_CH4_DATA_MASK 0xffffffff +#define DL_24CH_CH4_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH5_MON */ +#define DL_24CH_CH5_DATA_SFT 0 +#define DL_24CH_CH5_DATA_MASK 0xffffffff +#define DL_24CH_CH5_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH6_MON */ +#define DL_24CH_CH6_DATA_SFT 0 +#define DL_24CH_CH6_DATA_MASK 0xffffffff +#define DL_24CH_CH6_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH7_MON */ +#define DL_24CH_CH7_DATA_SFT 0 +#define DL_24CH_CH7_DATA_MASK 0xffffffff +#define DL_24CH_CH7_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH8_MON */ +#define DL_24CH_CH8_DATA_SFT 0 +#define DL_24CH_CH8_DATA_MASK 0xffffffff +#define DL_24CH_CH8_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH9_MON */ +#define DL_24CH_CH9_DATA_SFT 0 +#define DL_24CH_CH9_DATA_MASK 0xffffffff +#define DL_24CH_CH9_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH10_MON */ +#define DL_24CH_CH10_DATA_SFT 0 +#define DL_24CH_CH10_DATA_MASK 0xffffffff +#define DL_24CH_CH10_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH11_MON */ +#define DL_24CH_CH11_DATA_SFT 0 +#define DL_24CH_CH11_DATA_MASK 0xffffffff +#define DL_24CH_CH11_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH12_MON */ +#define DL_24CH_CH12_DATA_SFT 0 +#define DL_24CH_CH12_DATA_MASK 0xffffffff +#define DL_24CH_CH12_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH13_MON */ +#define DL_24CH_CH13_DATA_SFT 0 +#define DL_24CH_CH13_DATA_MASK 0xffffffff +#define DL_24CH_CH13_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH14_MON */ +#define DL_24CH_CH14_DATA_SFT 0 +#define DL_24CH_CH14_DATA_MASK 0xffffffff +#define DL_24CH_CH14_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_DL_24CH_CH15_MON */ +#define DL_24CH_CH15_DATA_SFT 0 +#define DL_24CH_CH15_DATA_MASK 0xffffffff +#define DL_24CH_CH15_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_SRAM_BOUND */ +#define SECURE_BIT_SFT 19 +#define SECURE_BIT_MASK 0x1 +#define SECURE_BIT_MASK_SFT (0x1 << 19) +#define SECURE_SRAM_BOUND_SFT 0 +#define SECURE_SRAM_BOUND_MASK 0x7ffff +#define SECURE_SRAM_BOUND_MASK_SFT (0x7ffff << 0) + +/* AFE_SECURE_CON0 */ +#define READ_EN15_NS_SFT 31 +#define READ_EN15_NS_MASK 0x1 +#define READ_EN15_NS_MASK_SFT (0x1 << 31) +#define WRITE_EN15_NS_SFT 30 +#define WRITE_EN15_NS_MASK 0x1 +#define WRITE_EN15_NS_MASK_SFT (0x1 << 30) +#define READ_EN14_NS_SFT 29 +#define READ_EN14_NS_MASK 0x1 +#define READ_EN14_NS_MASK_SFT (0x1 << 29) +#define WRITE_EN14_NS_SFT 28 +#define WRITE_EN14_NS_MASK 0x1 +#define WRITE_EN14_NS_MASK_SFT (0x1 << 28) +#define READ_EN13_NS_SFT 27 +#define READ_EN13_NS_MASK 0x1 +#define READ_EN13_NS_MASK_SFT (0x1 << 27) +#define WRITE_EN13_NS_SFT 26 +#define WRITE_EN13_NS_MASK 0x1 +#define WRITE_EN13_NS_MASK_SFT (0x1 << 26) +#define READ_EN12_NS_SFT 25 +#define READ_EN12_NS_MASK 0x1 +#define READ_EN12_NS_MASK_SFT (0x1 << 25) +#define WRITE_EN12_NS_SFT 24 +#define WRITE_EN12_NS_MASK 0x1 +#define WRITE_EN12_NS_MASK_SFT (0x1 << 24) +#define READ_EN11_NS_SFT 23 +#define READ_EN11_NS_MASK 0x1 +#define READ_EN11_NS_MASK_SFT (0x1 << 23) +#define WRITE_EN11_NS_SFT 22 +#define WRITE_EN11_NS_MASK 0x1 +#define WRITE_EN11_NS_MASK_SFT (0x1 << 22) +#define READ_EN10_NS_SFT 21 +#define READ_EN10_NS_MASK 0x1 +#define READ_EN10_NS_MASK_SFT (0x1 << 21) +#define WRITE_EN10_NS_SFT 20 +#define WRITE_EN10_NS_MASK 0x1 +#define WRITE_EN10_NS_MASK_SFT (0x1 << 20) +#define READ_EN9_NS_SFT 19 +#define READ_EN9_NS_MASK 0x1 +#define READ_EN9_NS_MASK_SFT (0x1 << 19) +#define WRITE_EN9_NS_SFT 18 +#define WRITE_EN9_NS_MASK 0x1 +#define WRITE_EN9_NS_MASK_SFT (0x1 << 18) +#define READ_EN8_NS_SFT 17 +#define READ_EN8_NS_MASK 0x1 +#define READ_EN8_NS_MASK_SFT (0x1 << 17) +#define WRITE_EN8_NS_SFT 16 +#define WRITE_EN8_NS_MASK 0x1 +#define WRITE_EN8_NS_MASK_SFT (0x1 << 16) +#define READ_EN7_NS_SFT 15 +#define READ_EN7_NS_MASK 0x1 +#define READ_EN7_NS_MASK_SFT (0x1 << 15) +#define WRITE_EN7_NS_SFT 14 +#define WRITE_EN7_NS_MASK 0x1 +#define WRITE_EN7_NS_MASK_SFT (0x1 << 14) +#define READ_EN6_NS_SFT 13 +#define READ_EN6_NS_MASK 0x1 +#define READ_EN6_NS_MASK_SFT (0x1 << 13) +#define WRITE_EN6_NS_SFT 12 +#define WRITE_EN6_NS_MASK 0x1 +#define WRITE_EN6_NS_MASK_SFT (0x1 << 12) +#define READ_EN5_NS_SFT 11 +#define READ_EN5_NS_MASK 0x1 +#define READ_EN5_NS_MASK_SFT (0x1 << 11) +#define WRITE_EN5_NS_SFT 10 +#define WRITE_EN5_NS_MASK 0x1 +#define WRITE_EN5_NS_MASK_SFT (0x1 << 10) +#define READ_EN4_NS_SFT 9 +#define READ_EN4_NS_MASK 0x1 +#define READ_EN4_NS_MASK_SFT (0x1 << 9) +#define WRITE_EN4_NS_SFT 8 +#define WRITE_EN4_NS_MASK 0x1 +#define WRITE_EN4_NS_MASK_SFT (0x1 << 8) +#define READ_EN3_NS_SFT 7 +#define READ_EN3_NS_MASK 0x1 +#define READ_EN3_NS_MASK_SFT (0x1 << 7) +#define WRITE_EN3_NS_SFT 6 +#define WRITE_EN3_NS_MASK 0x1 +#define WRITE_EN3_NS_MASK_SFT (0x1 << 6) +#define READ_EN2_NS_SFT 5 +#define READ_EN2_NS_MASK 0x1 +#define READ_EN2_NS_MASK_SFT (0x1 << 5) +#define WRITE_EN2_NS_SFT 4 +#define WRITE_EN2_NS_MASK 0x1 +#define WRITE_EN2_NS_MASK_SFT (0x1 << 4) +#define READ_EN1_NS_SFT 3 +#define READ_EN1_NS_MASK 0x1 +#define READ_EN1_NS_MASK_SFT (0x1 << 3) +#define WRITE_EN1_NS_SFT 2 +#define WRITE_EN1_NS_MASK 0x1 +#define WRITE_EN1_NS_MASK_SFT (0x1 << 2) +#define READ_EN0_NS_SFT 1 +#define READ_EN0_NS_MASK 0x1 +#define READ_EN0_NS_MASK_SFT (0x1 << 1) +#define WRITE_EN0_NS_SFT 0 +#define WRITE_EN0_NS_MASK 0x1 +#define WRITE_EN0_NS_MASK_SFT (0x1 << 0) + +/* AFE_SECURE_CON1 */ +#define READ_EN15_S_SFT 31 +#define READ_EN15_S_MASK 0x1 +#define READ_EN15_S_MASK_SFT (0x1 << 31) +#define WRITE_EN15_S_SFT 30 +#define WRITE_EN15_S_MASK 0x1 +#define WRITE_EN15_S_MASK_SFT (0x1 << 30) +#define READ_EN14_S_SFT 29 +#define READ_EN14_S_MASK 0x1 +#define READ_EN14_S_MASK_SFT (0x1 << 29) +#define WRITE_EN14_S_SFT 28 +#define WRITE_EN14_S_MASK 0x1 +#define WRITE_EN14_S_MASK_SFT (0x1 << 28) +#define READ_EN13_S_SFT 27 +#define READ_EN13_S_MASK 0x1 +#define READ_EN13_S_MASK_SFT (0x1 << 27) +#define WRITE_EN13_S_SFT 26 +#define WRITE_EN13_S_MASK 0x1 +#define WRITE_EN13_S_MASK_SFT (0x1 << 26) +#define READ_EN12_S_SFT 25 +#define READ_EN12_S_MASK 0x1 +#define READ_EN12_S_MASK_SFT (0x1 << 25) +#define WRITE_EN12_S_SFT 24 +#define WRITE_EN12_S_MASK 0x1 +#define WRITE_EN12_S_MASK_SFT (0x1 << 24) +#define READ_EN11_S_SFT 23 +#define READ_EN11_S_MASK 0x1 +#define READ_EN11_S_MASK_SFT (0x1 << 23) +#define WRITE_EN11_S_SFT 22 +#define WRITE_EN11_S_MASK 0x1 +#define WRITE_EN11_S_MASK_SFT (0x1 << 22) +#define READ_EN10_S_SFT 21 +#define READ_EN10_S_MASK 0x1 +#define READ_EN10_S_MASK_SFT (0x1 << 21) +#define WRITE_EN10_S_SFT 20 +#define WRITE_EN10_S_MASK 0x1 +#define WRITE_EN10_S_MASK_SFT (0x1 << 20) +#define READ_EN9_S_SFT 19 +#define READ_EN9_S_MASK 0x1 +#define READ_EN9_S_MASK_SFT (0x1 << 19) +#define WRITE_EN9_S_SFT 18 +#define WRITE_EN9_S_MASK 0x1 +#define WRITE_EN9_S_MASK_SFT (0x1 << 18) +#define READ_EN8_S_SFT 17 +#define READ_EN8_S_MASK 0x1 +#define READ_EN8_S_MASK_SFT (0x1 << 17) +#define WRITE_EN8_S_SFT 16 +#define WRITE_EN8_S_MASK 0x1 +#define WRITE_EN8_S_MASK_SFT (0x1 << 16) +#define READ_EN7_S_SFT 15 +#define READ_EN7_S_MASK 0x1 +#define READ_EN7_S_MASK_SFT (0x1 << 15) +#define WRITE_EN7_S_SFT 14 +#define WRITE_EN7_S_MASK 0x1 +#define WRITE_EN7_S_MASK_SFT (0x1 << 14) +#define READ_EN6_S_SFT 13 +#define READ_EN6_S_MASK 0x1 +#define READ_EN6_S_MASK_SFT (0x1 << 13) +#define WRITE_EN6_S_SFT 12 +#define WRITE_EN6_S_MASK 0x1 +#define WRITE_EN6_S_MASK_SFT (0x1 << 12) +#define READ_EN5_S_SFT 11 +#define READ_EN5_S_MASK 0x1 +#define READ_EN5_S_MASK_SFT (0x1 << 11) +#define WRITE_EN5_S_SFT 10 +#define WRITE_EN5_S_MASK 0x1 +#define WRITE_EN5_S_MASK_SFT (0x1 << 10) +#define READ_EN4_S_SFT 9 +#define READ_EN4_S_MASK 0x1 +#define READ_EN4_S_MASK_SFT (0x1 << 9) +#define WRITE_EN4_S_SFT 8 +#define WRITE_EN4_S_MASK 0x1 +#define WRITE_EN4_S_MASK_SFT (0x1 << 8) +#define READ_EN3_S_SFT 7 +#define READ_EN3_S_MASK 0x1 +#define READ_EN3_S_MASK_SFT (0x1 << 7) +#define WRITE_EN3_S_SFT 6 +#define WRITE_EN3_S_MASK 0x1 +#define WRITE_EN3_S_MASK_SFT (0x1 << 6) +#define READ_EN2_S_SFT 5 +#define READ_EN2_S_MASK 0x1 +#define READ_EN2_S_MASK_SFT (0x1 << 5) +#define WRITE_EN2_S_SFT 4 +#define WRITE_EN2_S_MASK 0x1 +#define WRITE_EN2_S_MASK_SFT (0x1 << 4) +#define READ_EN1_S_SFT 3 +#define READ_EN1_S_MASK 0x1 +#define READ_EN1_S_MASK_SFT (0x1 << 3) +#define WRITE_EN1_S_SFT 2 +#define WRITE_EN1_S_MASK 0x1 +#define WRITE_EN1_S_MASK_SFT (0x1 << 2) +#define READ_EN0_S_SFT 1 +#define READ_EN0_S_MASK 0x1 +#define READ_EN0_S_MASK_SFT (0x1 << 1) +#define WRITE_EN0_S_SFT 0 +#define WRITE_EN0_S_MASK 0x1 +#define WRITE_EN0_S_MASK_SFT (0x1 << 0) + +/* AFE_SE_SECURE_CON0 */ +#define AFE_HDMI_SE_SECURE_BIT_SFT 11 +#define AFE_HDMI_SE_SECURE_BIT_MASK 0x1 +#define AFE_HDMI_SE_SECURE_BIT_MASK_SFT (0x1 << 11) +#define AFE_SPDIF2_OUT_SE_SECURE_BIT_SFT 10 +#define AFE_SPDIF2_OUT_SE_SECURE_BIT_MASK 0x1 +#define AFE_SPDIF2_OUT_SE_SECURE_BIT_MASK_SFT (0x1 << 10) +#define AFE_SPDIF_OUT_SE_SECURE_BIT_SFT 9 +#define AFE_SPDIF_OUT_SE_SECURE_BIT_MASK 0x1 +#define AFE_SPDIF_OUT_SE_SECURE_BIT_MASK_SFT (0x1 << 9) +#define AFE_DL8_SE_SECURE_BIT_SFT 8 +#define AFE_DL8_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL8_SE_SECURE_BIT_MASK_SFT (0x1 << 8) +#define AFE_DL7_SE_SECURE_BIT_SFT 7 +#define AFE_DL7_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL7_SE_SECURE_BIT_MASK_SFT (0x1 << 7) +#define AFE_DL6_SE_SECURE_BIT_SFT 6 +#define AFE_DL6_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL6_SE_SECURE_BIT_MASK_SFT (0x1 << 6) +#define AFE_DL5_SE_SECURE_BIT_SFT 5 +#define AFE_DL5_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL5_SE_SECURE_BIT_MASK_SFT (0x1 << 5) +#define AFE_DL4_SE_SECURE_BIT_SFT 4 +#define AFE_DL4_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL4_SE_SECURE_BIT_MASK_SFT (0x1 << 4) +#define AFE_DL3_SE_SECURE_BIT_SFT 3 +#define AFE_DL3_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL3_SE_SECURE_BIT_MASK_SFT (0x1 << 3) +#define AFE_DL2_SE_SECURE_BIT_SFT 2 +#define AFE_DL2_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL2_SE_SECURE_BIT_MASK_SFT (0x1 << 2) +#define AFE_DL1_SE_SECURE_BIT_SFT 1 +#define AFE_DL1_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL1_SE_SECURE_BIT_MASK_SFT (0x1 << 1) +#define AFE_DL0_SE_SECURE_BIT_SFT 0 +#define AFE_DL0_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL0_SE_SECURE_BIT_MASK_SFT (0x1 << 0) + +/* AFE_SE_SECURE_CON1 */ +#define AFE_DL46_SE_SECURE_BIT_SFT 26 +#define AFE_DL46_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL46_SE_SECURE_BIT_MASK_SFT (0x1 << 26) +#define AFE_DL45_SE_SECURE_BIT_SFT 25 +#define AFE_DL45_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL45_SE_SECURE_BIT_MASK_SFT (0x1 << 25) +#define AFE_DL44_SE_SECURE_BIT_SFT 24 +#define AFE_DL44_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL44_SE_SECURE_BIT_MASK_SFT (0x1 << 24) +#define AFE_DL43_SE_SECURE_BIT_SFT 23 +#define AFE_DL43_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL43_SE_SECURE_BIT_MASK_SFT (0x1 << 23) +#define AFE_DL42_SE_SECURE_BIT_SFT 22 +#define AFE_DL42_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL42_SE_SECURE_BIT_MASK_SFT (0x1 << 22) +#define AFE_DL41_SE_SECURE_BIT_SFT 21 +#define AFE_DL41_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL41_SE_SECURE_BIT_MASK_SFT (0x1 << 21) +#define AFE_DL40_SE_SECURE_BIT_SFT 20 +#define AFE_DL40_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL40_SE_SECURE_BIT_MASK_SFT (0x1 << 20) +#define AFE_DL39_SE_SECURE_BIT_SFT 19 +#define AFE_DL39_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL39_SE_SECURE_BIT_MASK_SFT (0x1 << 19) +#define AFE_DL38_SE_SECURE_BIT_SFT 18 +#define AFE_DL38_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL38_SE_SECURE_BIT_MASK_SFT (0x1 << 18) +#define AFE_DL37_SE_SECURE_BIT_SFT 17 +#define AFE_DL37_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL37_SE_SECURE_BIT_MASK_SFT (0x1 << 17) +#define AFE_DL36_SE_SECURE_BIT_SFT 16 +#define AFE_DL36_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL36_SE_SECURE_BIT_MASK_SFT (0x1 << 16) +#define AFE_DL35_SE_SECURE_BIT_SFT 15 +#define AFE_DL35_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL35_SE_SECURE_BIT_MASK_SFT (0x1 << 15) +#define AFE_DL34_SE_SECURE_BIT_SFT 14 +#define AFE_DL34_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL34_SE_SECURE_BIT_MASK_SFT (0x1 << 14) +#define AFE_DL33_SE_SECURE_BIT_SFT 13 +#define AFE_DL33_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL33_SE_SECURE_BIT_MASK_SFT (0x1 << 13) +#define AFE_DL32_SE_SECURE_BIT_SFT 12 +#define AFE_DL32_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL32_SE_SECURE_BIT_MASK_SFT (0x1 << 12) +#define AFE_DL31_SE_SECURE_BIT_SFT 11 +#define AFE_DL31_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL31_SE_SECURE_BIT_MASK_SFT (0x1 << 11) +#define AFE_DL30_SE_SECURE_BIT_SFT 10 +#define AFE_DL30_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL30_SE_SECURE_BIT_MASK_SFT (0x1 << 10) +#define AFE_DL29_SE_SECURE_BIT_SFT 9 +#define AFE_DL29_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL29_SE_SECURE_BIT_MASK_SFT (0x1 << 9) +#define AFE_DL28_SE_SECURE_BIT_SFT 8 +#define AFE_DL28_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL28_SE_SECURE_BIT_MASK_SFT (0x1 << 8) +#define AFE_DL27_SE_SECURE_BIT_SFT 7 +#define AFE_DL27_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL27_SE_SECURE_BIT_MASK_SFT (0x1 << 7) +#define AFE_DL26_SE_SECURE_BIT_SFT 6 +#define AFE_DL26_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL26_SE_SECURE_BIT_MASK_SFT (0x1 << 6) +#define AFE_DL25_SE_SECURE_BIT_SFT 5 +#define AFE_DL25_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL25_SE_SECURE_BIT_MASK_SFT (0x1 << 5) +#define AFE_DL24_SE_SECURE_BIT_SFT 4 +#define AFE_DL24_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL24_SE_SECURE_BIT_MASK_SFT (0x1 << 4) +#define AFE_DL23_SE_SECURE_BIT_SFT 3 +#define AFE_DL23_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL23_SE_SECURE_BIT_MASK_SFT (0x1 << 3) +#define AFE_DL_48CH_SE_SECURE_BIT_SFT 2 +#define AFE_DL_48CH_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL_48CH_SE_SECURE_BIT_MASK_SFT (0x1 << 2) +#define AFE_DL_24CH_SE_SECURE_BIT_SFT 1 +#define AFE_DL_24CH_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL_24CH_SE_SECURE_BIT_MASK_SFT (0x1 << 1) +#define AFE_DL_4CH_SE_SECURE_BIT_SFT 0 +#define AFE_DL_4CH_SE_SECURE_BIT_MASK 0x1 +#define AFE_DL_4CH_SE_SECURE_BIT_MASK_SFT (0x1 << 0) + +/* AFE_SE_SECURE_CON2 */ +#define AFE_VUL38_SE_SECURE_BIT_SFT 28 +#define AFE_VUL38_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL38_SE_SECURE_BIT_MASK_SFT (0x1 << 28) +#define AFE_VUL37_SE_SECURE_BIT_SFT 27 +#define AFE_VUL37_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL37_SE_SECURE_BIT_MASK_SFT (0x1 << 27) +#define AFE_VUL36_SE_SECURE_BIT_SFT 26 +#define AFE_VUL36_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL36_SE_SECURE_BIT_MASK_SFT (0x1 << 26) +#define AFE_VUL35_SE_SECURE_BIT_SFT 25 +#define AFE_VUL35_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL35_SE_SECURE_BIT_MASK_SFT (0x1 << 25) +#define AFE_VUL34_SE_SECURE_BIT_SFT 24 +#define AFE_VUL34_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL34_SE_SECURE_BIT_MASK_SFT (0x1 << 24) +#define AFE_VUL33_SE_SECURE_BIT_SFT 23 +#define AFE_VUL33_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL33_SE_SECURE_BIT_MASK_SFT (0x1 << 23) +#define AFE_VUL32_SE_SECURE_BIT_SFT 22 +#define AFE_VUL32_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL32_SE_SECURE_BIT_MASK_SFT (0x1 << 22) +#define AFE_VUL31_SE_SECURE_BIT_SFT 21 +#define AFE_VUL31_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL31_SE_SECURE_BIT_MASK_SFT (0x1 << 21) +#define AFE_VUL30_SE_SECURE_BIT_SFT 20 +#define AFE_VUL30_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL30_SE_SECURE_BIT_MASK_SFT (0x1 << 20) +#define AFE_VUL29_SE_SECURE_BIT_SFT 19 +#define AFE_VUL29_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL29_SE_SECURE_BIT_MASK_SFT (0x1 << 19) +#define AFE_VUL28_SE_SECURE_BIT_SFT 18 +#define AFE_VUL28_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL28_SE_SECURE_BIT_MASK_SFT (0x1 << 18) +#define AFE_VUL27_SE_SECURE_BIT_SFT 17 +#define AFE_VUL27_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL27_SE_SECURE_BIT_MASK_SFT (0x1 << 17) +#define AFE_VUL26_SE_SECURE_BIT_SFT 16 +#define AFE_VUL26_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL26_SE_SECURE_BIT_MASK_SFT (0x1 << 16) +#define AFE_VUL25_SE_SECURE_BIT_SFT 15 +#define AFE_VUL25_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL25_SE_SECURE_BIT_MASK_SFT (0x1 << 15) +#define AFE_VUL24_SE_SECURE_BIT_SFT 14 +#define AFE_VUL24_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL24_SE_SECURE_BIT_MASK_SFT (0x1 << 14) +#define AFE_VUL_CM2_SE_SECURE_BIT_SFT 13 +#define AFE_VUL_CM2_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL_CM2_SE_SECURE_BIT_MASK_SFT (0x1 << 13) +#define AFE_VUL_CM1_SE_SECURE_BIT_SFT 12 +#define AFE_VUL_CM1_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL_CM1_SE_SECURE_BIT_MASK_SFT (0x1 << 12) +#define AFE_VUL_CM0_SE_SECURE_BIT_SFT 11 +#define AFE_VUL_CM0_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL_CM0_SE_SECURE_BIT_MASK_SFT (0x1 << 11) +#define AFE_VUL10_SE_SECURE_BIT_SFT 10 +#define AFE_VUL10_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL10_SE_SECURE_BIT_MASK_SFT (0x1 << 10) +#define AFE_VUL9_SE_SECURE_BIT_SFT 9 +#define AFE_VUL9_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL9_SE_SECURE_BIT_MASK_SFT (0x1 << 9) +#define AFE_VUL8_SE_SECURE_BIT_SFT 8 +#define AFE_VUL8_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL8_SE_SECURE_BIT_MASK_SFT (0x1 << 8) +#define AFE_VUL7_SE_SECURE_BIT_SFT 7 +#define AFE_VUL7_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL7_SE_SECURE_BIT_MASK_SFT (0x1 << 7) +#define AFE_VUL6_SE_SECURE_BIT_SFT 6 +#define AFE_VUL6_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL6_SE_SECURE_BIT_MASK_SFT (0x1 << 6) +#define AFE_VUL5_SE_SECURE_BIT_SFT 5 +#define AFE_VUL5_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL5_SE_SECURE_BIT_MASK_SFT (0x1 << 5) +#define AFE_VUL4_SE_SECURE_BIT_SFT 4 +#define AFE_VUL4_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL4_SE_SECURE_BIT_MASK_SFT (0x1 << 4) +#define AFE_VUL3_SE_SECURE_BIT_SFT 3 +#define AFE_VUL3_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL3_SE_SECURE_BIT_MASK_SFT (0x1 << 3) +#define AFE_VUL2_SE_SECURE_BIT_SFT 2 +#define AFE_VUL2_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL2_SE_SECURE_BIT_MASK_SFT (0x1 << 2) +#define AFE_VUL1_SE_SECURE_BIT_SFT 1 +#define AFE_VUL1_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL1_SE_SECURE_BIT_MASK_SFT (0x1 << 1) +#define AFE_VUL0_SE_SECURE_BIT_SFT 0 +#define AFE_VUL0_SE_SECURE_BIT_MASK 0x1 +#define AFE_VUL0_SE_SECURE_BIT_MASK_SFT (0x1 << 0) + +/* AFE_SE_SECURE_CON3 */ +#define AFE_SPDIFIN_SE_SECURE_BIT_SFT 10 +#define AFE_SPDIFIN_SE_SECURE_BIT_MASK 0x1 +#define AFE_SPDIFIN_SE_SECURE_BIT_MASK_SFT (0x1 << 10) +#define AFE_TDM_IN_SE_SECURE_BIT_SFT 9 +#define AFE_TDM_IN_SE_SECURE_BIT_MASK 0x1 +#define AFE_TDM_IN_SE_SECURE_BIT_MASK_SFT (0x1 << 9) +#define AFE_MPHONE_EARC_SE_SECURE_BIT_SFT 8 +#define AFE_MPHONE_EARC_SE_SECURE_BIT_MASK 0x1 +#define AFE_MPHONE_EARC_SE_SECURE_BIT_MASK_SFT (0x1 << 8) +#define AFE_MPHONE_SPDIF_SE_SECURE_BIT_SFT 7 +#define AFE_MPHONE_SPDIF_SE_SECURE_BIT_MASK 0x1 +#define AFE_MPHONE_SPDIF_SE_SECURE_BIT_MASK_SFT (0x1 << 7) +#define AFE_ETDM_IN6_SE_SECURE_BIT_SFT 6 +#define AFE_ETDM_IN6_SE_SECURE_BIT_MASK 0x1 +#define AFE_ETDM_IN6_SE_SECURE_BIT_MASK_SFT (0x1 << 6) +#define AFE_ETDM_IN5_SE_SECURE_BIT_SFT 5 +#define AFE_ETDM_IN5_SE_SECURE_BIT_MASK 0x1 +#define AFE_ETDM_IN5_SE_SECURE_BIT_MASK_SFT (0x1 << 5) +#define AFE_ETDM_IN4_SE_SECURE_BIT_SFT 4 +#define AFE_ETDM_IN4_SE_SECURE_BIT_MASK 0x1 +#define AFE_ETDM_IN4_SE_SECURE_BIT_MASK_SFT (0x1 << 4) +#define AFE_ETDM_IN3_SE_SECURE_BIT_SFT 3 +#define AFE_ETDM_IN3_SE_SECURE_BIT_MASK 0x1 +#define AFE_ETDM_IN3_SE_SECURE_BIT_MASK_SFT (0x1 << 3) +#define AFE_ETDM_IN2_SE_SECURE_BIT_SFT 2 +#define AFE_ETDM_IN2_SE_SECURE_BIT_MASK 0x1 +#define AFE_ETDM_IN2_SE_SECURE_BIT_MASK_SFT (0x1 << 2) +#define AFE_ETDM_IN1_SE_SECURE_BIT_SFT 1 +#define AFE_ETDM_IN1_SE_SECURE_BIT_MASK 0x1 +#define AFE_ETDM_IN1_SE_SECURE_BIT_MASK_SFT (0x1 << 1) +#define AFE_ETDM_IN0_SE_SECURE_BIT_SFT 0 +#define AFE_ETDM_IN0_SE_SECURE_BIT_MASK 0x1 +#define AFE_ETDM_IN0_SE_SECURE_BIT_MASK_SFT (0x1 << 0) + +/* AFE_SE_PROT_SIDEBAND0 */ +#define HDMI_HPROT_SFT 11 +#define HDMI_HPROT_MASK 0x1 +#define HDMI_HPROT_MASK_SFT (0x1 << 11) +#define SPDIF2_OUT_HPROT_SFT 10 +#define SPDIF2_OUT_HPROT_MASK 0x1 +#define SPDIF2_OUT_HPROT_MASK_SFT (0x1 << 10) +#define SPDIF_OUT_HPROT_SFT 9 +#define SPDIF_OUT_HPROT_MASK 0x1 +#define SPDIF_OUT_HPROT_MASK_SFT (0x1 << 9) +#define DL8_HPROT_SFT 8 +#define DL8_HPROT_MASK 0x1 +#define DL8_HPROT_MASK_SFT (0x1 << 8) +#define DL7_HPROT_SFT 7 +#define DL7_HPROT_MASK 0x1 +#define DL7_HPROT_MASK_SFT (0x1 << 7) +#define DL6_HPROT_SFT 6 +#define DL6_HPROT_MASK 0x1 +#define DL6_HPROT_MASK_SFT (0x1 << 6) +#define DL5_HPROT_SFT 5 +#define DL5_HPROT_MASK 0x1 +#define DL5_HPROT_MASK_SFT (0x1 << 5) +#define DL4_HPROT_SFT 4 +#define DL4_HPROT_MASK 0x1 +#define DL4_HPROT_MASK_SFT (0x1 << 4) +#define DL3_HPROT_SFT 3 +#define DL3_HPROT_MASK 0x1 +#define DL3_HPROT_MASK_SFT (0x1 << 3) +#define DL2_HPROT_SFT 2 +#define DL2_HPROT_MASK 0x1 +#define DL2_HPROT_MASK_SFT (0x1 << 2) +#define DL1_HPROT_SFT 1 +#define DL1_HPROT_MASK 0x1 +#define DL1_HPROT_MASK_SFT (0x1 << 1) +#define DL0_HPROT_SFT 0 +#define DL0_HPROT_MASK 0x1 +#define DL0_HPROT_MASK_SFT (0x1 << 0) + +/* AFE_SE_PROT_SIDEBAND1 */ +#define DL46_HPROT_SFT 26 +#define DL46_HPROT_MASK 0x1 +#define DL46_HPROT_MASK_SFT (0x1 << 26) +#define DL45_HPROT_SFT 25 +#define DL45_HPROT_MASK 0x1 +#define DL45_HPROT_MASK_SFT (0x1 << 25) +#define DL44_HPROT_SFT 24 +#define DL44_HPROT_MASK 0x1 +#define DL44_HPROT_MASK_SFT (0x1 << 24) +#define DL43_HPROT_SFT 23 +#define DL43_HPROT_MASK 0x1 +#define DL43_HPROT_MASK_SFT (0x1 << 23) +#define DL42_HPROT_SFT 22 +#define DL42_HPROT_MASK 0x1 +#define DL42_HPROT_MASK_SFT (0x1 << 22) +#define DL41_HPROT_SFT 21 +#define DL41_HPROT_MASK 0x1 +#define DL41_HPROT_MASK_SFT (0x1 << 21) +#define DL40_HPROT_SFT 20 +#define DL40_HPROT_MASK 0x1 +#define DL40_HPROT_MASK_SFT (0x1 << 20) +#define DL39_HPROT_SFT 19 +#define DL39_HPROT_MASK 0x1 +#define DL39_HPROT_MASK_SFT (0x1 << 19) +#define DL38_HPROT_SFT 18 +#define DL38_HPROT_MASK 0x1 +#define DL38_HPROT_MASK_SFT (0x1 << 18) +#define DL37_HPROT_SFT 17 +#define DL37_HPROT_MASK 0x1 +#define DL37_HPROT_MASK_SFT (0x1 << 17) +#define DL36_HPROT_SFT 16 +#define DL36_HPROT_MASK 0x1 +#define DL36_HPROT_MASK_SFT (0x1 << 16) +#define DL35_HPROT_SFT 15 +#define DL35_HPROT_MASK 0x1 +#define DL35_HPROT_MASK_SFT (0x1 << 15) +#define DL34_HPROT_SFT 14 +#define DL34_HPROT_MASK 0x1 +#define DL34_HPROT_MASK_SFT (0x1 << 14) +#define DL33_HPROT_SFT 13 +#define DL33_HPROT_MASK 0x1 +#define DL33_HPROT_MASK_SFT (0x1 << 13) +#define DL32_HPROT_SFT 12 +#define DL32_HPROT_MASK 0x1 +#define DL32_HPROT_MASK_SFT (0x1 << 12) +#define DL31_HPROT_SFT 11 +#define DL31_HPROT_MASK 0x1 +#define DL31_HPROT_MASK_SFT (0x1 << 11) +#define DL30_HPROT_SFT 10 +#define DL30_HPROT_MASK 0x1 +#define DL30_HPROT_MASK_SFT (0x1 << 10) +#define DL29_HPROT_SFT 9 +#define DL29_HPROT_MASK 0x1 +#define DL29_HPROT_MASK_SFT (0x1 << 9) +#define DL28_HPROT_SFT 8 +#define DL28_HPROT_MASK 0x1 +#define DL28_HPROT_MASK_SFT (0x1 << 8) +#define DL27_HPROT_SFT 7 +#define DL27_HPROT_MASK 0x1 +#define DL27_HPROT_MASK_SFT (0x1 << 7) +#define DL26_HPROT_SFT 6 +#define DL26_HPROT_MASK 0x1 +#define DL26_HPROT_MASK_SFT (0x1 << 6) +#define DL25_HPROT_SFT 5 +#define DL25_HPROT_MASK 0x1 +#define DL25_HPROT_MASK_SFT (0x1 << 5) +#define DL24_HPROT_SFT 4 +#define DL24_HPROT_MASK 0x1 +#define DL24_HPROT_MASK_SFT (0x1 << 4) +#define DL23_HPROT_SFT 3 +#define DL23_HPROT_MASK 0x1 +#define DL23_HPROT_MASK_SFT (0x1 << 3) +#define DL_48CH_PROT_SFT 2 +#define DL_48CH_PROT_MASK 0x1 +#define DL_48CH_PROT_MASK_SFT (0x1 << 2) +#define DL_24CH_PROT_SFT 1 +#define DL_24CH_PROT_MASK 0x1 +#define DL_24CH_PROT_MASK_SFT (0x1 << 1) +#define DL_4CH_PROT_SFT 0 +#define DL_4CH_PROT_MASK 0x1 +#define DL_4CH_PROT_MASK_SFT (0x1 << 0) + +/* AFE_SE_PROT_SIDEBAND2 */ +#define VUL38_HPROT_SFT 28 +#define VUL38_HPROT_MASK 0x1 +#define VUL38_HPROT_MASK_SFT (0x1 << 28) +#define VUL37_HPROT_SFT 27 +#define VUL37_HPROT_MASK 0x1 +#define VUL37_HPROT_MASK_SFT (0x1 << 27) +#define VUL36_HPROT_SFT 26 +#define VUL36_HPROT_MASK 0x1 +#define VUL36_HPROT_MASK_SFT (0x1 << 26) +#define VUL35_HPROT_SFT 25 +#define VUL35_HPROT_MASK 0x1 +#define VUL35_HPROT_MASK_SFT (0x1 << 25) +#define VUL34_HPROT_SFT 24 +#define VUL34_HPROT_MASK 0x1 +#define VUL34_HPROT_MASK_SFT (0x1 << 24) +#define VUL33_HPROT_SFT 23 +#define VUL33_HPROT_MASK 0x1 +#define VUL33_HPROT_MASK_SFT (0x1 << 23) +#define VUL32_HPROT_SFT 22 +#define VUL32_HPROT_MASK 0x1 +#define VUL32_HPROT_MASK_SFT (0x1 << 22) +#define VUL31_HPROT_SFT 21 +#define VUL31_HPROT_MASK 0x1 +#define VUL31_HPROT_MASK_SFT (0x1 << 21) +#define VUL30_HPROT_SFT 20 +#define VUL30_HPROT_MASK 0x1 +#define VUL30_HPROT_MASK_SFT (0x1 << 20) +#define VUL29_HPROT_SFT 19 +#define VUL29_HPROT_MASK 0x1 +#define VUL29_HPROT_MASK_SFT (0x1 << 19) +#define VUL28_HPROT_SFT 18 +#define VUL28_HPROT_MASK 0x1 +#define VUL28_HPROT_MASK_SFT (0x1 << 18) +#define VUL27_HPROT_SFT 17 +#define VUL27_HPROT_MASK 0x1 +#define VUL27_HPROT_MASK_SFT (0x1 << 17) +#define VUL26_HPROT_SFT 16 +#define VUL26_HPROT_MASK 0x1 +#define VUL26_HPROT_MASK_SFT (0x1 << 16) +#define VUL25_HPROT_SFT 15 +#define VUL25_HPROT_MASK 0x1 +#define VUL25_HPROT_MASK_SFT (0x1 << 15) +#define VUL24_HPROT_SFT 14 +#define VUL24_HPROT_MASK 0x1 +#define VUL24_HPROT_MASK_SFT (0x1 << 14) +#define VUL_CM2_HPROT_SFT 13 +#define VUL_CM2_HPROT_MASK 0x1 +#define VUL_CM2_HPROT_MASK_SFT (0x1 << 13) +#define VUL_CM1_HPROT_SFT 12 +#define VUL_CM1_HPROT_MASK 0x1 +#define VUL_CM1_HPROT_MASK_SFT (0x1 << 12) +#define VUL_CM0_HPROT_SFT 11 +#define VUL_CM0_HPROT_MASK 0x1 +#define VUL_CM0_HPROT_MASK_SFT (0x1 << 11) +#define VUL10_HPROT_SFT 10 +#define VUL10_HPROT_MASK 0x1 +#define VUL10_HPROT_MASK_SFT (0x1 << 10) +#define VUL9_HPROT_SFT 9 +#define VUL9_HPROT_MASK 0x1 +#define VUL9_HPROT_MASK_SFT (0x1 << 9) +#define VUL8_HPROT_SFT 8 +#define VUL8_HPROT_MASK 0x1 +#define VUL8_HPROT_MASK_SFT (0x1 << 8) +#define VUL7_HPROT_SFT 7 +#define VUL7_HPROT_MASK 0x1 +#define VUL7_HPROT_MASK_SFT (0x1 << 7) +#define VUL6_HPROT_SFT 6 +#define VUL6_HPROT_MASK 0x1 +#define VUL6_HPROT_MASK_SFT (0x1 << 6) +#define VUL5_HPROT_SFT 5 +#define VUL5_HPROT_MASK 0x1 +#define VUL5_HPROT_MASK_SFT (0x1 << 5) +#define VUL4_HPROT_SFT 4 +#define VUL4_HPROT_MASK 0x1 +#define VUL4_HPROT_MASK_SFT (0x1 << 4) +#define VUL3_HPROT_SFT 3 +#define VUL3_HPROT_MASK 0x1 +#define VUL3_HPROT_MASK_SFT (0x1 << 3) +#define VUL2_HPROT_SFT 2 +#define VUL2_HPROT_MASK 0x1 +#define VUL2_HPROT_MASK_SFT (0x1 << 2) +#define VUL1_HPROT_SFT 1 +#define VUL1_HPROT_MASK 0x1 +#define VUL1_HPROT_MASK_SFT (0x1 << 1) +#define VUL0_HPROT_SFT 0 +#define VUL0_HPROT_MASK 0x1 +#define VUL0_HPROT_MASK_SFT (0x1 << 0) + +/* AFE_SE_PROT_SIDEBAND3 */ +#define MPHONE_EARC_HPROT_SFT 10 +#define MPHONE_EARC_HPROT_MASK 0x1 +#define MPHONE_EARC_HPROT_MASK_SFT (0x1 << 10) +#define MPHONE_SPDIF_HPROT_SFT 9 +#define MPHONE_SPDIF_HPROT_MASK 0x1 +#define MPHONE_SPDIF_HPROT_MASK_SFT (0x1 << 9) +#define SPDIFIN_HPROT_SFT 8 +#define SPDIFIN_HPROT_MASK 0x1 +#define SPDIFIN_HPROT_MASK_SFT (0x1 << 8) +#define TDMIN_HPROT_SFT 7 +#define TDMIN_HPROT_MASK 0x1 +#define TDMIN_HPROT_MASK_SFT (0x1 << 7) +#define ETDM_IN6_HPROT_SFT 6 +#define ETDM_IN6_HPROT_MASK 0x1 +#define ETDM_IN6_HPROT_MASK_SFT (0x1 << 6) +#define ETDM_IN5_HPROT_SFT 5 +#define ETDM_IN5_HPROT_MASK 0x1 +#define ETDM_IN5_HPROT_MASK_SFT (0x1 << 5) +#define ETDM_IN4_HPROT_SFT 4 +#define ETDM_IN4_HPROT_MASK 0x1 +#define ETDM_IN4_HPROT_MASK_SFT (0x1 << 4) +#define ETDM_IN3_HPROT_SFT 3 +#define ETDM_IN3_HPROT_MASK 0x1 +#define ETDM_IN3_HPROT_MASK_SFT (0x1 << 3) +#define ETDM_IN2_HPROT_SFT 2 +#define ETDM_IN2_HPROT_MASK 0x1 +#define ETDM_IN2_HPROT_MASK_SFT (0x1 << 2) +#define ETDM_IN1_HPROT_SFT 1 +#define ETDM_IN1_HPROT_MASK 0x1 +#define ETDM_IN1_HPROT_MASK_SFT (0x1 << 1) +#define ETDM_IN0_HPROT_SFT 0 +#define ETDM_IN0_HPROT_MASK 0x1 +#define ETDM_IN0_HPROT_MASK_SFT (0x1 << 0) + +/* AFE_SE_DOMAIN_SIDEBAND0 */ +#define DL7_HDOMAIN_SFT 28 +#define DL7_HDOMAIN_MASK 0xf +#define DL7_HDOMAIN_MASK_SFT (0xf << 28) +#define DL6_HDOMAIN_SFT 24 +#define DL6_HDOMAIN_MASK 0xf +#define DL6_HDOMAIN_MASK_SFT (0xf << 24) +#define DL5_HDOMAIN_SFT 20 +#define DL5_HDOMAIN_MASK 0xf +#define DL5_HDOMAIN_MASK_SFT (0xf << 20) +#define DL4_HDOMAIN_SFT 16 +#define DL4_HDOMAIN_MASK 0xf +#define DL4_HDOMAIN_MASK_SFT (0xf << 16) +#define DL3_HDOMAIN_SFT 12 +#define DL3_HDOMAIN_MASK 0xf +#define DL3_HDOMAIN_MASK_SFT (0xf << 12) +#define DL2_HDOMAIN_SFT 8 +#define DL2_HDOMAIN_MASK 0xf +#define DL2_HDOMAIN_MASK_SFT (0xf << 8) +#define DL1_HDOMAIN_SFT 4 +#define DL1_HDOMAIN_MASK 0xf +#define DL1_HDOMAIN_MASK_SFT (0xf << 4) +#define DL0_HDOMAIN_SFT 0 +#define DL0_HDOMAIN_MASK 0xf +#define DL0_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND1 */ +#define DL_48CH_HDOMAIN_SFT 24 +#define DL_48CH_HDOMAIN_MASK 0xf +#define DL_48CH_HDOMAIN_MASK_SFT (0xf << 24) +#define DL_24CH_HDOMAIN_SFT 20 +#define DL_24CH_HDOMAIN_MASK 0xf +#define DL_24CH_HDOMAIN_MASK_SFT (0xf << 20) +#define DL_4CH_HDOMAIN_SFT 16 +#define DL_4CH_HDOMAIN_MASK 0xf +#define DL_4CH_HDOMAIN_MASK_SFT (0xf << 16) +#define HDMI_HDOMAIN_SFT 12 +#define HDMI_HDOMAIN_MASK 0xf +#define HDMI_HDOMAIN_MASK_SFT (0xf << 12) +#define SPDIF2_OUT_HDOMAIN_SFT 8 +#define SPDIF2_OUT_HDOMAIN_MASK 0xf +#define SPDIF2_OUT_HDOMAIN_MASK_SFT (0xf << 8) +#define SPDIF_OUT_HDOMAIN_SFT 4 +#define SPDIF_OUT_HDOMAIN_MASK 0xf +#define SPDIF_OUT_HDOMAIN_MASK_SFT (0xf << 4) +#define DL8_HDOMAIN_SFT 0 +#define DL8_HDOMAIN_MASK 0xf +#define DL8_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND2 */ +#define DL30_HDOMAIN_SFT 28 +#define DL30_HDOMAIN_MASK 0xf +#define DL30_HDOMAIN_MASK_SFT (0xf << 28) +#define DL29_HDOMAIN_SFT 24 +#define DL29_HDOMAIN_MASK 0xf +#define DL29_HDOMAIN_MASK_SFT (0xf << 24) +#define DL28_HDOMAIN_SFT 20 +#define DL28_HDOMAIN_MASK 0xf +#define DL28_HDOMAIN_MASK_SFT (0xf << 20) +#define DL27_HDOMAIN_SFT 16 +#define DL27_HDOMAIN_MASK 0xf +#define DL27_HDOMAIN_MASK_SFT (0xf << 16) +#define DL26_HDOMAIN_SFT 12 +#define DL26_HDOMAIN_MASK 0xf +#define DL26_HDOMAIN_MASK_SFT (0xf << 12) +#define DL25_HDOMAIN_SFT 8 +#define DL25_HDOMAIN_MASK 0xf +#define DL25_HDOMAIN_MASK_SFT (0xf << 8) +#define DL24_HDOMAIN_SFT 4 +#define DL24_HDOMAIN_MASK 0xf +#define DL24_HDOMAIN_MASK_SFT (0xf << 4) +#define DL23_HDOMAIN_SFT 0 +#define DL23_HDOMAIN_MASK 0xf +#define DL23_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND3 */ +#define DL38_HDOMAIN_SFT 28 +#define DL38_HDOMAIN_MASK 0xf +#define DL38_HDOMAIN_MASK_SFT (0xf << 28) +#define DL37_HDOMAIN_SFT 24 +#define DL37_HDOMAIN_MASK 0xf +#define DL37_HDOMAIN_MASK_SFT (0xf << 24) +#define DL36_HDOMAIN_SFT 20 +#define DL36_HDOMAIN_MASK 0xf +#define DL36_HDOMAIN_MASK_SFT (0xf << 20) +#define DL35_HDOMAIN_SFT 16 +#define DL35_HDOMAIN_MASK 0xf +#define DL35_HDOMAIN_MASK_SFT (0xf << 16) +#define DL34_HDOMAIN_SFT 12 +#define DL34_HDOMAIN_MASK 0xf +#define DL34_HDOMAIN_MASK_SFT (0xf << 12) +#define DL33_HDOMAIN_SFT 8 +#define DL33_HDOMAIN_MASK 0xf +#define DL33_HDOMAIN_MASK_SFT (0xf << 8) +#define DL32_HDOMAIN_SFT 4 +#define DL32_HDOMAIN_MASK 0xf +#define DL32_HDOMAIN_MASK_SFT (0xf << 4) +#define DL31_HDOMAIN_SFT 0 +#define DL31_HDOMAIN_MASK 0xf +#define DL31_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND4 */ +#define DL46_HDOMAIN_SFT 28 +#define DL46_HDOMAIN_MASK 0xf +#define DL46_HDOMAIN_MASK_SFT (0xf << 28) +#define DL45_HDOMAIN_SFT 24 +#define DL45_HDOMAIN_MASK 0xf +#define DL45_HDOMAIN_MASK_SFT (0xf << 24) +#define DL44_HDOMAIN_SFT 20 +#define DL44_HDOMAIN_MASK 0xf +#define DL44_HDOMAIN_MASK_SFT (0xf << 20) +#define DL43_HDOMAIN_SFT 16 +#define DL43_HDOMAIN_MASK 0xf +#define DL43_HDOMAIN_MASK_SFT (0xf << 16) +#define DL42_HDOMAIN_SFT 12 +#define DL42_HDOMAIN_MASK 0xf +#define DL42_HDOMAIN_MASK_SFT (0xf << 12) +#define DL41_HDOMAIN_SFT 8 +#define DL41_HDOMAIN_MASK 0xf +#define DL41_HDOMAIN_MASK_SFT (0xf << 8) +#define DL40_HDOMAIN_SFT 4 +#define DL40_HDOMAIN_MASK 0xf +#define DL40_HDOMAIN_MASK_SFT (0xf << 4) +#define DL39_HDOMAIN_SFT 0 +#define DL39_HDOMAIN_MASK 0xf +#define DL39_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND5 */ +#define VUL7_HDOMAIN_SFT 28 +#define VUL7_HDOMAIN_MASK 0xf +#define VUL7_HDOMAIN_MASK_SFT (0xf << 28) +#define VUL6_HDOMAIN_SFT 24 +#define VUL6_HDOMAIN_MASK 0xf +#define VUL6_HDOMAIN_MASK_SFT (0xf << 24) +#define VUL5_HDOMAIN_SFT 20 +#define VUL5_HDOMAIN_MASK 0xf +#define VUL5_HDOMAIN_MASK_SFT (0xf << 20) +#define VUL4_HDOMAIN_SFT 16 +#define VUL4_HDOMAIN_MASK 0xf +#define VUL4_HDOMAIN_MASK_SFT (0xf << 16) +#define VUL3_HDOMAIN_SFT 12 +#define VUL3_HDOMAIN_MASK 0xf +#define VUL3_HDOMAIN_MASK_SFT (0xf << 12) +#define VUL2_HDOMAIN_SFT 8 +#define VUL2_HDOMAIN_MASK 0xf +#define VUL2_HDOMAIN_MASK_SFT (0xf << 8) +#define VUL1_HDOMAIN_SFT 4 +#define VUL1_HDOMAIN_MASK 0xf +#define VUL1_HDOMAIN_MASK_SFT (0xf << 4) +#define VUL0_HDOMAIN_SFT 0 +#define VUL0_HDOMAIN_MASK 0xf +#define VUL0_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND6 */ +#define VU25_HDOMAIN_SFT 28 +#define VU25_HDOMAIN_MASK 0xf +#define VU25_HDOMAIN_MASK_SFT (0xf << 28) +#define VUL24_HDOMAIN_SFT 24 +#define VUL24_HDOMAIN_MASK 0xf +#define VUL24_HDOMAIN_MASK_SFT (0xf << 24) +#define VUL_CM2_HDOMAIN_SFT 20 +#define VUL_CM2_HDOMAIN_MASK 0xf +#define VUL_CM2_HDOMAIN_MASK_SFT (0xf << 20) +#define VUL_CM1_HDOMAIN_SFT 16 +#define VUL_CM1_HDOMAIN_MASK 0xf +#define VUL_CM1_HDOMAIN_MASK_SFT (0xf << 16) +#define VUL_CM0_HDOMAIN_SFT 12 +#define VUL_CM0_HDOMAIN_MASK 0xf +#define VUL_CM0_HDOMAIN_MASK_SFT (0xf << 12) +#define VUL10_HDOMAIN_SFT 8 +#define VUL10_HDOMAIN_MASK 0xf +#define VUL10_HDOMAIN_MASK_SFT (0xf << 8) +#define VUL9_HDOMAIN_SFT 4 +#define VUL9_HDOMAIN_MASK 0xf +#define VUL9_HDOMAIN_MASK_SFT (0xf << 4) +#define VUL8_HDOMAIN_SFT 0 +#define VUL8_HDOMAIN_MASK 0xf +#define VUL8_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND7 */ +#define VUL33_HDOMAIN_SFT 28 +#define VUL33_HDOMAIN_MASK 0xf +#define VUL33_HDOMAIN_MASK_SFT (0xf << 28) +#define VUL32_HDOMAIN_SFT 24 +#define VUL32_HDOMAIN_MASK 0xf +#define VUL32_HDOMAIN_MASK_SFT (0xf << 24) +#define VUL31_HDOMAIN_SFT 20 +#define VUL31_HDOMAIN_MASK 0xf +#define VUL31_HDOMAIN_MASK_SFT (0xf << 20) +#define VUL30_HDOMAIN_SFT 16 +#define VUL30_HDOMAIN_MASK 0xf +#define VUL30_HDOMAIN_MASK_SFT (0xf << 16) +#define VUL29_HDOMAIN_SFT 12 +#define VUL29_HDOMAIN_MASK 0xf +#define VUL29_HDOMAIN_MASK_SFT (0xf << 12) +#define VUL28_HDOMAIN_SFT 8 +#define VUL28_HDOMAIN_MASK 0xf +#define VUL28_HDOMAIN_MASK_SFT (0xf << 8) +#define VUL27_HDOMAIN_SFT 4 +#define VUL27_HDOMAIN_MASK 0xf +#define VUL27_HDOMAIN_MASK_SFT (0xf << 4) +#define VUL26_HDOMAIN_SFT 0 +#define VUL26_HDOMAIN_MASK 0xf +#define VUL26_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND8 */ +#define ETDM_IN2_HDOMAIN_SFT 28 +#define ETDM_IN2_HDOMAIN_MASK 0xf +#define ETDM_IN2_HDOMAIN_MASK_SFT (0xf << 28) +#define ETDM_IN1_HDOMAIN_SFT 24 +#define ETDM_IN1_HDOMAIN_MASK 0xf +#define ETDM_IN1_HDOMAIN_MASK_SFT (0xf << 24) +#define ETDM_IN0_HDOMAIN_SFT 20 +#define ETDM_IN0_HDOMAIN_MASK 0xf +#define ETDM_IN0_HDOMAIN_MASK_SFT (0xf << 20) +#define VUL38_HDOMAIN_SFT 16 +#define VUL38_HDOMAIN_MASK 0xf +#define VUL38_HDOMAIN_MASK_SFT (0xf << 16) +#define VUL37_HDOMAIN_SFT 12 +#define VUL37_HDOMAIN_MASK 0xf +#define VUL37_HDOMAIN_MASK_SFT (0xf << 12) +#define VUL36_HDOMAIN_SFT 8 +#define VUL36_HDOMAIN_MASK 0xf +#define VUL36_HDOMAIN_MASK_SFT (0xf << 8) +#define VUL35_HDOMAIN_SFT 4 +#define VUL35_HDOMAIN_MASK 0xf +#define VUL35_HDOMAIN_MASK_SFT (0xf << 4) +#define VUL34_HDOMAIN_SFT 0 +#define VUL34_HDOMAIN_MASK 0xf +#define VUL34_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_SE_DOMAIN_SIDEBAND9 */ +#define MPHONE_EARC_HDOMAIN_SFT 28 +#define MPHONE_EARC_HDOMAIN_MASK 0xf +#define MPHONE_EARC_HDOMAIN_MASK_SFT (0xf << 28) +#define MPHONE_SPDIF_HDOMAIN_SFT 24 +#define MPHONE_SPDIF_HDOMAIN_MASK 0xf +#define MPHONE_SPDIF_HDOMAIN_MASK_SFT (0xf << 24) +#define SPDIFIN_HDOMAIN_SFT 20 +#define SPDIFIN_HDOMAIN_MASK 0xf +#define SPDIFIN_HDOMAIN_MASK_SFT (0xf << 20) +#define TDMIN_HDOMAIN_SFT 16 +#define TDMIN_HDOMAIN_MASK 0xf +#define TDMIN_HDOMAIN_MASK_SFT (0xf << 16) +#define ETDM_IN6_HDOMAIN_SFT 12 +#define ETDM_IN6_HDOMAIN_MASK 0xf +#define ETDM_IN6_HDOMAIN_MASK_SFT (0xf << 12) +#define ETDM_IN5_HDOMAIN_SFT 8 +#define ETDM_IN5_HDOMAIN_MASK 0xf +#define ETDM_IN5_HDOMAIN_MASK_SFT (0xf << 8) +#define ETDM_IN4_HDOMAIN_SFT 4 +#define ETDM_IN4_HDOMAIN_MASK 0xf +#define ETDM_IN4_HDOMAIN_MASK_SFT (0xf << 4) +#define ETDM_IN3_HDOMAIN_SFT 0 +#define ETDM_IN3_HDOMAIN_MASK 0xf +#define ETDM_IN3_HDOMAIN_MASK_SFT (0xf << 0) + +/* AFE_PROT_SIDEBAND0_MON */ +#define AFE_DOMAIN_SIDEBAN0_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN0_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN0_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_PROT_SIDEBAND1_MON */ +#define AFE_DOMAIN_SIDEBAN1_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN1_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN1_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_PROT_SIDEBAND2_MON */ +#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_PROT_SIDEBAND3_MON */ +#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND0_MON */ +#define AFE_DOMAIN_SIDEBAN0_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN0_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN0_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND1_MON */ +#define AFE_DOMAIN_SIDEBAN1_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN1_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN1_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND2_MON */ +#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND3_MON */ +#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND4_MON */ +#define AFE_DOMAIN_SIDEBAN0_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN0_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN0_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND5_MON */ +#define AFE_DOMAIN_SIDEBAN1_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN1_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN1_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND6_MON */ +#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND7_MON */ +#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND8_MON */ +#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_DOMAIN_SIDEBAND9_MON */ +#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0 +#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff +#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_SECURE_CONN0 */ +#define AFE_SPDIFIN_LPBK_CON_MASK_S_SFT 26 +#define AFE_SPDIFIN_LPBK_CON_MASK_S_MASK 0x3 +#define AFE_SPDIFIN_LPBK_CON_MASK_S_MASK_SFT (0x3 << 26) +#define AFE_ADDA_DMIC1_SRC_CON0_MASK_S_SFT 25 +#define AFE_ADDA_DMIC1_SRC_CON0_MASK_S_MASK 0x1 +#define AFE_ADDA_DMIC1_SRC_CON0_MASK_S_MASK_SFT (0x1 << 25) +#define AFE_ADDA_DMIC0_SRC_CON0_MASK_S_SFT 24 +#define AFE_ADDA_DMIC0_SRC_CON0_MASK_S_MASK 0x1 +#define AFE_ADDA_DMIC0_SRC_CON0_MASK_S_MASK_SFT (0x1 << 24) +#define AFE_ADDA_UL3_SRC_CON0_MASK_S_SFT 23 +#define AFE_ADDA_UL3_SRC_CON0_MASK_S_MASK 0x1 +#define AFE_ADDA_UL3_SRC_CON0_MASK_S_MASK_SFT (0x1 << 23) +#define AFE_ADDA_UL2_SRC_CON0_MASK_S_SFT 22 +#define AFE_ADDA_UL2_SRC_CON0_MASK_S_MASK 0x1 +#define AFE_ADDA_UL2_SRC_CON0_MASK_S_MASK_SFT (0x1 << 22) +#define AFE_ADDA_UL1_SRC_CON0_MASK_S_SFT 21 +#define AFE_ADDA_UL1_SRC_CON0_MASK_S_MASK 0x1 +#define AFE_ADDA_UL1_SRC_CON0_MASK_S_MASK_SFT (0x1 << 21) +#define AFE_ADDA_UL0_SRC_CON0_MASK_S_SFT 20 +#define AFE_ADDA_UL0_SRC_CON0_MASK_S_MASK 0x1 +#define AFE_ADDA_UL0_SRC_CON0_MASK_S_MASK_SFT (0x1 << 20) +#define AFE_MRKAIF1_CFG0_MASK_S_SFT 19 +#define AFE_MRKAIF1_CFG0_MASK_S_MASK 0x1 +#define AFE_MRKAIF1_CFG0_MASK_S_MASK_SFT (0x1 << 19) +#define AFE_MRKAIF0_CFG0_MASK_S_SFT 18 +#define AFE_MRKAIF0_CFG0_MASK_S_MASK 0x1 +#define AFE_MRKAIF0_CFG0_MASK_S_MASK_SFT (0x1 << 18) +#define AFE_TDMIN_CON1_MASK_S_SFT 17 +#define AFE_TDMIN_CON1_MASK_S_MASK 0x1 +#define AFE_TDMIN_CON1_MASK_S_MASK_SFT (0x1 << 17) +#define AFE_TDM_CON2_MASK_S_SFT 16 +#define AFE_TDM_CON2_MASK_S_MASK 0x1 +#define AFE_TDM_CON2_MASK_S_MASK_SFT (0x1 << 16) +#define AFE_DAIBT_CON_MASK_S_SFT 14 +#define AFE_DAIBT_CON_MASK_S_MASK 0x3 +#define AFE_DAIBT_CON_MASK_S_MASK_SFT (0x3 << 14) +#define AFE_MRGIF_CON_MASK_S_SFT 12 +#define AFE_MRGIF_CON_MASK_S_MASK 0x3 +#define AFE_MRGIF_CON_MASK_S_MASK_SFT (0x3 << 12) +#define AFE_CONNSYS_I2S_CON_MASK_S_SFT 11 +#define AFE_CONNSYS_I2S_CON_MASK_S_MASK 0x1 +#define AFE_CONNSYS_I2S_CON_MASK_S_MASK_SFT (0x1 << 11) +#define AFE_PCM1_INFT_CON0_MASK_S_SFT 6 +#define AFE_PCM1_INFT_CON0_MASK_S_MASK 0x1f +#define AFE_PCM1_INFT_CON0_MASK_S_MASK_SFT (0x1f << 6) +#define AFE_PCM0_INTF_CON1_MASK_S_SFT 0 +#define AFE_PCM0_INTF_CON1_MASK_S_MASK 0x3f +#define AFE_PCM0_INTF_CON1_MASK_S_MASK_SFT (0x3f << 0) + +/* AFE_SECURE_CONN_ETDM0 */ +#define ETDM_0_3_COWORK_CON2_OUT3_DATA_SEL_SFT 28 +#define ETDM_0_3_COWORK_CON2_OUT3_DATA_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_OUT3_DATA_SEL_MASK_SFT (0xf << 28) +#define ETDM_0_3_COWORK_CON2_OUT2_DATA_SEL_SFT 24 +#define ETDM_0_3_COWORK_CON2_OUT2_DATA_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_OUT2_DATA_SEL_MASK_SFT (0xf << 24) +#define ETDM_0_3_COWORK_CON2_IN1_SDATA1_15_SEL_SFT 20 +#define ETDM_0_3_COWORK_CON2_IN1_SDATA1_15_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_IN1_SDATA1_15_SEL_MASK_SFT (0xf << 20) +#define ETDM_0_3_COWORK_CON2_IN1_SDATA0_SEL_SFT 16 +#define ETDM_0_3_COWORK_CON2_IN1_SDATA0_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_IN1_SDATA0_SEL_MASK_SFT (0xf << 16) +#define ETDM_0_3_COWORK_CON2_IN0_SDATA1_15_SEL_SFT 12 +#define ETDM_0_3_COWORK_CON2_IN0_SDATA1_15_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_IN0_SDATA1_15_SEL_MASK_SFT (0xf << 12) +#define ETDM_0_3_COWORK_CON2_IN0_SDATA0_SEL_SFT 8 +#define ETDM_0_3_COWORK_CON2_IN0_SDATA0_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_IN0_SDATA0_SEL_MASK_SFT (0xf << 8) +#define ETDM_0_3_COWORK_CON2_OUT1_DATA_SEL_SFT 4 +#define ETDM_0_3_COWORK_CON2_OUT1_DATA_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_OUT1_DATA_SEL_MASK_SFT (0xf << 4) +#define ETDM_0_3_COWORK_CON2_OUT0_DATA_SEL_SFT 0 +#define ETDM_0_3_COWORK_CON2_OUT0_DATA_SEL_MASK 0xf +#define ETDM_0_3_COWORK_CON2_OUT0_DATA_SEL_MASK_SFT (0xf << 0) + +/* AFE_SECURE_CONN_ETDM1 */ +#define ETDM_4_7_COWORK_CON1_IN4_SDATA1_15_SEL_SFT 28 +#define ETDM_4_7_COWORK_CON1_IN4_SDATA1_15_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_IN4_SDATA1_15_SEL_MASK_SFT (0xf << 28) +#define ETDM_4_7_COWORK_CON1_IN4_SDATA0_SEL_SFT 24 +#define ETDM_4_7_COWORK_CON1_IN4_SDATA0_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_IN4_SDATA0_SEL_MASK_SFT (0xf << 24) +#define ETDM_4_7_COWORK_CON1_OUT5_DATA_SEL_SFT 20 +#define ETDM_4_7_COWORK_CON1_OUT5_DATA_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_OUT5_DATA_SEL_MASK_SFT (0xf << 20) +#define ETDM_4_7_COWORK_CON1_OUT4_DATA_SEL_SFT 16 +#define ETDM_4_7_COWORK_CON1_OUT4_DATA_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_OUT4_DATA_SEL_MASK_SFT (0xf << 16) +#define ETDM_4_7_COWORK_CON1_IN3_SDATA1_15_SEL_SFT 12 +#define ETDM_4_7_COWORK_CON1_IN3_SDATA1_15_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_IN3_SDATA1_15_SEL_MASK_SFT (0xf << 12) +#define ETDM_4_7_COWORK_CON1_IN3_SDATA0_SEL_SFT 8 +#define ETDM_4_7_COWORK_CON1_IN3_SDATA0_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_IN3_SDATA0_SEL_MASK_SFT (0xf << 8) +#define ETDM_4_7_COWORK_CON1_IN2_SDATA1_15_SEL_SFT 4 +#define ETDM_4_7_COWORK_CON1_IN2_SDATA1_15_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_IN2_SDATA1_15_SEL_MASK_SFT (0xf << 4) +#define ETDM_4_7_COWORK_CON1_IN2_SDATA0_SEL_SFT 0 +#define ETDM_4_7_COWORK_CON1_IN2_SDATA0_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON1_IN2_SDATA0_SEL_MASK_SFT (0xf << 0) + +/* AFE_SECURE_CONN_ETDM2 */ +#define ETDM_4_7_COWORK_CON3_IN7_SDATA1_15_SEL_SFT 28 +#define ETDM_4_7_COWORK_CON3_IN7_SDATA1_15_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_IN7_SDATA1_15_SEL_MASK_SFT (0xf << 28) +#define ETDM_4_7_COWORK_CON3_IN7_SDATA0_SEL_SFT 24 +#define ETDM_4_7_COWORK_CON3_IN7_SDATA0_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_IN7_SDATA0_SEL_MASK_SFT (0xf << 24) +#define ETDM_4_7_COWORK_CON3_IN6_SDATA1_15_SEL_SFT 20 +#define ETDM_4_7_COWORK_CON3_IN6_SDATA1_15_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_IN6_SDATA1_15_SEL_MASK_SFT (0xf << 20) +#define ETDM_4_7_COWORK_CON3_IN6_SDATA0_SEL_SFT 16 +#define ETDM_4_7_COWORK_CON3_IN6_SDATA0_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_IN6_SDATA0_SEL_MASK_SFT (0xf << 16) +#define ETDM_4_7_COWORK_CON3_OUT7_DATA_SEL_SFT 12 +#define ETDM_4_7_COWORK_CON3_OUT7_DATA_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_OUT7_DATA_SEL_MASK_SFT (0xf << 12) +#define ETDM_4_7_COWORK_CON3_OUT6_DATA_SEL_SFT 8 +#define ETDM_4_7_COWORK_CON3_OUT6_DATA_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_OUT6_DATA_SEL_MASK_SFT (0xf << 8) +#define ETDM_4_7_COWORK_CON3_IN5_SDATA1_15_SEL_SFT 4 +#define ETDM_4_7_COWORK_CON3_IN5_SDATA1_15_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_IN5_SDATA1_15_SEL_MASK_SFT (0xf << 4) +#define ETDM_4_7_COWORK_CON3_IN5_SDATA0_SEL_SFT 0 +#define ETDM_4_7_COWORK_CON3_IN5_SDATA0_SEL_MASK 0xf +#define ETDM_4_7_COWORK_CON3_IN5_SDATA0_SEL_MASK_SFT (0xf << 0) + +/* AFE_SECURE_SRAM_CON0 */ +#define SRAM_READ_EN15_NS_SFT 31 +#define SRAM_READ_EN15_NS_MASK 0x1 +#define SRAM_READ_EN15_NS_MASK_SFT (0x1 << 31) +#define SRAM_WRITE_EN15_NS_SFT 30 +#define SRAM_WRITE_EN15_NS_MASK 0x1 +#define SRAM_WRITE_EN15_NS_MASK_SFT (0x1 << 30) +#define SRAM_READ_EN14_NS_SFT 29 +#define SRAM_READ_EN14_NS_MASK 0x1 +#define SRAM_READ_EN14_NS_MASK_SFT (0x1 << 29) +#define SRAM_WRITE_EN14_NS_SFT 28 +#define SRAM_WRITE_EN14_NS_MASK 0x1 +#define SRAM_WRITE_EN14_NS_MASK_SFT (0x1 << 28) +#define SRAM_READ_EN13_NS_SFT 27 +#define SRAM_READ_EN13_NS_MASK 0x1 +#define SRAM_READ_EN13_NS_MASK_SFT (0x1 << 27) +#define SRAM_WRITE_EN13_NS_SFT 26 +#define SRAM_WRITE_EN13_NS_MASK 0x1 +#define SRAM_WRITE_EN13_NS_MASK_SFT (0x1 << 26) +#define SRAM_READ_EN12_NS_SFT 25 +#define SRAM_READ_EN12_NS_MASK 0x1 +#define SRAM_READ_EN12_NS_MASK_SFT (0x1 << 25) +#define SRAM_WRITE_EN12_NS_SFT 24 +#define SRAM_WRITE_EN12_NS_MASK 0x1 +#define SRAM_WRITE_EN12_NS_MASK_SFT (0x1 << 24) +#define SRAM_READ_EN11_NS_SFT 23 +#define SRAM_READ_EN11_NS_MASK 0x1 +#define SRAM_READ_EN11_NS_MASK_SFT (0x1 << 23) +#define SRAM_WRITE_EN11_NS_SFT 22 +#define SRAM_WRITE_EN11_NS_MASK 0x1 +#define SRAM_WRITE_EN11_NS_MASK_SFT (0x1 << 22) +#define SRAM_READ_EN10_NS_SFT 21 +#define SRAM_READ_EN10_NS_MASK 0x1 +#define SRAM_READ_EN10_NS_MASK_SFT (0x1 << 21) +#define SRAM_WRITE_EN10_NS_SFT 20 +#define SRAM_WRITE_EN10_NS_MASK 0x1 +#define SRAM_WRITE_EN10_NS_MASK_SFT (0x1 << 20) +#define SRAM_READ_EN9_NS_SFT 19 +#define SRAM_READ_EN9_NS_MASK 0x1 +#define SRAM_READ_EN9_NS_MASK_SFT (0x1 << 19) +#define SRAM_WRITE_EN9_NS_SFT 18 +#define SRAM_WRITE_EN9_NS_MASK 0x1 +#define SRAM_WRITE_EN9_NS_MASK_SFT (0x1 << 18) +#define SRAM_READ_EN8_NS_SFT 17 +#define SRAM_READ_EN8_NS_MASK 0x1 +#define SRAM_READ_EN8_NS_MASK_SFT (0x1 << 17) +#define SRAM_WRITE_EN8_NS_SFT 16 +#define SRAM_WRITE_EN8_NS_MASK 0x1 +#define SRAM_WRITE_EN8_NS_MASK_SFT (0x1 << 16) +#define SRAM_READ_EN7_NS_SFT 15 +#define SRAM_READ_EN7_NS_MASK 0x1 +#define SRAM_READ_EN7_NS_MASK_SFT (0x1 << 15) +#define SRAM_WRITE_EN7_NS_SFT 14 +#define SRAM_WRITE_EN7_NS_MASK 0x1 +#define SRAM_WRITE_EN7_NS_MASK_SFT (0x1 << 14) +#define SRAM_READ_EN6_NS_SFT 13 +#define SRAM_READ_EN6_NS_MASK 0x1 +#define SRAM_READ_EN6_NS_MASK_SFT (0x1 << 13) +#define SRAM_WRITE_EN6_NS_SFT 12 +#define SRAM_WRITE_EN6_NS_MASK 0x1 +#define SRAM_WRITE_EN6_NS_MASK_SFT (0x1 << 12) +#define SRAM_READ_EN5_NS_SFT 11 +#define SRAM_READ_EN5_NS_MASK 0x1 +#define SRAM_READ_EN5_NS_MASK_SFT (0x1 << 11) +#define SRAM_WRITE_EN5_NS_SFT 10 +#define SRAM_WRITE_EN5_NS_MASK 0x1 +#define SRAM_WRITE_EN5_NS_MASK_SFT (0x1 << 10) +#define SRAM_READ_EN4_NS_SFT 9 +#define SRAM_READ_EN4_NS_MASK 0x1 +#define SRAM_READ_EN4_NS_MASK_SFT (0x1 << 9) +#define SRAM_WRITE_EN4_NS_SFT 8 +#define SRAM_WRITE_EN4_NS_MASK 0x1 +#define SRAM_WRITE_EN4_NS_MASK_SFT (0x1 << 8) +#define SRAM_READ_EN3_NS_SFT 7 +#define SRAM_READ_EN3_NS_MASK 0x1 +#define SRAM_READ_EN3_NS_MASK_SFT (0x1 << 7) +#define SRAM_WRITE_EN3_NS_SFT 6 +#define SRAM_WRITE_EN3_NS_MASK 0x1 +#define SRAM_WRITE_EN3_NS_MASK_SFT (0x1 << 6) +#define SRAM_READ_EN2_NS_SFT 5 +#define SRAM_READ_EN2_NS_MASK 0x1 +#define SRAM_READ_EN2_NS_MASK_SFT (0x1 << 5) +#define SRAM_WRITE_EN2_NS_SFT 4 +#define SRAM_WRITE_EN2_NS_MASK 0x1 +#define SRAM_WRITE_EN2_NS_MASK_SFT (0x1 << 4) +#define SRAM_READ_EN1_NS_SFT 3 +#define SRAM_READ_EN1_NS_MASK 0x1 +#define SRAM_READ_EN1_NS_MASK_SFT (0x1 << 3) +#define SRAM_WRITE_EN1_NS_SFT 2 +#define SRAM_WRITE_EN1_NS_MASK 0x1 +#define SRAM_WRITE_EN1_NS_MASK_SFT (0x1 << 2) +#define SRAM_READ_EN0_NS_SFT 1 +#define SRAM_READ_EN0_NS_MASK 0x1 +#define SRAM_READ_EN0_NS_MASK_SFT (0x1 << 1) +#define SRAM_WRITE_EN0_NS_SFT 0 +#define SRAM_WRITE_EN0_NS_MASK 0x1 +#define SRAM_WRITE_EN0_NS_MASK_SFT (0x1 << 0) + +/* AFE_SECURE_SRAM_CON1 */ +#define SRAM_READ_EN15_S_SFT 31 +#define SRAM_READ_EN15_S_MASK 0x1 +#define SRAM_READ_EN15_S_MASK_SFT (0x1 << 31) +#define SRAM_WRITE_EN15_S_SFT 30 +#define SRAM_WRITE_EN15_S_MASK 0x1 +#define SRAM_WRITE_EN15_S_MASK_SFT (0x1 << 30) +#define SRAM_READ_EN14_S_SFT 29 +#define SRAM_READ_EN14_S_MASK 0x1 +#define SRAM_READ_EN14_S_MASK_SFT (0x1 << 29) +#define SRAM_WRITE_EN14_S_SFT 28 +#define SRAM_WRITE_EN14_S_MASK 0x1 +#define SRAM_WRITE_EN14_S_MASK_SFT (0x1 << 28) +#define SRAM_READ_EN13_S_SFT 27 +#define SRAM_READ_EN13_S_MASK 0x1 +#define SRAM_READ_EN13_S_MASK_SFT (0x1 << 27) +#define SRAM_WRITE_EN13_S_SFT 26 +#define SRAM_WRITE_EN13_S_MASK 0x1 +#define SRAM_WRITE_EN13_S_MASK_SFT (0x1 << 26) +#define SRAM_READ_EN12_S_SFT 25 +#define SRAM_READ_EN12_S_MASK 0x1 +#define SRAM_READ_EN12_S_MASK_SFT (0x1 << 25) +#define SRAM_WRITE_EN12_S_SFT 24 +#define SRAM_WRITE_EN12_S_MASK 0x1 +#define SRAM_WRITE_EN12_S_MASK_SFT (0x1 << 24) +#define SRAM_READ_EN11_S_SFT 23 +#define SRAM_READ_EN11_S_MASK 0x1 +#define SRAM_READ_EN11_S_MASK_SFT (0x1 << 23) +#define SRAM_WRITE_EN11_S_SFT 22 +#define SRAM_WRITE_EN11_S_MASK 0x1 +#define SRAM_WRITE_EN11_S_MASK_SFT (0x1 << 22) +#define SRAM_READ_EN10_S_SFT 21 +#define SRAM_READ_EN10_S_MASK 0x1 +#define SRAM_READ_EN10_S_MASK_SFT (0x1 << 21) +#define SRAM_WRITE_EN10_S_SFT 20 +#define SRAM_WRITE_EN10_S_MASK 0x1 +#define SRAM_WRITE_EN10_S_MASK_SFT (0x1 << 20) +#define SRAM_READ_EN9_S_SFT 19 +#define SRAM_READ_EN9_S_MASK 0x1 +#define SRAM_READ_EN9_S_MASK_SFT (0x1 << 19) +#define SRAM_WRITE_EN9_S_SFT 18 +#define SRAM_WRITE_EN9_S_MASK 0x1 +#define SRAM_WRITE_EN9_S_MASK_SFT (0x1 << 18) +#define SRAM_READ_EN8_S_SFT 17 +#define SRAM_READ_EN8_S_MASK 0x1 +#define SRAM_READ_EN8_S_MASK_SFT (0x1 << 17) +#define SRAM_WRITE_EN8_S_SFT 16 +#define SRAM_WRITE_EN8_S_MASK 0x1 +#define SRAM_WRITE_EN8_S_MASK_SFT (0x1 << 16) +#define SRAM_READ_EN7_S_SFT 15 +#define SRAM_READ_EN7_S_MASK 0x1 +#define SRAM_READ_EN7_S_MASK_SFT (0x1 << 15) +#define SRAM_WRITE_EN7_S_SFT 14 +#define SRAM_WRITE_EN7_S_MASK 0x1 +#define SRAM_WRITE_EN7_S_MASK_SFT (0x1 << 14) +#define SRAM_READ_EN6_S_SFT 13 +#define SRAM_READ_EN6_S_MASK 0x1 +#define SRAM_READ_EN6_S_MASK_SFT (0x1 << 13) +#define SRAM_WRITE_EN6_S_SFT 12 +#define SRAM_WRITE_EN6_S_MASK 0x1 +#define SRAM_WRITE_EN6_S_MASK_SFT (0x1 << 12) +#define SRAM_READ_EN5_S_SFT 11 +#define SRAM_READ_EN5_S_MASK 0x1 +#define SRAM_READ_EN5_S_MASK_SFT (0x1 << 11) +#define SRAM_WRITE_EN5_S_SFT 10 +#define SRAM_WRITE_EN5_S_MASK 0x1 +#define SRAM_WRITE_EN5_S_MASK_SFT (0x1 << 10) +#define SRAM_READ_EN4_S_SFT 9 +#define SRAM_READ_EN4_S_MASK 0x1 +#define SRAM_READ_EN4_S_MASK_SFT (0x1 << 9) +#define SRAM_WRITE_EN4_S_SFT 8 +#define SRAM_WRITE_EN4_S_MASK 0x1 +#define SRAM_WRITE_EN4_S_MASK_SFT (0x1 << 8) +#define SRAM_READ_EN3_S_SFT 7 +#define SRAM_READ_EN3_S_MASK 0x1 +#define SRAM_READ_EN3_S_MASK_SFT (0x1 << 7) +#define SRAM_WRITE_EN3_S_SFT 6 +#define SRAM_WRITE_EN3_S_MASK 0x1 +#define SRAM_WRITE_EN3_S_MASK_SFT (0x1 << 6) +#define SRAM_READ_EN2_S_SFT 5 +#define SRAM_READ_EN2_S_MASK 0x1 +#define SRAM_READ_EN2_S_MASK_SFT (0x1 << 5) +#define SRAM_WRITE_EN2_S_SFT 4 +#define SRAM_WRITE_EN2_S_MASK 0x1 +#define SRAM_WRITE_EN2_S_MASK_SFT (0x1 << 4) +#define SRAM_READ_EN1_S_SFT 3 +#define SRAM_READ_EN1_S_MASK 0x1 +#define SRAM_READ_EN1_S_MASK_SFT (0x1 << 3) +#define SRAM_WRITE_EN1_S_SFT 2 +#define SRAM_WRITE_EN1_S_MASK 0x1 +#define SRAM_WRITE_EN1_S_MASK_SFT (0x1 << 2) +#define SRAM_READ_EN0_S_SFT 1 +#define SRAM_READ_EN0_S_MASK 0x1 +#define SRAM_READ_EN0_S_MASK_SFT (0x1 << 1) +#define SRAM_WRITE_EN0_S_SFT 0 +#define SRAM_WRITE_EN0_S_MASK 0x1 +#define SRAM_WRITE_EN0_S_MASK_SFT (0x1 << 0) + +/* AFE_SE_CONN_INPUT_MASK0 */ +#define SECURE_INTRCONN_I0_I31_S_SFT 0 +#define SECURE_INTRCONN_I0_I31_S_MASK 0xffffffff +#define SECURE_INTRCONN_I0_I31_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_INPUT_MASK1 */ +#define SECURE_INTRCONN_I32_I63_S_SFT 0 +#define SECURE_INTRCONN_I32_I63_S_MASK 0xffffffff +#define SECURE_INTRCONN_I32_I63_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_INPUT_MASK2 */ +#define SECURE_INTRCONN_I64_I95_S_SFT 0 +#define SECURE_INTRCONN_I64_I95_S_MASK 0xffffffff +#define SECURE_INTRCONN_I64_I95_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_INPUT_MASK3 */ +#define SECURE_INTRCONN_I96_I127_S_SFT 0 +#define SECURE_INTRCONN_I96_I127_S_MASK 0xffffffff +#define SECURE_INTRCONN_I96_I127_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_INPUT_MASK4 */ +#define SECURE_INTRCONN_I128_I159_S_SFT 0 +#define SECURE_INTRCONN_I128_I159_S_MASK 0xffffffff +#define SECURE_INTRCONN_I128_I159_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_INPUT_MASK5 */ +#define SECURE_INTRCONN_I160_I191_S_SFT 0 +#define SECURE_INTRCONN_I160_I191_S_MASK 0xffffffff +#define SECURE_INTRCONN_I160_I191_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_INPUT_MASK6 */ +#define SECURE_INTRCONN_I192_I223_S_SFT 0 +#define SECURE_INTRCONN_I192_I223_S_MASK 0xffffffff +#define SECURE_INTRCONN_I192_I223_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_INPUT_MASK7 */ +#define SECURE_INTRCONN_I224_I256_S_SFT 0 +#define SECURE_INTRCONN_I224_I256_S_MASK 0xffffffff +#define SECURE_INTRCONN_I224_I256_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK0 */ +#define NORMAL_INTRCONN_I0_I31_S_SFT 0 +#define NORMAL_INTRCONN_I0_I31_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I0_I31_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK1 */ +#define NORMAL_INTRCONN_I32_I63_S_SFT 0 +#define NORMAL_INTRCONN_I32_I63_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I32_I63_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK2 */ +#define NORMAL_INTRCONN_I64_I95_S_SFT 0 +#define NORMAL_INTRCONN_I64_I95_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I64_I95_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK3 */ +#define NORMAL_INTRCONN_I96_I127_S_SFT 0 +#define NORMAL_INTRCONN_I96_I127_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I96_I127_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK4 */ +#define NORMAL_INTRCONN_I128_I159_S_SFT 0 +#define NORMAL_INTRCONN_I128_I159_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I128_I159_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK5 */ +#define NORMAL_INTRCONN_I160_I191_S_SFT 0 +#define NORMAL_INTRCONN_I160_I191_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I160_I191_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK6 */ +#define NORMAL_INTRCONN_I192_I223_S_SFT 0 +#define NORMAL_INTRCONN_I192_I223_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I192_I223_S_MASK_SFT (0xffffffff << 0) + +/* AFE_NON_SE_CONN_INPUT_MASK7 */ +#define NORMAL_INTRCONN_I224_I256_S_SFT 0 +#define NORMAL_INTRCONN_I224_I256_S_MASK 0xffffffff +#define NORMAL_INTRCONN_I224_I256_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL0 */ +#define SECURE_INTRCONN_O0_O31_S_SFT 0 +#define SECURE_INTRCONN_O0_O31_S_MASK 0xffffffff +#define SECURE_INTRCONN_O0_O31_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL1 */ +#define SECURE_INTRCONN_O32_O63_S_SFT 0 +#define SECURE_INTRCONN_O32_O63_S_MASK 0xffffffff +#define SECURE_INTRCONN_O32_O63_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL2 */ +#define SECURE_INTRCONN_O64_O95_S_SFT 0 +#define SECURE_INTRCONN_O64_O95_S_MASK 0xffffffff +#define SECURE_INTRCONN_O64_O95_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL3 */ +#define SECURE_INTRCONN_O96_O127_S_SFT 0 +#define SECURE_INTRCONN_O96_O127_S_MASK 0xffffffff +#define SECURE_INTRCONN_O96_O127_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL4 */ +#define SECURE_INTRCONN_O128_O159_S_SFT 0 +#define SECURE_INTRCONN_O128_O159_S_MASK 0xffffffff +#define SECURE_INTRCONN_O128_O159_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL5 */ +#define SECURE_INTRCONN_O160_O191_S_SFT 0 +#define SECURE_INTRCONN_O160_O191_S_MASK 0xffffffff +#define SECURE_INTRCONN_O160_O191_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL6 */ +#define SECURE_INTRCONN_O192_O223_S_SFT 0 +#define SECURE_INTRCONN_O192_O223_S_MASK 0xffffffff +#define SECURE_INTRCONN_O192_O223_S_MASK_SFT (0xffffffff << 0) + +/* AFE_SE_CONN_OUTPUT_SEL7 */ +#define SECURE_INTRCONN_O224_O256_S_SFT 0 +#define SECURE_INTRCONN_O224_O256_S_MASK 0xffffffff +#define SECURE_INTRCONN_O224_O256_S_MASK_SFT (0xffffffff << 0) + +/* AFE_PCM0_INTF_CON1_MASK_MON */ +#define AFE_PCM0_INTF_CON1_MASK_MON_SFT 0 +#define AFE_PCM0_INTF_CON1_MASK_MON_MASK 0xffffffff +#define AFE_PCM0_INTF_CON1_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_PCM0_INTF_CON0_MASK_MON */ +#define AFE_PCM0_INTF_CON0_MASK_MON_SFT 0 +#define AFE_PCM0_INTF_CON0_MASK_MON_MASK 0xffffffff +#define AFE_PCM0_INTF_CON0_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_CONNSYS_I2S_CON_MASK_MON */ +#define AFE_CONNSYS_I2S_CON_MASK_MON_SFT 0 +#define AFE_CONNSYS_I2S_CON_MASK_MON_MASK 0xffffffff +#define AFE_CONNSYS_I2S_CON_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_TDM_CON2_MASK_MON */ +#define AFE_TDM_CON2_MASK_MON_SFT 0 +#define AFE_TDM_CON2_MASK_MON_MASK 0xffffffff +#define AFE_TDM_CON2_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_MTKAIF0_CFG0_MASK_MON */ +#define AFE_MTKAIF0_CFG0_MASK_MON_SFT 0 +#define AFE_MTKAIF0_CFG0_MASK_MON_MASK 0xffffffff +#define AFE_MTKAIF0_CFG0_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_MTKAIF1_CFG0_MASK_MON */ +#define AFE_MTKAIF1_CFG0_MASK_MON_SFT 0 +#define AFE_MTKAIF1_CFG0_MASK_MON_MASK 0xffffffff +#define AFE_MTKAIF1_CFG0_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL0_SRC_CON0_MASK_MON */ +#define AFE_ADDA_UL0_SRC_CON0_MASK_MON_SFT 0 +#define AFE_ADDA_UL0_SRC_CON0_MASK_MON_MASK 0xffffffff +#define AFE_ADDA_UL0_SRC_CON0_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL1_SRC_CON0_MASK_MON */ +#define AFE_ADDA_UL1_SRC_CON0_MASK_MON_SFT 0 +#define AFE_ADDA_UL1_SRC_CON0_MASK_MON_MASK 0xffffffff +#define AFE_ADDA_UL1_SRC_CON0_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_ADDA_UL2_SRC_CON0_MASK_MON */ +#define AFE_ADDA_UL2_SRC_CON0_MASK_MON_SFT 0 +#define AFE_ADDA_UL2_SRC_CON0_MASK_MON_MASK 0xffffffff +#define AFE_ADDA_UL2_SRC_CON0_MASK_MON_MASK_SFT (0xffffffff << 0) + +/* AFE_ASRC_NEW_CON0 */ +#define ONE_HEART_SFT 31 +#define ONE_HEART_MASK 0x1 +#define ONE_HEART_MASK_SFT (0x1 << 31) +#define CHSET0_OFS_ONE_HEART_DISABLE_SFT 30 +#define CHSET0_OFS_ONE_HEART_DISABLE_MASK 0x1 +#define CHSET0_OFS_ONE_HEART_DISABLE_MASK_SFT (0x1 << 30) +#define USE_SHORT_DELAY_COEFF_SFT 29 +#define USE_SHORT_DELAY_COEFF_MASK 0x1 +#define USE_SHORT_DELAY_COEFF_MASK_SFT (0x1 << 29) +#define CHSET0_O16BIT_SFT 19 +#define CHSET0_O16BIT_MASK 0x1 +#define CHSET0_O16BIT_MASK_SFT (0x1 << 19) +#define CHSET0_CLR_IIR_HISTORY_SFT 17 +#define CHSET0_CLR_IIR_HISTORY_MASK 0x1 +#define CHSET0_CLR_IIR_HISTORY_MASK_SFT (0x1 << 17) +#define CHSET0_IS_MONO_SFT 16 +#define CHSET0_IS_MONO_MASK 0x1 +#define CHSET0_IS_MONO_MASK_SFT (0x1 << 16) +#define CHSET0_OFS_SEL_SFT 14 +#define CHSET0_OFS_SEL_MASK 0x3 +#define CHSET0_OFS_SEL_MASK_SFT (0x3 << 14) +#define CHSET0_IFS_SEL_SFT 12 +#define CHSET0_IFS_SEL_MASK 0x3 +#define CHSET0_IFS_SEL_MASK_SFT (0x3 << 12) +#define CHSET0_IIR_EN_SFT 11 +#define CHSET0_IIR_EN_MASK 0x1 +#define CHSET0_IIR_EN_MASK_SFT (0x1 << 11) +#define CHSET0_IIR_STAGE_SFT 8 +#define CHSET0_IIR_STAGE_MASK 0x7 +#define CHSET0_IIR_STAGE_MASK_SFT (0x7 << 8) +#define ASM_ON_MOD_SFT 7 +#define ASM_ON_MOD_MASK 0x1 +#define ASM_ON_MOD_MASK_SFT (0x1 << 7) +#define CHSET_STR_CLR_SFT 4 +#define CHSET_STR_CLR_MASK 0x1 +#define CHSET_STR_CLR_MASK_SFT (0x1 << 4) +#define CHSET_ON_SFT 2 +#define CHSET_ON_MASK 0x1 +#define CHSET_ON_MASK_SFT (0x1 << 2) +#define COEFF_SRAM_CTRL_SFT 1 +#define COEFF_SRAM_CTRL_MASK 0x1 +#define COEFF_SRAM_CTRL_MASK_SFT (0x1 << 1) +#define ASM_ON_SFT 0 +#define ASM_ON_MASK 0x1 +#define ASM_ON_MASK_SFT (0x1 << 0) + +/* AFE_ASRC_NEW_CON1 */ +#define ASM_FREQ_0_SFT 0 +#define ASM_FREQ_0_MASK 0xffffff +#define ASM_FREQ_0_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON2 */ +#define ASM_FREQ_1_SFT 0 +#define ASM_FREQ_1_MASK 0xffffff +#define ASM_FREQ_1_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON3 */ +#define ASM_FREQ_2_SFT 0 +#define ASM_FREQ_2_MASK 0xffffff +#define ASM_FREQ_2_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON4 */ +#define ASM_FREQ_3_SFT 0 +#define ASM_FREQ_3_MASK 0xffffff +#define ASM_FREQ_3_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON5 */ +#define OUT_EN_SEL_DOMAIN_SFT 29 +#define OUT_EN_SEL_DOMAIN_MASK 0x7 +#define OUT_EN_SEL_DOMAIN_MASK_SFT (0x7 << 29) +#define OUT_EN_SEL_FS_SFT 24 +#define OUT_EN_SEL_FS_MASK 0x1f +#define OUT_EN_SEL_FS_MASK_SFT (0x1f << 24) +#define IN_EN_SEL_DOMAIN_SFT 21 +#define IN_EN_SEL_DOMAIN_MASK 0x7 +#define IN_EN_SEL_DOMAIN_MASK_SFT (0x7 << 21) +#define IN_EN_SEL_FS_SFT 16 +#define IN_EN_SEL_FS_MASK 0x1f +#define IN_EN_SEL_FS_MASK_SFT (0x1f << 16) +#define RESULT_SEL_SFT 8 +#define RESULT_SEL_MASK 0x7 +#define RESULT_SEL_MASK_SFT (0x7 << 8) +#define CALI_CK_SEL_SFT 4 +#define CALI_CK_SEL_MASK 0x7 +#define CALI_CK_SEL_MASK_SFT (0x7 << 4) +#define CALI_LRCK_SEL_SFT 1 +#define CALI_LRCK_SEL_MASK 0x7 +#define CALI_LRCK_SEL_MASK_SFT (0x7 << 1) +#define SOFT_RESET_SFT 0 +#define SOFT_RESET_MASK 0x1 +#define SOFT_RESET_MASK_SFT (0x1 << 0) + +/* AFE_ASRC_NEW_CON6 */ +#define FREQ_CALI_CYCLE_SFT 16 +#define FREQ_CALI_CYCLE_MASK 0xffff +#define FREQ_CALI_CYCLE_MASK_SFT (0xffff << 16) +#define FREQ_CALI_AUTORST_EN_SFT 15 +#define FREQ_CALI_AUTORST_EN_MASK 0x1 +#define FREQ_CALI_AUTORST_EN_MASK_SFT (0x1 << 15) +#define CALI_AUTORST_DETECT_SFT 14 +#define CALI_AUTORST_DETECT_MASK 0x1 +#define CALI_AUTORST_DETECT_MASK_SFT (0x1 << 14) +#define FREQ_CALC_RUNNING_SFT 13 +#define FREQ_CALC_RUNNING_MASK 0x1 +#define FREQ_CALC_RUNNING_MASK_SFT (0x1 << 13) +#define AUTO_TUNE_FREQ3_SFT 12 +#define AUTO_TUNE_FREQ3_MASK 0x1 +#define AUTO_TUNE_FREQ3_MASK_SFT (0x1 << 12) +#define COMP_FREQ_RES_EN_SFT 11 +#define COMP_FREQ_RES_EN_MASK 0x1 +#define COMP_FREQ_RES_EN_MASK_SFT (0x1 << 11) +#define FREQ_CALI_SEL_SFT 8 +#define FREQ_CALI_SEL_MASK 0x3 +#define FREQ_CALI_SEL_MASK_SFT (0x3 << 8) +#define FREQ_CALI_BP_DGL_SFT 7 +#define FREQ_CALI_BP_DGL_MASK 0x1 +#define FREQ_CALI_BP_DGL_MASK_SFT (0x1 << 7) +#define FREQ_CALI_MAX_GWIDTH_SFT 4 +#define FREQ_CALI_MAX_GWIDTH_MASK 0x7 +#define FREQ_CALI_MAX_GWIDTH_MASK_SFT (0x7 << 4) +#define AUTO_TUNE_FREQ2_SFT 3 +#define AUTO_TUNE_FREQ2_MASK 0x1 +#define AUTO_TUNE_FREQ2_MASK_SFT (0x1 << 3) +#define FREQ_CALI_AUTO_RESTART_SFT 2 +#define FREQ_CALI_AUTO_RESTART_MASK 0x1 +#define FREQ_CALI_AUTO_RESTART_MASK_SFT (0x1 << 2) +#define CALI_USE_FREQ_OUT_SFT 1 +#define CALI_USE_FREQ_OUT_MASK 0x1 +#define CALI_USE_FREQ_OUT_MASK_SFT (0x1 << 1) +#define CALI_EN_SFT 0 +#define CALI_EN_MASK 0x1 +#define CALI_EN_MASK_SFT (0x1 << 0) + +/* AFE_ASRC_NEW_CON7 */ +#define FREQ_CALC_DENOMINATOR_SFT 0 +#define FREQ_CALC_DENOMINATOR_MASK 0xffffff +#define FREQ_CALC_DENOMINATOR_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON8 */ +#define PRD_CALI_RESULT_RECORD_SFT 0 +#define PRD_CALI_RESULT_RECORD_MASK 0xffffff +#define PRD_CALI_RESULT_RECORD_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON9 */ +#define FREQ_CALI_RESULT_SFT 0 +#define FREQ_CALI_RESULT_MASK 0xffffff +#define FREQ_CALI_RESULT_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON10 */ +#define COEFF_SRAM_DATA_SFT 0 +#define COEFF_SRAM_DATA_MASK 0xffffffff +#define COEFF_SRAM_DATA_MASK_SFT (0xffffffff << 0) + +/* AFE_ASRC_NEW_CON11 */ +#define COEFF_SRAM_ADR_SFT 0 +#define COEFF_SRAM_ADR_MASK 0x3f +#define COEFF_SRAM_ADR_MASK_SFT (0x3f << 0) + +/* AFE_ASRC_NEW_CON12 */ +#define RING_DBG_RD_SFT 0 +#define RING_DBG_RD_MASK 0x3ffffff +#define RING_DBG_RD_MASK_SFT (0x3ffffff << 0) + +/* AFE_ASRC_NEW_CON13 */ +#define FREQ_CALI_AUTORST_TH_HIGH_SFT 0 +#define FREQ_CALI_AUTORST_TH_HIGH_MASK 0xffffff +#define FREQ_CALI_AUTORST_TH_HIGH_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_CON14 */ +#define FREQ_CALI_AUTORST_TH_LOW_SFT 0 +#define FREQ_CALI_AUTORST_TH_LOW_MASK 0xffffff +#define FREQ_CALI_AUTORST_TH_LOW_MASK_SFT (0xffffff << 0) + +/* AFE_ASRC_NEW_IP_VERSION */ +#define IP_VERSION_SFT 0 +#define IP_VERSION_MASK 0xffffffff +#define IP_VERSION_MASK_SFT (0xffffffff << 0) + +#define AUDIO_TOP_CON0 0x0 +#define AUDIO_TOP_CON1 0x4 +#define AUDIO_TOP_CON2 0x8 +#define AUDIO_TOP_CON3 0xc +#define AUDIO_TOP_CON4 0x10 +#define AUDIO_ENGEN_CON0 0x14 +#define AUDIO_ENGEN_CON0_USER1 0x18 +#define AUDIO_ENGEN_CON0_USER2 0x1c +#define AFE_SINEGEN_CON0 0x20 +#define AFE_SINEGEN_CON1 0x24 +#define AFE_SINEGEN_CON2 0x28 +#define AFE_SINEGEN_CON3 0x2c +#define AFE_APLL1_TUNER_CFG 0x30 +#define AFE_APLL1_TUNER_MON0 0x34 +#define AFE_APLL2_TUNER_CFG 0x38 +#define AFE_APLL2_TUNER_MON0 0x3c +#define AUDIO_TOP_RG0 0x4c +#define AUDIO_TOP_RG1 0x50 +#define AUDIO_TOP_RG2 0x54 +#define AUDIO_TOP_RG3 0x58 +#define AUDIO_TOP_RG4 0x5c +#define AFE_SPM_CONTROL_REQ 0x60 +#define AFE_SPM_CONTROL_ACK 0x64 +#define AUD_TOP_CFG_VCORE_RG 0x68 +#define AUDIO_TOP_IP_VERSION 0x6c +#define AUDIO_ENGEN_CON0_MON 0x7c +#define AUD_TOP_CFG_VLP_RG 0x98 +#define AUD_TOP_MON_RG 0x9c +#define AUDIO_USE_DEFAULT_DELSEL0 0xa0 +#define AUDIO_USE_DEFAULT_DELSEL1 0xa4 +#define AUDIO_USE_DEFAULT_DELSEL2 0xa8 +#define AFE_CONNSYS_I2S_IPM_VER_MON 0xb0 +#define AFE_CONNSYS_I2S_MON_SEL 0xb4 +#define AFE_CONNSYS_I2S_MON 0xb8 +#define AFE_CONNSYS_I2S_CON 0xbc +#define AFE_PCM0_INTF_CON0 0xc0 +#define AFE_PCM0_INTF_CON1 0xc4 +#define AFE_PCM_INTF_MON 0xc8 +#define AFE_PCM1_INTF_CON0 0xd0 +#define AFE_PCM1_INTF_CON1 0xd4 +#define AFE_PCM_TOP_IP_VERSION 0xe8 +#define AFE_IRQ_MCU_EN 0x100 +#define AFE_IRQ_MCU_DSP_EN 0x104 +#define AFE_IRQ_MCU_DSP2_EN 0x108 +#define AFE_IRQ_MCU_SCP_EN 0x10c +#define AFE_CUSTOM_IRQ_MCU_EN 0x110 +#define AFE_CUSTOM_IRQ_MCU_DSP_EN 0x114 +#define AFE_CUSTOM_IRQ_MCU_DSP2_EN 0x118 +#define AFE_CUSTOM_IRQ_MCU_SCP_EN 0x11c +#define AFE_IRQ_MCU_STATUS 0x120 +#define AFE_CUSTOM_IRQ_MCU_STATUS 0x124 +#define AFE_IRQ0_MCU_CFG0 0x140 +#define AFE_IRQ0_MCU_CFG1 0x144 +#define AFE_IRQ1_MCU_CFG0 0x148 +#define AFE_IRQ1_MCU_CFG1 0x14c +#define AFE_IRQ2_MCU_CFG0 0x150 +#define AFE_IRQ2_MCU_CFG1 0x154 +#define AFE_IRQ3_MCU_CFG0 0x158 +#define AFE_IRQ3_MCU_CFG1 0x15c +#define AFE_IRQ4_MCU_CFG0 0x160 +#define AFE_IRQ4_MCU_CFG1 0x164 +#define AFE_IRQ5_MCU_CFG0 0x168 +#define AFE_IRQ5_MCU_CFG1 0x16c +#define AFE_IRQ6_MCU_CFG0 0x170 +#define AFE_IRQ6_MCU_CFG1 0x174 +#define AFE_IRQ7_MCU_CFG0 0x178 +#define AFE_IRQ7_MCU_CFG1 0x17c +#define AFE_IRQ8_MCU_CFG0 0x180 +#define AFE_IRQ8_MCU_CFG1 0x184 +#define AFE_IRQ9_MCU_CFG0 0x188 +#define AFE_IRQ9_MCU_CFG1 0x18c +#define AFE_IRQ10_MCU_CFG0 0x190 +#define AFE_IRQ10_MCU_CFG1 0x194 +#define AFE_IRQ11_MCU_CFG0 0x198 +#define AFE_IRQ11_MCU_CFG1 0x19c +#define AFE_IRQ12_MCU_CFG0 0x1a0 +#define AFE_IRQ12_MCU_CFG1 0x1a4 +#define AFE_IRQ13_MCU_CFG0 0x1a8 +#define AFE_IRQ13_MCU_CFG1 0x1ac +#define AFE_IRQ14_MCU_CFG0 0x1b0 +#define AFE_IRQ14_MCU_CFG1 0x1b4 +#define AFE_IRQ15_MCU_CFG0 0x1b8 +#define AFE_IRQ15_MCU_CFG1 0x1bc +#define AFE_IRQ16_MCU_CFG0 0x1c0 +#define AFE_IRQ16_MCU_CFG1 0x1c4 +#define AFE_IRQ17_MCU_CFG0 0x1c8 +#define AFE_IRQ17_MCU_CFG1 0x1cc +#define AFE_IRQ18_MCU_CFG0 0x1d0 +#define AFE_IRQ18_MCU_CFG1 0x1d4 +#define AFE_IRQ19_MCU_CFG0 0x1d8 +#define AFE_IRQ19_MCU_CFG1 0x1dc +#define AFE_IRQ20_MCU_CFG0 0x1e0 +#define AFE_IRQ20_MCU_CFG1 0x1e4 +#define AFE_IRQ21_MCU_CFG0 0x1e8 +#define AFE_IRQ21_MCU_CFG1 0x1ec +#define AFE_IRQ22_MCU_CFG0 0x1f0 +#define AFE_IRQ22_MCU_CFG1 0x1f4 +#define AFE_IRQ23_MCU_CFG0 0x1f8 +#define AFE_IRQ23_MCU_CFG1 0x1fc +#define AFE_IRQ24_MCU_CFG0 0x200 +#define AFE_IRQ24_MCU_CFG1 0x204 +#define AFE_IRQ25_MCU_CFG0 0x208 +#define AFE_IRQ25_MCU_CFG1 0x20c +#define AFE_IRQ26_MCU_CFG0 0x210 +#define AFE_IRQ26_MCU_CFG1 0x214 +#define AFE_CUSTOM_IRQ0_MCU_CFG0 0x268 +#define AFE_IRQ_MCU_MON0 0x300 +#define AFE_IRQ_MCU_MON1 0x304 +#define AFE_IRQ_MCU_MON2 0x308 +#define AFE_IRQ0_CNT_MON 0x310 +#define AFE_IRQ1_CNT_MON 0x314 +#define AFE_IRQ2_CNT_MON 0x318 +#define AFE_IRQ3_CNT_MON 0x31c +#define AFE_IRQ4_CNT_MON 0x320 +#define AFE_IRQ5_CNT_MON 0x324 +#define AFE_IRQ6_CNT_MON 0x328 +#define AFE_IRQ7_CNT_MON 0x32c +#define AFE_IRQ8_CNT_MON 0x330 +#define AFE_IRQ9_CNT_MON 0x334 +#define AFE_IRQ10_CNT_MON 0x338 +#define AFE_IRQ11_CNT_MON 0x33c +#define AFE_IRQ12_CNT_MON 0x340 +#define AFE_IRQ13_CNT_MON 0x344 +#define AFE_IRQ14_CNT_MON 0x348 +#define AFE_IRQ15_CNT_MON 0x34c +#define AFE_IRQ16_CNT_MON 0x350 +#define AFE_IRQ17_CNT_MON 0x354 +#define AFE_IRQ18_CNT_MON 0x358 +#define AFE_IRQ19_CNT_MON 0x35c +#define AFE_IRQ20_CNT_MON 0x360 +#define AFE_IRQ21_CNT_MON 0x364 +#define AFE_IRQ22_CNT_MON 0x368 +#define AFE_IRQ23_CNT_MON 0x36c +#define AFE_IRQ24_CNT_MON 0x370 +#define AFE_IRQ25_CNT_MON 0x374 +#define AFE_IRQ26_CNT_MON 0x378 +#define AFE_CUSTOM_IRQ0_CNT_MON 0x390 +#define AFE_CUSTOM_IRQ0_MCU_CFG1 0x3dc +#define AFE_GAIN0_CON0 0x400 +#define AFE_GAIN0_CON1_R 0x404 +#define AFE_GAIN0_CON1_L 0x408 +#define AFE_GAIN0_CON2 0x40c +#define AFE_GAIN0_CON3 0x410 +#define AFE_GAIN0_CUR_R 0x414 +#define AFE_GAIN0_CUR_L 0x418 +#define AFE_GAIN1_CON0 0x41c +#define AFE_GAIN1_CON1_R 0x420 +#define AFE_GAIN1_CON1_L 0x424 +#define AFE_GAIN1_CON2 0x428 +#define AFE_GAIN1_CON3 0x42c +#define AFE_GAIN1_CUR_R 0x430 +#define AFE_GAIN1_CUR_L 0x434 +#define AFE_GAIN2_CON0 0x438 +#define AFE_GAIN2_CON1_R 0x43c +#define AFE_GAIN2_CON1_L 0x440 +#define AFE_GAIN2_CON2 0x444 +#define AFE_GAIN2_CON3 0x448 +#define AFE_GAIN2_CUR_R 0x44c +#define AFE_GAIN2_CUR_L 0x450 +#define AFE_GAIN3_CON0 0x454 +#define AFE_GAIN3_CON1_R 0x458 +#define AFE_GAIN3_CON1_L 0x45c +#define AFE_GAIN3_CON2 0x460 +#define AFE_GAIN3_CON3 0x464 +#define AFE_GAIN3_CUR_R 0x468 +#define AFE_GAIN3_CUR_L 0x46c +#define AFE_STF_CON0 0xb80 +#define AFE_STF_CON1 0xb84 +#define AFE_STF_COEFF 0xb88 +#define AFE_STF_GAIN 0xb8c +#define AFE_STF_MON 0xb90 +#define AFE_STF_IP_VERSION 0xb94 +#define AFE_CM0_CON0 0xba0 +#define AFE_CM0_MON 0xba4 +#define AFE_CM0_IP_VERSION 0xba8 +#define AFE_CM1_CON0 0xbb0 +#define AFE_CM1_MON 0xbb4 +#define AFE_CM1_IP_VERSION 0xbb8 +#define AFE_CM2_CON0 0xbc0 +#define AFE_CM2_MON 0xbc4 +#define AFE_CM2_IP_VERSION 0xbc8 +#define AFE_ADDA_UL0_SRC_CON0 0xbd0 +#define AFE_ADDA_UL0_SRC_CON1 0xbd4 +#define AFE_ADDA_UL0_SRC_CON2 0xbd8 +#define AFE_ADDA_UL0_SRC_DEBUG 0xbdc +#define AFE_ADDA_UL0_SRC_DEBUG_MON0 0xbe0 +#define AFE_ADDA_UL0_SRC_MON0 0xbe4 +#define AFE_ADDA_UL0_SRC_MON1 0xbe8 +#define AFE_ADDA_UL0_IIR_COEF_02_01 0xbec +#define AFE_ADDA_UL0_IIR_COEF_04_03 0xbf0 +#define AFE_ADDA_UL0_IIR_COEF_06_05 0xbf4 +#define AFE_ADDA_UL0_IIR_COEF_08_07 0xbf8 +#define AFE_ADDA_UL0_IIR_COEF_10_09 0xbfc +#define AFE_ADDA_UL0_ULCF_CFG_02_01 0xc00 +#define AFE_ADDA_UL0_ULCF_CFG_04_03 0xc04 +#define AFE_ADDA_UL0_ULCF_CFG_06_05 0xc08 +#define AFE_ADDA_UL0_ULCF_CFG_08_07 0xc0c +#define AFE_ADDA_UL0_ULCF_CFG_10_09 0xc10 +#define AFE_ADDA_UL0_ULCF_CFG_12_11 0xc14 +#define AFE_ADDA_UL0_ULCF_CFG_14_13 0xc18 +#define AFE_ADDA_UL0_ULCF_CFG_16_15 0xc1c +#define AFE_ADDA_UL0_ULCF_CFG_18_17 0xc20 +#define AFE_ADDA_UL0_ULCF_CFG_20_19 0xc24 +#define AFE_ADDA_UL0_ULCF_CFG_22_21 0xc28 +#define AFE_ADDA_UL0_ULCF_CFG_24_23 0xc2c +#define AFE_ADDA_UL0_ULCF_CFG_26_25 0xc30 +#define AFE_ADDA_UL0_ULCF_CFG_28_27 0xc34 +#define AFE_ADDA_UL0_ULCF_CFG_30_29 0xc38 +#define AFE_ADDA_UL0_ULCF_CFG_32_31 0xc3c +#define AFE_ADDA_UL0_IP_VERSION 0xc4c +#define AFE_ADDA_UL1_SRC_CON0 0xc50 +#define AFE_ADDA_UL1_SRC_CON1 0xc54 +#define AFE_ADDA_UL1_SRC_CON2 0xc58 +#define AFE_ADDA_UL1_SRC_DEBUG 0xc5c +#define AFE_ADDA_UL1_SRC_DEBUG_MON0 0xc60 +#define AFE_ADDA_UL1_SRC_MON0 0xc64 +#define AFE_ADDA_UL1_SRC_MON1 0xc68 +#define AFE_ADDA_UL1_IIR_COEF_02_01 0xc6c +#define AFE_ADDA_UL1_IIR_COEF_04_03 0xc70 +#define AFE_ADDA_UL1_IIR_COEF_06_05 0xc74 +#define AFE_ADDA_UL1_IIR_COEF_08_07 0xc78 +#define AFE_ADDA_UL1_IIR_COEF_10_09 0xc7c +#define AFE_ADDA_UL1_ULCF_CFG_02_01 0xc80 +#define AFE_ADDA_UL1_ULCF_CFG_04_03 0xc84 +#define AFE_ADDA_UL1_ULCF_CFG_06_05 0xc88 +#define AFE_ADDA_UL1_ULCF_CFG_08_07 0xc8c +#define AFE_ADDA_UL1_ULCF_CFG_10_09 0xc90 +#define AFE_ADDA_UL1_ULCF_CFG_12_11 0xc94 +#define AFE_ADDA_UL1_ULCF_CFG_14_13 0xc98 +#define AFE_ADDA_UL1_ULCF_CFG_16_15 0xc9c +#define AFE_ADDA_UL1_ULCF_CFG_18_17 0xca0 +#define AFE_ADDA_UL1_ULCF_CFG_20_19 0xca4 +#define AFE_ADDA_UL1_ULCF_CFG_22_21 0xca8 +#define AFE_ADDA_UL1_ULCF_CFG_24_23 0xcac +#define AFE_ADDA_UL1_ULCF_CFG_26_25 0xcb0 +#define AFE_ADDA_UL1_ULCF_CFG_28_27 0xcb4 +#define AFE_ADDA_UL1_ULCF_CFG_30_29 0xcb8 +#define AFE_ADDA_UL1_ULCF_CFG_32_31 0xcbc +#define AFE_ADDA_UL1_IP_VERSION 0xccc +#define AFE_ADDA_UL2_SRC_CON0 0xcd0 +#define AFE_ADDA_UL2_SRC_CON1 0xcd4 +#define AFE_ADDA_UL2_SRC_CON2 0xcd8 +#define AFE_ADDA_UL2_SRC_DEBUG 0xcdc +#define AFE_ADDA_UL2_SRC_DEBUG_MON0 0xce0 +#define AFE_ADDA_UL2_SRC_MON0 0xce4 +#define AFE_ADDA_UL2_SRC_MON1 0xce8 +#define AFE_ADDA_UL2_IIR_COEF_02_01 0xcec +#define AFE_ADDA_UL2_IIR_COEF_04_03 0xcf0 +#define AFE_ADDA_UL2_IIR_COEF_06_05 0xcf4 +#define AFE_ADDA_UL2_IIR_COEF_08_07 0xcf8 +#define AFE_ADDA_UL2_IIR_COEF_10_09 0xcfc +#define AFE_ADDA_UL2_ULCF_CFG_02_01 0xd00 +#define AFE_ADDA_UL2_ULCF_CFG_04_03 0xd04 +#define AFE_ADDA_UL2_ULCF_CFG_06_05 0xd08 +#define AFE_ADDA_UL2_ULCF_CFG_08_07 0xd0c +#define AFE_ADDA_UL2_ULCF_CFG_10_09 0xd10 +#define AFE_ADDA_UL2_ULCF_CFG_12_11 0xd14 +#define AFE_ADDA_UL2_ULCF_CFG_14_13 0xd18 +#define AFE_ADDA_UL2_ULCF_CFG_16_15 0xd1c +#define AFE_ADDA_UL2_ULCF_CFG_18_17 0xd20 +#define AFE_ADDA_UL2_ULCF_CFG_20_19 0xd24 +#define AFE_ADDA_UL2_ULCF_CFG_22_21 0xd28 +#define AFE_ADDA_UL2_ULCF_CFG_24_23 0xd2c +#define AFE_ADDA_UL2_ULCF_CFG_26_25 0xd30 +#define AFE_ADDA_UL2_ULCF_CFG_28_27 0xd34 +#define AFE_ADDA_UL2_ULCF_CFG_30_29 0xd38 +#define AFE_ADDA_UL2_ULCF_CFG_32_31 0xd3c +#define AFE_ADDA_UL2_IP_VERSION 0xd4c +#define AFE_ADDA_PROXIMITY_CON0 0xed0 +#define AFE_ADDA_ULSRC_PHASE_CON0 0xf00 +#define AFE_ADDA_ULSRC_PHASE_CON1 0xf04 +#define AFE_ADDA_ULSRC_PHASE_CON2 0xf08 +#define AFE_ADDA_ULSRC_PHASE_CON3 0xf0c +#define AFE_MTKAIF_IPM_VER_MON 0x1180 +#define AFE_MTKAIF_MON_SEL 0x1184 +#define AFE_MTKAIF_MON 0x1188 +#define AFE_MTKAIF0_CFG0 0x1190 +#define AFE_MTKAIF0_TX_CFG0 0x1194 +#define AFE_MTKAIF0_RX_CFG0 0x1198 +#define AFE_MTKAIF0_RX_CFG1 0x119c +#define AFE_MTKAIF0_RX_CFG2 0x11a0 +#define AFE_MTKAIF1_CFG0 0x11f0 +#define AFE_MTKAIF1_TX_CFG0 0x11f4 +#define AFE_MTKAIF1_RX_CFG0 0x11f8 +#define AFE_MTKAIF1_RX_CFG1 0x11fc +#define AFE_MTKAIF1_RX_CFG2 0x1200 +#define AFE_AUD_PAD_TOP_CFG0 0x1204 +#define AFE_AUD_PAD_TOP_MON 0x1208 +#define AFE_ADDA_MTKAIFV4_TX_CFG0 0x1280 +#define AFE_ADDA6_MTKAIFV4_TX_CFG0 0x1284 +#define AFE_ADDA_MTKAIFV4_RX_CFG0 0x1288 +#define AFE_ADDA_MTKAIFV4_RX_CFG1 0x128c +#define AFE_ADDA6_MTKAIFV4_RX_CFG0 0x1290 +#define AFE_ADDA6_MTKAIFV4_RX_CFG1 0x1294 +#define AFE_ADDA_MTKAIFV4_TX_SYNCWORD_CFG 0x1298 +#define AFE_ADDA_MTKAIFV4_RX_SYNCWORD_CFG 0x129c +#define AFE_ADDA_MTKAIFV4_MON0 0x12a0 +#define AFE_ADDA_MTKAIFV4_MON1 0x12a4 +#define AFE_ADDA6_MTKAIFV4_MON0 0x12a8 +#define ETDM_IN0_CON0 0x1300 +#define ETDM_IN0_CON1 0x1304 +#define ETDM_IN0_CON2 0x1308 +#define ETDM_IN0_CON3 0x130c +#define ETDM_IN0_CON4 0x1310 +#define ETDM_IN0_CON5 0x1314 +#define ETDM_IN0_CON6 0x1318 +#define ETDM_IN0_CON7 0x131c +#define ETDM_IN0_CON8 0x1320 +#define ETDM_IN0_CON9 0x1324 +#define ETDM_IN0_MON 0x1328 +#define ETDM_IN1_CON0 0x1330 +#define ETDM_IN1_CON1 0x1334 +#define ETDM_IN1_CON2 0x1338 +#define ETDM_IN1_CON3 0x133c +#define ETDM_IN1_CON4 0x1340 +#define ETDM_IN1_CON5 0x1344 +#define ETDM_IN1_CON6 0x1348 +#define ETDM_IN1_CON7 0x134c +#define ETDM_IN1_CON8 0x1350 +#define ETDM_IN1_CON9 0x1354 +#define ETDM_IN1_MON 0x1358 +#define ETDM_IN2_CON0 0x1360 +#define ETDM_IN2_CON1 0x1364 +#define ETDM_IN2_CON2 0x1368 +#define ETDM_IN2_CON3 0x136c +#define ETDM_IN2_CON4 0x1370 +#define ETDM_IN2_CON5 0x1374 +#define ETDM_IN2_CON6 0x1378 +#define ETDM_IN2_CON7 0x137c +#define ETDM_IN2_CON8 0x1380 +#define ETDM_IN2_CON9 0x1384 +#define ETDM_IN2_MON 0x1388 +#define ETDM_IN3_CON0 0x1390 +#define ETDM_IN3_CON1 0x1394 +#define ETDM_IN3_CON2 0x1398 +#define ETDM_IN3_CON3 0x139c +#define ETDM_IN3_CON4 0x13a0 +#define ETDM_IN3_CON5 0x13a4 +#define ETDM_IN3_CON6 0x13a8 +#define ETDM_IN3_CON7 0x13ac +#define ETDM_IN3_CON8 0x13b0 +#define ETDM_IN3_CON9 0x13b4 +#define ETDM_IN3_MON 0x13b8 +#define ETDM_IN4_CON0 0x13c0 +#define ETDM_IN4_CON1 0x13c4 +#define ETDM_IN4_CON2 0x13c8 +#define ETDM_IN4_CON3 0x13cc +#define ETDM_IN4_CON4 0x13d0 +#define ETDM_IN4_CON5 0x13d4 +#define ETDM_IN4_CON6 0x13d8 +#define ETDM_IN4_CON7 0x13dc +#define ETDM_IN4_CON8 0x13e0 +#define ETDM_IN4_CON9 0x13e4 +#define ETDM_IN4_MON 0x13e8 +#define ETDM_IN5_CON0 0x13f0 +#define ETDM_IN5_CON1 0x13f4 +#define ETDM_IN5_CON2 0x13f8 +#define ETDM_IN5_CON3 0x13fc +#define ETDM_IN5_CON4 0x1400 +#define ETDM_IN5_CON5 0x1404 +#define ETDM_IN5_CON6 0x1408 +#define ETDM_IN5_CON7 0x140c +#define ETDM_IN5_CON8 0x1410 +#define ETDM_IN5_CON9 0x1414 +#define ETDM_IN5_MON 0x1418 +#define ETDM_IN6_CON0 0x1420 +#define ETDM_IN6_CON1 0x1424 +#define ETDM_IN6_CON2 0x1428 +#define ETDM_IN6_CON3 0x142c +#define ETDM_IN6_CON4 0x1430 +#define ETDM_IN6_CON5 0x1434 +#define ETDM_IN6_CON6 0x1438 +#define ETDM_IN6_CON7 0x143c +#define ETDM_IN6_CON8 0x1440 +#define ETDM_IN6_CON9 0x1444 +#define ETDM_IN6_MON 0x1448 +#define ETDM_OUT0_CON0 0x1480 +#define ETDM_OUT0_CON1 0x1484 +#define ETDM_OUT0_CON2 0x1488 +#define ETDM_OUT0_CON3 0x148c +#define ETDM_OUT0_CON4 0x1490 +#define ETDM_OUT0_CON5 0x1494 +#define ETDM_OUT0_CON6 0x1498 +#define ETDM_OUT0_CON7 0x149c +#define ETDM_OUT0_CON8 0x14a0 +#define ETDM_OUT0_CON9 0x14a4 +#define ETDM_OUT0_MON 0x14a8 +#define ETDM_OUT1_CON0 0x14c0 +#define ETDM_OUT1_CON1 0x14c4 +#define ETDM_OUT1_CON2 0x14c8 +#define ETDM_OUT1_CON3 0x14cc +#define ETDM_OUT1_CON4 0x14d0 +#define ETDM_OUT1_CON5 0x14d4 +#define ETDM_OUT1_CON6 0x14d8 +#define ETDM_OUT1_CON7 0x14dc +#define ETDM_OUT1_CON8 0x14e0 +#define ETDM_OUT1_CON9 0x14e4 +#define ETDM_OUT1_MON 0x14e8 +#define ETDM_OUT2_CON0 0x1500 +#define ETDM_OUT2_CON1 0x1504 +#define ETDM_OUT2_CON2 0x1508 +#define ETDM_OUT2_CON3 0x150c +#define ETDM_OUT2_CON4 0x1510 +#define ETDM_OUT2_CON5 0x1514 +#define ETDM_OUT2_CON6 0x1518 +#define ETDM_OUT2_CON7 0x151c +#define ETDM_OUT2_CON8 0x1520 +#define ETDM_OUT2_CON9 0x1524 +#define ETDM_OUT2_MON 0x1528 +#define ETDM_OUT3_CON0 0x1540 +#define ETDM_OUT3_CON1 0x1544 +#define ETDM_OUT3_CON2 0x1548 +#define ETDM_OUT3_CON3 0x154c +#define ETDM_OUT3_CON4 0x1550 +#define ETDM_OUT3_CON5 0x1554 +#define ETDM_OUT3_CON6 0x1558 +#define ETDM_OUT3_CON7 0x155c +#define ETDM_OUT3_CON8 0x1560 +#define ETDM_OUT3_CON9 0x1564 +#define ETDM_OUT3_MON 0x1568 +#define ETDM_OUT4_CON0 0x1580 +#define ETDM_OUT4_CON1 0x1584 +#define ETDM_OUT4_CON2 0x1588 +#define ETDM_OUT4_CON3 0x158c +#define ETDM_OUT4_CON4 0x1590 +#define ETDM_OUT4_CON5 0x1594 +#define ETDM_OUT4_CON6 0x1598 +#define ETDM_OUT4_CON7 0x159c +#define ETDM_OUT4_CON8 0x15a0 +#define ETDM_OUT4_CON9 0x15a4 +#define ETDM_OUT4_MON 0x15a8 +#define ETDM_OUT5_CON0 0x15c0 +#define ETDM_OUT5_CON1 0x15c4 +#define ETDM_OUT5_CON2 0x15c8 +#define ETDM_OUT5_CON3 0x15cc +#define ETDM_OUT5_CON4 0x15d0 +#define ETDM_OUT5_CON5 0x15d4 +#define ETDM_OUT5_CON6 0x15d8 +#define ETDM_OUT5_CON7 0x15dc +#define ETDM_OUT5_CON8 0x15e0 +#define ETDM_OUT5_CON9 0x15e4 +#define ETDM_OUT5_MON 0x15e8 +#define ETDM_OUT6_CON0 0x1600 +#define ETDM_OUT6_CON1 0x1604 +#define ETDM_OUT6_CON2 0x1608 +#define ETDM_OUT6_CON3 0x160c +#define ETDM_OUT6_CON4 0x1610 +#define ETDM_OUT6_CON5 0x1614 +#define ETDM_OUT6_CON6 0x1618 +#define ETDM_OUT6_CON7 0x161c +#define ETDM_OUT6_CON8 0x1620 +#define ETDM_OUT6_CON9 0x1624 +#define ETDM_OUT6_MON 0x1628 +#define ETDM_0_3_COWORK_CON0 0x1680 +#define ETDM_0_3_COWORK_CON1 0x1684 +#define ETDM_0_3_COWORK_CON2 0x1688 +#define ETDM_0_3_COWORK_CON3 0x168c +#define ETDM_4_7_COWORK_CON0 0x1690 +#define ETDM_4_7_COWORK_CON1 0x1694 +#define ETDM_4_7_COWORK_CON2 0x1698 +#define ETDM_4_7_COWORK_CON3 0x169c +#define AFE_DPTX_CON 0x2040 +#define AFE_DPTX_MON 0x2044 +#define AFE_TDM_CON1 0x2048 +#define AFE_TDM_CON2 0x204c +#define AFE_TDM_CON3 0x2050 +#define AFE_TDM_OUT_MON 0x2054 +#define AFE_HDMI_CONN0 0x2078 +#define AFE_TDM_TOP_IP_VERSION 0x207c +#define AFE_CONN004_0 0x2100 +#define AFE_CONN004_1 0x2104 +#define AFE_CONN004_2 0x2108 +#define AFE_CONN004_4 0x2110 +#define AFE_CONN004_5 0x2114 +#define AFE_CONN004_6 0x2118 +#define AFE_CONN004_7 0x211c +#define AFE_CONN005_0 0x2120 +#define AFE_CONN005_1 0x2124 +#define AFE_CONN005_2 0x2128 +#define AFE_CONN005_4 0x2130 +#define AFE_CONN005_5 0x2134 +#define AFE_CONN005_6 0x2138 +#define AFE_CONN005_7 0x213c +#define AFE_CONN006_0 0x2140 +#define AFE_CONN006_1 0x2144 +#define AFE_CONN006_2 0x2148 +#define AFE_CONN006_4 0x2150 +#define AFE_CONN006_5 0x2154 +#define AFE_CONN006_6 0x2158 +#define AFE_CONN006_7 0x215c +#define AFE_CONN007_0 0x2160 +#define AFE_CONN007_1 0x2164 +#define AFE_CONN007_2 0x2168 +#define AFE_CONN007_4 0x2170 +#define AFE_CONN007_5 0x2174 +#define AFE_CONN007_6 0x2178 +#define AFE_CONN007_7 0x217c +#define AFE_CONN008_0 0x2180 +#define AFE_CONN008_1 0x2184 +#define AFE_CONN008_2 0x2188 +#define AFE_CONN008_4 0x2190 +#define AFE_CONN008_5 0x2194 +#define AFE_CONN008_6 0x2198 +#define AFE_CONN008_7 0x219c +#define AFE_CONN009_0 0x21a0 +#define AFE_CONN009_1 0x21a4 +#define AFE_CONN009_2 0x21a8 +#define AFE_CONN009_4 0x21b0 +#define AFE_CONN009_5 0x21b4 +#define AFE_CONN009_6 0x21b8 +#define AFE_CONN009_7 0x21bc +#define AFE_CONN010_0 0x21c0 +#define AFE_CONN010_1 0x21c4 +#define AFE_CONN010_2 0x21c8 +#define AFE_CONN010_4 0x21d0 +#define AFE_CONN010_5 0x21d4 +#define AFE_CONN010_6 0x21d8 +#define AFE_CONN010_7 0x21dc +#define AFE_CONN011_0 0x21e0 +#define AFE_CONN011_1 0x21e4 +#define AFE_CONN011_2 0x21e8 +#define AFE_CONN011_4 0x21f0 +#define AFE_CONN011_5 0x21f4 +#define AFE_CONN011_6 0x21f8 +#define AFE_CONN011_7 0x21fc +#define AFE_CONN012_0 0x2200 +#define AFE_CONN012_1 0x2204 +#define AFE_CONN012_2 0x2208 +#define AFE_CONN012_4 0x2210 +#define AFE_CONN012_5 0x2214 +#define AFE_CONN012_6 0x2218 +#define AFE_CONN012_7 0x221c +#define AFE_CONN014_0 0x2240 +#define AFE_CONN014_1 0x2244 +#define AFE_CONN014_2 0x2248 +#define AFE_CONN014_4 0x2250 +#define AFE_CONN014_5 0x2254 +#define AFE_CONN014_6 0x2258 +#define AFE_CONN014_7 0x225c +#define AFE_CONN015_0 0x2260 +#define AFE_CONN015_1 0x2264 +#define AFE_CONN015_2 0x2268 +#define AFE_CONN015_4 0x2270 +#define AFE_CONN015_5 0x2274 +#define AFE_CONN015_6 0x2278 +#define AFE_CONN015_7 0x227c +#define AFE_CONN016_0 0x2280 +#define AFE_CONN016_1 0x2284 +#define AFE_CONN016_2 0x2288 +#define AFE_CONN016_4 0x2290 +#define AFE_CONN016_5 0x2294 +#define AFE_CONN016_6 0x2298 +#define AFE_CONN016_7 0x229c +#define AFE_CONN017_0 0x22a0 +#define AFE_CONN017_1 0x22a4 +#define AFE_CONN017_2 0x22a8 +#define AFE_CONN017_4 0x22b0 +#define AFE_CONN017_5 0x22b4 +#define AFE_CONN017_6 0x22b8 +#define AFE_CONN017_7 0x22bc +#define AFE_CONN018_0 0x22c0 +#define AFE_CONN018_1 0x22c4 +#define AFE_CONN018_2 0x22c8 +#define AFE_CONN018_4 0x22d0 +#define AFE_CONN018_5 0x22d4 +#define AFE_CONN018_6 0x22d8 +#define AFE_CONN018_7 0x22dc +#define AFE_CONN019_0 0x22e0 +#define AFE_CONN019_1 0x22e4 +#define AFE_CONN019_2 0x22e8 +#define AFE_CONN019_4 0x22f0 +#define AFE_CONN019_5 0x22f4 +#define AFE_CONN019_6 0x22f8 +#define AFE_CONN019_7 0x22fc +#define AFE_CONN020_0 0x2300 +#define AFE_CONN020_1 0x2304 +#define AFE_CONN020_2 0x2308 +#define AFE_CONN020_4 0x2310 +#define AFE_CONN020_5 0x2314 +#define AFE_CONN020_6 0x2318 +#define AFE_CONN020_7 0x231c +#define AFE_CONN021_0 0x2320 +#define AFE_CONN021_1 0x2324 +#define AFE_CONN021_2 0x2328 +#define AFE_CONN021_4 0x2330 +#define AFE_CONN021_5 0x2334 +#define AFE_CONN021_6 0x2338 +#define AFE_CONN021_7 0x233c +#define AFE_CONN022_0 0x2340 +#define AFE_CONN022_1 0x2344 +#define AFE_CONN022_2 0x2348 +#define AFE_CONN022_4 0x2350 +#define AFE_CONN022_5 0x2354 +#define AFE_CONN022_6 0x2358 +#define AFE_CONN022_7 0x235c +#define AFE_CONN023_0 0x2360 +#define AFE_CONN023_1 0x2364 +#define AFE_CONN023_2 0x2368 +#define AFE_CONN023_4 0x2370 +#define AFE_CONN023_5 0x2374 +#define AFE_CONN023_6 0x2378 +#define AFE_CONN023_7 0x237c +#define AFE_CONN024_0 0x2380 +#define AFE_CONN024_1 0x2384 +#define AFE_CONN024_2 0x2388 +#define AFE_CONN024_4 0x2390 +#define AFE_CONN024_5 0x2394 +#define AFE_CONN024_6 0x2398 +#define AFE_CONN024_7 0x239c +#define AFE_CONN025_0 0x23a0 +#define AFE_CONN025_1 0x23a4 +#define AFE_CONN025_2 0x23a8 +#define AFE_CONN025_4 0x23b0 +#define AFE_CONN025_5 0x23b4 +#define AFE_CONN025_6 0x23b8 +#define AFE_CONN025_7 0x23bc +#define AFE_CONN026_0 0x23c0 +#define AFE_CONN026_1 0x23c4 +#define AFE_CONN026_2 0x23c8 +#define AFE_CONN026_4 0x23d0 +#define AFE_CONN026_5 0x23d4 +#define AFE_CONN026_6 0x23d8 +#define AFE_CONN026_7 0x23dc +#define AFE_CONN027_0 0x23e0 +#define AFE_CONN027_1 0x23e4 +#define AFE_CONN027_2 0x23e8 +#define AFE_CONN027_4 0x23f0 +#define AFE_CONN027_5 0x23f4 +#define AFE_CONN027_6 0x23f8 +#define AFE_CONN027_7 0x23fc +#define AFE_CONN028_0 0x2400 +#define AFE_CONN028_1 0x2404 +#define AFE_CONN028_2 0x2408 +#define AFE_CONN028_4 0x2410 +#define AFE_CONN028_5 0x2414 +#define AFE_CONN028_6 0x2418 +#define AFE_CONN028_7 0x241c +#define AFE_CONN029_0 0x2420 +#define AFE_CONN029_1 0x2424 +#define AFE_CONN029_2 0x2428 +#define AFE_CONN029_4 0x2430 +#define AFE_CONN029_5 0x2434 +#define AFE_CONN029_6 0x2438 +#define AFE_CONN029_7 0x243c +#define AFE_CONN030_0 0x2440 +#define AFE_CONN030_1 0x2444 +#define AFE_CONN030_2 0x2448 +#define AFE_CONN030_4 0x2450 +#define AFE_CONN030_5 0x2454 +#define AFE_CONN030_6 0x2458 +#define AFE_CONN030_7 0x245c +#define AFE_CONN031_0 0x2460 +#define AFE_CONN031_1 0x2464 +#define AFE_CONN031_2 0x2468 +#define AFE_CONN031_4 0x2470 +#define AFE_CONN031_5 0x2474 +#define AFE_CONN031_6 0x2478 +#define AFE_CONN031_7 0x247c +#define AFE_CONN032_0 0x2480 +#define AFE_CONN032_1 0x2484 +#define AFE_CONN032_2 0x2488 +#define AFE_CONN032_4 0x2490 +#define AFE_CONN032_5 0x2494 +#define AFE_CONN032_6 0x2498 +#define AFE_CONN032_7 0x249c +#define AFE_CONN033_0 0x24a0 +#define AFE_CONN033_1 0x24a4 +#define AFE_CONN033_2 0x24a8 +#define AFE_CONN033_4 0x24b0 +#define AFE_CONN033_5 0x24b4 +#define AFE_CONN033_6 0x24b8 +#define AFE_CONN033_7 0x24bc +#define AFE_CONN034_0 0x24c0 +#define AFE_CONN034_1 0x24c4 +#define AFE_CONN034_2 0x24c8 +#define AFE_CONN034_4 0x24d0 +#define AFE_CONN034_5 0x24d4 +#define AFE_CONN034_6 0x24d8 +#define AFE_CONN034_7 0x24dc +#define AFE_CONN035_0 0x24e0 +#define AFE_CONN035_1 0x24e4 +#define AFE_CONN035_2 0x24e8 +#define AFE_CONN035_4 0x24f0 +#define AFE_CONN035_5 0x24f4 +#define AFE_CONN035_6 0x24f8 +#define AFE_CONN035_7 0x24fc +#define AFE_CONN036_0 0x2500 +#define AFE_CONN036_1 0x2504 +#define AFE_CONN036_2 0x2508 +#define AFE_CONN036_4 0x2510 +#define AFE_CONN036_5 0x2514 +#define AFE_CONN036_6 0x2518 +#define AFE_CONN036_7 0x251c +#define AFE_CONN037_0 0x2520 +#define AFE_CONN037_1 0x2524 +#define AFE_CONN037_2 0x2528 +#define AFE_CONN037_4 0x2530 +#define AFE_CONN037_5 0x2534 +#define AFE_CONN037_6 0x2538 +#define AFE_CONN037_7 0x253c +#define AFE_CONN038_0 0x2540 +#define AFE_CONN038_1 0x2544 +#define AFE_CONN038_2 0x2548 +#define AFE_CONN038_4 0x2550 +#define AFE_CONN038_5 0x2554 +#define AFE_CONN038_6 0x2558 +#define AFE_CONN038_7 0x255c +#define AFE_CONN039_0 0x2560 +#define AFE_CONN039_1 0x2564 +#define AFE_CONN039_2 0x2568 +#define AFE_CONN039_4 0x2570 +#define AFE_CONN039_5 0x2574 +#define AFE_CONN039_6 0x2578 +#define AFE_CONN039_7 0x257c +#define AFE_CONN040_0 0x2580 +#define AFE_CONN040_1 0x2584 +#define AFE_CONN040_2 0x2588 +#define AFE_CONN040_4 0x2590 +#define AFE_CONN040_5 0x2594 +#define AFE_CONN040_6 0x2598 +#define AFE_CONN040_7 0x259c +#define AFE_CONN041_0 0x25a0 +#define AFE_CONN041_1 0x25a4 +#define AFE_CONN041_2 0x25a8 +#define AFE_CONN041_4 0x25b0 +#define AFE_CONN041_5 0x25b4 +#define AFE_CONN041_6 0x25b8 +#define AFE_CONN041_7 0x25bc +#define AFE_CONN042_0 0x25c0 +#define AFE_CONN042_1 0x25c4 +#define AFE_CONN042_2 0x25c8 +#define AFE_CONN042_4 0x25d0 +#define AFE_CONN042_5 0x25d4 +#define AFE_CONN042_6 0x25d8 +#define AFE_CONN042_7 0x25dc +#define AFE_CONN043_0 0x25e0 +#define AFE_CONN043_1 0x25e4 +#define AFE_CONN043_2 0x25e8 +#define AFE_CONN043_4 0x25f0 +#define AFE_CONN043_5 0x25f4 +#define AFE_CONN043_6 0x25f8 +#define AFE_CONN043_7 0x25fc +#define AFE_CONN044_0 0x2600 +#define AFE_CONN044_1 0x2604 +#define AFE_CONN044_2 0x2608 +#define AFE_CONN044_4 0x2610 +#define AFE_CONN044_5 0x2614 +#define AFE_CONN044_6 0x2618 +#define AFE_CONN044_7 0x261c +#define AFE_CONN045_0 0x2620 +#define AFE_CONN045_1 0x2624 +#define AFE_CONN045_2 0x2628 +#define AFE_CONN045_4 0x2630 +#define AFE_CONN045_5 0x2634 +#define AFE_CONN045_6 0x2638 +#define AFE_CONN045_7 0x263c +#define AFE_CONN046_0 0x2640 +#define AFE_CONN046_1 0x2644 +#define AFE_CONN046_2 0x2648 +#define AFE_CONN046_4 0x2650 +#define AFE_CONN046_5 0x2654 +#define AFE_CONN046_6 0x2658 +#define AFE_CONN046_7 0x265c +#define AFE_CONN047_0 0x2660 +#define AFE_CONN047_1 0x2664 +#define AFE_CONN047_2 0x2668 +#define AFE_CONN047_4 0x2670 +#define AFE_CONN047_5 0x2674 +#define AFE_CONN047_6 0x2678 +#define AFE_CONN047_7 0x267c +#define AFE_CONN048_0 0x2680 +#define AFE_CONN048_1 0x2684 +#define AFE_CONN048_2 0x2688 +#define AFE_CONN048_4 0x2690 +#define AFE_CONN048_5 0x2694 +#define AFE_CONN048_6 0x2698 +#define AFE_CONN048_7 0x269c +#define AFE_CONN049_0 0x26a0 +#define AFE_CONN049_1 0x26a4 +#define AFE_CONN049_2 0x26a8 +#define AFE_CONN049_4 0x26b0 +#define AFE_CONN049_5 0x26b4 +#define AFE_CONN049_6 0x26b8 +#define AFE_CONN049_7 0x26bc +#define AFE_CONN050_0 0x26c0 +#define AFE_CONN050_1 0x26c4 +#define AFE_CONN050_2 0x26c8 +#define AFE_CONN050_4 0x26d0 +#define AFE_CONN050_5 0x26d4 +#define AFE_CONN050_6 0x26d8 +#define AFE_CONN050_7 0x26dc +#define AFE_CONN051_0 0x26e0 +#define AFE_CONN051_1 0x26e4 +#define AFE_CONN051_2 0x26e8 +#define AFE_CONN051_4 0x26f0 +#define AFE_CONN051_5 0x26f4 +#define AFE_CONN051_6 0x26f8 +#define AFE_CONN051_7 0x26fc +#define AFE_CONN052_0 0x2700 +#define AFE_CONN052_1 0x2704 +#define AFE_CONN052_2 0x2708 +#define AFE_CONN052_4 0x2710 +#define AFE_CONN052_5 0x2714 +#define AFE_CONN052_6 0x2718 +#define AFE_CONN052_7 0x271c +#define AFE_CONN053_0 0x2720 +#define AFE_CONN053_1 0x2724 +#define AFE_CONN053_2 0x2728 +#define AFE_CONN053_4 0x2730 +#define AFE_CONN053_5 0x2734 +#define AFE_CONN053_6 0x2738 +#define AFE_CONN053_7 0x273c +#define AFE_CONN054_0 0x2740 +#define AFE_CONN054_1 0x2744 +#define AFE_CONN054_2 0x2748 +#define AFE_CONN054_4 0x2750 +#define AFE_CONN054_5 0x2754 +#define AFE_CONN054_6 0x2758 +#define AFE_CONN054_7 0x275c +#define AFE_CONN055_0 0x2760 +#define AFE_CONN055_1 0x2764 +#define AFE_CONN055_2 0x2768 +#define AFE_CONN055_4 0x2770 +#define AFE_CONN055_5 0x2774 +#define AFE_CONN055_6 0x2778 +#define AFE_CONN055_7 0x277c +#define AFE_CONN056_0 0x2780 +#define AFE_CONN056_1 0x2784 +#define AFE_CONN056_2 0x2788 +#define AFE_CONN056_4 0x2790 +#define AFE_CONN056_5 0x2794 +#define AFE_CONN056_6 0x2798 +#define AFE_CONN056_7 0x279c +#define AFE_CONN057_0 0x27a0 +#define AFE_CONN057_1 0x27a4 +#define AFE_CONN057_2 0x27a8 +#define AFE_CONN057_4 0x27b0 +#define AFE_CONN057_5 0x27b4 +#define AFE_CONN057_6 0x27b8 +#define AFE_CONN057_7 0x27bc +#define AFE_CONN058_0 0x27c0 +#define AFE_CONN058_1 0x27c4 +#define AFE_CONN058_2 0x27c8 +#define AFE_CONN058_4 0x27d0 +#define AFE_CONN058_5 0x27d4 +#define AFE_CONN058_6 0x27d8 +#define AFE_CONN058_7 0x27dc +#define AFE_CONN059_0 0x27e0 +#define AFE_CONN059_1 0x27e4 +#define AFE_CONN059_2 0x27e8 +#define AFE_CONN059_4 0x27f0 +#define AFE_CONN059_5 0x27f4 +#define AFE_CONN059_6 0x27f8 +#define AFE_CONN059_7 0x27fc +#define AFE_CONN060_0 0x2800 +#define AFE_CONN060_1 0x2804 +#define AFE_CONN060_2 0x2808 +#define AFE_CONN060_4 0x2810 +#define AFE_CONN060_5 0x2814 +#define AFE_CONN060_6 0x2818 +#define AFE_CONN060_7 0x281c +#define AFE_CONN061_0 0x2820 +#define AFE_CONN061_1 0x2824 +#define AFE_CONN061_2 0x2828 +#define AFE_CONN061_4 0x2830 +#define AFE_CONN061_5 0x2834 +#define AFE_CONN061_6 0x2838 +#define AFE_CONN061_7 0x283c +#define AFE_CONN062_0 0x2840 +#define AFE_CONN062_1 0x2844 +#define AFE_CONN062_2 0x2848 +#define AFE_CONN062_4 0x2850 +#define AFE_CONN062_5 0x2854 +#define AFE_CONN062_6 0x2858 +#define AFE_CONN062_7 0x285c +#define AFE_CONN063_0 0x2860 +#define AFE_CONN063_1 0x2864 +#define AFE_CONN063_2 0x2868 +#define AFE_CONN063_4 0x2870 +#define AFE_CONN063_5 0x2874 +#define AFE_CONN063_6 0x2878 +#define AFE_CONN063_7 0x287c +#define AFE_CONN064_0 0x2880 +#define AFE_CONN064_1 0x2884 +#define AFE_CONN064_2 0x2888 +#define AFE_CONN064_4 0x2890 +#define AFE_CONN064_5 0x2894 +#define AFE_CONN064_6 0x2898 +#define AFE_CONN064_7 0x289c +#define AFE_CONN065_0 0x28a0 +#define AFE_CONN065_1 0x28a4 +#define AFE_CONN065_2 0x28a8 +#define AFE_CONN065_4 0x28b0 +#define AFE_CONN065_5 0x28b4 +#define AFE_CONN065_6 0x28b8 +#define AFE_CONN065_7 0x28bc +#define AFE_CONN066_0 0x28c0 +#define AFE_CONN066_1 0x28c4 +#define AFE_CONN066_2 0x28c8 +#define AFE_CONN066_4 0x28d0 +#define AFE_CONN066_5 0x28d4 +#define AFE_CONN066_6 0x28d8 +#define AFE_CONN066_7 0x28dc +#define AFE_CONN067_0 0x28e0 +#define AFE_CONN067_1 0x28e4 +#define AFE_CONN067_2 0x28e8 +#define AFE_CONN067_4 0x28f0 +#define AFE_CONN067_5 0x28f4 +#define AFE_CONN067_6 0x28f8 +#define AFE_CONN067_7 0x28fc +#define AFE_CONN068_0 0x2900 +#define AFE_CONN068_1 0x2904 +#define AFE_CONN068_2 0x2908 +#define AFE_CONN068_4 0x2910 +#define AFE_CONN068_5 0x2914 +#define AFE_CONN068_6 0x2918 +#define AFE_CONN068_7 0x291c +#define AFE_CONN069_0 0x2920 +#define AFE_CONN069_1 0x2924 +#define AFE_CONN069_2 0x2928 +#define AFE_CONN069_4 0x2930 +#define AFE_CONN069_5 0x2934 +#define AFE_CONN069_6 0x2938 +#define AFE_CONN069_7 0x293c +#define AFE_CONN070_0 0x2940 +#define AFE_CONN070_1 0x2944 +#define AFE_CONN070_2 0x2948 +#define AFE_CONN070_4 0x2950 +#define AFE_CONN070_5 0x2954 +#define AFE_CONN070_6 0x2958 +#define AFE_CONN070_7 0x295c +#define AFE_CONN071_0 0x2960 +#define AFE_CONN071_1 0x2964 +#define AFE_CONN071_2 0x2968 +#define AFE_CONN071_4 0x2970 +#define AFE_CONN071_5 0x2974 +#define AFE_CONN071_6 0x2978 +#define AFE_CONN071_7 0x297c +#define AFE_CONN072_0 0x2980 +#define AFE_CONN072_1 0x2984 +#define AFE_CONN072_2 0x2988 +#define AFE_CONN072_4 0x2990 +#define AFE_CONN072_5 0x2994 +#define AFE_CONN072_6 0x2998 +#define AFE_CONN072_7 0x299c +#define AFE_CONN073_0 0x29a0 +#define AFE_CONN073_1 0x29a4 +#define AFE_CONN073_2 0x29a8 +#define AFE_CONN073_4 0x29b0 +#define AFE_CONN073_5 0x29b4 +#define AFE_CONN073_6 0x29b8 +#define AFE_CONN073_7 0x29bc +#define AFE_CONN074_0 0x29c0 +#define AFE_CONN074_1 0x29c4 +#define AFE_CONN074_2 0x29c8 +#define AFE_CONN074_4 0x29d0 +#define AFE_CONN074_5 0x29d4 +#define AFE_CONN074_6 0x29d8 +#define AFE_CONN074_7 0x29dc +#define AFE_CONN075_0 0x29e0 +#define AFE_CONN075_1 0x29e4 +#define AFE_CONN075_2 0x29e8 +#define AFE_CONN075_4 0x29f0 +#define AFE_CONN075_5 0x29f4 +#define AFE_CONN075_6 0x29f8 +#define AFE_CONN075_7 0x29fc +#define AFE_CONN076_0 0x2a00 +#define AFE_CONN076_1 0x2a04 +#define AFE_CONN076_2 0x2a08 +#define AFE_CONN076_4 0x2a10 +#define AFE_CONN076_5 0x2a14 +#define AFE_CONN076_6 0x2a18 +#define AFE_CONN076_7 0x2a1c +#define AFE_CONN077_0 0x2a20 +#define AFE_CONN077_1 0x2a24 +#define AFE_CONN077_2 0x2a28 +#define AFE_CONN077_4 0x2a30 +#define AFE_CONN077_5 0x2a34 +#define AFE_CONN077_6 0x2a38 +#define AFE_CONN077_7 0x2a3c +#define AFE_CONN078_0 0x2a40 +#define AFE_CONN078_1 0x2a44 +#define AFE_CONN078_2 0x2a48 +#define AFE_CONN078_4 0x2a50 +#define AFE_CONN078_5 0x2a54 +#define AFE_CONN078_6 0x2a58 +#define AFE_CONN078_7 0x2a5c +#define AFE_CONN079_0 0x2a60 +#define AFE_CONN079_1 0x2a64 +#define AFE_CONN079_2 0x2a68 +#define AFE_CONN079_4 0x2a70 +#define AFE_CONN079_5 0x2a74 +#define AFE_CONN079_6 0x2a78 +#define AFE_CONN079_7 0x2a7c +#define AFE_CONN080_0 0x2a80 +#define AFE_CONN080_1 0x2a84 +#define AFE_CONN080_2 0x2a88 +#define AFE_CONN080_4 0x2a90 +#define AFE_CONN080_5 0x2a94 +#define AFE_CONN080_6 0x2a98 +#define AFE_CONN080_7 0x2a9c +#define AFE_CONN081_0 0x2aa0 +#define AFE_CONN081_1 0x2aa4 +#define AFE_CONN081_2 0x2aa8 +#define AFE_CONN081_4 0x2ab0 +#define AFE_CONN081_5 0x2ab4 +#define AFE_CONN081_6 0x2ab8 +#define AFE_CONN081_7 0x2abc +#define AFE_CONN082_0 0x2ac0 +#define AFE_CONN082_1 0x2ac4 +#define AFE_CONN082_2 0x2ac8 +#define AFE_CONN082_4 0x2ad0 +#define AFE_CONN082_5 0x2ad4 +#define AFE_CONN082_6 0x2ad8 +#define AFE_CONN082_7 0x2adc +#define AFE_CONN083_0 0x2ae0 +#define AFE_CONN083_1 0x2ae4 +#define AFE_CONN083_2 0x2ae8 +#define AFE_CONN083_4 0x2af0 +#define AFE_CONN083_5 0x2af4 +#define AFE_CONN083_6 0x2af8 +#define AFE_CONN083_7 0x2afc +#define AFE_CONN084_0 0x2b00 +#define AFE_CONN084_1 0x2b04 +#define AFE_CONN084_2 0x2b08 +#define AFE_CONN084_4 0x2b10 +#define AFE_CONN084_5 0x2b14 +#define AFE_CONN084_6 0x2b18 +#define AFE_CONN084_7 0x2b1c +#define AFE_CONN085_0 0x2b20 +#define AFE_CONN085_1 0x2b24 +#define AFE_CONN085_2 0x2b28 +#define AFE_CONN085_4 0x2b30 +#define AFE_CONN085_5 0x2b34 +#define AFE_CONN085_6 0x2b38 +#define AFE_CONN085_7 0x2b3c +#define AFE_CONN086_0 0x2b40 +#define AFE_CONN086_1 0x2b44 +#define AFE_CONN086_2 0x2b48 +#define AFE_CONN086_4 0x2b50 +#define AFE_CONN086_5 0x2b54 +#define AFE_CONN086_6 0x2b58 +#define AFE_CONN086_7 0x2b5c +#define AFE_CONN087_0 0x2b60 +#define AFE_CONN087_1 0x2b64 +#define AFE_CONN087_2 0x2b68 +#define AFE_CONN087_4 0x2b70 +#define AFE_CONN087_5 0x2b74 +#define AFE_CONN087_6 0x2b78 +#define AFE_CONN087_7 0x2b7c +#define AFE_CONN088_0 0x2b80 +#define AFE_CONN088_1 0x2b84 +#define AFE_CONN088_2 0x2b88 +#define AFE_CONN088_4 0x2b90 +#define AFE_CONN088_5 0x2b94 +#define AFE_CONN088_6 0x2b98 +#define AFE_CONN088_7 0x2b9c +#define AFE_CONN089_0 0x2ba0 +#define AFE_CONN089_1 0x2ba4 +#define AFE_CONN089_2 0x2ba8 +#define AFE_CONN089_4 0x2bb0 +#define AFE_CONN089_5 0x2bb4 +#define AFE_CONN089_6 0x2bb8 +#define AFE_CONN089_7 0x2bbc +#define AFE_CONN090_0 0x2bc0 +#define AFE_CONN090_1 0x2bc4 +#define AFE_CONN090_2 0x2bc8 +#define AFE_CONN090_4 0x2bd0 +#define AFE_CONN090_5 0x2bd4 +#define AFE_CONN090_6 0x2bd8 +#define AFE_CONN090_7 0x2bdc +#define AFE_CONN091_0 0x2be0 +#define AFE_CONN091_1 0x2be4 +#define AFE_CONN091_2 0x2be8 +#define AFE_CONN091_4 0x2bf0 +#define AFE_CONN091_5 0x2bf4 +#define AFE_CONN091_6 0x2bf8 +#define AFE_CONN091_7 0x2bfc +#define AFE_CONN092_0 0x2c00 +#define AFE_CONN092_1 0x2c04 +#define AFE_CONN092_2 0x2c08 +#define AFE_CONN092_4 0x2c10 +#define AFE_CONN092_5 0x2c14 +#define AFE_CONN092_6 0x2c18 +#define AFE_CONN092_7 0x2c1c +#define AFE_CONN093_0 0x2c20 +#define AFE_CONN093_1 0x2c24 +#define AFE_CONN093_2 0x2c28 +#define AFE_CONN093_4 0x2c30 +#define AFE_CONN093_5 0x2c34 +#define AFE_CONN093_6 0x2c38 +#define AFE_CONN093_7 0x2c3c +#define AFE_CONN094_0 0x2c40 +#define AFE_CONN094_1 0x2c44 +#define AFE_CONN094_2 0x2c48 +#define AFE_CONN094_4 0x2c50 +#define AFE_CONN094_5 0x2c54 +#define AFE_CONN094_6 0x2c58 +#define AFE_CONN094_7 0x2c5c +#define AFE_CONN095_0 0x2c60 +#define AFE_CONN095_1 0x2c64 +#define AFE_CONN095_2 0x2c68 +#define AFE_CONN095_4 0x2c70 +#define AFE_CONN095_5 0x2c74 +#define AFE_CONN095_6 0x2c78 +#define AFE_CONN095_7 0x2c7c +#define AFE_CONN096_0 0x2c80 +#define AFE_CONN096_1 0x2c84 +#define AFE_CONN096_2 0x2c88 +#define AFE_CONN096_4 0x2c90 +#define AFE_CONN096_5 0x2c94 +#define AFE_CONN096_6 0x2c98 +#define AFE_CONN096_7 0x2c9c +#define AFE_CONN097_0 0x2ca0 +#define AFE_CONN097_1 0x2ca4 +#define AFE_CONN097_2 0x2ca8 +#define AFE_CONN097_4 0x2cb0 +#define AFE_CONN097_5 0x2cb4 +#define AFE_CONN097_6 0x2cb8 +#define AFE_CONN097_7 0x2cbc +#define AFE_CONN098_0 0x2cc0 +#define AFE_CONN098_1 0x2cc4 +#define AFE_CONN098_2 0x2cc8 +#define AFE_CONN098_4 0x2cd0 +#define AFE_CONN098_5 0x2cd4 +#define AFE_CONN098_6 0x2cd8 +#define AFE_CONN098_7 0x2cdc +#define AFE_CONN099_0 0x2ce0 +#define AFE_CONN099_1 0x2ce4 +#define AFE_CONN099_2 0x2ce8 +#define AFE_CONN099_4 0x2cf0 +#define AFE_CONN099_5 0x2cf4 +#define AFE_CONN099_6 0x2cf8 +#define AFE_CONN099_7 0x2cfc +#define AFE_CONN100_0 0x2d00 +#define AFE_CONN100_1 0x2d04 +#define AFE_CONN100_2 0x2d08 +#define AFE_CONN100_4 0x2d10 +#define AFE_CONN100_5 0x2d14 +#define AFE_CONN100_6 0x2d18 +#define AFE_CONN100_7 0x2d1c +#define AFE_CONN102_0 0x2d40 +#define AFE_CONN102_1 0x2d44 +#define AFE_CONN102_2 0x2d48 +#define AFE_CONN102_4 0x2d50 +#define AFE_CONN102_5 0x2d54 +#define AFE_CONN102_6 0x2d58 +#define AFE_CONN102_7 0x2d5c +#define AFE_CONN103_0 0x2d60 +#define AFE_CONN103_1 0x2d64 +#define AFE_CONN103_2 0x2d68 +#define AFE_CONN103_4 0x2d70 +#define AFE_CONN103_5 0x2d74 +#define AFE_CONN103_6 0x2d78 +#define AFE_CONN103_7 0x2d7c +#define AFE_CONN104_0 0x2d80 +#define AFE_CONN104_1 0x2d84 +#define AFE_CONN104_2 0x2d88 +#define AFE_CONN104_4 0x2d90 +#define AFE_CONN104_5 0x2d94 +#define AFE_CONN104_6 0x2d98 +#define AFE_CONN104_7 0x2d9c +#define AFE_CONN105_0 0x2da0 +#define AFE_CONN105_1 0x2da4 +#define AFE_CONN105_2 0x2da8 +#define AFE_CONN105_4 0x2db0 +#define AFE_CONN105_5 0x2db4 +#define AFE_CONN105_6 0x2db8 +#define AFE_CONN105_7 0x2dbc +#define AFE_CONN106_0 0x2dc0 +#define AFE_CONN106_1 0x2dc4 +#define AFE_CONN106_2 0x2dc8 +#define AFE_CONN106_4 0x2dd0 +#define AFE_CONN106_5 0x2dd4 +#define AFE_CONN106_6 0x2dd8 +#define AFE_CONN106_7 0x2ddc +#define AFE_CONN108_0 0x2e00 +#define AFE_CONN108_1 0x2e04 +#define AFE_CONN108_2 0x2e08 +#define AFE_CONN108_4 0x2e10 +#define AFE_CONN108_5 0x2e14 +#define AFE_CONN108_6 0x2e18 +#define AFE_CONN108_7 0x2e1c +#define AFE_CONN109_0 0x2e20 +#define AFE_CONN109_1 0x2e24 +#define AFE_CONN109_2 0x2e28 +#define AFE_CONN109_4 0x2e30 +#define AFE_CONN109_5 0x2e34 +#define AFE_CONN109_6 0x2e38 +#define AFE_CONN109_7 0x2e3c +#define AFE_CONN110_0 0x2e40 +#define AFE_CONN110_1 0x2e44 +#define AFE_CONN110_2 0x2e48 +#define AFE_CONN110_4 0x2e50 +#define AFE_CONN110_5 0x2e54 +#define AFE_CONN110_6 0x2e58 +#define AFE_CONN110_7 0x2e5c +#define AFE_CONN111_0 0x2e60 +#define AFE_CONN111_1 0x2e64 +#define AFE_CONN111_2 0x2e68 +#define AFE_CONN111_4 0x2e70 +#define AFE_CONN111_5 0x2e74 +#define AFE_CONN111_6 0x2e78 +#define AFE_CONN111_7 0x2e7c +#define AFE_CONN112_0 0x2e80 +#define AFE_CONN112_1 0x2e84 +#define AFE_CONN112_2 0x2e88 +#define AFE_CONN112_4 0x2e90 +#define AFE_CONN112_5 0x2e94 +#define AFE_CONN112_6 0x2e98 +#define AFE_CONN112_7 0x2e9c +#define AFE_CONN113_0 0x2ea0 +#define AFE_CONN113_1 0x2ea4 +#define AFE_CONN113_2 0x2ea8 +#define AFE_CONN113_4 0x2eb0 +#define AFE_CONN113_5 0x2eb4 +#define AFE_CONN113_6 0x2eb8 +#define AFE_CONN113_7 0x2ebc +#define AFE_CONN114_0 0x2ec0 +#define AFE_CONN114_1 0x2ec4 +#define AFE_CONN114_2 0x2ec8 +#define AFE_CONN114_4 0x2ed0 +#define AFE_CONN114_5 0x2ed4 +#define AFE_CONN114_6 0x2ed8 +#define AFE_CONN114_7 0x2edc +#define AFE_CONN115_0 0x2ee0 +#define AFE_CONN115_1 0x2ee4 +#define AFE_CONN115_2 0x2ee8 +#define AFE_CONN115_4 0x2ef0 +#define AFE_CONN115_5 0x2ef4 +#define AFE_CONN115_6 0x2ef8 +#define AFE_CONN115_7 0x2efc +#define AFE_CONN116_0 0x2f00 +#define AFE_CONN116_1 0x2f04 +#define AFE_CONN116_2 0x2f08 +#define AFE_CONN116_4 0x2f10 +#define AFE_CONN116_5 0x2f14 +#define AFE_CONN116_6 0x2f18 +#define AFE_CONN116_7 0x2f1c +#define AFE_CONN117_0 0x2f20 +#define AFE_CONN117_1 0x2f24 +#define AFE_CONN117_2 0x2f28 +#define AFE_CONN117_4 0x2f30 +#define AFE_CONN117_5 0x2f34 +#define AFE_CONN117_6 0x2f38 +#define AFE_CONN117_7 0x2f3c +#define AFE_CONN118_0 0x2f40 +#define AFE_CONN118_1 0x2f44 +#define AFE_CONN118_2 0x2f48 +#define AFE_CONN118_4 0x2f50 +#define AFE_CONN118_5 0x2f54 +#define AFE_CONN118_6 0x2f58 +#define AFE_CONN118_7 0x2f5c +#define AFE_CONN119_0 0x2f60 +#define AFE_CONN119_1 0x2f64 +#define AFE_CONN119_2 0x2f68 +#define AFE_CONN119_4 0x2f70 +#define AFE_CONN119_5 0x2f74 +#define AFE_CONN119_6 0x2f78 +#define AFE_CONN119_7 0x2f7c +#define AFE_CONN120_0 0x2f80 +#define AFE_CONN120_1 0x2f84 +#define AFE_CONN120_2 0x2f88 +#define AFE_CONN120_4 0x2f90 +#define AFE_CONN120_5 0x2f94 +#define AFE_CONN120_6 0x2f98 +#define AFE_CONN120_7 0x2f9c +#define AFE_CONN121_0 0x2fa0 +#define AFE_CONN121_1 0x2fa4 +#define AFE_CONN121_2 0x2fa8 +#define AFE_CONN121_4 0x2fb0 +#define AFE_CONN121_5 0x2fb4 +#define AFE_CONN121_6 0x2fb8 +#define AFE_CONN121_7 0x2fbc +#define AFE_CONN122_0 0x2fc0 +#define AFE_CONN122_1 0x2fc4 +#define AFE_CONN122_2 0x2fc8 +#define AFE_CONN122_4 0x2fd0 +#define AFE_CONN122_5 0x2fd4 +#define AFE_CONN122_6 0x2fd8 +#define AFE_CONN122_7 0x2fdc +#define AFE_CONN123_0 0x2fe0 +#define AFE_CONN123_1 0x2fe4 +#define AFE_CONN123_2 0x2fe8 +#define AFE_CONN123_4 0x2ff0 +#define AFE_CONN123_5 0x2ff4 +#define AFE_CONN123_6 0x2ff8 +#define AFE_CONN123_7 0x2ffc +#define AFE_CONN124_0 0x3000 +#define AFE_CONN124_1 0x3004 +#define AFE_CONN124_2 0x3008 +#define AFE_CONN124_4 0x3010 +#define AFE_CONN124_5 0x3014 +#define AFE_CONN124_6 0x3018 +#define AFE_CONN124_7 0x301c +#define AFE_CONN125_0 0x3020 +#define AFE_CONN125_1 0x3024 +#define AFE_CONN125_2 0x3028 +#define AFE_CONN125_4 0x3030 +#define AFE_CONN125_5 0x3034 +#define AFE_CONN125_6 0x3038 +#define AFE_CONN125_7 0x303c +#define AFE_CONN126_0 0x3040 +#define AFE_CONN126_1 0x3044 +#define AFE_CONN126_2 0x3048 +#define AFE_CONN126_4 0x3050 +#define AFE_CONN126_5 0x3054 +#define AFE_CONN126_6 0x3058 +#define AFE_CONN126_7 0x305c +#define AFE_CONN127_0 0x3060 +#define AFE_CONN127_1 0x3064 +#define AFE_CONN127_2 0x3068 +#define AFE_CONN127_4 0x3070 +#define AFE_CONN127_5 0x3074 +#define AFE_CONN127_6 0x3078 +#define AFE_CONN127_7 0x307c +#define AFE_CONN128_0 0x3080 +#define AFE_CONN128_1 0x3084 +#define AFE_CONN128_2 0x3088 +#define AFE_CONN128_4 0x3090 +#define AFE_CONN128_5 0x3094 +#define AFE_CONN128_6 0x3098 +#define AFE_CONN128_7 0x309c +#define AFE_CONN129_0 0x30a0 +#define AFE_CONN129_1 0x30a4 +#define AFE_CONN129_2 0x30a8 +#define AFE_CONN129_4 0x30b0 +#define AFE_CONN129_5 0x30b4 +#define AFE_CONN129_6 0x30b8 +#define AFE_CONN129_7 0x30bc +#define AFE_CONN130_0 0x30c0 +#define AFE_CONN130_1 0x30c4 +#define AFE_CONN130_2 0x30c8 +#define AFE_CONN130_4 0x30d0 +#define AFE_CONN130_5 0x30d4 +#define AFE_CONN130_6 0x30d8 +#define AFE_CONN130_7 0x30dc +#define AFE_CONN131_0 0x30e0 +#define AFE_CONN131_1 0x30e4 +#define AFE_CONN131_2 0x30e8 +#define AFE_CONN131_4 0x30f0 +#define AFE_CONN131_5 0x30f4 +#define AFE_CONN131_6 0x30f8 +#define AFE_CONN131_7 0x30fc +#define AFE_CONN132_0 0x3100 +#define AFE_CONN132_1 0x3104 +#define AFE_CONN132_2 0x3108 +#define AFE_CONN132_4 0x3110 +#define AFE_CONN132_5 0x3114 +#define AFE_CONN132_6 0x3118 +#define AFE_CONN132_7 0x311c +#define AFE_CONN133_0 0x3120 +#define AFE_CONN133_1 0x3124 +#define AFE_CONN133_2 0x3128 +#define AFE_CONN133_4 0x3130 +#define AFE_CONN133_5 0x3134 +#define AFE_CONN133_6 0x3138 +#define AFE_CONN133_7 0x313c +#define AFE_CONN134_0 0x3140 +#define AFE_CONN134_1 0x3144 +#define AFE_CONN134_2 0x3148 +#define AFE_CONN134_4 0x3150 +#define AFE_CONN134_5 0x3154 +#define AFE_CONN134_6 0x3158 +#define AFE_CONN134_7 0x315c +#define AFE_CONN135_0 0x3160 +#define AFE_CONN135_1 0x3164 +#define AFE_CONN135_2 0x3168 +#define AFE_CONN135_4 0x3170 +#define AFE_CONN135_5 0x3174 +#define AFE_CONN135_6 0x3178 +#define AFE_CONN135_7 0x317c +#define AFE_CONN136_0 0x3180 +#define AFE_CONN136_1 0x3184 +#define AFE_CONN136_2 0x3188 +#define AFE_CONN136_4 0x3190 +#define AFE_CONN136_5 0x3194 +#define AFE_CONN136_6 0x3198 +#define AFE_CONN136_7 0x319c +#define AFE_CONN137_0 0x31a0 +#define AFE_CONN137_1 0x31a4 +#define AFE_CONN137_2 0x31a8 +#define AFE_CONN137_4 0x31b0 +#define AFE_CONN137_5 0x31b4 +#define AFE_CONN137_6 0x31b8 +#define AFE_CONN137_7 0x31bc +#define AFE_CONN138_0 0x31c0 +#define AFE_CONN138_1 0x31c4 +#define AFE_CONN138_2 0x31c8 +#define AFE_CONN138_4 0x31d0 +#define AFE_CONN138_5 0x31d4 +#define AFE_CONN138_6 0x31d8 +#define AFE_CONN138_7 0x31dc +#define AFE_CONN139_0 0x31e0 +#define AFE_CONN139_1 0x31e4 +#define AFE_CONN139_2 0x31e8 +#define AFE_CONN139_4 0x31f0 +#define AFE_CONN139_5 0x31f4 +#define AFE_CONN139_6 0x31f8 +#define AFE_CONN139_7 0x31fc +#define AFE_CONN148_0 0x3300 +#define AFE_CONN148_1 0x3304 +#define AFE_CONN148_2 0x3308 +#define AFE_CONN148_4 0x3310 +#define AFE_CONN148_5 0x3314 +#define AFE_CONN148_6 0x3318 +#define AFE_CONN148_7 0x331c +#define AFE_CONN149_0 0x3320 +#define AFE_CONN149_1 0x3324 +#define AFE_CONN149_2 0x3328 +#define AFE_CONN149_4 0x3330 +#define AFE_CONN149_5 0x3334 +#define AFE_CONN149_6 0x3338 +#define AFE_CONN149_7 0x333c +#define AFE_CONN180_0 0x3700 +#define AFE_CONN180_1 0x3704 +#define AFE_CONN180_2 0x3708 +#define AFE_CONN180_4 0x3710 +#define AFE_CONN180_5 0x3714 +#define AFE_CONN180_6 0x3718 +#define AFE_CONN180_7 0x371c +#define AFE_CONN181_0 0x3720 +#define AFE_CONN181_1 0x3724 +#define AFE_CONN181_2 0x3728 +#define AFE_CONN181_4 0x3730 +#define AFE_CONN181_5 0x3734 +#define AFE_CONN181_6 0x3738 +#define AFE_CONN181_7 0x373c +#define AFE_CONN182_0 0x3740 +#define AFE_CONN182_1 0x3744 +#define AFE_CONN182_2 0x3748 +#define AFE_CONN182_4 0x3750 +#define AFE_CONN182_5 0x3754 +#define AFE_CONN182_6 0x3758 +#define AFE_CONN182_7 0x375c +#define AFE_CONN183_0 0x3760 +#define AFE_CONN183_1 0x3764 +#define AFE_CONN183_2 0x3768 +#define AFE_CONN183_4 0x3770 +#define AFE_CONN183_5 0x3774 +#define AFE_CONN183_6 0x3778 +#define AFE_CONN183_7 0x377c +#define AFE_CONN184_0 0x3780 +#define AFE_CONN184_1 0x3784 +#define AFE_CONN184_2 0x3788 +#define AFE_CONN184_4 0x3790 +#define AFE_CONN184_5 0x3794 +#define AFE_CONN184_6 0x3798 +#define AFE_CONN184_7 0x379c +#define AFE_CONN185_0 0x37a0 +#define AFE_CONN185_1 0x37a4 +#define AFE_CONN185_2 0x37a8 +#define AFE_CONN185_4 0x37b0 +#define AFE_CONN185_5 0x37b4 +#define AFE_CONN185_6 0x37b8 +#define AFE_CONN185_7 0x37bc +#define AFE_CONN186_0 0x37c0 +#define AFE_CONN186_1 0x37c4 +#define AFE_CONN186_2 0x37c8 +#define AFE_CONN186_4 0x37d0 +#define AFE_CONN186_5 0x37d4 +#define AFE_CONN186_6 0x37d8 +#define AFE_CONN186_7 0x37dc +#define AFE_CONN187_0 0x37e0 +#define AFE_CONN187_1 0x37e4 +#define AFE_CONN187_2 0x37e8 +#define AFE_CONN187_4 0x37f0 +#define AFE_CONN187_5 0x37f4 +#define AFE_CONN187_6 0x37f8 +#define AFE_CONN187_7 0x37fc +#define AFE_CONN188_0 0x3800 +#define AFE_CONN188_1 0x3804 +#define AFE_CONN188_2 0x3808 +#define AFE_CONN188_4 0x3810 +#define AFE_CONN188_5 0x3814 +#define AFE_CONN188_6 0x3818 +#define AFE_CONN188_7 0x381c +#define AFE_CONN189_0 0x3820 +#define AFE_CONN189_1 0x3824 +#define AFE_CONN189_2 0x3828 +#define AFE_CONN189_4 0x3830 +#define AFE_CONN189_5 0x3834 +#define AFE_CONN189_6 0x3838 +#define AFE_CONN189_7 0x383c +#define AFE_CONN190_0 0x3840 +#define AFE_CONN190_1 0x3844 +#define AFE_CONN190_2 0x3848 +#define AFE_CONN190_4 0x3850 +#define AFE_CONN190_5 0x3854 +#define AFE_CONN190_6 0x3858 +#define AFE_CONN190_7 0x385c +#define AFE_CONN191_0 0x3860 +#define AFE_CONN191_1 0x3864 +#define AFE_CONN191_2 0x3868 +#define AFE_CONN191_4 0x3870 +#define AFE_CONN191_5 0x3874 +#define AFE_CONN191_6 0x3878 +#define AFE_CONN191_7 0x387c +#define AFE_CONN192_0 0x3880 +#define AFE_CONN192_1 0x3884 +#define AFE_CONN192_2 0x3888 +#define AFE_CONN192_4 0x3890 +#define AFE_CONN192_5 0x3894 +#define AFE_CONN192_6 0x3898 +#define AFE_CONN192_7 0x389c +#define AFE_CONN193_0 0x38a0 +#define AFE_CONN193_1 0x38a4 +#define AFE_CONN193_2 0x38a8 +#define AFE_CONN193_4 0x38b0 +#define AFE_CONN193_5 0x38b4 +#define AFE_CONN193_6 0x38b8 +#define AFE_CONN193_7 0x38bc +#define AFE_CONN194_0 0x38c0 +#define AFE_CONN194_1 0x38c4 +#define AFE_CONN194_2 0x38c8 +#define AFE_CONN194_4 0x38d0 +#define AFE_CONN194_5 0x38d4 +#define AFE_CONN194_6 0x38d8 +#define AFE_CONN194_7 0x38dc +#define AFE_CONN195_0 0x38e0 +#define AFE_CONN195_1 0x38e4 +#define AFE_CONN195_2 0x38e8 +#define AFE_CONN195_4 0x38f0 +#define AFE_CONN195_5 0x38f4 +#define AFE_CONN195_6 0x38f8 +#define AFE_CONN195_7 0x38fc +#define AFE_CONN196_0 0x3900 +#define AFE_CONN196_1 0x3904 +#define AFE_CONN196_2 0x3908 +#define AFE_CONN196_4 0x3910 +#define AFE_CONN196_5 0x3914 +#define AFE_CONN196_6 0x3918 +#define AFE_CONN196_7 0x391c +#define AFE_CONN197_0 0x3920 +#define AFE_CONN197_1 0x3924 +#define AFE_CONN197_2 0x3928 +#define AFE_CONN197_4 0x3930 +#define AFE_CONN197_5 0x3934 +#define AFE_CONN197_6 0x3938 +#define AFE_CONN197_7 0x393c +#define AFE_CONN198_0 0x3940 +#define AFE_CONN198_1 0x3944 +#define AFE_CONN198_2 0x3948 +#define AFE_CONN198_4 0x3950 +#define AFE_CONN198_5 0x3954 +#define AFE_CONN198_6 0x3958 +#define AFE_CONN198_7 0x395c +#define AFE_CONN199_0 0x3960 +#define AFE_CONN199_1 0x3964 +#define AFE_CONN199_2 0x3968 +#define AFE_CONN199_4 0x3970 +#define AFE_CONN199_5 0x3974 +#define AFE_CONN199_6 0x3978 +#define AFE_CONN199_7 0x397c +#define AFE_CONN200_0 0x3980 +#define AFE_CONN200_1 0x3984 +#define AFE_CONN200_2 0x3988 +#define AFE_CONN200_4 0x3990 +#define AFE_CONN200_5 0x3994 +#define AFE_CONN200_6 0x3998 +#define AFE_CONN200_7 0x399c +#define AFE_CONN201_0 0x39a0 +#define AFE_CONN201_1 0x39a4 +#define AFE_CONN201_2 0x39a8 +#define AFE_CONN201_4 0x39b0 +#define AFE_CONN201_5 0x39b4 +#define AFE_CONN201_6 0x39b8 +#define AFE_CONN201_7 0x39bc +#define AFE_CONN202_0 0x39c0 +#define AFE_CONN202_1 0x39c4 +#define AFE_CONN202_2 0x39c8 +#define AFE_CONN202_4 0x39d0 +#define AFE_CONN202_5 0x39d4 +#define AFE_CONN202_6 0x39d8 +#define AFE_CONN202_7 0x39dc +#define AFE_CONN203_0 0x39e0 +#define AFE_CONN203_1 0x39e4 +#define AFE_CONN203_2 0x39e8 +#define AFE_CONN203_4 0x39f0 +#define AFE_CONN203_5 0x39f4 +#define AFE_CONN203_6 0x39f8 +#define AFE_CONN203_7 0x39fc +#define AFE_CONN204_0 0x3a00 +#define AFE_CONN204_1 0x3a04 +#define AFE_CONN204_2 0x3a08 +#define AFE_CONN204_4 0x3a10 +#define AFE_CONN204_5 0x3a14 +#define AFE_CONN204_6 0x3a18 +#define AFE_CONN204_7 0x3a1c +#define AFE_CONN205_0 0x3a20 +#define AFE_CONN205_1 0x3a24 +#define AFE_CONN205_2 0x3a28 +#define AFE_CONN205_4 0x3a30 +#define AFE_CONN205_5 0x3a34 +#define AFE_CONN205_6 0x3a38 +#define AFE_CONN205_7 0x3a3c +#define AFE_CONN206_0 0x3a40 +#define AFE_CONN206_1 0x3a44 +#define AFE_CONN206_2 0x3a48 +#define AFE_CONN206_4 0x3a50 +#define AFE_CONN206_5 0x3a54 +#define AFE_CONN206_6 0x3a58 +#define AFE_CONN206_7 0x3a5c +#define AFE_CONN207_0 0x3a60 +#define AFE_CONN207_1 0x3a64 +#define AFE_CONN207_2 0x3a68 +#define AFE_CONN207_4 0x3a70 +#define AFE_CONN207_5 0x3a74 +#define AFE_CONN207_6 0x3a78 +#define AFE_CONN207_7 0x3a7c +#define AFE_CONN208_0 0x3a80 +#define AFE_CONN208_1 0x3a84 +#define AFE_CONN208_2 0x3a88 +#define AFE_CONN208_4 0x3a90 +#define AFE_CONN208_5 0x3a94 +#define AFE_CONN208_6 0x3a98 +#define AFE_CONN208_7 0x3a9c +#define AFE_CONN209_0 0x3aa0 +#define AFE_CONN209_1 0x3aa4 +#define AFE_CONN209_2 0x3aa8 +#define AFE_CONN209_4 0x3ab0 +#define AFE_CONN209_5 0x3ab4 +#define AFE_CONN209_6 0x3ab8 +#define AFE_CONN209_7 0x3abc +#define AFE_CONN210_0 0x3ac0 +#define AFE_CONN210_1 0x3ac4 +#define AFE_CONN210_2 0x3ac8 +#define AFE_CONN210_4 0x3ad0 +#define AFE_CONN210_5 0x3ad4 +#define AFE_CONN210_6 0x3ad8 +#define AFE_CONN210_7 0x3adc +#define AFE_CONN211_0 0x3ae0 +#define AFE_CONN211_1 0x3ae4 +#define AFE_CONN211_2 0x3ae8 +#define AFE_CONN211_4 0x3af0 +#define AFE_CONN211_5 0x3af4 +#define AFE_CONN211_6 0x3af8 +#define AFE_CONN211_7 0x3afc +#define AFE_CONN_MON_CFG 0x4080 +#define AFE_CONN_MON0 0x4084 +#define AFE_CONN_MON1 0x4088 +#define AFE_CONN_MON2 0x408c +#define AFE_CONN_MON3 0x4090 +#define AFE_CONN_MON4 0x4094 +#define AFE_CONN_MON5 0x4098 +#define AFE_CONN_RS_0 0x40a0 +#define AFE_CONN_RS_1 0x40a4 +#define AFE_CONN_RS_2 0x40a8 +#define AFE_CONN_RS_3 0x40ac +#define AFE_CONN_RS_4 0x40b0 +#define AFE_CONN_RS_5 0x40b4 +#define AFE_CONN_RS_6 0x40b8 +#define AFE_CONN_DI_0 0x40c0 +#define AFE_CONN_DI_1 0x40c4 +#define AFE_CONN_DI_2 0x40c8 +#define AFE_CONN_DI_3 0x40cc +#define AFE_CONN_DI_4 0x40d0 +#define AFE_CONN_DI_5 0x40d4 +#define AFE_CONN_DI_6 0x40d8 +#define AFE_CONN_16BIT_0 0x40e0 +#define AFE_CONN_16BIT_1 0x40e4 +#define AFE_CONN_16BIT_2 0x40e8 +#define AFE_CONN_16BIT_3 0x40ec +#define AFE_CONN_16BIT_4 0x40f0 +#define AFE_CONN_16BIT_5 0x40f4 +#define AFE_CONN_16BIT_6 0x40f8 +#define AFE_CONN_24BIT_0 0x4100 +#define AFE_CONN_24BIT_1 0x4104 +#define AFE_CONN_24BIT_2 0x4108 +#define AFE_CONN_24BIT_3 0x410c +#define AFE_CONN_24BIT_4 0x4110 +#define AFE_CONN_24BIT_5 0x4114 +#define AFE_CONN_24BIT_6 0x4118 +#define AFE_CBIP_CFG0 0x4380 +#define AFE_CBIP_SLV_DECODER_MON0 0x4384 +#define AFE_CBIP_SLV_DECODER_MON1 0x4388 +#define AFE_CBIP_SLV_MUX_MON_CFG 0x438c +#define AFE_CBIP_SLV_MUX_MON0 0x4390 +#define AFE_CBIP_SLV_MUX_MON1 0x4394 +#define AFE_MEMIF_CON0 0x4400 +#define AFE_MEMIF_ONE_HEART 0x4420 +#define AFE_DL0_BASE_MSB 0x4440 +#define AFE_DL0_BASE 0x4444 +#define AFE_DL0_CUR_MSB 0x4448 +#define AFE_DL0_CUR 0x444c +#define AFE_DL0_END_MSB 0x4450 +#define AFE_DL0_END 0x4454 +#define AFE_DL0_RCH_MON 0x4458 +#define AFE_DL0_LCH_MON 0x445c +#define AFE_DL0_CON0 0x4460 +#define AFE_DL0_MON0 0x4464 +#define AFE_DL1_BASE_MSB 0x4470 +#define AFE_DL1_BASE 0x4474 +#define AFE_DL1_CUR_MSB 0x4478 +#define AFE_DL1_CUR 0x447c +#define AFE_DL1_END_MSB 0x4480 +#define AFE_DL1_END 0x4484 +#define AFE_DL1_RCH_MON 0x4488 +#define AFE_DL1_LCH_MON 0x448c +#define AFE_DL1_CON0 0x4490 +#define AFE_DL1_MON0 0x4494 +#define AFE_DL2_BASE_MSB 0x44a0 +#define AFE_DL2_BASE 0x44a4 +#define AFE_DL2_CUR_MSB 0x44a8 +#define AFE_DL2_CUR 0x44ac +#define AFE_DL2_END_MSB 0x44b0 +#define AFE_DL2_END 0x44b4 +#define AFE_DL2_RCH_MON 0x44b8 +#define AFE_DL2_LCH_MON 0x44bc +#define AFE_DL2_CON0 0x44c0 +#define AFE_DL2_MON0 0x44c4 +#define AFE_DL3_BASE_MSB 0x44d0 +#define AFE_DL3_BASE 0x44d4 +#define AFE_DL3_CUR_MSB 0x44d8 +#define AFE_DL3_CUR 0x44dc +#define AFE_DL3_END_MSB 0x44e0 +#define AFE_DL3_END 0x44e4 +#define AFE_DL3_RCH_MON 0x44e8 +#define AFE_DL3_LCH_MON 0x44ec +#define AFE_DL3_CON0 0x44f0 +#define AFE_DL3_MON0 0x44f4 +#define AFE_DL4_BASE_MSB 0x4500 +#define AFE_DL4_BASE 0x4504 +#define AFE_DL4_CUR_MSB 0x4508 +#define AFE_DL4_CUR 0x450c +#define AFE_DL4_END_MSB 0x4510 +#define AFE_DL4_END 0x4514 +#define AFE_DL4_RCH_MON 0x4518 +#define AFE_DL4_LCH_MON 0x451c +#define AFE_DL4_CON0 0x4520 +#define AFE_DL4_MON0 0x4524 +#define AFE_DL5_BASE_MSB 0x4530 +#define AFE_DL5_BASE 0x4534 +#define AFE_DL5_CUR_MSB 0x4538 +#define AFE_DL5_CUR 0x453c +#define AFE_DL5_END_MSB 0x4540 +#define AFE_DL5_END 0x4544 +#define AFE_DL5_RCH_MON 0x4548 +#define AFE_DL5_LCH_MON 0x454c +#define AFE_DL5_CON0 0x4550 +#define AFE_DL5_MON0 0x4554 +#define AFE_DL6_BASE_MSB 0x4560 +#define AFE_DL6_BASE 0x4564 +#define AFE_DL6_CUR_MSB 0x4568 +#define AFE_DL6_CUR 0x456c +#define AFE_DL6_END_MSB 0x4570 +#define AFE_DL6_END 0x4574 +#define AFE_DL6_RCH_MON 0x4578 +#define AFE_DL6_LCH_MON 0x457c +#define AFE_DL6_CON0 0x4580 +#define AFE_DL6_MON0 0x4584 +#define AFE_DL7_BASE_MSB 0x4590 +#define AFE_DL7_BASE 0x4594 +#define AFE_DL7_CUR_MSB 0x4598 +#define AFE_DL7_CUR 0x459c +#define AFE_DL7_END_MSB 0x45a0 +#define AFE_DL7_END 0x45a4 +#define AFE_DL7_RCH_MON 0x45a8 +#define AFE_DL7_LCH_MON 0x45ac +#define AFE_DL7_CON0 0x45b0 +#define AFE_DL7_MON0 0x45b4 +#define AFE_DL8_BASE_MSB 0x45c0 +#define AFE_DL8_BASE 0x45c4 +#define AFE_DL8_CUR_MSB 0x45c8 +#define AFE_DL8_CUR 0x45cc +#define AFE_DL8_END_MSB 0x45d0 +#define AFE_DL8_END 0x45d4 +#define AFE_DL8_RCH_MON 0x45d8 +#define AFE_DL8_LCH_MON 0x45dc +#define AFE_DL8_CON0 0x45e0 +#define AFE_DL8_MON0 0x45e4 +#define AFE_DL_4CH_BASE_MSB 0x45f0 +#define AFE_DL_4CH_BASE 0x45f4 +#define AFE_DL_4CH_CUR_MSB 0x45f8 +#define AFE_DL_4CH_CUR 0x45fc +#define AFE_DL_4CH_END_MSB 0x4600 +#define AFE_DL_4CH_END 0x4604 +#define AFE_DL_4CH_CON0 0x4610 +#define AFE_DL_4CH_MON0 0x4618 +#define AFE_DL_24CH_BASE_MSB 0x4620 +#define AFE_DL_24CH_BASE 0x4624 +#define AFE_DL_24CH_CUR_MSB 0x4628 +#define AFE_DL_24CH_CUR 0x462c +#define AFE_DL_24CH_END_MSB 0x4630 +#define AFE_DL_24CH_END 0x4634 +#define AFE_DL_24CH_CON0 0x4640 +#define AFE_DL_24CH_MON0 0x4648 +#define AFE_DL23_BASE_MSB 0x4680 +#define AFE_DL23_BASE 0x4684 +#define AFE_DL23_CUR_MSB 0x4688 +#define AFE_DL23_CUR 0x468c +#define AFE_DL23_END_MSB 0x4690 +#define AFE_DL23_END 0x4694 +#define AFE_DL23_RCH_MON 0x4698 +#define AFE_DL23_LCH_MON 0x469c +#define AFE_DL23_CON0 0x46a0 +#define AFE_DL23_MON0 0x46a4 +#define AFE_DL24_BASE_MSB 0x46b0 +#define AFE_DL24_BASE 0x46b4 +#define AFE_DL24_CUR_MSB 0x46b8 +#define AFE_DL24_CUR 0x46bc +#define AFE_DL24_END_MSB 0x46c0 +#define AFE_DL24_END 0x46c4 +#define AFE_DL24_RCH_MON 0x46c8 +#define AFE_DL24_LCH_MON 0x46cc +#define AFE_DL24_CON0 0x46d0 +#define AFE_DL24_MON0 0x46d4 +#define AFE_DL25_BASE_MSB 0x46e0 +#define AFE_DL25_BASE 0x46e4 +#define AFE_DL25_CUR_MSB 0x46e8 +#define AFE_DL25_CUR 0x46ec +#define AFE_DL25_END_MSB 0x46f0 +#define AFE_DL25_END 0x46f4 +#define AFE_DL25_RCH_MON 0x46f8 +#define AFE_DL25_LCH_MON 0x46fc +#define AFE_DL25_CON0 0x4700 +#define AFE_DL25_MON0 0x4704 +#define AFE_DL26_BASE_MSB 0x4710 +#define AFE_DL26_BASE 0x4714 +#define AFE_DL26_CUR_MSB 0x4718 +#define AFE_DL26_CUR 0x471c +#define AFE_DL26_END_MSB 0x4720 +#define AFE_DL26_END 0x4724 +#define AFE_DL26_RCH_MON 0x4728 +#define AFE_DL26_LCH_MON 0x472c +#define AFE_DL26_CON0 0x4730 +#define AFE_DL26_MON0 0x4734 +#define AFE_VUL0_BASE_MSB 0x4d60 +#define AFE_VUL0_BASE 0x4d64 +#define AFE_VUL0_CUR_MSB 0x4d68 +#define AFE_VUL0_CUR 0x4d6c +#define AFE_VUL0_END_MSB 0x4d70 +#define AFE_VUL0_END 0x4d74 +#define AFE_VUL0_RCH_MON 0x4d78 +#define AFE_VUL0_LCH_MON 0x4d7c +#define AFE_VUL0_CON0 0x4d80 +#define AFE_VUL0_MON0 0x4d84 +#define AFE_VUL1_BASE_MSB 0x4d90 +#define AFE_VUL1_BASE 0x4d94 +#define AFE_VUL1_CUR_MSB 0x4d98 +#define AFE_VUL1_CUR 0x4d9c +#define AFE_VUL1_END_MSB 0x4da0 +#define AFE_VUL1_END 0x4da4 +#define AFE_VUL1_RCH_MON 0x4da8 +#define AFE_VUL1_LCH_MON 0x4dac +#define AFE_VUL1_CON0 0x4db0 +#define AFE_VUL1_MON0 0x4db4 +#define AFE_VUL2_BASE_MSB 0x4dc0 +#define AFE_VUL2_BASE 0x4dc4 +#define AFE_VUL2_CUR_MSB 0x4dc8 +#define AFE_VUL2_CUR 0x4dcc +#define AFE_VUL2_END_MSB 0x4dd0 +#define AFE_VUL2_END 0x4dd4 +#define AFE_VUL2_RCH_MON 0x4dd8 +#define AFE_VUL2_LCH_MON 0x4ddc +#define AFE_VUL2_CON0 0x4de0 +#define AFE_VUL2_MON0 0x4de4 +#define AFE_VUL3_BASE_MSB 0x4df0 +#define AFE_VUL3_BASE 0x4df4 +#define AFE_VUL3_CUR_MSB 0x4df8 +#define AFE_VUL3_CUR 0x4dfc +#define AFE_VUL3_END_MSB 0x4e00 +#define AFE_VUL3_END 0x4e04 +#define AFE_VUL3_RCH_MON 0x4e08 +#define AFE_VUL3_LCH_MON 0x4e0c +#define AFE_VUL3_CON0 0x4e10 +#define AFE_VUL3_MON0 0x4e14 +#define AFE_VUL4_BASE_MSB 0x4e20 +#define AFE_VUL4_BASE 0x4e24 +#define AFE_VUL4_CUR_MSB 0x4e28 +#define AFE_VUL4_CUR 0x4e2c +#define AFE_VUL4_END_MSB 0x4e30 +#define AFE_VUL4_END 0x4e34 +#define AFE_VUL4_RCH_MON 0x4e38 +#define AFE_VUL4_LCH_MON 0x4e3c +#define AFE_VUL4_CON0 0x4e40 +#define AFE_VUL4_MON0 0x4e44 +#define AFE_VUL5_BASE_MSB 0x4e50 +#define AFE_VUL5_BASE 0x4e54 +#define AFE_VUL5_CUR_MSB 0x4e58 +#define AFE_VUL5_CUR 0x4e5c +#define AFE_VUL5_END_MSB 0x4e60 +#define AFE_VUL5_END 0x4e64 +#define AFE_VUL5_RCH_MON 0x4e68 +#define AFE_VUL5_LCH_MON 0x4e6c +#define AFE_VUL5_CON0 0x4e70 +#define AFE_VUL5_MON0 0x4e74 +#define AFE_VUL6_BASE_MSB 0x4e80 +#define AFE_VUL6_BASE 0x4e84 +#define AFE_VUL6_CUR_MSB 0x4e88 +#define AFE_VUL6_CUR 0x4e8c +#define AFE_VUL6_END_MSB 0x4e90 +#define AFE_VUL6_END 0x4e94 +#define AFE_VUL6_RCH_MON 0x4e98 +#define AFE_VUL6_LCH_MON 0x4e9c +#define AFE_VUL6_CON0 0x4ea0 +#define AFE_VUL6_MON0 0x4ea4 +#define AFE_VUL7_BASE_MSB 0x4eb0 +#define AFE_VUL7_BASE 0x4eb4 +#define AFE_VUL7_CUR_MSB 0x4eb8 +#define AFE_VUL7_CUR 0x4ebc +#define AFE_VUL7_END_MSB 0x4ec0 +#define AFE_VUL7_END 0x4ec4 +#define AFE_VUL7_RCH_MON 0x4ec8 +#define AFE_VUL7_LCH_MON 0x4ecc +#define AFE_VUL7_CON0 0x4ed0 +#define AFE_VUL7_MON0 0x4ed4 +#define AFE_VUL8_BASE_MSB 0x4ee0 +#define AFE_VUL8_BASE 0x4ee4 +#define AFE_VUL8_CUR_MSB 0x4ee8 +#define AFE_VUL8_CUR 0x4eec +#define AFE_VUL8_END_MSB 0x4ef0 +#define AFE_VUL8_END 0x4ef4 +#define AFE_VUL8_RCH_MON 0x4ef8 +#define AFE_VUL8_LCH_MON 0x4efc +#define AFE_VUL8_CON0 0x4f00 +#define AFE_VUL8_MON0 0x4f04 +#define AFE_VUL9_BASE_MSB 0x4f10 +#define AFE_VUL9_BASE 0x4f14 +#define AFE_VUL9_CUR_MSB 0x4f18 +#define AFE_VUL9_CUR 0x4f1c +#define AFE_VUL9_END_MSB 0x4f20 +#define AFE_VUL9_END 0x4f24 +#define AFE_VUL9_RCH_MON 0x4f28 +#define AFE_VUL9_LCH_MON 0x4f2c +#define AFE_VUL9_CON0 0x4f30 +#define AFE_VUL9_MON0 0x4f34 +#define AFE_VUL10_BASE_MSB 0x4f40 +#define AFE_VUL10_BASE 0x4f44 +#define AFE_VUL10_CUR_MSB 0x4f48 +#define AFE_VUL10_CUR 0x4f4c +#define AFE_VUL10_END_MSB 0x4f50 +#define AFE_VUL10_END 0x4f54 +#define AFE_VUL10_RCH_MON 0x4f58 +#define AFE_VUL10_LCH_MON 0x4f5c +#define AFE_VUL10_CON0 0x4f60 +#define AFE_VUL10_MON0 0x4f64 +#define AFE_VUL24_BASE_MSB 0x4fa0 +#define AFE_VUL24_BASE 0x4fa4 +#define AFE_VUL24_CUR_MSB 0x4fa8 +#define AFE_VUL24_CUR 0x4fac +#define AFE_VUL24_END_MSB 0x4fb0 +#define AFE_VUL24_END 0x4fb4 +#define AFE_VUL24_CON0 0x4fb8 +#define AFE_VUL24_MON0 0x4fbc +#define AFE_VUL25_BASE_MSB 0x4fc0 +#define AFE_VUL25_BASE 0x4fc4 +#define AFE_VUL25_CUR_MSB 0x4fc8 +#define AFE_VUL25_CUR 0x4fcc +#define AFE_VUL25_END_MSB 0x4fd0 +#define AFE_VUL25_END 0x4fd4 +#define AFE_VUL25_CON0 0x4fd8 +#define AFE_VUL25_MON0 0x4fdc +#define AFE_VUL26_BASE_MSB 0x4fe0 +#define AFE_VUL26_BASE 0x4fe4 +#define AFE_VUL26_CUR_MSB 0x4fe8 +#define AFE_VUL26_CUR 0x4fec +#define AFE_VUL26_END_MSB 0x4ff0 +#define AFE_VUL26_END 0x4ff4 +#define AFE_VUL26_CON0 0x4ff8 +#define AFE_VUL26_MON0 0x4ffc +#define AFE_VUL_CM0_BASE_MSB 0x51c0 +#define AFE_VUL_CM0_BASE 0x51c4 +#define AFE_VUL_CM0_CUR_MSB 0x51c8 +#define AFE_VUL_CM0_CUR 0x51cc +#define AFE_VUL_CM0_END_MSB 0x51d0 +#define AFE_VUL_CM0_END 0x51d4 +#define AFE_VUL_CM0_CON0 0x51d8 +#define AFE_VUL_CM1_BASE_MSB 0x51e0 +#define AFE_VUL_CM1_BASE 0x51e4 +#define AFE_VUL_CM1_CUR_MSB 0x51e8 +#define AFE_VUL_CM1_CUR 0x51ec +#define AFE_VUL_CM1_END_MSB 0x51f0 +#define AFE_VUL_CM1_END 0x51f4 +#define AFE_VUL_CM1_CON0 0x51f8 +#define AFE_VUL_CM2_BASE_MSB 0x5200 +#define AFE_VUL_CM2_BASE 0x5204 +#define AFE_VUL_CM2_CUR_MSB 0x5208 +#define AFE_VUL_CM2_CUR 0x520c +#define AFE_VUL_CM2_END_MSB 0x5210 +#define AFE_VUL_CM2_END 0x5214 +#define AFE_VUL_CM2_CON0 0x5218 +#define AFE_ETDM_IN0_BASE_MSB 0x5220 +#define AFE_ETDM_IN0_BASE 0x5224 +#define AFE_ETDM_IN0_CUR_MSB 0x5228 +#define AFE_ETDM_IN0_CUR 0x522c +#define AFE_ETDM_IN0_END_MSB 0x5230 +#define AFE_ETDM_IN0_END 0x5234 +#define AFE_ETDM_IN0_CON0 0x5238 +#define AFE_ETDM_IN1_BASE_MSB 0x5240 +#define AFE_ETDM_IN1_BASE 0x5244 +#define AFE_ETDM_IN1_CUR_MSB 0x5248 +#define AFE_ETDM_IN1_CUR 0x524c +#define AFE_ETDM_IN1_END_MSB 0x5250 +#define AFE_ETDM_IN1_END 0x5254 +#define AFE_ETDM_IN1_CON0 0x5258 +#define AFE_ETDM_IN2_BASE_MSB 0x5260 +#define AFE_ETDM_IN2_BASE 0x5264 +#define AFE_ETDM_IN2_CUR_MSB 0x5268 +#define AFE_ETDM_IN2_CUR 0x526c +#define AFE_ETDM_IN2_END_MSB 0x5270 +#define AFE_ETDM_IN2_END 0x5274 +#define AFE_ETDM_IN2_CON0 0x5278 +#define AFE_ETDM_IN3_BASE_MSB 0x5280 +#define AFE_ETDM_IN3_BASE 0x5284 +#define AFE_ETDM_IN3_CUR_MSB 0x5288 +#define AFE_ETDM_IN3_CUR 0x528c +#define AFE_ETDM_IN3_END_MSB 0x5290 +#define AFE_ETDM_IN3_END 0x5294 +#define AFE_ETDM_IN3_CON0 0x5298 +#define AFE_ETDM_IN4_BASE_MSB 0x52a0 +#define AFE_ETDM_IN4_BASE 0x52a4 +#define AFE_ETDM_IN4_CUR_MSB 0x52a8 +#define AFE_ETDM_IN4_CUR 0x52ac +#define AFE_ETDM_IN4_END_MSB 0x52b0 +#define AFE_ETDM_IN4_END 0x52b4 +#define AFE_ETDM_IN4_CON0 0x52b8 +#define AFE_ETDM_IN5_BASE_MSB 0x52c0 +#define AFE_ETDM_IN5_BASE 0x52c4 +#define AFE_ETDM_IN5_CUR_MSB 0x52c8 +#define AFE_ETDM_IN5_CUR 0x52cc +#define AFE_ETDM_IN5_END_MSB 0x52d0 +#define AFE_ETDM_IN5_END 0x52d4 +#define AFE_ETDM_IN5_CON0 0x52d8 +#define AFE_ETDM_IN6_BASE_MSB 0x52e0 +#define AFE_ETDM_IN6_BASE 0x52e4 +#define AFE_ETDM_IN6_CUR_MSB 0x52e8 +#define AFE_ETDM_IN6_CUR 0x52ec +#define AFE_ETDM_IN6_END_MSB 0x52f0 +#define AFE_ETDM_IN6_END 0x52f4 +#define AFE_ETDM_IN6_CON0 0x52f8 +#define AFE_HDMI_OUT_BASE_MSB 0x5360 +#define AFE_HDMI_OUT_BASE 0x5364 +#define AFE_HDMI_OUT_CUR_MSB 0x5368 +#define AFE_HDMI_OUT_CUR 0x536c +#define AFE_HDMI_OUT_END_MSB 0x5370 +#define AFE_HDMI_OUT_END 0x5374 +#define AFE_HDMI_OUT_CON0 0x5378 +#define AFE_VUL24_RCH_MON 0x53e0 +#define AFE_VUL24_LCH_MON 0x53e4 +#define AFE_VUL25_RCH_MON 0x53e8 +#define AFE_VUL25_LCH_MON 0x53ec +#define AFE_VUL26_RCH_MON 0x53f0 +#define AFE_VUL26_LCH_MON 0x53f4 +#define AFE_VUL_CM0_RCH_MON 0x5458 +#define AFE_VUL_CM0_LCH_MON 0x545c +#define AFE_VUL_CM1_RCH_MON 0x5460 +#define AFE_VUL_CM1_LCH_MON 0x5464 +#define AFE_VUL_CM2_RCH_MON 0x5468 +#define AFE_VUL_CM2_LCH_MON 0x546c +#define AFE_DL_4CH_CH0_MON 0x54f4 +#define AFE_DL_4CH_CH1_MON 0x54f8 +#define AFE_DL_4CH_CH2_MON 0x54fc +#define AFE_DL_4CH_CH3_MON 0x5500 +#define AFE_DL_24CH_CH0_MON 0x5504 +#define AFE_DL_24CH_CH1_MON 0x5508 +#define AFE_DL_24CH_CH2_MON 0x550c +#define AFE_DL_24CH_CH3_MON 0x5510 +#define AFE_DL_24CH_CH4_MON 0x5514 +#define AFE_DL_24CH_CH5_MON 0x5518 +#define AFE_DL_24CH_CH6_MON 0x551c +#define AFE_DL_24CH_CH7_MON 0x5520 +#define AFE_DL_24CH_CH8_MON 0x5524 +#define AFE_DL_24CH_CH9_MON 0x5528 +#define AFE_DL_24CH_CH10_MON 0x552c +#define AFE_DL_24CH_CH11_MON 0x5530 +#define AFE_DL_24CH_CH12_MON 0x5534 +#define AFE_DL_24CH_CH13_MON 0x5538 +#define AFE_DL_24CH_CH14_MON 0x553c +#define AFE_DL_24CH_CH15_MON 0x5540 +#define AFE_SRAM_BOUND 0x5620 +#define AFE_SECURE_CON0 0x5624 +#define AFE_SECURE_CON1 0x5628 +#define AFE_SE_SECURE_CON0 0x5630 +#define AFE_SE_SECURE_CON1 0x5634 +#define AFE_SE_SECURE_CON2 0x5638 +#define AFE_SE_SECURE_CON3 0x563c +#define AFE_SE_PROT_SIDEBAND0 0x5640 +#define AFE_SE_PROT_SIDEBAND1 0x5644 +#define AFE_SE_PROT_SIDEBAND2 0x5648 +#define AFE_SE_PROT_SIDEBAND3 0x564c +#define AFE_SE_DOMAIN_SIDEBAND0 0x5650 +#define AFE_SE_DOMAIN_SIDEBAND1 0x5654 +#define AFE_SE_DOMAIN_SIDEBAND2 0x5658 +#define AFE_SE_DOMAIN_SIDEBAND3 0x565c +#define AFE_SE_DOMAIN_SIDEBAND4 0x5660 +#define AFE_SE_DOMAIN_SIDEBAND5 0x5664 +#define AFE_SE_DOMAIN_SIDEBAND6 0x5668 +#define AFE_SE_DOMAIN_SIDEBAND7 0x566c +#define AFE_SE_DOMAIN_SIDEBAND8 0x5670 +#define AFE_SE_DOMAIN_SIDEBAND9 0x5674 +#define AFE_PROT_SIDEBAND0_MON 0x5678 +#define AFE_PROT_SIDEBAND1_MON 0x567c +#define AFE_PROT_SIDEBAND2_MON 0x5680 +#define AFE_PROT_SIDEBAND3_MON 0x5684 +#define AFE_DOMAIN_SIDEBAND0_MON 0x5688 +#define AFE_DOMAIN_SIDEBAND1_MON 0x568c +#define AFE_DOMAIN_SIDEBAND2_MON 0x5690 +#define AFE_DOMAIN_SIDEBAND3_MON 0x5694 +#define AFE_DOMAIN_SIDEBAND4_MON 0x5698 +#define AFE_DOMAIN_SIDEBAND5_MON 0x569c +#define AFE_DOMAIN_SIDEBAND6_MON 0x56a0 +#define AFE_DOMAIN_SIDEBAND7_MON 0x56a4 +#define AFE_DOMAIN_SIDEBAND8_MON 0x56a8 +#define AFE_DOMAIN_SIDEBAND9_MON 0x56ac +#define AFE_SECURE_CONN0 0x56b0 +#define AFE_SECURE_CONN_ETDM0 0x56b4 +#define AFE_SECURE_CONN_ETDM1 0x56b8 +#define AFE_SECURE_CONN_ETDM2 0x56bc +#define AFE_SECURE_SRAM_CON0 0x56c0 +#define AFE_SECURE_SRAM_CON1 0x56c4 +#define AFE_SE_CONN_INPUT_MASK0 0x56d0 +#define AFE_SE_CONN_INPUT_MASK1 0x56d4 +#define AFE_SE_CONN_INPUT_MASK2 0x56d8 +#define AFE_SE_CONN_INPUT_MASK3 0x56dc +#define AFE_SE_CONN_INPUT_MASK4 0x56e0 +#define AFE_SE_CONN_INPUT_MASK5 0x56e4 +#define AFE_SE_CONN_INPUT_MASK6 0x56e8 +#define AFE_SE_CONN_INPUT_MASK7 0x56ec +#define AFE_NON_SE_CONN_INPUT_MASK0 0x56f0 +#define AFE_NON_SE_CONN_INPUT_MASK1 0x56f4 +#define AFE_NON_SE_CONN_INPUT_MASK2 0x56f8 +#define AFE_NON_SE_CONN_INPUT_MASK3 0x56fc +#define AFE_NON_SE_CONN_INPUT_MASK4 0x5700 +#define AFE_NON_SE_CONN_INPUT_MASK5 0x5704 +#define AFE_NON_SE_CONN_INPUT_MASK6 0x5708 +#define AFE_NON_SE_CONN_INPUT_MASK7 0x570c +#define AFE_SE_CONN_OUTPUT_SEL0 0x5710 +#define AFE_SE_CONN_OUTPUT_SEL1 0x5714 +#define AFE_SE_CONN_OUTPUT_SEL2 0x5718 +#define AFE_SE_CONN_OUTPUT_SEL3 0x571c +#define AFE_SE_CONN_OUTPUT_SEL4 0x5720 +#define AFE_SE_CONN_OUTPUT_SEL5 0x5724 +#define AFE_SE_CONN_OUTPUT_SEL6 0x5728 +#define AFE_SE_CONN_OUTPUT_SEL7 0x572c +#define AFE_PCM0_INTF_CON1_MASK_MON 0x5730 +#define AFE_PCM0_INTF_CON0_MASK_MON 0x5734 +#define AFE_CONNSYS_I2S_CON_MASK_MON 0x5738 +#define AFE_TDM_CON2_MASK_MON 0x5744 +#define AFE_MTKAIF0_CFG0_MASK_MON 0x574c +#define AFE_MTKAIF1_CFG0_MASK_MON 0x5750 +#define AFE_ADDA_UL0_SRC_CON0_MASK_MON 0x5754 +#define AFE_ADDA_UL1_SRC_CON0_MASK_MON 0x5758 +#define AFE_ADDA_UL2_SRC_CON0_MASK_MON 0x575c +#define AFE_ASRC_NEW_CON0 0x7800 +#define AFE_ASRC_NEW_CON1 0x7804 +#define AFE_ASRC_NEW_CON2 0x7808 +#define AFE_ASRC_NEW_CON3 0x780c +#define AFE_ASRC_NEW_CON4 0x7810 +#define AFE_ASRC_NEW_CON5 0x7814 +#define AFE_ASRC_NEW_CON6 0x7818 +#define AFE_ASRC_NEW_CON7 0x781c +#define AFE_ASRC_NEW_CON8 0x7820 +#define AFE_ASRC_NEW_CON9 0x7824 +#define AFE_ASRC_NEW_CON10 0x7828 +#define AFE_ASRC_NEW_CON11 0x782c +#define AFE_ASRC_NEW_CON12 0x7830 +#define AFE_ASRC_NEW_CON13 0x7834 +#define AFE_ASRC_NEW_CON14 0x7838 +#define AFE_ASRC_NEW_IP_VERSION 0x783c +#define AFE_GASRC0_NEW_CON0 0x7840 +#define AFE_GASRC0_NEW_CON1 0x7844 +#define AFE_GASRC0_NEW_CON2 0x7848 +#define AFE_GASRC0_NEW_CON3 0x784c +#define AFE_GASRC0_NEW_CON4 0x7850 +#define AFE_GASRC0_NEW_CON5 0x7854 +#define AFE_GASRC0_NEW_CON6 0x7858 +#define AFE_GASRC0_NEW_CON7 0x785c +#define AFE_GASRC0_NEW_CON8 0x7860 +#define AFE_GASRC0_NEW_CON9 0x7864 +#define AFE_GASRC0_NEW_CON10 0x7868 +#define AFE_GASRC0_NEW_CON11 0x786c +#define AFE_GASRC0_NEW_CON12 0x7870 +#define AFE_GASRC0_NEW_CON13 0x7874 +#define AFE_GASRC0_NEW_CON14 0x7878 +#define AFE_GASRC0_NEW_IP_VERSION 0x787c +#define AFE_GASRC1_NEW_CON0 0x7880 +#define AFE_GASRC1_NEW_CON1 0x7884 +#define AFE_GASRC1_NEW_CON2 0x7888 +#define AFE_GASRC1_NEW_CON3 0x788c +#define AFE_GASRC1_NEW_CON4 0x7890 +#define AFE_GASRC1_NEW_CON5 0x7894 +#define AFE_GASRC1_NEW_CON6 0x7898 +#define AFE_GASRC1_NEW_CON7 0x789c +#define AFE_GASRC1_NEW_CON8 0x78a0 +#define AFE_GASRC1_NEW_CON9 0x78a4 +#define AFE_GASRC1_NEW_CON10 0x78a8 +#define AFE_GASRC1_NEW_CON11 0x78ac +#define AFE_GASRC1_NEW_CON12 0x78b0 +#define AFE_GASRC1_NEW_CON13 0x78b4 +#define AFE_GASRC1_NEW_CON14 0x78b8 +#define AFE_GASRC1_NEW_IP_VERSION 0x78bc +#define AFE_GASRC2_NEW_CON0 0x78c0 +#define AFE_GASRC2_NEW_CON1 0x78c4 +#define AFE_GASRC2_NEW_CON2 0x78c8 +#define AFE_GASRC2_NEW_CON3 0x78cc +#define AFE_GASRC2_NEW_CON4 0x78d0 +#define AFE_GASRC2_NEW_CON5 0x78d4 +#define AFE_GASRC2_NEW_CON6 0x78d8 +#define AFE_GASRC2_NEW_CON7 0x78dc +#define AFE_GASRC2_NEW_CON8 0x78e0 +#define AFE_GASRC2_NEW_CON9 0x78e4 +#define AFE_GASRC2_NEW_CON10 0x78e8 +#define AFE_GASRC2_NEW_CON11 0x78ec +#define AFE_GASRC2_NEW_CON12 0x78f0 +#define AFE_GASRC2_NEW_CON13 0x78f4 +#define AFE_GASRC2_NEW_CON14 0x78f8 +#define AFE_GASRC2_NEW_IP_VERSION 0x78fc +#define AFE_GASRC3_NEW_CON0 0x7900 +#define AFE_GASRC3_NEW_CON1 0x7904 +#define AFE_GASRC3_NEW_CON2 0x7908 +#define AFE_GASRC3_NEW_CON3 0x790c +#define AFE_GASRC3_NEW_CON4 0x7910 +#define AFE_GASRC3_NEW_CON5 0x7914 +#define AFE_GASRC3_NEW_CON6 0x7918 +#define AFE_GASRC3_NEW_CON7 0x791c +#define AFE_GASRC3_NEW_CON8 0x7920 +#define AFE_GASRC3_NEW_CON9 0x7924 +#define AFE_GASRC3_NEW_CON10 0x7928 +#define AFE_GASRC3_NEW_CON11 0x792c +#define AFE_GASRC3_NEW_CON12 0x7930 +#define AFE_GASRC3_NEW_CON13 0x7934 +#define AFE_GASRC3_NEW_CON14 0x7938 +#define AFE_GASRC3_NEW_IP_VERSION 0x793c +#define AFE_GASRC4_NEW_CON0 0x7940 +#define AFE_GASRC4_NEW_CON1 0x7944 +#define AFE_GASRC4_NEW_CON2 0x7948 +#define AFE_GASRC4_NEW_CON3 0x794c +#define AFE_GASRC4_NEW_CON4 0x7950 +#define AFE_GASRC4_NEW_CON5 0x7954 +#define AFE_GASRC4_NEW_CON6 0x7958 +#define AFE_GASRC4_NEW_CON7 0x795c +#define AFE_GASRC4_NEW_CON8 0x7960 +#define AFE_GASRC4_NEW_CON9 0x7964 +#define AFE_GASRC4_NEW_CON10 0x7968 +#define AFE_GASRC4_NEW_CON11 0x796c +#define AFE_GASRC4_NEW_CON12 0x7970 +#define AFE_GASRC4_NEW_CON13 0x7974 +#define AFE_GASRC4_NEW_CON14 0x7978 +#define AFE_GASRC4_NEW_IP_VERSION 0x797c +#define AFE_GASRC5_NEW_CON0 0x7980 +#define AFE_GASRC5_NEW_CON1 0x7984 +#define AFE_GASRC5_NEW_CON2 0x7988 +#define AFE_GASRC5_NEW_CON3 0x798c +#define AFE_GASRC5_NEW_CON4 0x7990 +#define AFE_GASRC5_NEW_CON5 0x7994 +#define AFE_GASRC5_NEW_CON6 0x7998 +#define AFE_GASRC5_NEW_CON7 0x799c +#define AFE_GASRC5_NEW_CON8 0x79a0 +#define AFE_GASRC5_NEW_CON9 0x79a4 +#define AFE_GASRC5_NEW_CON10 0x79a8 +#define AFE_GASRC5_NEW_CON11 0x79ac +#define AFE_GASRC5_NEW_CON12 0x79b0 +#define AFE_GASRC5_NEW_CON13 0x79b4 +#define AFE_GASRC5_NEW_CON14 0x79b8 +#define AFE_GASRC5_NEW_IP_VERSION 0x79bc +#define AFE_GASRC6_NEW_CON0 0x79c0 +#define AFE_GASRC6_NEW_CON1 0x79c4 +#define AFE_GASRC6_NEW_CON2 0x79c8 +#define AFE_GASRC6_NEW_CON3 0x79cc +#define AFE_GASRC6_NEW_CON4 0x79d0 +#define AFE_GASRC6_NEW_CON5 0x79d4 +#define AFE_GASRC6_NEW_CON6 0x79d8 +#define AFE_GASRC6_NEW_CON7 0x79dc +#define AFE_GASRC6_NEW_CON8 0x79e0 +#define AFE_GASRC6_NEW_CON9 0x79e4 +#define AFE_GASRC6_NEW_CON10 0x79e8 +#define AFE_GASRC6_NEW_CON11 0x79ec +#define AFE_GASRC6_NEW_CON12 0x79f0 +#define AFE_GASRC6_NEW_CON13 0x79f4 +#define AFE_GASRC6_NEW_CON14 0x79f8 +#define AFE_GASRC6_NEW_IP_VERSION 0x79fc +#define AFE_GASRC7_NEW_CON0 0x7a00 +#define AFE_GASRC7_NEW_CON1 0x7a04 +#define AFE_GASRC7_NEW_CON2 0x7a08 +#define AFE_GASRC7_NEW_CON3 0x7a0c +#define AFE_GASRC7_NEW_CON4 0x7a10 +#define AFE_GASRC7_NEW_CON5 0x7a14 +#define AFE_GASRC7_NEW_CON6 0x7a18 +#define AFE_GASRC7_NEW_CON7 0x7a1c +#define AFE_GASRC7_NEW_CON8 0x7a20 +#define AFE_GASRC7_NEW_CON9 0x7a24 +#define AFE_GASRC7_NEW_CON10 0x7a28 +#define AFE_GASRC7_NEW_CON11 0x7a2c +#define AFE_GASRC7_NEW_CON12 0x7a30 +#define AFE_GASRC7_NEW_CON13 0x7a34 +#define AFE_GASRC7_NEW_CON14 0x7a38 +#define AFE_GASRC7_NEW_IP_VERSION 0x7a3c +#define AFE_GASRC8_NEW_CON0 0x7a40 +#define AFE_GASRC8_NEW_CON1 0x7a44 +#define AFE_GASRC8_NEW_CON2 0x7a48 +#define AFE_GASRC8_NEW_CON3 0x7a4c +#define AFE_GASRC8_NEW_CON4 0x7a50 +#define AFE_GASRC8_NEW_CON5 0x7a54 +#define AFE_GASRC8_NEW_CON6 0x7a58 +#define AFE_GASRC8_NEW_CON7 0x7a5c +#define AFE_GASRC8_NEW_CON8 0x7a60 +#define AFE_GASRC8_NEW_CON9 0x7a64 +#define AFE_GASRC8_NEW_CON10 0x7a68 +#define AFE_GASRC8_NEW_CON11 0x7a6c +#define AFE_GASRC8_NEW_CON12 0x7a70 +#define AFE_GASRC8_NEW_CON13 0x7a74 +#define AFE_GASRC8_NEW_CON14 0x7a78 +#define AFE_GASRC8_NEW_IP_VERSION 0x7a7c +#define AFE_GASRC9_NEW_CON0 0x7a80 +#define AFE_GASRC9_NEW_CON1 0x7a84 +#define AFE_GASRC9_NEW_CON2 0x7a88 +#define AFE_GASRC9_NEW_CON3 0x7a8c +#define AFE_GASRC9_NEW_CON4 0x7a90 +#define AFE_GASRC9_NEW_CON5 0x7a94 +#define AFE_GASRC9_NEW_CON6 0x7a98 +#define AFE_GASRC9_NEW_CON7 0x7a9c +#define AFE_GASRC9_NEW_CON8 0x7aa0 +#define AFE_GASRC9_NEW_CON9 0x7aa4 +#define AFE_GASRC9_NEW_CON10 0x7aa8 +#define AFE_GASRC9_NEW_CON11 0x7aac +#define AFE_GASRC9_NEW_CON12 0x7ab0 +#define AFE_GASRC9_NEW_CON13 0x7ab4 +#define AFE_GASRC9_NEW_CON14 0x7ab8 +#define AFE_GASRC9_NEW_IP_VERSION 0x7abc +#define AFE_GASRC10_NEW_CON0 0x7ac0 +#define AFE_GASRC10_NEW_CON1 0x7ac4 +#define AFE_GASRC10_NEW_CON2 0x7ac8 +#define AFE_GASRC10_NEW_CON3 0x7acc +#define AFE_GASRC10_NEW_CON4 0x7ad0 +#define AFE_GASRC10_NEW_CON5 0x7ad4 +#define AFE_GASRC10_NEW_CON6 0x7ad8 +#define AFE_GASRC10_NEW_CON7 0x7adc +#define AFE_GASRC10_NEW_CON8 0x7ae0 +#define AFE_GASRC10_NEW_CON9 0x7ae4 +#define AFE_GASRC10_NEW_CON10 0x7ae8 +#define AFE_GASRC10_NEW_CON11 0x7aec +#define AFE_GASRC10_NEW_CON12 0x7af0 +#define AFE_GASRC10_NEW_CON13 0x7af4 +#define AFE_GASRC10_NEW_CON14 0x7af8 +#define AFE_GASRC10_NEW_IP_VERSION 0x7afc +#define AFE_GASRC11_NEW_CON0 0x7b00 +#define AFE_GASRC11_NEW_CON1 0x7b04 +#define AFE_GASRC11_NEW_CON2 0x7b08 +#define AFE_GASRC11_NEW_CON3 0x7b0c +#define AFE_GASRC11_NEW_CON4 0x7b10 +#define AFE_GASRC11_NEW_CON5 0x7b14 +#define AFE_GASRC11_NEW_CON6 0x7b18 +#define AFE_GASRC11_NEW_CON7 0x7b1c +#define AFE_GASRC11_NEW_CON8 0x7b20 +#define AFE_GASRC11_NEW_CON9 0x7b24 +#define AFE_GASRC11_NEW_CON10 0x7b28 +#define AFE_GASRC11_NEW_CON11 0x7b2c +#define AFE_GASRC11_NEW_CON12 0x7b30 +#define AFE_GASRC11_NEW_CON13 0x7b34 +#define AFE_GASRC11_NEW_CON14 0x7b38 +#define AFE_GASRC11_NEW_IP_VERSION 0x7b3c +#define AFE_GASRC12_NEW_CON0 0x7b40 +#define AFE_GASRC12_NEW_CON1 0x7b44 +#define AFE_GASRC12_NEW_CON2 0x7b48 +#define AFE_GASRC12_NEW_CON3 0x7b4c +#define AFE_GASRC12_NEW_CON4 0x7b50 +#define AFE_GASRC12_NEW_CON5 0x7b54 +#define AFE_GASRC12_NEW_CON6 0x7b58 +#define AFE_GASRC12_NEW_CON7 0x7b5c +#define AFE_GASRC12_NEW_CON8 0x7b60 +#define AFE_GASRC12_NEW_CON9 0x7b64 +#define AFE_GASRC12_NEW_CON10 0x7b68 +#define AFE_GASRC12_NEW_CON11 0x7b6c +#define AFE_GASRC12_NEW_CON12 0x7b70 +#define AFE_GASRC12_NEW_CON13 0x7b74 +#define AFE_GASRC12_NEW_CON14 0x7b78 +#define AFE_GASRC12_NEW_IP_VERSION 0x7b7c +#define AFE_GASRC13_NEW_CON0 0x7b80 +#define AFE_GASRC13_NEW_CON1 0x7b84 +#define AFE_GASRC13_NEW_CON2 0x7b88 +#define AFE_GASRC13_NEW_CON3 0x7b8c +#define AFE_GASRC13_NEW_CON4 0x7b90 +#define AFE_GASRC13_NEW_CON5 0x7b94 +#define AFE_GASRC13_NEW_CON6 0x7b98 +#define AFE_GASRC13_NEW_CON7 0x7b9c +#define AFE_GASRC13_NEW_CON8 0x7ba0 +#define AFE_GASRC13_NEW_CON9 0x7ba4 +#define AFE_GASRC13_NEW_CON10 0x7ba8 +#define AFE_GASRC13_NEW_CON11 0x7bac +#define AFE_GASRC13_NEW_CON12 0x7bb0 +#define AFE_GASRC13_NEW_CON13 0x7bb4 +#define AFE_GASRC13_NEW_CON14 0x7bb8 +#define AFE_GASRC13_NEW_IP_VERSION 0x7bbc +#define AFE_GASRC14_NEW_CON0 0x7bc0 +#define AFE_GASRC14_NEW_CON1 0x7bc4 +#define AFE_GASRC14_NEW_CON2 0x7bc8 +#define AFE_GASRC14_NEW_CON3 0x7bcc +#define AFE_GASRC14_NEW_CON4 0x7bd0 +#define AFE_GASRC14_NEW_CON5 0x7bd4 +#define AFE_GASRC14_NEW_CON6 0x7bd8 +#define AFE_GASRC14_NEW_CON7 0x7bdc +#define AFE_GASRC14_NEW_CON8 0x7be0 +#define AFE_GASRC14_NEW_CON9 0x7be4 +#define AFE_GASRC14_NEW_CON10 0x7be8 +#define AFE_GASRC14_NEW_CON11 0x7bec +#define AFE_GASRC14_NEW_CON12 0x7bf0 +#define AFE_GASRC14_NEW_CON13 0x7bf4 +#define AFE_GASRC14_NEW_CON14 0x7bf8 +#define AFE_GASRC14_NEW_IP_VERSION 0x7bfc +#define AFE_GASRC15_NEW_CON0 0x7c00 +#define AFE_GASRC15_NEW_CON1 0x7c04 +#define AFE_GASRC15_NEW_CON2 0x7c08 +#define AFE_GASRC15_NEW_CON3 0x7c0c +#define AFE_GASRC15_NEW_CON4 0x7c10 +#define AFE_GASRC15_NEW_CON5 0x7c14 +#define AFE_GASRC15_NEW_CON6 0x7c18 +#define AFE_GASRC15_NEW_CON7 0x7c1c +#define AFE_GASRC15_NEW_CON8 0x7c20 +#define AFE_GASRC15_NEW_CON9 0x7c24 +#define AFE_GASRC15_NEW_CON10 0x7c28 +#define AFE_GASRC15_NEW_CON11 0x7c2c +#define AFE_GASRC15_NEW_CON12 0x7c30 +#define AFE_GASRC15_NEW_CON13 0x7c34 +#define AFE_GASRC15_NEW_CON14 0x7c38 +#define AFE_GASRC15_NEW_IP_VERSION 0x7c3c + +#define AFE_MAX_REGISTER AFE_GASRC15_NEW_IP_VERSION + +#define AFE_IRQ_STATUS_BITS 0x87FFFFFF +#define AFE_IRQ_CNT_SHIFT 0 +#define AFE_IRQ_CNT_MASK 0xffffff +#endif + diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c index 7078c01ba19b..af96aa446fe2 100644 --- a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c +++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c @@ -194,16 +194,13 @@ int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) unsigned int reg = get_top_cg_reg(cg_type); unsigned int mask = get_top_cg_mask(cg_type); unsigned int val = get_top_cg_on_val(cg_type); - unsigned long flags; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); afe_priv->top_cg_ref_cnt[cg_type]++; if (afe_priv->top_cg_ref_cnt[cg_type] == 1) regmap_update_bits(afe->regmap, reg, mask, val); - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); - return 0; } @@ -213,9 +210,8 @@ int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) unsigned int reg = get_top_cg_reg(cg_type); unsigned int mask = get_top_cg_mask(cg_type); unsigned int val = get_top_cg_off_val(cg_type); - unsigned long flags; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); afe_priv->top_cg_ref_cnt[cg_type]--; if (afe_priv->top_cg_ref_cnt[cg_type] == 0) @@ -223,8 +219,6 @@ int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) else if (afe_priv->top_cg_ref_cnt[cg_type] < 0) afe_priv->top_cg_ref_cnt[cg_type] = 0; - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); - return 0; } @@ -263,25 +257,21 @@ int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe) int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe) { struct mt8365_afe_private *afe_priv = afe->platform_priv; - unsigned long flags; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); afe_priv->afe_on_ref_cnt++; if (afe_priv->afe_on_ref_cnt == 1) regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1); - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); - return 0; } int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe) { struct mt8365_afe_private *afe_priv = afe->platform_priv; - unsigned long flags; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); afe_priv->afe_on_ref_cnt--; if (afe_priv->afe_on_ref_cnt == 0) @@ -289,8 +279,6 @@ int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe) else if (afe_priv->afe_on_ref_cnt < 0) afe_priv->afe_on_ref_cnt = 0; - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); - return 0; } @@ -322,13 +310,11 @@ int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll { struct mt8365_afe_private *afe_priv = afe->platform_priv; - mutex_lock(&afe_priv->afe_clk_mutex); + guard(mutex)(&afe_priv->afe_clk_mutex); afe_priv->apll_tuner_ref_cnt[apll]++; - if (afe_priv->apll_tuner_ref_cnt[apll] != 1) { - mutex_unlock(&afe_priv->afe_clk_mutex); + if (afe_priv->apll_tuner_ref_cnt[apll] != 1) return 0; - } if (apll == MT8365_AFE_APLL1) { regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG, @@ -342,7 +328,6 @@ int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll AFE_APLL_TUNER_CFG1_EN_MASK, 0x1); } - mutex_unlock(&afe_priv->afe_clk_mutex); return 0; } @@ -350,7 +335,7 @@ int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apl { struct mt8365_afe_private *afe_priv = afe->platform_priv; - mutex_lock(&afe_priv->afe_clk_mutex); + guard(mutex)(&afe_priv->afe_clk_mutex); afe_priv->apll_tuner_ref_cnt[apll]--; if (afe_priv->apll_tuner_ref_cnt[apll] == 0) { @@ -365,7 +350,6 @@ int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apl afe_priv->apll_tuner_ref_cnt[apll] = 0; } - mutex_unlock(&afe_priv->afe_clk_mutex); return 0; } diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c index d01793394f22..5966ca18c7c9 100644 --- a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c +++ b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c @@ -1974,10 +1974,15 @@ static int mt8365_afe_suspend(struct device *dev) mt8365_afe_enable_main_clk(afe); - if (!afe->reg_back_up) + if (!afe->reg_back_up) { afe->reg_back_up = devm_kcalloc(dev, afe->reg_back_up_list_num, sizeof(unsigned int), GFP_KERNEL); + if (!afe->reg_back_up) { + mt8365_afe_disable_main_clk(afe); + return -ENOMEM; + } + } for (i = 0; i < afe->reg_back_up_list_num; i++) regmap_read(regmap, afe->reg_back_up_list[i], @@ -2011,11 +2016,15 @@ static int mt8365_afe_resume(struct device *dev) static int mt8365_afe_dev_runtime_suspend(struct device *dev) { struct mtk_base_afe *afe = dev_get_drvdata(dev); + int ret; if (pm_runtime_status_suspended(dev) || afe->suspended) return 0; - mt8365_afe_suspend(dev); + ret = mt8365_afe_suspend(dev); + if (ret) + return ret; + afe->suspended = true; return 0; } diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-adda.c b/sound/soc/mediatek/mt8365/mt8365-dai-adda.c index a04c24bbfcff..d8eda9e17eb8 100644 --- a/sound/soc/mediatek/mt8365/mt8365-dai-adda.c +++ b/sound/soc/mediatek/mt8365/mt8365-dai-adda.c @@ -63,10 +63,9 @@ static int mt8365_dai_set_adda_in(struct mtk_base_afe *afe, unsigned int rate) int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe) { - unsigned long flags; struct mt8365_afe_private *afe_priv = afe->platform_priv; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); adda_afe_on_ref_cnt++; if (adda_afe_on_ref_cnt == 1) @@ -74,17 +73,14 @@ int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe) AFE_ADDA_UL_DL_ADDA_AFE_ON, AFE_ADDA_UL_DL_ADDA_AFE_ON); - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); - return 0; } int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe) { - unsigned long flags; struct mt8365_afe_private *afe_priv = afe->platform_priv; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); adda_afe_on_ref_cnt--; if (adda_afe_on_ref_cnt == 0) @@ -96,8 +92,6 @@ int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe) dev_warn(afe->dev, "Abnormal adda_on ref count. Force it to 0\n"); } - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); - return 0; } diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c index cb9beb172ed5..a058973662b3 100644 --- a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c +++ b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c @@ -463,7 +463,6 @@ static int mt8365_afe_set_2nd_i2s_asrc_enable(struct mtk_base_afe *afe, void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable) { int i; - unsigned long flags; struct mt8365_afe_private *afe_priv = afe->platform_priv; struct mtk_afe_i2s_priv *i2s_data = NULL; @@ -475,7 +474,7 @@ void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable) if (!i2s_data) return; - spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock); if (enable) { i2s_data->i2s_out_on_ref_cnt++; @@ -490,8 +489,6 @@ void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable) else if (i2s_data->i2s_out_on_ref_cnt < 0) i2s_data->i2s_out_on_ref_cnt = 0; } - - spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); } static void mt8365_dai_set_enable(struct mtk_base_afe *afe, diff --git a/sound/soc/mediatek/mt8365/mt8365-mt6357.c b/sound/soc/mediatek/mt8365/mt8365-mt6357.c index a998fba82bfe..10f9ef73c130 100644 --- a/sound/soc/mediatek/mt8365/mt8365-mt6357.c +++ b/sound/soc/mediatek/mt8365/mt8365-mt6357.c @@ -247,26 +247,26 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = { static int mt8365_mt6357_gpio_probe(struct snd_soc_card *card) { struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(card); + struct device *dev = card->dev; int ret, i; - priv->pinctrl = devm_pinctrl_get(card->dev); + priv->pinctrl = devm_pinctrl_get(dev); if (IS_ERR(priv->pinctrl)) { ret = PTR_ERR(priv->pinctrl); - return dev_err_probe(card->dev, ret, - "Failed to get pinctrl\n"); + return dev_err_probe(dev, ret, "Failed to get pinctrl\n"); } for (i = PIN_STATE_DEFAULT ; i < PIN_STATE_MAX ; i++) { priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, mt8365_mt6357_pin_str[i]); if (IS_ERR(priv->pin_states[i])) { - dev_info(card->dev, "No pin state for %s\n", + dev_info(dev, "No pin state for %s\n", mt8365_mt6357_pin_str[i]); } else { ret = pinctrl_select_state(priv->pinctrl, priv->pin_states[i]); if (ret) { - dev_err_probe(card->dev, ret, + dev_err_probe(dev, ret, "Failed to select pin state %s\n", mt8365_mt6357_pin_str[i]); return ret; diff --git a/sound/soc/meson/aiu-acodec-ctrl.c b/sound/soc/meson/aiu-acodec-ctrl.c index 483772ba69cd..94c5d6533523 100644 --- a/sound/soc/meson/aiu-acodec-ctrl.c +++ b/sound/soc/meson/aiu-acodec-ctrl.c @@ -36,6 +36,9 @@ static int aiu_acodec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int mux, changed; + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); changed = snd_soc_component_test_bits(component, e->reg, CTRL_DIN_LRCLK_SRC, diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c index 396f815077e2..60bb4cdfee52 100644 --- a/sound/soc/meson/aiu-codec-ctrl.c +++ b/sound/soc/meson/aiu-codec-ctrl.c @@ -28,6 +28,9 @@ static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol, struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsigned int mux, changed; + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); changed = snd_soc_component_test_bits(component, e->reg, CTRL_DATA_SEL, diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c index f451e4dce442..a6ba401104d5 100644 --- a/sound/soc/meson/axg-tdm-formatter.c +++ b/sound/soc/meson/axg-tdm-formatter.c @@ -157,20 +157,19 @@ static int axg_tdm_formatter_attach(struct axg_tdm_formatter *formatter) struct axg_tdm_stream *ts = formatter->stream; int ret = 0; - mutex_lock(&ts->lock); + guard(mutex)(&ts->lock); /* Catch up if the stream is already running when we attach */ if (ts->ready) { ret = axg_tdm_formatter_enable(formatter); if (ret) { pr_err("failed to enable formatter\n"); - goto out; + return ret; } } list_add_tail(&formatter->list, &ts->formatter_list); -out: - mutex_unlock(&ts->lock); + return ret; } @@ -178,9 +177,8 @@ static void axg_tdm_formatter_dettach(struct axg_tdm_formatter *formatter) { struct axg_tdm_stream *ts = formatter->stream; - mutex_lock(&ts->lock); - list_del(&formatter->list); - mutex_unlock(&ts->lock); + scoped_guard(mutex, &ts->lock) + list_del(&formatter->list); axg_tdm_formatter_disable(formatter); } @@ -330,7 +328,7 @@ int axg_tdm_stream_start(struct axg_tdm_stream *ts) struct axg_tdm_formatter *formatter; int ret = 0; - mutex_lock(&ts->lock); + guard(mutex)(&ts->lock); ts->ready = true; /* Start all the formatters attached to the stream */ @@ -338,12 +336,10 @@ int axg_tdm_stream_start(struct axg_tdm_stream *ts) ret = axg_tdm_formatter_enable(formatter); if (ret) { pr_err("failed to start tdm stream\n"); - goto out; + return ret; } } -out: - mutex_unlock(&ts->lock); return ret; } EXPORT_SYMBOL_GPL(axg_tdm_stream_start); @@ -352,15 +348,13 @@ void axg_tdm_stream_stop(struct axg_tdm_stream *ts) { struct axg_tdm_formatter *formatter; - mutex_lock(&ts->lock); + guard(mutex)(&ts->lock); ts->ready = false; /* Stop all the formatters attached to the stream */ list_for_each_entry(formatter, &ts->formatter_list, list) { axg_tdm_formatter_disable(formatter); } - - mutex_unlock(&ts->lock); } EXPORT_SYMBOL_GPL(axg_tdm_stream_stop); diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 4bd14ae330d5..2788514be6b1 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -54,4 +54,10 @@ config SND_PXA910_SOC Say Y if you want to add support for SoC audio on the Marvell PXA910 reference platform. +config SND_PXA2XX_LIB + tristate + select SND_DMAENGINE_PCM + +config SND_PXA2XX_LIB_AC97 + bool endmenu diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 93b4e57eaa5c..bf504a85657c 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 # PXA Platform Support snd-soc-pxa2xx-y := pxa2xx-pcm.o -snd-soc-pxa2xx-ac97-y := pxa2xx-ac97.o +snd-soc-pxa2xx-ac97-y := pxa2xx-ac97.o pxa2xx-ac97-lib.o snd-soc-pxa2xx-i2s-y := pxa2xx-i2s.o +snd-soc-pxa2xx-lib-y := pxa2xx-pcm-lib.o snd-soc-pxa-ssp-y := pxa-ssp.o snd-soc-mmp-sspa-y := mmp-sspa.o @@ -11,6 +12,7 @@ obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o +obj-$(CONFIG_SND_PXA2XX_LIB) += snd-soc-pxa2xx-lib.o # PXA Machine Support snd-soc-spitz-y := spitz.o diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 73f36c9dd35c..fbbce81680cf 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include "pxa2xx-lib.h" #include "mmp-sspa.h" /* diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 37bd8dbd541f..f8054c1c59fa 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -27,9 +27,9 @@ #include #include #include -#include #include +#include "pxa2xx-lib.h" #include "pxa-ssp.h" /* diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/soc/pxa/pxa2xx-ac97-lib.c similarity index 91% rename from sound/arm/pxa2xx-ac97-lib.c rename to sound/soc/pxa/pxa2xx-ac97-lib.c index 79eb557d4942..d9c3935636da 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/soc/pxa/pxa2xx-ac97-lib.c @@ -23,13 +23,13 @@ #include #include "pxa2xx-ac97-regs.h" +#include "pxa2xx-lib.h" static DEFINE_MUTEX(car_mutex); static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); static volatile long gsr_bits; static struct clk *ac97_clk; static struct clk *ac97conf_clk; -static int reset_gpio; struct gpio_desc *rst_gpio; static void __iomem *ac97_reg_base; @@ -83,7 +83,6 @@ int pxa2xx_ac97_read(int slot, unsigned short reg) wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1); return val; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_read); int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val) { @@ -113,7 +112,6 @@ int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val) return ret; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_write); #ifdef CONFIG_PXA25x static inline void pxa_ac97_warm_pxa25x(void) @@ -140,10 +138,10 @@ static inline void pxa_ac97_warm_pxa27x(void) gsr_bits = 0; /* warm reset broken on Bulverde, so manually keep AC97 reset high */ - pxa27x_configure_ac97reset(reset_gpio, true); + pxa27x_configure_ac97reset(rst_gpio, true); udelay(10); writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR); - pxa27x_configure_ac97reset(reset_gpio, false); + pxa27x_configure_ac97reset(rst_gpio, false); udelay(500); } @@ -226,7 +224,6 @@ bool pxa2xx_ac97_try_warm_reset(void) return true; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset); bool pxa2xx_ac97_try_cold_reset(void) { @@ -263,7 +260,6 @@ bool pxa2xx_ac97_try_cold_reset(void) return true; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset); void pxa2xx_ac97_finish_reset(void) @@ -273,7 +269,6 @@ void pxa2xx_ac97_finish_reset(void) gcr |= GCR_SDONE_IE|GCR_CDONE_IE; writel(gcr, ac97_reg_base + GCR); } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset); static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) { @@ -307,14 +302,12 @@ int pxa2xx_ac97_hw_suspend(void) clk_disable_unprepare(ac97_clk); return 0; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend); int pxa2xx_ac97_hw_resume(void) { clk_prepare_enable(ac97_clk); return 0; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); #endif int pxa2xx_ac97_hw_probe(struct platform_device *dev) @@ -328,24 +321,14 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) return PTR_ERR(ac97_reg_base); } - if (dev->dev.of_node) { - /* Assert reset using GPIOD_OUT_HIGH, because reset is GPIO_ACTIVE_LOW */ - rst_gpio = devm_gpiod_get(&dev->dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(rst_gpio)) { - ret = PTR_ERR(rst_gpio); - if (ret == -ENOENT) - reset_gpio = -1; - else if (ret) - return ret; - } else { - reset_gpio = desc_to_gpio(rst_gpio); - } - } else { - if (cpu_is_pxa27x()) - reset_gpio = 113; - } - if (cpu_is_pxa27x()) { + /* Assert reset using GPIOD_OUT_HIGH, because reset is GPIO_ACTIVE_LOW */ + rst_gpio = devm_gpiod_get_optional(&dev->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(rst_gpio)) + return dev_err_probe(&dev->dev, PTR_ERR(rst_gpio), + "reset gpio failed\n"); + /* * This gpio is needed for a work-around to a bug in the ac97 * controller during warm reset. The direction and level is set @@ -353,7 +336,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) * AC97_nRESET alt function to generic gpio. */ gpiod_set_consumer_name(rst_gpio, "pxa27x ac97 reset"); - pxa27x_configure_ac97reset(reset_gpio, false); + pxa27x_configure_ac97reset(rst_gpio, false); ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { @@ -399,7 +382,6 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) err_conf: return ret; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); void pxa2xx_ac97_hw_remove(struct platform_device *dev) { @@ -413,7 +395,6 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev) clk_put(ac97_clk); ac97_clk = NULL; } -EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove); u32 pxa2xx_ac97_read_modr(void) { diff --git a/sound/arm/pxa2xx-ac97-regs.h b/sound/soc/pxa/pxa2xx-ac97-regs.h similarity index 100% rename from sound/arm/pxa2xx-ac97-regs.h rename to sound/soc/pxa/pxa2xx-ac97-regs.h diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index a0c672602918..7b9036947dfc 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -18,11 +18,12 @@ #include #include #include -#include #include #include +#include "pxa2xx-lib.h" + #define PCDR 0x0040 /* PCM FIFO Data Register */ #define MODR 0x0140 /* Modem FIFO Data Register */ #define MCDR 0x0060 /* Mic-in FIFO Data Register */ @@ -246,8 +247,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) } ctrl = snd_ac97_controller_register(&pxa2xx_ac97_ops, &pdev->dev, - AC97_SLOTS_AVAILABLE_ALL, - NULL); + AC97_SLOTS_AVAILABLE_ALL); if (IS_ERR(ctrl)) return PTR_ERR(ctrl); diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index f6ada6cffc88..fe1df78926f5 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -18,11 +18,11 @@ #include #include #include -#include #include #include +#include "pxa2xx-lib.h" #include "pxa2xx-i2s.h" /* diff --git a/sound/soc/pxa/pxa2xx-lib.h b/sound/soc/pxa/pxa2xx-lib.h new file mode 100644 index 000000000000..3a9d6ac8d367 --- /dev/null +++ b/sound/soc/pxa/pxa2xx-lib.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PXA2XX_LIB_H +#define __PXA2XX_LIB_H + +#include +#include + +/* PCM */ +struct snd_pcm_substream; +struct snd_pcm_hw_params; +struct snd_soc_pcm_runtime; +struct snd_pcm; +struct snd_soc_component; + +int pxa2xx_soc_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd); +int pxa2xx_soc_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int pxa2xx_soc_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream); +int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd); +snd_pcm_uframes_t pxa2xx_soc_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream); + +/* AC97 */ +int pxa2xx_ac97_read(int slot, unsigned short reg); +int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val); + +bool pxa2xx_ac97_try_warm_reset(void); +bool pxa2xx_ac97_try_cold_reset(void); +void pxa2xx_ac97_finish_reset(void); + +int pxa2xx_ac97_hw_suspend(void); +int pxa2xx_ac97_hw_resume(void); + +int pxa2xx_ac97_hw_probe(struct platform_device *dev); +void pxa2xx_ac97_hw_remove(struct platform_device *dev); + +#endif diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/soc/pxa/pxa2xx-pcm-lib.c similarity index 86% rename from sound/arm/pxa2xx-pcm-lib.c rename to sound/soc/pxa/pxa2xx-pcm-lib.c index 571e9d909cdf..88a9d3226302 100644 --- a/sound/arm/pxa2xx-pcm-lib.c +++ b/sound/soc/pxa/pxa2xx-pcm-lib.c @@ -9,9 +9,10 @@ #include #include #include -#include #include +#include "pxa2xx-lib.h" + static const struct snd_pcm_hardware pxa2xx_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | @@ -29,8 +30,8 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = { .fifo_size = 32, }; -int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) +static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) { struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); @@ -56,28 +57,24 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, return 0; } -EXPORT_SYMBOL(pxa2xx_pcm_hw_params); -int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { return snd_dmaengine_pcm_trigger(substream, cmd); } -EXPORT_SYMBOL(pxa2xx_pcm_trigger); -snd_pcm_uframes_t +static snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream) { return snd_dmaengine_pcm_pointer(substream); } -EXPORT_SYMBOL(pxa2xx_pcm_pointer); -int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) +static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) { return 0; } -EXPORT_SYMBOL(pxa2xx_pcm_prepare); -int pxa2xx_pcm_open(struct snd_pcm_substream *substream) +static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; @@ -114,22 +111,19 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream) substream, dma_request_slave_channel(snd_soc_rtd_to_cpu(rtd, 0)->dev, dma_params->chan_name)); } -EXPORT_SYMBOL(pxa2xx_pcm_open); -int pxa2xx_pcm_close(struct snd_pcm_substream *substream) +static int pxa2xx_pcm_close(struct snd_pcm_substream *substream) { return snd_dmaengine_pcm_close_release_chan(substream); } -EXPORT_SYMBOL(pxa2xx_pcm_close); -int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm) +static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm) { size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC, pcm->card->dev, size); } -EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer); int pxa2xx_soc_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index ff0fbb61dccd..71b7bd948b5e 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -14,9 +14,10 @@ #include #include -#include #include +#include "pxa2xx-lib.h" + static const struct snd_soc_component_driver pxa2xx_soc_platform = { .pcm_new = pxa2xx_soc_pcm_new, .open = pxa2xx_soc_pcm_open, diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index cf1f3a767cee..edc4611691f7 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -25,10 +25,6 @@ static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = { int qcom_snd_parse_of(struct snd_soc_card *card) { - struct device_node *np; - struct device_node *codec = NULL; - struct device_node *platform = NULL; - struct device_node *cpu = NULL; struct device *dev = card->dev; struct snd_soc_dai_link *link; struct of_phandle_args args; @@ -82,12 +78,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card) card->num_links = num_links; link = card->dai_link; - for_each_available_child_of_node(dev->of_node, np) { + for_each_available_child_of_node_scoped(dev->of_node, np) { dlc = devm_kcalloc(dev, 2, sizeof(*dlc), GFP_KERNEL); - if (!dlc) { - ret = -ENOMEM; - goto err_put_np; - } + if (!dlc) + return -ENOMEM; link->cpus = &dlc[0]; link->platforms = &dlc[1]; @@ -98,32 +92,33 @@ int qcom_snd_parse_of(struct snd_soc_card *card) ret = of_property_read_string(np, "link-name", &link->name); if (ret) { dev_err(card->dev, "error getting codec dai_link name\n"); - goto err_put_np; + return ret; } - cpu = of_get_child_by_name(np, "cpu"); - platform = of_get_child_by_name(np, "platform"); - codec = of_get_child_by_name(np, "codec"); + struct device_node *cpu __free(device_node) = + of_get_child_by_name(np, "cpu"); + struct device_node *platform __free(device_node) = + of_get_child_by_name(np, "platform"); + struct device_node *codec __free(device_node) = + of_get_child_by_name(np, "codec"); if (!cpu) { dev_err(dev, "%s: Can't find cpu DT node\n", link->name); - ret = -EINVAL; - goto err; + return -EINVAL; } ret = snd_soc_of_get_dlc(cpu, &args, link->cpus, 0); if (ret) { dev_err_probe(card->dev, ret, "%s: error getting cpu dai name\n", link->name); - goto err; + return ret; } link->id = args.args[0]; if (link->id >= LPASS_MAX_PORT) { dev_err(dev, "%s: Invalid cpu dai id %d\n", link->name, link->id); - ret = -EINVAL; - goto err; + return -EINVAL; } if (platform) { @@ -132,8 +127,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) 0); if (!link->platforms->of_node) { dev_err(card->dev, "%s: platform dai not found\n", link->name); - ret = -EINVAL; - goto err; + return -EINVAL; } } else { link->platforms->of_node = link->cpus->of_node; @@ -144,7 +138,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card) if (ret < 0) { dev_err_probe(card->dev, ret, "%s: codec dai not found\n", link->name); - goto err; + return ret; } if (platform) { @@ -167,10 +161,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card) link->stream_name = link->name; link++; - - of_node_put(cpu); - of_node_put(codec); - of_node_put(platform); } if (!card->dapm_widgets) { @@ -179,13 +169,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card) } return 0; -err: - of_node_put(cpu); - of_node_put(codec); - of_node_put(platform); -err_put_np: - of_node_put(np); - return ret; } EXPORT_SYMBOL_GPL(qcom_snd_parse_of); diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c index a13f753eff98..e6e9eb2e85aa 100644 --- a/sound/soc/qcom/qdsp6/audioreach.c +++ b/sound/soc/qcom/qdsp6/audioreach.c @@ -955,7 +955,7 @@ int audioreach_compr_set_param(struct q6apm_graph *graph, struct media_format *header; int rc; void *p; - int iid = q6apm_graph_get_rx_shmem_module_iid(graph); + int iid = graph->shm_iid; int payload_size = sizeof(struct apm_sh_module_media_fmt_cmd); struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size, @@ -1118,6 +1118,42 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph, return q6apm_send_cmd_sync(graph->apm, pkt, 0); } +int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int num_levels) +{ + struct apm_module_register_events *event; + struct event_cfg_sh_mem_pull_push_mode_watermark_t *level; + int i, payload_size; + struct gpr_pkt *pkt __free(kfree) = NULL; + void *p; + + if (num_levels <= 0 || bytes <= 0) + return -EINVAL; + + payload_size = sizeof(*event) + sizeof(*level) + num_levels * sizeof(uint32_t); + + pkt = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_REGISTER_MODULE_EVENTS, 0, + graph->port->id, graph->shm_iid); + if (IS_ERR(pkt)) + return PTR_ERR(pkt); + + p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; + + event = p; + event->module_instance_id = graph->shm_iid; + event->event_id = EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK; + event->is_register = 1; + event->event_config_payload_size = sizeof(*level) + num_levels * sizeof(uint32_t); + p += sizeof(*event); + level = p; + level->num_water_mark_levels = num_levels; + + for (i = 0; i < num_levels; i++) + level->level[i] = (i + 1) * bytes; + + return audioreach_graph_send_cmd_sync(graph, pkt, 0); +} +EXPORT_SYMBOL_GPL(audioreach_shmem_register_event); + static int audioreach_shmem_set_media_format(struct q6apm_graph *graph, const struct audioreach_module *module, const struct audioreach_module_config *mcfg) @@ -1342,6 +1378,7 @@ int audioreach_set_media_format(struct q6apm_graph *graph, rc = audioreach_i2s_set_media_format(graph, module, cfg); break; case MODULE_ID_WR_SHARED_MEM_EP: + case MODULE_ID_SH_MEM_PULL_MODE: rc = audioreach_shmem_set_media_format(graph, module, cfg); break; case MODULE_ID_GAIN: @@ -1401,10 +1438,48 @@ void audioreach_graph_free_buf(struct q6apm_graph *graph) } EXPORT_SYMBOL_GPL(audioreach_graph_free_buf); +int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys, + phys_addr_t pphys, uint32_t mem_map_handle, + uint32_t pos_buf_mem_map_handle, uint32_t size) +{ + struct param_id_sh_mem_pull_push_mode_cfg *cfg; + struct apm_module_param_data *param_data; + int payload_size; + struct gpr_pkt *pkt __free(kfree) = NULL; + void *p; + + payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE; + pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0); + if (IS_ERR(pkt)) + return PTR_ERR(pkt); + + p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE; + + param_data = p; + param_data->module_instance_id = graph->shm_iid; + param_data->error_code = 0; + param_data->param_id = PARAM_ID_SH_MEM_PULL_PUSH_MODE_CFG; + param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE; + + p = p + APM_MODULE_PARAM_DATA_SIZE; + cfg = p; + + cfg->shared_circ_buf_addr_lsw = lower_32_bits(bphys); + cfg->shared_circ_buf_addr_msw = upper_32_bits(bphys); + cfg->shared_circ_buf_size = size; + cfg->circ_buf_mem_map_handle = mem_map_handle; + cfg->shared_pos_buf_addr_lsw = lower_32_bits(pphys); + cfg->shared_pos_buf_addr_msw = upper_32_bits(pphys); + cfg->pos_buf_mem_map_handle = pos_buf_mem_map_handle; + + return q6apm_send_cmd_sync(graph->apm, pkt, 0); +} +EXPORT_SYMBOL_GPL(audioreach_setup_push_pull); + int audioreach_shared_memory_send_eos(struct q6apm_graph *graph) { struct data_cmd_wr_sh_mem_ep_eos *eos; - int iid = q6apm_graph_get_rx_shmem_module_iid(graph); + int iid = graph->shm_iid; struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*eos), DATA_CMD_WR_SH_MEM_EP_EOS, 0, graph->port->id, iid); if (IS_ERR(pkt)) diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h index 6859770b38a6..62a2fd79bbcb 100644 --- a/sound/soc/qcom/qdsp6/audioreach.h +++ b/sound/soc/qcom/qdsp6/audioreach.h @@ -16,6 +16,8 @@ struct q6apm_graph; #define MODULE_ID_PCM_CNV 0x07001003 #define MODULE_ID_PCM_ENC 0x07001004 #define MODULE_ID_PCM_DEC 0x07001005 +#define MODULE_ID_SH_MEM_PULL_MODE 0x07001006 +#define MODULE_ID_SH_MEM_PUSH_MODE 0x07001007 #define MODULE_ID_PLACEHOLDER_ENCODER 0x07001008 #define MODULE_ID_PLACEHOLDER_DECODER 0x07001009 #define MODULE_ID_I2S_SINK 0x0700100A @@ -60,10 +62,57 @@ struct q6apm_graph; #define APM_CMD_GET_CFG 0x01001007 #define APM_CMD_SHARED_MEM_MAP_REGIONS 0x0100100C #define APM_CMD_SHARED_MEM_UNMAP_REGIONS 0x0100100D +#define APM_CMD_REGISTER_MODULE_EVENTS 0x0100100E +#define APM_EVENT_MODULE_TO_CLIENT 0x03001000 #define APM_CMD_RSP_SHARED_MEM_MAP_REGIONS 0x02001001 +#define APM_MMAP_TOKEN_GID_MASK GENMASK(15, 0) +#define APM_MMAP_TOKEN_MAP_TYPE_POS_BUF BIT(16) +#define APM_MMAP_TOKEN_MAP_TYPE_SHIFT 16 #define APM_CMD_RSP_GET_CFG 0x02001000 #define APM_CMD_CLOSE_ALL 0x01001013 #define APM_CMD_REGISTER_SHARED_CFG 0x0100100A +#define EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK 0x0800101C + +/** + * struct event_cfg_sh_mem_pull_push_mode_watermark_t - Watermark config + * @num_water_mark_levels: Number of watermark levels. + * @level: Watermark levels. + * + * If @num_water_mark_levels is zero, no watermark levels are specified + * and watermark events are not supported. + */ +struct event_cfg_sh_mem_pull_push_mode_watermark_t { + uint32_t num_water_mark_levels; + uint32_t level[]; +} __packed; + +/** + * struct apm_module_register_events - Register or unregister module events + * @module_instance_id: Module instance identifier. + * @event_id: Module event identifier. + * @is_register: 1 to register the event, 0 to unregister it. + * @error_code: Error code for out-of-band command mode. + * @event_config_payload_size: Event configuration payload size in bytes. + * @reserved: Reserved for alignment; must be zero. + */ +struct apm_module_register_events { + uint32_t module_instance_id; + uint32_t event_id; + uint32_t is_register; + uint32_t error_code; + uint32_t event_config_payload_size; + uint32_t reserved; +} __packed; + +/** + * struct apm_module_event - Module event descriptor + * @event_id: Module event identifier. + * @event_payload_size: Event payload size in bytes. + */ +struct apm_module_event { + uint32_t event_id; + uint32_t event_payload_size; +} __packed; #define APM_MEMORY_MAP_SHMEM8_4K_POOL 3 @@ -710,6 +759,46 @@ struct param_id_placeholder_real_module_id { uint32_t real_module_id; } __packed; + +#define PARAM_ID_SH_MEM_PULL_PUSH_MODE_CFG 0x0800100A + +/** + * struct param_id_sh_mem_pull_push_mode_cfg - Shared memory push/pull config + * @shared_circ_buf_addr_lsw: Lower 32 bits of the circular buffer address. + * @shared_circ_buf_addr_msw: Upper 32 bits of the circular buffer address. + * @shared_circ_buf_size: Circular buffer size in bytes. + * @circ_buf_mem_map_handle: Circular buffer memory map handle. + * @shared_pos_buf_addr_lsw: Lower 32 bits of the position buffer address. + * @shared_pos_buf_addr_msw: Upper 32 bits of the position buffer address. + * @pos_buf_mem_map_handle: Position buffer memory map handle. + */ +struct param_id_sh_mem_pull_push_mode_cfg { + uint32_t shared_circ_buf_addr_lsw; + uint32_t shared_circ_buf_addr_msw; + uint32_t shared_circ_buf_size; + uint32_t circ_buf_mem_map_handle; + uint32_t shared_pos_buf_addr_lsw; + uint32_t shared_pos_buf_addr_msw; + uint32_t pos_buf_mem_map_handle; +} __packed; + +/** + * struct sh_mem_pull_push_mode_position_buffer - Shared position buffer + * @frame_counter: Synchronization counter. + * @index: Current read/write index in bytes. + * @timestamp_us_lsw: Lower 32 bits of the timestamp in microseconds. + * @timestamp_us_msw: Upper 32 bits of the timestamp in microseconds. + * + * The frame counter should be read before and after the other fields to + * ensure the DSP did not update them while they were being read. + */ +struct sh_mem_pull_push_mode_position_buffer { + uint32_t frame_counter; + uint32_t index; + uint32_t timestamp_us_lsw; + uint32_t timestamp_us_msw; +} __packed; + /* Graph */ struct audioreach_connection { /* Connections */ @@ -723,8 +812,10 @@ struct audioreach_connection { struct audioreach_graph_info { int id; uint32_t mem_map_handle; + uint32_t pos_buf_mem_map_handle; uint32_t num_sub_graphs; struct list_head sg_list; + bool is_push_pull_mode; /* DPCM connection from FE Graph to BE graph */ uint32_t src_mod_inst_id; uint32_t src_mod_op_port_id; @@ -855,5 +946,10 @@ int audioreach_send_u32_param(struct q6apm_graph *graph, uint32_t param_id, uint32_t param_val); int audioreach_compr_set_param(struct q6apm_graph *graph, const struct audioreach_module_config *mcfg); +int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys, + phys_addr_t pphys, uint32_t mem_map_handle, + uint32_t pos_buf_mem_map_handle, uint32_t size); +int audioreach_map_memory_position_buffer(struct q6apm_graph *graph, unsigned int dir); +int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int num_levels); #endif /* __AUDIOREACH_H__ */ diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 3a1be41df096..bf1f872a09f4 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -18,6 +18,7 @@ #include "q6apm.h" #define DRV_NAME "q6apm-dai" +#define POS_BUFFER_BYTES 4096 #define PLAYBACK_MIN_NUM_PERIODS 2 #define PLAYBACK_MAX_NUM_PERIODS 8 @@ -62,8 +63,12 @@ struct q6apm_dai_rtd { struct snd_codec codec; struct snd_compr_params codec_param; struct snd_dma_buffer dma_buffer; + struct sh_mem_pull_push_mode_position_buffer *pos_buffer; + uint32_t last_pos_index; phys_addr_t phys; + phys_addr_t pos_phys; unsigned int pcm_size; + unsigned int push_pull_size; unsigned int pcm_count; unsigned int periods; uint64_t bytes_sent; @@ -128,6 +133,9 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void * struct snd_pcm_substream *substream = prtd->substream; switch (opcode) { + case APM_CLIENT_EVENT_WATERMARK_EVENT: + snd_pcm_period_elapsed(substream); + break; case APM_CLIENT_EVENT_CMD_EOS_DONE: prtd->state = Q6APM_STREAM_STOPPED; break; @@ -234,24 +242,47 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, q6apm_free_fragments(prtd->graph, substream->stream); } + prtd->last_pos_index = 0; prtd->pcm_count = snd_pcm_lib_period_bytes(substream); - /* rate and channels are sent to audio driver */ - ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); - if (ret < 0) { - dev_err(dev, "%s: q6apm_open_write failed\n", __func__); - return ret; + if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) { + if (prtd->pcm_size != prtd->push_pull_size) { + ret = q6apm_push_pull_config(prtd->graph, prtd->phys, prtd->pos_phys, + prtd->pcm_size); + if (ret < 0) { + dev_err(dev, "Push/Pull config failed rc = %d\n", ret); + return ret; + } + + ret = q6apm_register_watermark_event(prtd->graph, + prtd->pcm_size / prtd->periods, + prtd->periods); + if (ret < 0) { + dev_err(dev, "WaterMark event config failed rc = %d\n", ret); + return ret; + } + prtd->push_pull_size = prtd->pcm_size; + } + } else { + ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys, + (prtd->pcm_size / prtd->periods), prtd->periods); + if (ret < 0) { + dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); + return ret; + } + } ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg); - if (ret < 0) - dev_err(dev, "%s: CMD Format block failed\n", __func__); - - ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys, - (prtd->pcm_size / prtd->periods), prtd->periods); - if (ret < 0) { - dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); - return -ENOMEM; + dev_err(dev, "%s: CMD Format block failed\n", __func__); + return ret; + } + + /* rate and channels are sent to audio driver */ + ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); + if (ret < 0) { + dev_err(dev, "Failed to set media format %d\n", ret); + return ret; } ret = q6apm_graph_prepare(prtd->graph); @@ -265,13 +296,13 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, dev_err(dev, "Failed to Start Graph %d\n", ret); return ret; } - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - int i; - /* Queue the buffers for Capture ONLY after graph is started */ - for (i = 0; i < runtime->periods; i++) - q6apm_read(prtd->graph); - + if (!q6apm_is_graph_in_push_pull_mode(prtd->graph)) { + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + int i; + /* Queue the buffers for Capture ONLY after graph is started */ + for (i = 0; i < runtime->periods; i++) + q6apm_read(prtd->graph); + } } /* Now that graph as been prepared and started update the internal state accordingly */ @@ -286,6 +317,9 @@ static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_sub struct q6apm_dai_rtd *prtd = runtime->private_data; int i, ret = 0, avail_periods; + if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) + return 0; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size; for (i = 0; i < avail_periods; i++) { @@ -317,6 +351,7 @@ static int q6apm_dai_trigger(struct snd_soc_component *component, /* TODO support be handled via SoftPause Module */ prtd->state = Q6APM_STREAM_STOPPED; prtd->queue_ptr = 0; + prtd->last_pos_index = 0; break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: @@ -402,6 +437,14 @@ static int q6apm_dai_open(struct snd_soc_component *component, else prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32); + if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) { + void *pos_buffer; + + prtd->pos_phys = prtd->phys + BUFFER_BYTES_MAX; + pos_buffer = (void *)(substream->dma_buffer.area + BUFFER_BYTES_MAX); + prtd->pos_buffer = (struct sh_mem_pull_push_mode_position_buffer *)(pos_buffer); + } + return 0; err: kfree(prtd); @@ -436,6 +479,25 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component, struct q6apm_dai_rtd *prtd = runtime->private_data; snd_pcm_uframes_t ptr; + if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) { + int retries = 10; + uint32_t index, fc1, fc2; + + /* index is valid if frame_counter does not change while reading. */ + do { + fc1 = READ_ONCE(prtd->pos_buffer->frame_counter); + index = READ_ONCE(prtd->pos_buffer->index); + fc2 = READ_ONCE(prtd->pos_buffer->frame_counter); + } while (fc1 != fc2 && --retries); + + if (fc1 != fc2) + index = prtd->last_pos_index; + else + prtd->last_pos_index = index; + + ptr = bytes_to_frames(runtime, index); + return ptr; + } ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size; if (ptr) return ptr - 1; @@ -468,7 +530,8 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component, } static int q6apm_dai_memory_map(struct snd_soc_component *component, - struct snd_pcm_substream *substream, int graph_id) + struct snd_pcm_substream *substream, + int graph_id, bool is_push_pull) { struct q6apm_dai_data *pdata; struct device *dev = component->dev; @@ -490,6 +553,19 @@ static int q6apm_dai_memory_map(struct snd_soc_component *component, if (ret < 0) dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); + if (is_push_pull) { + if (pdata->sid < 0) + phys = substream->dma_buffer.addr + BUFFER_BYTES_MAX; + else + phys = (substream->dma_buffer.addr + BUFFER_BYTES_MAX) | (pdata->sid << 32); + + ret = q6apm_map_pos_buffer(dev, graph_id, phys, POS_BUFFER_BYTES); + if (ret < 0) + dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); + } else { + + } + return ret; } @@ -504,25 +580,30 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc */ int size = BUFFER_BYTES_MAX + PAGE_SIZE; int graph_id, ret; - struct snd_pcm_substream *substream; + bool is_push_pull; + struct snd_pcm_substream *substream = NULL; graph_id = cpu_dai->driver->id; - ret = snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, component->dev, size); - if (ret) - return ret; - /* Note: DSP backend dais are uni-directional ONLY(either playback or capture) */ - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; - ret = q6apm_dai_memory_map(component, substream, graph_id); + else if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) + substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; + + + if (substream) { + is_push_pull = q6apm_is_graph_in_push_pull_mode_from_id(component->dev, + graph_id, + substream->stream); + if (is_push_pull) + size += POS_BUFFER_BYTES; + + ret = snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, component->dev, size); if (ret) return ret; - } - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; - ret = q6apm_dai_memory_map(component, substream, graph_id); + ret = q6apm_dai_memory_map(component, substream, graph_id, is_push_pull); if (ret) return ret; } @@ -547,6 +628,9 @@ static void q6apm_dai_memory_unmap(struct snd_soc_component *component, graph_id = cpu_dai->driver->id; q6apm_unmap_memory_fixed_region(component->dev, graph_id); + + if (q6apm_is_graph_in_push_pull_mode_from_id(component->dev, graph_id, substream->stream)) + q6apm_unmap_pos_buffer(component->dev, graph_id); } static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 2ab378fb5032..2e5b25b8d00f 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -186,23 +186,27 @@ int q6apm_graph_media_format_shmem(struct q6apm_graph *graph, { struct audioreach_module *module; - if (cfg->direction == SNDRV_PCM_STREAM_CAPTURE) - module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP); - else - module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP); + if (cfg->direction == SNDRV_PCM_STREAM_CAPTURE) { + module = q6apm_find_module_by_mid(graph, MODULE_ID_SH_MEM_PUSH_MODE); + if (!module) + module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP); + } else { + module = q6apm_find_module_by_mid(graph, MODULE_ID_SH_MEM_PULL_MODE); + if (!module) + module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP); + } - if (!module) + if (!module) { + dev_err(graph->dev, "No SHMEM module found in graph\n"); return -ENODEV; + } - audioreach_set_media_format(graph, module, cfg); - - return 0; - + return audioreach_set_media_format(graph, module, cfg); } EXPORT_SYMBOL_GPL(q6apm_graph_media_format_shmem); -int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys, - size_t sz) +static int __q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, + phys_addr_t phys, size_t sz, bool is_pos_buf) { struct audioreach_graph_info *info; struct q6apm *apm = dev_get_drvdata(dev->parent); @@ -211,8 +215,10 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy int payload_size = sizeof(*cmd) + (sizeof(*mregions)); uint32_t buf_sz; void *p; + uint32_t pos_mask = is_pos_buf ? APM_MMAP_TOKEN_MAP_TYPE_POS_BUF : 0; struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size, - APM_CMD_SHARED_MEM_MAP_REGIONS, graph_id); + APM_CMD_SHARED_MEM_MAP_REGIONS, (graph_id | pos_mask)); + if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -220,8 +226,13 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy if (!info) return -ENODEV; - if (info->mem_map_handle) - return 0; + if (is_pos_buf) { + if (info->pos_buf_mem_map_handle) + return 0; + } else { + if (info->mem_map_handle) + return 0; + } /* DSP expects size should be aligned to 4K */ buf_sz = ALIGN(sz, 4096); @@ -230,7 +241,10 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy cmd = p; cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL; cmd->num_regions = 1; - cmd->property_flag = 0x0; + if (is_pos_buf) + cmd->property_flag = 0x2; + else + cmd->property_flag = 0x0; mregions = p + sizeof(*cmd); @@ -240,6 +254,18 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy return q6apm_send_cmd_sync(apm, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS); } + +int q6apm_map_pos_buffer(struct device *dev, unsigned int graph_id, phys_addr_t phys, size_t sz) +{ + return __q6apm_map_memory_fixed_region(dev, graph_id, phys, sz, true); +} +EXPORT_SYMBOL_GPL(q6apm_map_pos_buffer); + +int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, + phys_addr_t phys, size_t sz) +{ + return __q6apm_map_memory_fixed_region(dev, graph_id, phys, sz, false); +} EXPORT_SYMBOL_GPL(q6apm_map_memory_fixed_region); int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys, @@ -293,11 +319,13 @@ int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr } EXPORT_SYMBOL_GPL(q6apm_alloc_fragments); -int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id) +static int __q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id, + bool is_pos_buf) { struct apm_cmd_shared_mem_unmap_regions *cmd; struct q6apm *apm = dev_get_drvdata(dev->parent); struct audioreach_graph_info *info; + uint32_t mem_map_handle; struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(sizeof(*cmd), APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id); if (IS_ERR(pkt)) @@ -307,16 +335,35 @@ int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id) if (!info) return -ENODEV; - if (!info->mem_map_handle) - return 0; + if (is_pos_buf) { + if (!info->pos_buf_mem_map_handle) + return 0; + mem_map_handle = info->pos_buf_mem_map_handle; + } else { + + if (!info->mem_map_handle) + return 0; + mem_map_handle = info->mem_map_handle; + } cmd = (void *)pkt + GPR_HDR_SIZE; - cmd->mem_map_handle = info->mem_map_handle; + cmd->mem_map_handle = mem_map_handle; return q6apm_send_cmd_sync(apm, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS); } + +int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id) +{ + return __q6apm_unmap_memory_fixed_region(dev, graph_id, false); +} EXPORT_SYMBOL_GPL(q6apm_unmap_memory_fixed_region); +int q6apm_unmap_pos_buffer(struct device *dev, unsigned int graph_id) +{ + return __q6apm_unmap_memory_fixed_region(dev, graph_id, true); +} +EXPORT_SYMBOL_GPL(q6apm_unmap_pos_buffer); + int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir) { audioreach_graph_free_buf(graph); @@ -399,15 +446,20 @@ int q6apm_graph_media_format_pcm(struct q6apm_graph *graph, struct audioreach_mo struct audioreach_sub_graph *sgs; struct audioreach_container *container; struct audioreach_module *module; + int ret; list_for_each_entry(sgs, &info->sg_list, node) { list_for_each_entry(container, &sgs->container_list, node) { list_for_each_entry(module, &container->modules_list, node) { if ((module->module_id == MODULE_ID_WR_SHARED_MEM_EP) || - (module->module_id == MODULE_ID_RD_SHARED_MEM_EP)) + (module->module_id == MODULE_ID_RD_SHARED_MEM_EP) || + (module->module_id == MODULE_ID_SH_MEM_PULL_MODE) || + (module->module_id == MODULE_ID_SH_MEM_PUSH_MODE)) continue; - audioreach_set_media_format(graph, module, cfg); + ret = audioreach_set_media_format(graph, module, cfg); + if (ret) + return ret; } } } @@ -417,31 +469,6 @@ int q6apm_graph_media_format_pcm(struct q6apm_graph *graph, struct audioreach_mo } EXPORT_SYMBOL_GPL(q6apm_graph_media_format_pcm); -static int q6apm_graph_get_tx_shmem_module_iid(struct q6apm_graph *graph) -{ - struct audioreach_module *module; - - module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP); - if (!module) - return -ENODEV; - - return module->instance_id; - -} - -int q6apm_graph_get_rx_shmem_module_iid(struct q6apm_graph *graph) -{ - struct audioreach_module *module; - - module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP); - if (!module) - return -ENODEV; - - return module->instance_id; - -} -EXPORT_SYMBOL_GPL(q6apm_graph_get_rx_shmem_module_iid); - int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts, uint32_t lsw_ts, uint32_t wflags) { @@ -530,6 +557,7 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op) { struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done; struct data_cmd_rsp_wr_sh_mem_ep_data_buffer_done_v2 *done; + struct apm_module_event *event; const struct gpr_ibasic_rsp_result_t *result; struct q6apm_graph *graph = priv; const struct gpr_hdr *hdr = &data->hdr; @@ -541,6 +569,16 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op) result = data->payload; switch (hdr->opcode) { + case APM_EVENT_MODULE_TO_CLIENT: + event = data->payload; + switch (event->event_id) { + case EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK: + client_event = APM_CLIENT_EVENT_WATERMARK_EVENT; + graph->cb(client_event, hdr->token, data->payload, graph->priv); + break; + } + + break; case DATA_CMD_RSP_WR_SH_MEM_EP_DATA_BUFFER_DONE_V2: if (!graph->ar_graph) break; @@ -596,6 +634,7 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op) switch (result->opcode) { case APM_CMD_SHARED_MEM_MAP_REGIONS: case DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT: + case APM_CMD_REGISTER_MODULE_EVENTS: case APM_CMD_SET_CFG: graph->result.opcode = result->opcode; graph->result.status = result->status; @@ -614,13 +653,67 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op) return 0; } +int q6apm_register_watermark_event(struct q6apm_graph *graph, int water_mark_level_bytes, + int num_levels) +{ + return audioreach_shmem_register_event(graph, water_mark_level_bytes, num_levels); +} +EXPORT_SYMBOL_GPL(q6apm_register_watermark_event); + +int q6apm_push_pull_config(struct q6apm_graph *graph, phys_addr_t bphys, + phys_addr_t pphys, uint32_t size) +{ + struct audioreach_graph_info *info = graph->info; + + return audioreach_setup_push_pull(graph, bphys, pphys, info->mem_map_handle, + info->pos_buf_mem_map_handle, size); +} +EXPORT_SYMBOL_GPL(q6apm_push_pull_config); + +bool q6apm_is_graph_in_push_pull_mode_from_id(struct device *dev, unsigned int graph_id, int dir) +{ + struct audioreach_graph_info *info; + struct q6apm *apm = dev_get_drvdata(dev->parent); + struct audioreach_module *module; + + info = idr_find(&apm->graph_info_idr, graph_id); + if (!info) + return false; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + module = __q6apm_find_module_by_mid(apm, info, MODULE_ID_SH_MEM_PULL_MODE); + else + module = __q6apm_find_module_by_mid(apm, info, MODULE_ID_SH_MEM_PUSH_MODE); + + return !!module; + +} +EXPORT_SYMBOL_GPL(q6apm_is_graph_in_push_pull_mode_from_id); + +bool q6apm_is_graph_in_push_pull_mode(struct q6apm_graph *graph) +{ + return graph->info->is_push_pull_mode; +} +EXPORT_SYMBOL_GPL(q6apm_is_graph_in_push_pull_mode); + +static int q6apm_graph_get_module_iid(struct q6apm_graph *graph, uint32_t mid) +{ + struct audioreach_module *module; + + module = q6apm_find_module_by_mid(graph, mid); + if (!module) + return -ENODEV; + + return module->instance_id; +} + struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb, void *priv, int graph_id, int dir) { struct q6apm *apm = dev_get_drvdata(dev->parent); struct audioreach_graph *ar_graph; struct q6apm_graph *graph; - int ret; + int ret, iid = 0; ar_graph = q6apm_get_audioreach_graph(apm, graph_id); if (IS_ERR(ar_graph)) { @@ -642,11 +735,23 @@ struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb, graph->id = ar_graph->id; graph->dev = dev; - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - graph->shm_iid = q6apm_graph_get_rx_shmem_module_iid(graph); - else - graph->shm_iid = q6apm_graph_get_tx_shmem_module_iid(graph); + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + iid = q6apm_graph_get_module_iid(graph, MODULE_ID_SH_MEM_PULL_MODE); + if (iid < 0) + iid = q6apm_graph_get_module_iid(graph, MODULE_ID_WR_SHARED_MEM_EP); + else + graph->info->is_push_pull_mode = true; + } else { + iid = q6apm_graph_get_module_iid(graph, MODULE_ID_SH_MEM_PUSH_MODE); + if (iid < 0) + iid = q6apm_graph_get_module_iid(graph, MODULE_ID_RD_SHARED_MEM_EP); + else + graph->info->is_push_pull_mode = true; + } + + if (iid > 0) + graph->shm_iid = iid; mutex_init(&graph->lock); init_waitqueue_head(&graph->cmd_wait); @@ -803,6 +908,7 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op) struct device *dev = &gdev->dev; struct gpr_ibasic_rsp_result_t *result; const struct gpr_hdr *hdr = &data->hdr; + int graph_id, is_pos_buf; result = data->payload; @@ -853,13 +959,19 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op) apm->result.opcode = hdr->opcode; apm->result.status = 0; rsp = data->payload; + graph_id = hdr->token & APM_MMAP_TOKEN_GID_MASK; + is_pos_buf = hdr->token & APM_MMAP_TOKEN_MAP_TYPE_POS_BUF; - info = idr_find(&apm->graph_info_idr, hdr->token); - if (info) - info->mem_map_handle = rsp->mem_map_handle; - else + info = idr_find(&apm->graph_info_idr, graph_id); + if (info) { + if (is_pos_buf) + info->pos_buf_mem_map_handle = rsp->mem_map_handle; + else + info->mem_map_handle = rsp->mem_map_handle; + } else { dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status, result->opcode); + } wake_up(&apm->wait); break; diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h index 376a36700c53..5cb51ca491dc 100644 --- a/sound/soc/qcom/qdsp6/q6apm.h +++ b/sound/soc/qcom/qdsp6/q6apm.h @@ -41,6 +41,7 @@ #define APM_CLIENT_EVENT_CMD_RUN_DONE 0x1008 #define APM_CLIENT_EVENT_DATA_WRITE_DONE 0x1009 #define APM_CLIENT_EVENT_DATA_READ_DONE 0x100a +#define APM_CLIENT_EVENT_WATERMARK_EVENT 0x100b #define APM_WRITE_TOKEN_MASK GENMASK(15, 0) #define APM_WRITE_TOKEN_LEN_MASK GENMASK(31, 16) #define APM_WRITE_TOKEN_LEN_SHIFT 16 @@ -136,6 +137,10 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts, int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys, size_t sz); +int q6apm_map_pos_buffer(struct device *dev, + unsigned int graph_id, phys_addr_t phys, + size_t sz); +int q6apm_unmap_pos_buffer(struct device *dev, unsigned int graph_id); int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys, size_t period_sz, unsigned int periods); @@ -148,8 +153,6 @@ int q6apm_send_cmd_sync(struct q6apm *apm, const struct gpr_pkt *pkt, /* Callback for graph specific */ struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph, uint32_t mid); -int q6apm_graph_get_rx_shmem_module_iid(struct q6apm_graph *graph); - bool q6apm_is_adsp_ready(void); int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, bool en); @@ -157,4 +160,10 @@ int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id); int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir); +bool q6apm_is_graph_in_push_pull_mode(struct q6apm_graph *graph); +bool q6apm_is_graph_in_push_pull_mode_from_id(struct device *dev, unsigned int graph_id, int dir); +int q6apm_push_pull_config(struct q6apm_graph *graph, phys_addr_t bphys, + phys_addr_t pphys, uint32_t size); + +int q6apm_register_watermark_event(struct q6apm_graph *graph, int watermark_bytes, int num_levels); #endif /* __APM_GRAPH_ */ diff --git a/sound/soc/renesas/fsi.c b/sound/soc/renesas/fsi.c index 8cbd7acc26f4..ae86014c3819 100644 --- a/sound/soc/renesas/fsi.c +++ b/sound/soc/renesas/fsi.c @@ -292,6 +292,7 @@ struct fsi_master { void __iomem *base; struct fsi_priv fsia; struct fsi_priv fsib; + struct clk *clk_spu; const struct fsi_core *core; spinlock_t lock; }; @@ -442,6 +443,16 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples) return samples / fsi->chan_num; } +static int fsi_stream_is_working(struct fsi_priv *fsi, + struct fsi_stream *io) +{ + struct fsi_master *master = fsi_get_master(fsi); + + guard(spinlock_irqsave)(&master->lock); + + return !!(io->substream && io->substream->runtime); +} + static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, struct fsi_stream *io) { @@ -460,6 +471,10 @@ static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, static void fsi_count_fifo_err(struct fsi_priv *fsi) { + if (!fsi_stream_is_working(fsi, &fsi->playback) && + !fsi_stream_is_working(fsi, &fsi->capture)) + return; + u32 ostatus = fsi_reg_read(fsi, DOFF_ST); u32 istatus = fsi_reg_read(fsi, DIFF_ST); @@ -488,16 +503,6 @@ static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi, return fsi_is_play(substream) ? &fsi->playback : &fsi->capture; } -static int fsi_stream_is_working(struct fsi_priv *fsi, - struct fsi_stream *io) -{ - struct fsi_master *master = fsi_get_master(fsi); - - guard(spinlock_irqsave)(&master->lock); - - return !!(io->substream && io->substream->runtime); -} - static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io) { return io->priv; @@ -681,6 +686,10 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi) u32 data = 0; struct fsi_master *master = fsi_get_master(fsi); + if (!fsi_stream_is_working(fsi, &fsi->playback) && + !fsi_stream_is_working(fsi, &fsi->capture)) + return; + data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback)); data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture)); @@ -709,70 +718,6 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) /* * clock function */ -static int fsi_clk_init(struct device *dev, - struct fsi_priv *fsi, - int xck, - int ick, - int div, - int (*set_rate)(struct device *dev, - struct fsi_priv *fsi)) -{ - struct fsi_clk *clock = &fsi->clock; - int is_porta = fsi_is_port_a(fsi); - - clock->xck = NULL; - clock->ick = NULL; - clock->div = NULL; - clock->rate = 0; - clock->count = 0; - clock->set_rate = set_rate; - - clock->own = devm_clk_get(dev, NULL); - if (IS_ERR(clock->own)) - return -EINVAL; - - /* external clock */ - if (xck) { - clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb"); - if (IS_ERR(clock->xck)) { - dev_err(dev, "can't get xck clock\n"); - return -EINVAL; - } - if (clock->xck == clock->own) { - dev_err(dev, "cpu doesn't support xck clock\n"); - return -EINVAL; - } - } - - /* FSIACLK/FSIBCLK */ - if (ick) { - clock->ick = devm_clk_get(dev, is_porta ? "icka" : "ickb"); - if (IS_ERR(clock->ick)) { - dev_err(dev, "can't get ick clock\n"); - return -EINVAL; - } - if (clock->ick == clock->own) { - dev_err(dev, "cpu doesn't support ick clock\n"); - return -EINVAL; - } - } - - /* FSI-DIV */ - if (div) { - clock->div = devm_clk_get(dev, is_porta ? "diva" : "divb"); - if (IS_ERR(clock->div)) { - dev_err(dev, "can't get div clock\n"); - return -EINVAL; - } - if (clock->div == clock->own) { - dev_err(dev, "cpu doesn't support div clock\n"); - return -EINVAL; - } - } - - return 0; -} - #define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0) static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate) { @@ -785,6 +730,54 @@ static int fsi_clk_is_valid(struct fsi_priv *fsi) fsi->clock.rate; } +static int fsi_clk_prepare(struct fsi_priv *fsi) +{ + struct fsi_clk *clock = &fsi->clock; + struct clk *spu = fsi->master->clk_spu; + struct clk *xck = clock->xck; + struct clk *ick = clock->ick; + struct clk *div = clock->div; + int ret; + + ret = clk_prepare(spu); + if (ret) + return ret; + ret = clk_prepare(xck); + if (ret) + goto err_spu; + ret = clk_prepare(ick); + if (ret) + goto err_xck; + ret = clk_prepare(div); + if (ret) + goto err_ick; + + return 0; + +err_ick: + clk_unprepare(ick); +err_xck: + clk_unprepare(xck); +err_spu: + clk_unprepare(spu); + + return ret; +} + +static void fsi_clk_unprepare(struct fsi_priv *fsi) +{ + struct fsi_clk *clock = &fsi->clock; + struct clk *spu = fsi->master->clk_spu; + struct clk *xck = clock->xck; + struct clk *ick = clock->ick; + struct clk *div = clock->div; + + clk_unprepare(div); + clk_unprepare(ick); + clk_unprepare(xck); + clk_unprepare(spu); +} + static int fsi_clk_enable(struct device *dev, struct fsi_priv *fsi) { @@ -918,6 +911,11 @@ static int fsi_clk_set_rate_external(struct device *dev, int ackmd, bpfmd; int ret = 0; + if (!xck || !ick) { + dev_err(dev, "xck clock or ick clock is missing\n"); + return -EINVAL; + } + /* check clock rate */ xrate = clk_get_rate(xck); if (xrate % rate) { @@ -954,6 +952,11 @@ static int fsi_clk_set_rate_cpg(struct device *dev, int ackmd, bpfmd; int ret = -EINVAL; + if (!ick || !div) { + dev_err(dev, "ick clock or div clock is missing\n"); + return -EINVAL; + } + if (!(12288000 % rate)) target = 12288000; if (!(11289600 % rate)) @@ -1026,6 +1029,74 @@ static int fsi_clk_set_rate_cpg(struct device *dev, return ret; } +static int fsi_clk_init(struct device *dev, struct fsi_priv *fsi) +{ + struct fsi_clk *clock = &fsi->clock; + struct fsi_master *master = fsi->master; + int is_porta = fsi_is_port_a(fsi); + int xck, ick, div; + + if (fsi->clk_cpg) { + xck = 0; ick = 1; div = 1; + clock->set_rate = fsi_clk_set_rate_cpg; + } else { + xck = 1; ick = 1; div = 0; + clock->set_rate = fsi_clk_set_rate_external; + } + + clock->xck = NULL; + clock->ick = NULL; + clock->div = NULL; + clock->rate = 0; + clock->count = 0; + + clock->own = devm_clk_get(dev, NULL); + if (IS_ERR(clock->own)) + return dev_err_probe(dev, PTR_ERR(clock->own), "Can't get fck clock\n"); + + if (!master->clk_spu) { + master->clk_spu = devm_clk_get_optional(dev, "spu"); + if (IS_ERR(master->clk_spu)) + return dev_err_probe(dev, PTR_ERR(master->clk_spu), + "Can't get spu clock\n"); + } + + /* external clock */ + if (xck) { + clock->xck = devm_clk_get_optional(dev, is_porta ? "xcka" : "xckb"); + if (IS_ERR(clock->xck)) + return dev_err_probe(dev, PTR_ERR(clock->xck), "Can't get xck clock\n"); + if (clock->xck == clock->own) { + dev_err(dev, "cpu doesn't support xck clock\n"); + return -EINVAL; + } + } + + /* FSIACLK/FSIBCLK */ + if (ick) { + clock->ick = devm_clk_get_optional(dev, is_porta ? "icka" : "ickb"); + if (IS_ERR(clock->ick)) + return dev_err_probe(dev, PTR_ERR(clock->ick), "Can't get ick clock\n"); + if (clock->ick == clock->own) { + dev_err(dev, "cpu doesn't support ick clock\n"); + return -EINVAL; + } + } + + /* FSI-DIV */ + if (div) { + clock->div = devm_clk_get_optional(dev, is_porta ? "diva" : "divb"); + if (IS_ERR(clock->div)) + return dev_err_probe(dev, PTR_ERR(clock->div), "Can't get div clock\n"); + if (clock->div == clock->own) { + dev_err(dev, "cpu doesn't support div clock\n"); + return -EINVAL; + } + } + + return 0; +} + static void fsi_pointer_update(struct fsi_stream *io, int size) { io->buff_sample_pos += size; @@ -1489,6 +1560,11 @@ static int fsi_hw_startup(struct fsi_priv *fsi, struct device *dev) { u32 data = 0; + int ret; + /* enable spu bus bridge clock */ + ret = clk_enable(fsi->master->clk_spu); + if (ret) + return ret; /* clock setting */ if (fsi_is_clk_master(fsi)) @@ -1534,8 +1610,13 @@ static int fsi_hw_startup(struct fsi_priv *fsi, fsi_fifo_init(fsi, io, dev); /* start master clock */ - if (fsi_is_clk_master(fsi)) - return fsi_clk_enable(dev, fsi); + if (fsi_is_clk_master(fsi)) { + ret = fsi_clk_enable(dev, fsi); + if (ret) { + clk_disable(fsi->master->clk_spu); + return ret; + } + } return 0; } @@ -1543,9 +1624,15 @@ static int fsi_hw_startup(struct fsi_priv *fsi, static int fsi_hw_shutdown(struct fsi_priv *fsi, struct device *dev) { + int ret; /* stop master clock */ - if (fsi_is_clk_master(fsi)) - return fsi_clk_disable(dev, fsi); + if (fsi_is_clk_master(fsi)) { + ret = fsi_clk_disable(dev, fsi); + if (ret) + return ret; + } + /* stop spu bus bridge clock */ + clk_disable(fsi->master->clk_spu); return 0; } @@ -1557,7 +1644,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, fsi_clk_invalid(fsi); - return 0; + return fsi_clk_prepare(fsi); } static void fsi_dai_shutdown(struct snd_pcm_substream *substream, @@ -1565,6 +1652,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, { struct fsi_priv *fsi = fsi_get_priv(substream); + fsi_clk_unprepare(fsi); fsi_clk_invalid(fsi); } @@ -1586,10 +1674,10 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, ret = fsi_stream_transfer(io); break; case SNDRV_PCM_TRIGGER_STOP: - if (!ret) - ret = fsi_hw_shutdown(fsi, dai->dev); fsi_stream_stop(fsi, io); fsi_stream_quit(fsi, io); + if (!ret) + ret = fsi_hw_shutdown(fsi, dai->dev); break; } @@ -1664,15 +1752,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) break; } - if (fsi_is_clk_master(fsi)) { - if (fsi->clk_cpg) - fsi_clk_init(dai->dev, fsi, 0, 1, 1, - fsi_clk_set_rate_cpg); - else - fsi_clk_init(dai->dev, fsi, 1, 1, 0, - fsi_clk_set_rate_external); - } - /* set format */ if (fsi_is_spdif(fsi)) ret = fsi_set_fmt_spdif(fsi); @@ -1694,11 +1773,6 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, return 0; } -/* - * Select below from Sound Card, not auto - * SND_SOC_DAIFMT_CBC_CFC - * SND_SOC_DAIFMT_CBP_CFP - */ static const u64 fsi_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_LEFT_J | @@ -1923,20 +1997,10 @@ static int fsi_probe(struct platform_device *pdev) memset(&info, 0, sizeof(info)); - core = NULL; - if (np) { - core = of_device_get_match_data(&pdev->dev); - fsi_of_parse("fsia", np, &info.port_a, &pdev->dev); - fsi_of_parse("fsib", np, &info.port_b, &pdev->dev); - } else { - const struct platform_device_id *id_entry = pdev->id_entry; - if (id_entry) - core = (struct fsi_core *)id_entry->driver_data; - - if (pdev->dev.platform_data) - memcpy(&info, pdev->dev.platform_data, sizeof(info)); - } + fsi_of_parse("fsia", np, &info.port_a, &pdev->dev); + fsi_of_parse("fsib", np, &info.port_b, &pdev->dev); + core = of_device_get_match_data(&pdev->dev); if (!core) { dev_err(&pdev->dev, "unknown fsi device\n"); return -ENODEV; @@ -1970,6 +2034,11 @@ static int fsi_probe(struct platform_device *pdev) fsi->master = master; fsi_port_info_init(fsi, &info.port_a); fsi_handler_init(fsi, &info.port_a); + ret = fsi_clk_init(&pdev->dev, fsi); + if (ret) { + dev_err(&pdev->dev, "FSIA clk init failed\n"); + return ret; + } ret = fsi_stream_probe(fsi, &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "FSIA stream probe failed\n"); @@ -1983,6 +2052,11 @@ static int fsi_probe(struct platform_device *pdev) fsi->master = master; fsi_port_info_init(fsi, &info.port_b); fsi_handler_init(fsi, &info.port_b); + ret = fsi_clk_init(&pdev->dev, fsi); + if (ret) { + dev_err(&pdev->dev, "FSIB clk init failed\n"); + goto exit_fsia; + } ret = fsi_stream_probe(fsi, &pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "FSIB stream probe failed\n"); diff --git a/sound/soc/renesas/rcar/adg.c b/sound/soc/renesas/rcar/adg.c index 8641b73d1f77..5479cefb6dbe 100644 --- a/sound/soc/renesas/rcar/adg.c +++ b/sound/soc/renesas/rcar/adg.c @@ -19,6 +19,9 @@ #define CLKOUT3 3 #define CLKOUTMAX 4 +/* Maximum SSI count for per-SSI clocks */ +#define ADG_SSI_MAX 10 + #define BRGCKR_31 (1 << 31) #define BRRx_MASK(x) (0x3FF & x) @@ -34,10 +37,14 @@ struct rsnd_adg { struct clk *adg; struct clk *clkin[CLKINMAX]; struct clk *clkout[CLKOUTMAX]; + /* RZ/G3E: per-SSI ADG clocks (adg-ssi-0 through adg-ssi-9) */ + struct clk *clk_adg_ssi[ADG_SSI_MAX]; + struct clk *clk_ssif_supply; struct clk *null_clk; struct clk_onecell_data onecell; struct rsnd_mod mod; int clkin_rate[CLKINMAX]; + bool ssi_clk_prepared; int clkin_size; int clkout_size; u32 ckr; @@ -70,6 +77,13 @@ static const char * const clkin_name_gen2[] = { [CLKI] = "clk_i", }; +static const char * const clkin_name_rzg3e[] = { + [CLKA] = "audio-clka", + [CLKB] = "audio-clkb", + [CLKC] = "audio-clkc", + [CLKI] = "audio-clki", +}; + static const char * const clkout_name_gen2[] = { [CLKOUT] = "audio_clkout", [CLKOUT1] = "audio_clkout1", @@ -343,8 +357,16 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod) { + struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + int id = rsnd_mod_id(ssi_mod); + rsnd_adg_set_ssi_clk(ssi_mod, 0); + /* RZ/G3E: only disable here, unprepare is done in hw_free */ + clk_disable(adg->clk_adg_ssi[id]); + clk_disable(adg->clk_ssif_supply); + return 0; } @@ -354,7 +376,8 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod *adg_mod = rsnd_mod_get(adg); - int data; + int id = rsnd_mod_id(ssi_mod); + int ret, data; u32 ckr = 0; data = rsnd_adg_clk_query(priv, rate); @@ -376,9 +399,63 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) (ckr) ? adg->brg_rate[ADG_HZ_48] : adg->brg_rate[ADG_HZ_441]); + /* + * RZ/G3E: enable per-SSI and supply clocks + */ + ret = clk_enable(adg->clk_adg_ssi[id]); + if (ret) { + dev_err(dev, "Cannot enable adg-ssi-%d ADG clock\n", id); + return ret; + } + + ret = clk_enable(adg->clk_ssif_supply); + if (ret) { + dev_err(dev, "Cannot enable SSIF supply clock\n"); + clk_disable(adg->clk_adg_ssi[id]); + return ret; + } + return 0; } +static int rsnd_adg_ssi_clk_prepare(struct rsnd_adg *adg) +{ + int i, ret; + + if (adg->ssi_clk_prepared) + return 0; + + for (i = 0; i < ADG_SSI_MAX; i++) { + ret = clk_prepare(adg->clk_adg_ssi[i]); + if (ret) + goto unwind; + } + ret = clk_prepare(adg->clk_ssif_supply); + if (ret) + goto unwind; + + adg->ssi_clk_prepared = true; + return 0; + +unwind: + while (i--) + clk_unprepare(adg->clk_adg_ssi[i]); + return ret; +} + +static void rsnd_adg_ssi_clk_unprepare(struct rsnd_adg *adg) +{ + int i; + + if (!adg->ssi_clk_prepared) + return; + adg->ssi_clk_prepared = false; + + clk_unprepare(adg->clk_ssif_supply); + for (i = 0; i < ADG_SSI_MAX; i++) + clk_unprepare(adg->clk_adg_ssi[i]); +} + int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); @@ -417,6 +494,28 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) } } + /* + * rsnd_adg_clk_enable() might return error (_disable() will not). + * We need to rollback in such case + */ + /* + * RZ/G3E per-SSI ADG and SSIF supply clocks. + * + * Follow the same style as for_each_rsnd_clkin() above: on enable, + * try to prepare every clock and accumulate the error. On disable, + * unprepare every clock. Absent optional clocks are NULL, for + * which clk_prepare() and clk_unprepare() are no-ops. + */ + if (enable) { + int sub_ret = rsnd_adg_ssi_clk_prepare(adg); + + /* Preserve the first error from the clkin loop above. */ + if (sub_ret && !ret) + ret = sub_ret; + } else { + rsnd_adg_ssi_clk_unprepare(adg); + } + /* * rsnd_adg_clk_enable() might return error (_disable() will not). * We need to rollback in such case @@ -482,6 +581,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv) if (rsnd_is_gen4(priv)) { clkin_name = clkin_name_gen4; clkin_size = ARRAY_SIZE(clkin_name_gen4); + } else if (rsnd_is_rzg3e(priv)) { + clkin_name = clkin_name_rzg3e; + clkin_size = ARRAY_SIZE(clkin_name_rzg3e); } /* @@ -769,8 +871,34 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m) #define rsnd_adg_clk_dbg_info(priv, m) #endif +static int rsnd_adg_get_ssi_clks(struct rsnd_priv *priv) +{ + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + struct device *dev = rsnd_priv_to_dev(priv); + char name[16]; + int i; + + /* SSIF supply clock */ + adg->clk_ssif_supply = devm_clk_get_optional(dev, "ssif_supply"); + if (IS_ERR(adg->clk_ssif_supply)) + return dev_err_probe(dev, PTR_ERR(adg->clk_ssif_supply), + "failed to get ssif_supply clock\n"); + + /* Per-SSI ADG clocks (RZ/G3E-only; no legacy dotted form exists) */ + for (i = 0; i < ADG_SSI_MAX; i++) { + snprintf(name, sizeof(name), "adg-ssi-%d", i); + adg->clk_adg_ssi[i] = devm_clk_get_optional(dev, name); + if (IS_ERR(adg->clk_adg_ssi[i])) + return dev_err_probe(dev, PTR_ERR(adg->clk_adg_ssi[i]), + "failed to get %s clock\n", name); + } + + return 0; +} + int rsnd_adg_probe(struct rsnd_priv *priv) { + struct reset_control *rstc; struct rsnd_adg *adg; struct device *dev = rsnd_priv_to_dev(priv); int ret; @@ -779,8 +907,11 @@ int rsnd_adg_probe(struct rsnd_priv *priv) if (!adg) return -ENOMEM; - ret = rsnd_mod_init(priv, &adg->mod, &adg_ops, - NULL, 0, 0); + rstc = devm_reset_control_get_optional_exclusive(dev, "adg"); + if (IS_ERR(rstc)) + return dev_err_probe(dev, PTR_ERR(rstc), "failed to get adg reset\n"); + + ret = rsnd_mod_init(priv, &adg->mod, &adg_ops, NULL, rstc, 0, 0); if (ret) return ret; @@ -794,6 +925,11 @@ int rsnd_adg_probe(struct rsnd_priv *priv) if (ret) return ret; + /* RZ/G3E-specific: per-SSI ADG and SSIF supply clocks */ + ret = rsnd_adg_get_ssi_clks(priv); + if (ret) + return ret; + ret = rsnd_adg_clk_enable(priv); if (ret) return ret; @@ -817,3 +953,29 @@ void rsnd_adg_remove(struct rsnd_priv *priv) /* It should be called after rsnd_adg_clk_disable() */ rsnd_adg_null_clk_clean(priv); } + +static struct rsnd_mod *rsnd_adg_mod_get(struct rsnd_priv *priv) +{ + struct rsnd_adg *adg = rsnd_priv_to_adg(priv); + + if (!adg) + return NULL; + + return rsnd_mod_get(adg); +} + +void rsnd_adg_suspend(struct rsnd_priv *priv) +{ + struct rsnd_mod *mod = rsnd_adg_mod_get(priv); + + if (mod) + rsnd_suspend_clk_reset(mod->clk, mod->rstc); +} + +void rsnd_adg_resume(struct rsnd_priv *priv) +{ + struct rsnd_mod *mod = rsnd_adg_mod_get(priv); + + if (mod) + rsnd_resume_clk_reset(mod->clk, mod->rstc); +} diff --git a/sound/soc/renesas/rcar/cmd.c b/sound/soc/renesas/rcar/cmd.c index 8d9a1e345a22..13beef389797 100644 --- a/sound/soc/renesas/rcar/cmd.c +++ b/sound/soc/renesas/rcar/cmd.c @@ -171,7 +171,7 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) for_each_rsnd_cmd(cmd, priv, i) { int ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), - &rsnd_cmd_ops, NULL, + &rsnd_cmd_ops, NULL, NULL, RSND_MOD_CMD, i); if (ret) return ret; diff --git a/sound/soc/renesas/rcar/core.c b/sound/soc/renesas/rcar/core.c index 2dc078358612..b7954746e953 100644 --- a/sound/soc/renesas/rcar/core.c +++ b/sound/soc/renesas/rcar/core.c @@ -106,6 +106,8 @@ static const struct of_device_id rsnd_of_match[] = { { .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 }, /* Special Handling */ { .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) }, + { .compatible = "renesas,r9a09g047-sound", + .data = (void *)(RSND_RZ3 | RSND_RZG3E | RSND_SSIU_BUSIF_STATUS_COUNT_2) }, {}, }; MODULE_DEVICE_TABLE(of, rsnd_of_match); @@ -196,18 +198,29 @@ int rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, struct clk *clk, + struct reset_control *rstc, enum rsnd_mod_type type, int id) { - int ret = clk_prepare(clk); + int ret; + ret = clk_prepare_enable(clk); if (ret) return ret; + ret = reset_control_deassert(rstc); + if (ret) { + clk_disable_unprepare(clk); + return ret; + } + + clk_disable(clk); + mod->id = id; mod->ops = ops; mod->type = type; mod->clk = clk; + mod->rstc = rstc; mod->priv = priv; return 0; @@ -215,6 +228,8 @@ int rsnd_mod_init(struct rsnd_priv *priv, void rsnd_mod_quit(struct rsnd_mod *mod) { + reset_control_assert(mod->rstc); + mod->rstc = NULL; clk_unprepare(mod->clk); mod->clk = NULL; } @@ -947,7 +962,8 @@ static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, static const struct snd_pcm_hardware rsnd_pcm_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_RESUME, .buffer_bytes_max = 64 * 1024, .period_bytes_min = 32, .period_bytes_max = 8192, @@ -1042,9 +1058,6 @@ static const u64 rsnd_soc_dai_formats[] = { * 1st Priority * * Well tested formats. - * Select below from Sound Card, not auto - * SND_SOC_DAIFMT_CBC_CFC - * SND_SOC_DAIFMT_CBP_CFP */ SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | @@ -1058,8 +1071,15 @@ static const u64 rsnd_soc_dai_formats[] = { * * Supported, but not well tested */ + SND_SOC_POSSIBLE_DAIFMT_I2S | + SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | + SND_SOC_POSSIBLE_DAIFMT_LEFT_J | SND_SOC_POSSIBLE_DAIFMT_DSP_A | - SND_SOC_POSSIBLE_DAIFMT_DSP_B, + SND_SOC_POSSIBLE_DAIFMT_DSP_B | + SND_SOC_POSSIBLE_DAIFMT_NB_NF | + SND_SOC_POSSIBLE_DAIFMT_NB_IF | + SND_SOC_POSSIBLE_DAIFMT_IB_NF | + SND_SOC_POSSIBLE_DAIFMT_IB_IF, }; static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv, @@ -1219,6 +1239,107 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name return i; } +/* + * Build "-" or "." and try the hyphen form first, + * falling back to the dot form if the hyphen form is not present. This lets + * the driver accept both the new DT convention ("ssi-0", "src-0", ...) and + * the legacy R-Car convention ("ssi.0", "src.0", ...) transparently. + * + * @base: name prefix ("ssi", "src", "ctu", "mix", "dvc", "adg.ssi", ...) + * @index: integer suffix + * + * On -ENOENT from the hyphen form, the dot form is tried. All other errors + * (including -EPROBE_DEFER) are returned to the caller unchanged, so + * behaviour against the clock and reset frameworks is preserved. + */ +#define RSND_INDEXED_NAME_MAX 32 + +static void rsnd_format_indexed_name(char *buf, size_t buflen, char sep, + const char *base, int index) +{ + snprintf(buf, buflen, "%s%c%d", base, sep, index); +} + +struct clk *rsnd_devm_clk_get_indexed(struct device *dev, + const char *base, int index) +{ + char name[RSND_INDEXED_NAME_MAX]; + struct clk *clk; + + rsnd_format_indexed_name(name, sizeof(name), '-', base, index); + clk = devm_clk_get(dev, name); + if (!IS_ERR(clk) || PTR_ERR(clk) != -ENOENT) + return clk; + + rsnd_format_indexed_name(name, sizeof(name), '.', base, index); + return devm_clk_get(dev, name); +} + +struct clk *rsnd_devm_clk_get_optional_indexed(struct device *dev, + const char *base, int index) +{ + char name[RSND_INDEXED_NAME_MAX]; + struct clk *clk; + + rsnd_format_indexed_name(name, sizeof(name), '-', base, index); + clk = devm_clk_get_optional(dev, name); + if (IS_ERR(clk) || clk) + return clk; + + rsnd_format_indexed_name(name, sizeof(name), '.', base, index); + return devm_clk_get_optional(dev, name); +} + +struct reset_control * +rsnd_devm_reset_control_get_optional_indexed(struct device *dev, + const char *base, int index) +{ + char name[RSND_INDEXED_NAME_MAX]; + struct reset_control *rstc; + + rsnd_format_indexed_name(name, sizeof(name), '-', base, index); + rstc = devm_reset_control_get_optional(dev, name); + if (IS_ERR(rstc) || rstc) + return rstc; + + rsnd_format_indexed_name(name, sizeof(name), '.', base, index); + return devm_reset_control_get_optional(dev, name); +} + +/* + * Strip the "rcar_sound," prefix from a legacy node name. + * + * The RZ/G3E binding uses unprefixed sub-node names (e.g. "ssi", + * "ssiu") while earlier R-Car bindings use the legacy "rcar_sound,*" + * form. This helper returns the unprefixed portion (the part after + * the comma) or NULL if there is no prefix. + * + * Centralising the convention here keeps every call site consistent. + */ +static const char *rsnd_node_name_strip_prefix(const char *name) +{ + const char *comma = strchr(name, ','); + + return comma ? comma + 1 : NULL; +} + +struct device_node *rsnd_parse_of_node(struct rsnd_priv *priv, const char *name) +{ + struct device_node *np = rsnd_priv_to_dev(priv)->of_node; + struct device_node *node; + const char *unprefixed; + + node = of_get_child_by_name(np, name); + if (node) + return node; + + unprefixed = rsnd_node_name_strip_prefix(name); + if (unprefixed) + node = of_get_child_by_name(np, unprefixed); + + return node; +} + static struct device_node* rsnd_pick_endpoint_node_for_ports(struct device_node *e_ports, struct device_node *e_port) @@ -2043,11 +2164,35 @@ static void rsnd_remove(struct platform_device *pdev) remove_func[i](priv); } +void rsnd_suspend_clk_reset(struct clk *clk, struct reset_control *rstc) +{ + clk_unprepare(clk); + reset_control_assert(rstc); +} + +void rsnd_resume_clk_reset(struct clk *clk, struct reset_control *rstc) +{ + reset_control_deassert(rstc); + clk_prepare(clk); +} + static int rsnd_suspend(struct device *dev) { struct rsnd_priv *priv = dev_get_drvdata(dev); + /* + * Reverse order of probe: + * ADG -> DVC -> MIX -> CTU -> SRC -> SSIU -> SSI -> DMA + */ rsnd_adg_clk_disable(priv); + rsnd_adg_suspend(priv); + rsnd_dvc_suspend(priv); + rsnd_mix_suspend(priv); + rsnd_ctu_suspend(priv); + rsnd_src_suspend(priv); + rsnd_ssiu_suspend(priv); + rsnd_ssi_suspend(priv); + rsnd_dma_suspend(priv); return 0; } @@ -2056,7 +2201,21 @@ static int rsnd_resume(struct device *dev) { struct rsnd_priv *priv = dev_get_drvdata(dev); - return rsnd_adg_clk_enable(priv); + /* + * Same order as probe: + * DMA -> SSI -> SSIU -> SRC -> CTU -> MIX -> DVC -> ADG + */ + rsnd_dma_resume(priv); + rsnd_ssi_resume(priv); + rsnd_ssiu_resume(priv); + rsnd_src_resume(priv); + rsnd_ctu_resume(priv); + rsnd_mix_resume(priv); + rsnd_dvc_resume(priv); + rsnd_adg_resume(priv); + rsnd_adg_clk_enable(priv); + + return 0; } static const struct dev_pm_ops rsnd_pm_ops = { diff --git a/sound/soc/renesas/rcar/ctu.c b/sound/soc/renesas/rcar/ctu.c index bd4c61f9fb3c..7db0fb3612bc 100644 --- a/sound/soc/renesas/rcar/ctu.c +++ b/sound/soc/renesas/rcar/ctu.c @@ -6,7 +6,6 @@ #include "rsnd.h" -#define CTU_NAME_SIZE 16 #define CTU_NAME "ctu" /* @@ -319,7 +318,6 @@ int rsnd_ctu_probe(struct rsnd_priv *priv) struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_ctu *ctu; struct clk *clk; - char name[CTU_NAME_SIZE]; int i, nr, ret; node = rsnd_ctu_of_node(priv); @@ -350,17 +348,14 @@ int rsnd_ctu_probe(struct rsnd_priv *priv) * CTU00, CTU01, CTU02, CTU03 => CTU0 * CTU10, CTU11, CTU12, CTU13 => CTU1 */ - snprintf(name, CTU_NAME_SIZE, "%s.%d", - CTU_NAME, i / 4); - - clk = devm_clk_get(dev, name); + clk = rsnd_devm_clk_get_indexed(dev, CTU_NAME, i / 4); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto rsnd_ctu_probe_done; } ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, - clk, RSND_MOD_CTU, i); + clk, NULL, RSND_MOD_CTU, i); if (ret) goto rsnd_ctu_probe_done; @@ -383,3 +378,23 @@ void rsnd_ctu_remove(struct rsnd_priv *priv) rsnd_mod_quit(rsnd_mod_get(ctu)); } } + +void rsnd_ctu_suspend(struct rsnd_priv *priv) +{ + struct rsnd_ctu *ctu; + int i; + + for_each_rsnd_ctu(ctu, priv, i) + rsnd_suspend_clk_reset(rsnd_mod_get(ctu)->clk, + rsnd_mod_get(ctu)->rstc); +} + +void rsnd_ctu_resume(struct rsnd_priv *priv) +{ + struct rsnd_ctu *ctu; + int i; + + for_each_rsnd_ctu(ctu, priv, i) + rsnd_resume_clk_reset(rsnd_mod_get(ctu)->clk, + rsnd_mod_get(ctu)->rstc); +} diff --git a/sound/soc/renesas/rcar/dma.c b/sound/soc/renesas/rcar/dma.c index 2035ce06fe4c..793dd4adbe5c 100644 --- a/sound/soc/renesas/rcar/dma.c +++ b/sound/soc/renesas/rcar/dma.c @@ -47,6 +47,9 @@ struct rsnd_dma_ctrl { phys_addr_t ppres; int dmaen_num; int dmapp_num; + /* RZ/G3E: Audio DMAC peri-peri clock and reset */ + struct clk *audmapp_clk; + struct reset_control *audmapp_rstc; }; #define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma) @@ -478,6 +481,69 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = { DEBUG_INFO }; +struct rsnd_dma_addr { + dma_addr_t out_addr; + dma_addr_t in_addr; +}; + +struct rsnd_dma_addr_dir { + struct rsnd_dma_addr capture[3]; + struct rsnd_dma_addr playback[3]; +}; + +struct rsnd_dma_addr_map { + struct rsnd_dma_addr_dir src; + struct rsnd_dma_addr_dir ssi; + struct rsnd_dma_addr_dir ssiu; +}; + +static dma_addr_t +rsnd_dma_addr_lookup(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, + struct rsnd_priv *priv, + const struct rsnd_dma_addr_map *map, + int is_play, int is_from) +{ + struct device *dev = rsnd_priv_to_dev(priv); + int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) || + !!(rsnd_io_to_mod_ssiu(io) == mod); + int use_src = !!rsnd_io_to_mod_src(io); + int use_cmd = !!rsnd_io_to_mod_dvc(io) || + !!rsnd_io_to_mod_mix(io) || + !!rsnd_io_to_mod_ctu(io); + int id = rsnd_mod_id(mod); + const struct rsnd_dma_addr_dir *dir; + const struct rsnd_dma_addr *addr; + + /* it shouldn't happen */ + if (use_cmd && !use_src) + dev_err(dev, "DVC is selected without SRC\n"); + + /* use SSIU or SSI? */ + if (is_ssi && rsnd_ssi_use_busif(io)) + is_ssi++; + + dev_dbg(dev, "dma%d addr : is_ssi=%d use_src=%d use_cmd=%d\n", + id, is_ssi, use_src, use_cmd); + + switch (is_ssi) { + case 2: + dir = &map->ssiu; + break; + case 1: + dir = &map->ssi; + break; + default: + dir = &map->src; + break; + } + + addr = is_play ? &dir->playback[use_src + use_cmd] + : &dir->capture[use_src + use_cmd]; + + return is_from ? addr->out_addr : addr->in_addr; +} + /* * Common DMAC Interface */ @@ -524,47 +590,45 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, struct device *dev = rsnd_priv_to_dev(priv); phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI); phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU); - int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) || - !!(rsnd_io_to_mod_ssiu(io) == mod); - int use_src = !!rsnd_io_to_mod_src(io); - int use_cmd = !!rsnd_io_to_mod_dvc(io) || - !!rsnd_io_to_mod_mix(io) || - !!rsnd_io_to_mod_ctu(io); int id = rsnd_mod_id(mod); int busif = rsnd_mod_id_sub(rsnd_io_to_mod_ssiu(io)); - struct dma_addr { - dma_addr_t out_addr; - dma_addr_t in_addr; - } dma_addrs[3][2][3] = { - /* SRC */ - /* Capture */ - {{{ 0, 0 }, - { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, - { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, - /* Playback */ - {{ 0, 0, }, - { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, - { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } + const struct rsnd_dma_addr_map map = { + .src = { + .capture = { + { 0, 0 }, + { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, + { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) }, + }, + .playback = { + { 0, 0 }, + { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, + { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) }, + }, }, - /* SSI */ - /* Capture */ - {{{ RDMA_SSI_O_N(ssi, id), 0 }, - { RDMA_SSIU_O_P(ssi, id, busif), 0 }, - { RDMA_SSIU_O_P(ssi, id, busif), 0 } }, - /* Playback */ - {{ 0, RDMA_SSI_I_N(ssi, id) }, - { 0, RDMA_SSIU_I_P(ssi, id, busif) }, - { 0, RDMA_SSIU_I_P(ssi, id, busif) } } + .ssi = { + .capture = { + { RDMA_SSI_O_N(ssi, id), 0 }, + { RDMA_SSIU_O_P(ssi, id, busif), 0 }, + { RDMA_SSIU_O_P(ssi, id, busif), 0 }, + }, + .playback = { + { 0, RDMA_SSI_I_N(ssi, id) }, + { 0, RDMA_SSIU_I_P(ssi, id, busif) }, + { 0, RDMA_SSIU_I_P(ssi, id, busif) }, + }, + }, + .ssiu = { + .capture = { + { RDMA_SSIU_O_N(ssi, id, busif), 0 }, + { RDMA_SSIU_O_P(ssi, id, busif), 0 }, + { RDMA_SSIU_O_P(ssi, id, busif), 0 }, + }, + .playback = { + { 0, RDMA_SSIU_I_N(ssi, id, busif) }, + { 0, RDMA_SSIU_I_P(ssi, id, busif) }, + { 0, RDMA_SSIU_I_P(ssi, id, busif) }, + }, }, - /* SSIU */ - /* Capture */ - {{{ RDMA_SSIU_O_N(ssi, id, busif), 0 }, - { RDMA_SSIU_O_P(ssi, id, busif), 0 }, - { RDMA_SSIU_O_P(ssi, id, busif), 0 } }, - /* Playback */ - {{ 0, RDMA_SSIU_I_N(ssi, id, busif) }, - { 0, RDMA_SSIU_I_P(ssi, id, busif) }, - { 0, RDMA_SSIU_I_P(ssi, id, busif) } } }, }; /* @@ -577,17 +641,86 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, dev_err(dev, "This driver doesn't support SSI%d-%d, so far", id, busif); - /* it shouldn't happen */ - if (use_cmd && !use_src) - dev_err(dev, "DVC is selected without SRC\n"); + return rsnd_dma_addr_lookup(io, mod, priv, &map, is_play, is_from); +} - /* use SSIU or SSI ? */ - if (is_ssi && rsnd_ssi_use_busif(io)) - is_ssi++; +/* + * ex) G3E case + * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out + * SSI : 0x13C31000 / 0x13C40000 / 0x13C40000 + * SSIU: 0x13C31000 / 0x13C40000 / 0x13C40000 / 0xEC400000 / 0xEC400000 + * SCU : 0x13C00000 / 0x13C10000 / 0x13C14000 / 0xEC300000 / 0xEC304000 + * CMD : 0x13C00000 / / 0x13C18000 0xEC308000 + */ - return (is_from) ? - dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr : - dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr; +/* RZ/G3E DMA address macros */ +#define RDMA_SSI_I_N_G3E(addr, i) (addr ##_reg + 0x0000F000 + (0x1000 * (i))) +#define RDMA_SSI_O_N_G3E(addr, i) (addr ##_reg + 0x0000F000 + (0x1000 * (i))) + +#define RDMA_SSIU_I_N_G3E(addr, i, j) (addr ##_reg + 0x0000F000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4))) +#define RDMA_SSIU_O_N_G3E(addr, i, j) RDMA_SSIU_I_N_G3E(addr, i, j) + +#define RDMA_SSIU_I_P_G3E(addr, i, j) (addr ##_reg + 0xD87CF000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4))) +#define RDMA_SSIU_O_P_G3E(addr, i, j) RDMA_SSIU_I_P_G3E(addr, i, j) + +#define RDMA_SRC_I_N_G3E(addr, i) (addr ##_reg + 0x00010000 + (0x400 * (i))) +#define RDMA_SRC_O_N_G3E(addr, i) (addr ##_reg + 0x00014000 + (0x400 * (i))) + +#define RDMA_SRC_I_P_G3E(addr, i) (addr ##_reg + 0xD8700000 + (0x400 * (i))) +#define RDMA_SRC_O_P_G3E(addr, i) (addr ##_reg + 0xD8704000 + (0x400 * (i))) + +#define RDMA_CMD_O_N_G3E(addr, i) (addr ##_reg + 0x00018000 + (0x400 * (i))) +#define RDMA_CMD_O_P_G3E(addr, i) (addr ##_reg + 0xD8708000 + (0x400 * (i))) + +static dma_addr_t +rsnd_rzg3e_dma_addr(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, int is_play, int is_from) +{ + struct rsnd_priv *priv = rsnd_io_to_priv(io); + phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI); + phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU); + int id = rsnd_mod_id(mod); + int busif = rsnd_mod_id_sub(rsnd_io_to_mod_ssiu(io)); + const struct rsnd_dma_addr_map map = { + .src = { + .capture = { + { 0, 0 }, + { RDMA_SRC_O_N_G3E(src, id), RDMA_SRC_I_P_G3E(src, id) }, + { RDMA_CMD_O_N_G3E(src, id), RDMA_SRC_I_P_G3E(src, id) }, + }, + .playback = { + { 0, 0 }, + { RDMA_SRC_O_P_G3E(src, id), RDMA_SRC_I_N_G3E(src, id) }, + { RDMA_CMD_O_P_G3E(src, id), RDMA_SRC_I_N_G3E(src, id) }, + }, + }, + .ssi = { + .capture = { + { RDMA_SSI_O_N_G3E(ssi, id), 0 }, + { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 }, + { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 }, + }, + .playback = { + { 0, RDMA_SSI_I_N_G3E(ssi, id) }, + { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) }, + { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) }, + }, + }, + .ssiu = { + .capture = { + { RDMA_SSIU_O_N_G3E(ssi, id, busif), 0 }, + { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 }, + { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 }, + }, + .playback = { + { 0, RDMA_SSIU_I_N_G3E(ssi, id, busif) }, + { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) }, + { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) }, + }, + }, + }; + + return rsnd_dma_addr_lookup(io, mod, priv, &map, is_play, is_from); } /* @@ -636,6 +769,8 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io, return 0; else if (rsnd_is_gen4(priv)) return rsnd_gen4_dma_addr(io, mod, is_play, is_from); + else if (rsnd_is_rzg3e(priv)) + return rsnd_rzg3e_dma_addr(io, mod, is_play, is_from); else return rsnd_gen2_dma_addr(io, mod, is_play, is_from); } @@ -659,11 +794,11 @@ static void rsnd_dma_of_path(struct rsnd_mod *this, int nr, i, idx; /* - * It should use "rcar_sound,ssiu" on DT. - * But, we need to keep compatibility for old version. + * It should use "rcar_sound,ssiu" (R-Car) or "ssiu" (RZ/G3E) on DT. + * We need to keep compatibility for old version. * - * If it has "rcar_sound.ssiu", it will be used. - * If not, "rcar_sound.ssi" will be used. + * If it has "rcar_sound.ssiu" or "ssiu", it will be used. + * If not, "rcar_sound.ssi" or "ssi" will be used. * see * rsnd_ssiu_dma_req() * rsnd_ssi_dma_req() @@ -803,7 +938,7 @@ static int rsnd_dma_alloc(struct rsnd_dai_stream *io, struct rsnd_mod *mod, *dma_mod = rsnd_mod_get(dma); - ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, + ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, NULL, type, dma_id); if (ret < 0) return ret; @@ -870,6 +1005,25 @@ int rsnd_dma_probe(struct rsnd_priv *priv) return 0; /* it will be PIO mode */ } + /* + * Audio DMAC peri-peri clock and reset for RZ/G3E. + * These use optional APIs, so they gracefully return NULL + * (no error) on platforms whose DT does not provide them. + * + * Enable the clock first so the block sees a stable clock on + * the way out of reset, then deassert the reset line. + */ + dmac->audmapp_clk = devm_clk_get_optional_enabled(dev, "audmapp"); + if (IS_ERR(dmac->audmapp_clk)) + return dev_err_probe(dev, PTR_ERR(dmac->audmapp_clk), + "failed to get audmapp clock\n"); + + dmac->audmapp_rstc = + devm_reset_control_get_optional_exclusive_deasserted(dev, "audmapp"); + if (IS_ERR(dmac->audmapp_rstc)) + return dev_err_probe(dev, PTR_ERR(dmac->audmapp_rstc), + "failed to get audmapp reset\n"); + dmac->dmapp_num = 0; dmac->ppres = res->start; dmac->ppbase = devm_ioremap_resource(dev, res); @@ -879,5 +1033,27 @@ int rsnd_dma_probe(struct rsnd_priv *priv) priv->dma = dmac; /* dummy mem mod for debug */ - return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, 0, 0); + return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, NULL, 0, 0); +} + +void rsnd_dma_suspend(struct rsnd_priv *priv) +{ + struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); + + if (dmac) { + /* Mirror probe (which enables clk before deasserting reset) */ + rsnd_suspend_clk_reset(NULL, dmac->audmapp_rstc); + clk_disable_unprepare(dmac->audmapp_clk); + } +} + +void rsnd_dma_resume(struct rsnd_priv *priv) +{ + struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); + + if (dmac) { + /* Clock must be stable before reset is deasserted */ + clk_prepare_enable(dmac->audmapp_clk); + rsnd_resume_clk_reset(NULL, dmac->audmapp_rstc); + } } diff --git a/sound/soc/renesas/rcar/dvc.c b/sound/soc/renesas/rcar/dvc.c index 988cbddbc611..7601dfb0810a 100644 --- a/sound/soc/renesas/rcar/dvc.c +++ b/sound/soc/renesas/rcar/dvc.c @@ -29,7 +29,6 @@ #include "rsnd.h" -#define RSND_DVC_NAME_SIZE 16 #define DVC_NAME "dvc" @@ -327,7 +326,6 @@ int rsnd_dvc_probe(struct rsnd_priv *priv) struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_dvc *dvc; struct clk *clk; - char name[RSND_DVC_NAME_SIZE]; int i, nr, ret; node = rsnd_dvc_of_node(priv); @@ -354,17 +352,14 @@ int rsnd_dvc_probe(struct rsnd_priv *priv) for_each_child_of_node_scoped(node, np) { dvc = rsnd_dvc_get(priv, i); - snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d", - DVC_NAME, i); - - clk = devm_clk_get(dev, name); + clk = rsnd_devm_clk_get_indexed(dev, DVC_NAME, i); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto rsnd_dvc_probe_done; } ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops, - clk, RSND_MOD_DVC, i); + clk, NULL, RSND_MOD_DVC, i); if (ret) goto rsnd_dvc_probe_done; @@ -386,3 +381,23 @@ void rsnd_dvc_remove(struct rsnd_priv *priv) rsnd_mod_quit(rsnd_mod_get(dvc)); } } + +void rsnd_dvc_suspend(struct rsnd_priv *priv) +{ + struct rsnd_dvc *dvc; + int i; + + for_each_rsnd_dvc(dvc, priv, i) + rsnd_suspend_clk_reset(rsnd_mod_get(dvc)->clk, + rsnd_mod_get(dvc)->rstc); +} + +void rsnd_dvc_resume(struct rsnd_priv *priv) +{ + struct rsnd_dvc *dvc; + int i; + + for_each_rsnd_dvc(dvc, priv, i) + rsnd_resume_clk_reset(rsnd_mod_get(dvc)->clk, + rsnd_mod_get(dvc)->rstc); +} diff --git a/sound/soc/renesas/rcar/gen.c b/sound/soc/renesas/rcar/gen.c index d1f20cde66be..05d5f656fb01 100644 --- a/sound/soc/renesas/rcar/gen.c +++ b/sound/soc/renesas/rcar/gen.c @@ -464,6 +464,184 @@ static int rsnd_gen1_probe(struct rsnd_priv *priv) return ret_adg | ret_ssi; } +/* + * RZ/G3E Generation + */ +static int rsnd_rzg3e_probe(struct rsnd_priv *priv) +{ + static const struct rsnd_regmap_field_conf conf_ssiu[] = { + RSND_GEN_S_REG(SSI_MODE1, 0x804), + RSND_GEN_S_REG(SSI_MODE2, 0x808), + RSND_GEN_S_REG(SSI_MODE3, 0x80c), + RSND_GEN_S_REG(SSI_CONTROL, 0x810), + RSND_GEN_S_REG(SSI_CONTROL2, 0x814), + RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840), + RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844), + RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848), + RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c), + RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80), + RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80), + RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80), + RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80), + RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80), + RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80), + RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80), + RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80), + RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80), + RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80), + RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80), + RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80), + RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80), + RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), + RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), + RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x480), + RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484), + RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488), + RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0), + RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4), + RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8), + RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0), + RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4), + RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8), + RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0), + RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4), + RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8), + }; + static const struct rsnd_regmap_field_conf conf_scu[] = { + RSND_GEN_M_REG(SRC_I_BUSIF_MODE, 0x0, 0x20), + RSND_GEN_M_REG(SRC_O_BUSIF_MODE, 0x4, 0x20), + RSND_GEN_M_REG(SRC_BUSIF_DALIGN, 0x8, 0x20), + RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), + RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), + RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), + RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20), + RSND_GEN_M_REG(CMD_BUSIF_DALIGN, 0x188, 0x20), + RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), + RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), + RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8), + RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc), + RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0), + RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4), + RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), + RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), + RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), + RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), + RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), + RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), + RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), + RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), + RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100), + RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100), + RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100), + RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100), + RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100), + RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100), + RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100), + RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100), + RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100), + RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100), + RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100), + RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100), + RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100), + RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100), + RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100), + RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100), + RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100), + RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100), + RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100), + RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100), + RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100), + RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100), + RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100), + RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100), + RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100), + RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100), + RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100), + RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100), + RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100), + RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100), + RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100), + RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100), + RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100), + RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100), + RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100), + RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100), + RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100), + RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40), + RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40), + RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40), + RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40), + RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40), + RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40), + RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40), + RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40), + RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40), + RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40), + RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), + RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), + RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), + RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), + RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), + RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100), + RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100), + RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100), + RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), + RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), + RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100), + RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100), + RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100), + RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100), + RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100), + RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100), + RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), + }; + static const struct rsnd_regmap_field_conf conf_adg[] = { + RSND_GEN_S_REG(BRRA, 0x00), + RSND_GEN_S_REG(BRRB, 0x04), + RSND_GEN_S_REG(BRGCKR, 0x08), + RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), + RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), + RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), + RSND_GEN_S_REG(AUDIO_CLK_SEL3, 0x18), + RSND_GEN_S_REG(DIV_EN, 0x30), + RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34), + RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38), + RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c), + RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40), + RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44), + RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48), + RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c), + RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50), + RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54), + RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), + RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), + }; + static const struct rsnd_regmap_field_conf conf_ssi[] = { + RSND_GEN_M_REG(SSICR, 0x00, 0x40), + RSND_GEN_M_REG(SSISR, 0x04, 0x40), + RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), + }; + int ret; + + ret = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SCU, "scu", conf_scu); + if (ret < 0) + return ret; + + ret = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_adg); + if (ret < 0) + return ret; + + ret = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSIU, "ssiu", conf_ssiu); + if (ret < 0) + return ret; + + return rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSI, "ssi", conf_ssi); +} + /* * Gen */ @@ -487,6 +665,8 @@ int rsnd_gen_probe(struct rsnd_priv *priv) ret = rsnd_gen2_probe(priv); else if (rsnd_is_gen4(priv)) ret = rsnd_gen4_probe(priv); + else if (rsnd_is_rzg3e(priv)) + ret = rsnd_rzg3e_probe(priv); if (ret < 0) dev_err(dev, "unknown generation R-Car sound device\n"); diff --git a/sound/soc/renesas/rcar/mix.c b/sound/soc/renesas/rcar/mix.c index aea74e703305..c4da4c4bedb3 100644 --- a/sound/soc/renesas/rcar/mix.c +++ b/sound/soc/renesas/rcar/mix.c @@ -32,7 +32,6 @@ #include "rsnd.h" -#define MIX_NAME_SIZE 16 #define MIX_NAME "mix" struct rsnd_mix { @@ -291,7 +290,6 @@ int rsnd_mix_probe(struct rsnd_priv *priv) struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mix *mix; struct clk *clk; - char name[MIX_NAME_SIZE]; int i, nr, ret; node = rsnd_mix_of_node(priv); @@ -318,17 +316,14 @@ int rsnd_mix_probe(struct rsnd_priv *priv) for_each_child_of_node_scoped(node, np) { mix = rsnd_mix_get(priv, i); - snprintf(name, MIX_NAME_SIZE, "%s.%d", - MIX_NAME, i); - - clk = devm_clk_get(dev, name); + clk = rsnd_devm_clk_get_indexed(dev, MIX_NAME, i); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto rsnd_mix_probe_done; } ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops, - clk, RSND_MOD_MIX, i); + clk, NULL, RSND_MOD_MIX, i); if (ret) goto rsnd_mix_probe_done; @@ -350,3 +345,23 @@ void rsnd_mix_remove(struct rsnd_priv *priv) rsnd_mod_quit(rsnd_mod_get(mix)); } } + +void rsnd_mix_suspend(struct rsnd_priv *priv) +{ + struct rsnd_mix *mix; + int i; + + for_each_rsnd_mix(mix, priv, i) + rsnd_suspend_clk_reset(rsnd_mod_get(mix)->clk, + rsnd_mod_get(mix)->rstc); +} + +void rsnd_mix_resume(struct rsnd_priv *priv) +{ + struct rsnd_mix *mix; + int i; + + for_each_rsnd_mix(mix, priv, i) + rsnd_resume_clk_reset(rsnd_mod_get(mix)->clk, + rsnd_mod_get(mix)->rstc); +} diff --git a/sound/soc/renesas/rcar/msiof.c b/sound/soc/renesas/rcar/msiof.c index 2671abc028cc..128543fc4fc9 100644 --- a/sound/soc/renesas/rcar/msiof.c +++ b/sound/soc/renesas/rcar/msiof.c @@ -363,11 +363,6 @@ static int msiof_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } -/* - * Select below from Sound Card, not auto - * SND_SOC_DAIFMT_CBC_CFC - * SND_SOC_DAIFMT_CBP_CFP - */ static const u64 msiof_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_LEFT_J | SND_SOC_POSSIBLE_DAIFMT_NB_NF; diff --git a/sound/soc/renesas/rcar/rsnd.h b/sound/soc/renesas/rcar/rsnd.h index 04c70690f7a2..b480085fb0e7 100644 --- a/sound/soc/renesas/rcar/rsnd.h +++ b/sound/soc/renesas/rcar/rsnd.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -142,13 +143,16 @@ enum rsnd_reg { AUDIO_CLK_SEL0, AUDIO_CLK_SEL1, AUDIO_CLK_SEL2, + AUDIO_CLK_SEL3, /* SSIU */ SSI_MODE, SSI_MODE0, SSI_MODE1, SSI_MODE2, + SSI_MODE3, SSI_CONTROL, + SSI_CONTROL2, SSI_CTRL, SSI_BUSIF0_MODE, SSI_BUSIF1_MODE, @@ -263,6 +267,8 @@ u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod); int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod, struct rsnd_mod **dma_mod); int rsnd_dma_probe(struct rsnd_priv *priv); +void rsnd_dma_suspend(struct rsnd_priv *priv); +void rsnd_dma_resume(struct rsnd_priv *priv); struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name, struct rsnd_mod *mod, char *x); @@ -353,6 +359,7 @@ struct rsnd_mod { struct rsnd_mod_ops *ops; struct rsnd_priv *priv; struct clk *clk; + struct reset_control *rstc; u32 status; }; /* @@ -420,9 +427,12 @@ int rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, struct rsnd_mod_ops *ops, struct clk *clk, + struct reset_control *rstc, enum rsnd_mod_type type, int id); void rsnd_mod_quit(struct rsnd_mod *mod); +void rsnd_suspend_clk_reset(struct clk *clk, struct reset_control *rstc); +void rsnd_resume_clk_reset(struct clk *clk, struct reset_control *rstc); struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, struct rsnd_mod *mod); void rsnd_mod_interrupt(struct rsnd_mod *mod, @@ -473,11 +483,30 @@ int rsnd_runtime_is_multi_ssi(struct rsnd_dai_stream *io); int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io); int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io); +/* + * Indexed clock and reset name helpers. + * + * Historically the rsnd driver has looked up per-instance clocks and + * resets using dot-separated names (e.g. "ssi.0", "src.0", "adg.ssi.0"). + * Newer Renesas SoC bindings (RZ/G3E and later) use hyphen-separated + * names ("ssi-0", "src-0", ...) to follow the standard Device Tree + * naming convention. These helpers look up the hyphenated name first + * and transparently fall back to the dotted name, so a single driver + * build supports both conventions. + */ +struct clk *rsnd_devm_clk_get_indexed(struct device *dev, + const char *base, int index); +struct clk *rsnd_devm_clk_get_optional_indexed(struct device *dev, + const char *base, int index); +struct reset_control * +rsnd_devm_reset_control_get_optional_indexed(struct device *dev, + const char *base, int index); + /* * DT */ -#define rsnd_parse_of_node(priv, node) \ - of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, node) +struct device_node *rsnd_parse_of_node(struct rsnd_priv *priv, const char *name); + #define RSND_NODE_DAI "rcar_sound,dai" #define RSND_NODE_SSI "rcar_sound,ssi" #define RSND_NODE_SSIU "rcar_sound,ssiu" @@ -600,6 +629,8 @@ int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod); int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate); int rsnd_adg_probe(struct rsnd_priv *priv); void rsnd_adg_remove(struct rsnd_priv *priv); +void rsnd_adg_suspend(struct rsnd_priv *priv); +void rsnd_adg_resume(struct rsnd_priv *priv); int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod, struct rsnd_dai_stream *io, unsigned int in_rate, @@ -619,14 +650,29 @@ struct rsnd_priv { struct platform_device *pdev; spinlock_t lock; unsigned long flags; + + /* + * Flags layout: 0xDCBA + * + * A: R-Car generation (Gen1/Gen2/Gen3/Gen4) + * B: R-Car SoC variant (e.g. SOC_E for E1/E2/E3) + * C: RZ series generation + * D: RZ series SoC identifier (e.g. RZG3E) + * + * Bits 16+ are used for capability flags. + */ #define RSND_GEN_MASK (0xF << 0) #define RSND_GEN1 (1 << 0) #define RSND_GEN2 (2 << 0) #define RSND_GEN3 (3 << 0) #define RSND_GEN4 (4 << 0) -#define RSND_SOC_MASK (0xFF << 4) -#define RSND_SOC_E (1 << 4) /* E1/E2/E3 */ - +#define RSND_SOC_MASK (0xF << 4) /* nibble B */ +#define RSND_SOC_E (1 << 4) /* E1/E2/E3 */ +#define RSND_RZ_MASK (0xF << 8) /* nibble C */ +#define RSND_RZ3 (3 << 8) +#define RSND_RZ_ID_MASK (0xF << 12) /* nibble D */ +#define RSND_RZG3E (1 << 12) +#define RSND_SSIU_BUSIF_STATUS_COUNT_2 BIT(16) /* Only 2 BUSIF error-status register pairs */ /* * below value will be filled on rsnd_gen_probe() */ @@ -651,12 +697,14 @@ struct rsnd_priv { /* * below value will be filled on rsnd_ssiu_probe() */ + void *ssiu_ctrl; void *ssiu; int ssiu_nr; /* * below value will be filled on rsnd_src_probe() */ + void *src_ctrl; void *src; int src_nr; @@ -705,6 +753,9 @@ struct rsnd_priv { #define rsnd_is_gen3_e3(priv) (((priv)->flags & \ (RSND_GEN_MASK | RSND_SOC_MASK)) == \ (RSND_GEN3 | RSND_SOC_E)) +#define rsnd_is_rzg3e(priv) (((priv)->flags & \ + (RSND_RZ_MASK | RSND_RZ_ID_MASK)) == \ + (RSND_RZ3 | RSND_RZG3E)) #define rsnd_flags_has(p, f) ((p)->flags & (f)) #define rsnd_flags_set(p, f) ((p)->flags |= (f)) @@ -777,6 +828,8 @@ extern const char * const volume_ramp_rate[]; */ int rsnd_ssi_probe(struct rsnd_priv *priv); void rsnd_ssi_remove(struct rsnd_priv *priv); +void rsnd_ssi_suspend(struct rsnd_priv *priv); +void rsnd_ssi_resume(struct rsnd_priv *priv); struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); int rsnd_ssi_use_busif(struct rsnd_dai_stream *io); u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io); @@ -800,6 +853,8 @@ int rsnd_ssiu_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod); int rsnd_ssiu_probe(struct rsnd_priv *priv); void rsnd_ssiu_remove(struct rsnd_priv *priv); +void rsnd_ssiu_suspend(struct rsnd_priv *priv); +void rsnd_ssiu_resume(struct rsnd_priv *priv); void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai, struct device_node *playback, struct device_node *capture); @@ -811,6 +866,8 @@ bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod); */ int rsnd_src_probe(struct rsnd_priv *priv); void rsnd_src_remove(struct rsnd_priv *priv); +void rsnd_src_suspend(struct rsnd_priv *priv); +void rsnd_src_resume(struct rsnd_priv *priv); struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id); #define rsnd_src_get_in_rate(priv, io) rsnd_src_get_rate(priv, io, 1) @@ -830,6 +887,8 @@ unsigned int rsnd_src_get_rate(struct rsnd_priv *priv, */ int rsnd_ctu_probe(struct rsnd_priv *priv); void rsnd_ctu_remove(struct rsnd_priv *priv); +void rsnd_ctu_suspend(struct rsnd_priv *priv); +void rsnd_ctu_resume(struct rsnd_priv *priv); struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id); #define rsnd_ctu_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_CTU) #define rsnd_parse_connect_ctu(rdai, playback, capture) \ @@ -842,6 +901,8 @@ struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id); */ int rsnd_mix_probe(struct rsnd_priv *priv); void rsnd_mix_remove(struct rsnd_priv *priv); +void rsnd_mix_suspend(struct rsnd_priv *priv); +void rsnd_mix_resume(struct rsnd_priv *priv); struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id); #define rsnd_mix_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_MIX) #define rsnd_parse_connect_mix(rdai, playback, capture) \ @@ -854,6 +915,8 @@ struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id); */ int rsnd_dvc_probe(struct rsnd_priv *priv); void rsnd_dvc_remove(struct rsnd_priv *priv); +void rsnd_dvc_suspend(struct rsnd_priv *priv); +void rsnd_dvc_resume(struct rsnd_priv *priv); struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id); #define rsnd_dvc_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_DVC) #define rsnd_parse_connect_dvc(rdai, playback, capture) \ diff --git a/sound/soc/renesas/rcar/src.c b/sound/soc/renesas/rcar/src.c index 6a3dbc84f474..ac806bdc96d9 100644 --- a/sound/soc/renesas/rcar/src.c +++ b/sound/soc/renesas/rcar/src.c @@ -39,7 +39,6 @@ struct rsnd_src { int irq; }; -#define RSND_SRC_NAME_SIZE 16 #define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id) #define rsnd_src_nr(priv) ((priv)->src_nr) @@ -54,6 +53,14 @@ struct rsnd_src { ((pos) = (struct rsnd_src *)(priv)->src + i); \ i++) +struct rsnd_src_ctrl { + struct clk *scu; + struct clk *scu_x2; + struct clk *scu_supply; +}; + +#define rsnd_priv_to_src_ctrl(priv) \ + ((struct rsnd_src_ctrl *)(priv)->src_ctrl) /* * image of SRC (Sampling Rate Converter) @@ -713,9 +720,10 @@ int rsnd_src_probe(struct rsnd_priv *priv) { struct device_node *node; struct device *dev = rsnd_priv_to_dev(priv); + struct reset_control *rstc; + struct rsnd_src_ctrl *src_ctrl; struct rsnd_src *src; struct clk *clk; - char name[RSND_SRC_NAME_SIZE]; int i, nr, ret; node = rsnd_src_of_node(priv); @@ -728,6 +736,12 @@ int rsnd_src_probe(struct rsnd_priv *priv) goto rsnd_src_probe_done; } + src_ctrl = devm_kzalloc(dev, sizeof(*src_ctrl), GFP_KERNEL); + if (!src_ctrl) { + ret = -ENOMEM; + goto rsnd_src_probe_done; + } + src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL); if (!src) { ret = -ENOMEM; @@ -736,6 +750,38 @@ int rsnd_src_probe(struct rsnd_priv *priv) priv->src_nr = nr; priv->src = src; + priv->src_ctrl = src_ctrl; + + src_ctrl->scu = devm_clk_get_optional_enabled(dev, "scu"); + if (IS_ERR(src_ctrl->scu)) { + ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu), + "failed to get scu clock\n"); + goto rsnd_src_probe_done; + } + + src_ctrl->scu_x2 = devm_clk_get_optional_enabled(dev, "scu_x2"); + if (IS_ERR(src_ctrl->scu_x2)) { + ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu_x2), + "failed to get scu_x2 clock\n"); + goto rsnd_src_probe_done; + } + + src_ctrl->scu_supply = devm_clk_get_optional_enabled(dev, "scu_supply"); + if (IS_ERR(src_ctrl->scu_supply)) { + ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu_supply), + "failed to get scu_supply clock\n"); + goto rsnd_src_probe_done; + } + + /* + * Shared SCU reset for every SRC module; acquire once. + * R-Car platforms typically don't have SRC reset controls. + */ + rstc = devm_reset_control_get_optional_shared(dev, "scu"); + if (IS_ERR(rstc)) { + ret = PTR_ERR(rstc); + goto rsnd_src_probe_done; + } i = 0; for_each_child_of_node_scoped(node, np) { @@ -750,23 +796,20 @@ int rsnd_src_probe(struct rsnd_priv *priv) src = rsnd_src_get(priv, i); - snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d", - SRC_NAME, i); - src->irq = irq_of_parse_and_map(np, 0); if (!src->irq) { ret = -EINVAL; goto rsnd_src_probe_done; } - clk = devm_clk_get(dev, name); + clk = rsnd_devm_clk_get_indexed(dev, SRC_NAME, i); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto rsnd_src_probe_done; } ret = rsnd_mod_init(priv, rsnd_mod_get(src), - &rsnd_src_ops, clk, RSND_MOD_SRC, i); + &rsnd_src_ops, clk, rstc, RSND_MOD_SRC, i); if (ret) goto rsnd_src_probe_done; @@ -791,3 +834,37 @@ void rsnd_src_remove(struct rsnd_priv *priv) rsnd_mod_quit(rsnd_mod_get(src)); } } + +void rsnd_src_suspend(struct rsnd_priv *priv) +{ + struct rsnd_src_ctrl *src_ctrl = rsnd_priv_to_src_ctrl(priv); + struct rsnd_src *src; + int i; + + if (!src_ctrl) + return; + + for_each_rsnd_src(src, priv, i) + rsnd_suspend_clk_reset(rsnd_mod_get(src)->clk, + rsnd_mod_get(src)->rstc); + + clk_disable_unprepare(src_ctrl->scu_x2); + clk_disable_unprepare(src_ctrl->scu); +} + +void rsnd_src_resume(struct rsnd_priv *priv) +{ + struct rsnd_src_ctrl *src_ctrl = rsnd_priv_to_src_ctrl(priv); + struct rsnd_src *src; + int i; + + if (!src_ctrl) + return; + + clk_prepare_enable(src_ctrl->scu); + clk_prepare_enable(src_ctrl->scu_x2); + + for_each_rsnd_src(src, priv, i) + rsnd_resume_clk_reset(rsnd_mod_get(src)->clk, + rsnd_mod_get(src)->rstc); +} diff --git a/sound/soc/renesas/rcar/ssi.c b/sound/soc/renesas/rcar/ssi.c index 0420041e282c..2fa76a079982 100644 --- a/sound/soc/renesas/rcar/ssi.c +++ b/sound/soc/renesas/rcar/ssi.c @@ -21,7 +21,6 @@ #include #include #include "rsnd.h" -#define RSND_SSI_NAME_SIZE 16 /* * SSICR @@ -1010,11 +1009,11 @@ static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io, char *name; /* - * It should use "rcar_sound,ssiu" on DT. - * But, we need to keep compatibility for old version. + * It should use "rcar_sound,ssiu" (R-Car) or "ssiu" (RZ/G3E) on DT. + * We need to keep compatibility for old version. * - * If it has "rcar_sound.ssiu", it will be used. - * If not, "rcar_sound.ssi" will be used. + * If it has "rcar_sound.ssiu" or "ssiu", it will be used. + * If not, "rcar_sound.ssi" or "ssi" will be used. * see * rsnd_ssiu_dma_req() * rsnd_dma_of_path() @@ -1158,12 +1157,12 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) int rsnd_ssi_probe(struct rsnd_priv *priv) { + struct reset_control *rstc; struct device_node *node; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; struct clk *clk; struct rsnd_ssi *ssi; - char name[RSND_SSI_NAME_SIZE]; int i, nr, ret; node = rsnd_ssi_of_node(priv); @@ -1198,15 +1197,23 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) ssi = rsnd_ssi_get(priv, i); - snprintf(name, RSND_SSI_NAME_SIZE, "%s.%d", - SSI_NAME, i); - - clk = devm_clk_get(dev, name); + clk = rsnd_devm_clk_get_indexed(dev, SSI_NAME, i); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto rsnd_ssi_probe_done; } + /* + * RZ/G3E uses per-SSI reset controllers. + * R-Car platforms typically don't have SSI reset controls. + */ + rstc = rsnd_devm_reset_control_get_optional_indexed(dev, + SSI_NAME, i); + if (IS_ERR(rstc)) { + ret = PTR_ERR(rstc); + goto rsnd_ssi_probe_done; + } + if (of_property_read_bool(np, "shared-pin")) rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE); @@ -1225,7 +1232,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) ops = &rsnd_ssi_dma_ops; ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk, - RSND_MOD_SSI, i); + rstc, RSND_MOD_SSI, i); if (ret) goto rsnd_ssi_probe_done; @@ -1250,3 +1257,23 @@ void rsnd_ssi_remove(struct rsnd_priv *priv) rsnd_mod_quit(rsnd_mod_get(ssi)); } } + +void rsnd_ssi_suspend(struct rsnd_priv *priv) +{ + struct rsnd_ssi *ssi; + int i; + + for_each_rsnd_ssi(ssi, priv, i) + rsnd_suspend_clk_reset(rsnd_mod_get(ssi)->clk, + rsnd_mod_get(ssi)->rstc); +} + +void rsnd_ssi_resume(struct rsnd_priv *priv) +{ + struct rsnd_ssi *ssi; + int i; + + for_each_rsnd_ssi(ssi, priv, i) + rsnd_resume_clk_reset(rsnd_mod_get(ssi)->clk, + rsnd_mod_get(ssi)->rstc); +} diff --git a/sound/soc/renesas/rcar/ssiu.c b/sound/soc/renesas/rcar/ssiu.c index 244fb833292a..2a8593a5d4a6 100644 --- a/sound/soc/renesas/rcar/ssiu.c +++ b/sound/soc/renesas/rcar/ssiu.c @@ -29,31 +29,39 @@ struct rsnd_ssiu { i++) /* - * SSI Gen2 Gen3 Gen4 - * 0 BUSIF0-3 BUSIF0-7 BUSIF0-7 - * 1 BUSIF0-3 BUSIF0-7 - * 2 BUSIF0-3 BUSIF0-7 - * 3 BUSIF0 BUSIF0-7 - * 4 BUSIF0 BUSIF0-7 - * 5 BUSIF0 BUSIF0 - * 6 BUSIF0 BUSIF0 - * 7 BUSIF0 BUSIF0 - * 8 BUSIF0 BUSIF0 - * 9 BUSIF0-3 BUSIF0-7 - * total 22 52 8 + * SSI Gen2 Gen3 Gen4 RZ/G3E + * 0 BUSIF0-3 BUSIF0-7 BUSIF0-7 BUSIF0-3 + * 1 BUSIF0-3 BUSIF0-7 BUSIF0-3 + * 2 BUSIF0-3 BUSIF0-7 BUSIF0-3 + * 3 BUSIF0 BUSIF0-7 BUSIF0-3 + * 4 BUSIF0 BUSIF0-7 BUSIF0-3 + * 5 BUSIF0 BUSIF0 BUSIF0 + * 6 BUSIF0 BUSIF0 BUSIF0 + * 7 BUSIF0 BUSIF0 BUSIF0 + * 8 BUSIF0 BUSIF0 BUSIF0 + * 9 BUSIF0-3 BUSIF0-7 BUSIF0-3 + * total 22 52 8 28 */ static const int gen2_id[] = { 0, 4, 8, 12, 13, 14, 15, 16, 17, 18 }; static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 }; static const int gen4_id[] = { 0 }; +static const int rzg3e_id[] = { 0, 4, 8, 12, 16, 20, 21, 22, 23, 24 }; + +struct rsnd_ssiu_ctrl { + unsigned int busif_status_count; +}; + +#define rsnd_priv_to_ssiu_ctrl(priv) \ + ((struct rsnd_ssiu_ctrl *)(priv)->ssiu_ctrl) /* enable busif buffer over/under run interrupt. */ #define rsnd_ssiu_busif_err_irq_enable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 1) #define rsnd_ssiu_busif_err_irq_disable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 0) static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); int id = rsnd_mod_id(mod); int shift, offset; - int i; switch (id) { case 0: @@ -72,7 +80,7 @@ static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable) return; } - for (i = 0; i < 4; i++) { + for (unsigned int i = 0; i < rsnd_priv_to_ssiu_ctrl(priv)->busif_status_count; i++) { enum rsnd_reg reg = SSI_SYS_INT_ENABLE((i * 2) + offset); u32 val = 0xf << (shift * 4); u32 sys_int_enable = rsnd_mod_read(mod, reg); @@ -87,10 +95,10 @@ static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable) bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod) { + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); bool error = false; int id = rsnd_mod_id(mod); int shift, offset; - int i; switch (id) { case 0: @@ -109,14 +117,13 @@ bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod) goto out; } - for (i = 0; i < 4; i++) { + for (unsigned int i = 0; i < rsnd_priv_to_ssiu_ctrl(priv)->busif_status_count; i++) { u32 reg = SSI_SYS_STATUS(i * 2) + offset; u32 status = rsnd_mod_read(mod, reg); u32 val = 0xf << (shift * 4); status &= val; if (status) { - struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct device *dev = rsnd_priv_to_dev(priv); rsnd_print_irq_status(dev, "%s err status : 0x%08x\n", @@ -160,7 +167,8 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod, /* * SSI_MODE0 */ - rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id); + if (!rsnd_is_rzg3e(priv)) + rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id); /* * SSI_MODE1 / SSI_MODE2 @@ -392,11 +400,11 @@ static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io, char *name; /* - * It should use "rcar_sound,ssiu" on DT. - * But, we need to keep compatibility for old version. + * It should use "rcar_sound,ssiu" (R-Car) or "ssiu" (RZ/G3E) on DT. + * We need to keep compatibility for old versions. * - * If it has "rcar_sound.ssiu", it will be used. - * If not, "rcar_sound.ssi" will be used. + * If it has "rcar_sound.ssiu" or "ssiu", it will be used. + * If not, "rcar_sound.ssi" or "ssi" will be used. * see * rsnd_ssi_dma_req() * rsnd_dma_of_path() @@ -510,6 +518,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct device_node *node __free(device_node) = rsnd_ssiu_of_node(priv); + struct reset_control *rstc; + struct rsnd_ssiu_ctrl *ctrl; struct rsnd_ssiu *ssiu; struct rsnd_mod_ops *ops; const int *list = NULL; @@ -534,8 +544,15 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) if (!ssiu) return -ENOMEM; + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + ctrl->busif_status_count = rsnd_flags_has(priv, RSND_SSIU_BUSIF_STATUS_COUNT_2) ? 2 : 4; + priv->ssiu = ssiu; priv->ssiu_nr = nr; + priv->ssiu_ctrl = ctrl; if (rsnd_is_gen1(priv)) ops = &rsnd_ssiu_ops_gen1; @@ -558,12 +575,21 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) } else if (rsnd_is_gen4(priv)) { list = gen4_id; nr = ARRAY_SIZE(gen4_id); + } else if (rsnd_is_rzg3e(priv)) { + list = rzg3e_id; + nr = ARRAY_SIZE(rzg3e_id); } else { dev_err(dev, "unknown SSIU\n"); return -ENODEV; } } + /* Acquire shared reset once for all SSIU modules */ + rstc = devm_reset_control_get_optional_shared(dev, "ssi-all"); + if (IS_ERR(rstc)) + return dev_err_probe(dev, PTR_ERR(rstc), + "failed to get ssi-all reset\n"); + for_each_rsnd_ssiu(ssiu, priv, i) { int ret; @@ -586,7 +612,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) } ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), - ops, NULL, RSND_MOD_SSIU, i); + ops, NULL, rstc, RSND_MOD_SSIU, i); if (ret) return ret; } @@ -603,3 +629,23 @@ void rsnd_ssiu_remove(struct rsnd_priv *priv) rsnd_mod_quit(rsnd_mod_get(ssiu)); } } + +void rsnd_ssiu_suspend(struct rsnd_priv *priv) +{ + struct rsnd_ssiu *ssiu; + int i; + + for_each_rsnd_ssiu(ssiu, priv, i) + rsnd_suspend_clk_reset(rsnd_mod_get(ssiu)->clk, + rsnd_mod_get(ssiu)->rstc); +} + +void rsnd_ssiu_resume(struct rsnd_priv *priv) +{ + struct rsnd_ssiu *ssiu; + int i; + + for_each_rsnd_ssiu(ssiu, priv, i) + rsnd_resume_clk_reset(rsnd_mod_get(ssiu)->clk, + rsnd_mod_get(ssiu)->rstc); +} diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index c8137e8883c4..b80acb221d24 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -606,6 +606,7 @@ static const struct of_device_id rockchip_sound_of_match[] = { { .compatible = "rockchip,rk3399-gru-sound", }, {}, }; +MODULE_DEVICE_TABLE(of, rockchip_sound_of_match); static struct platform_driver rockchip_sound_driver = { .probe = rockchip_sound_probe, @@ -624,4 +625,3 @@ MODULE_AUTHOR("Xing Zheng "); MODULE_DESCRIPTION("Rockchip ASoC Machine Driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, rockchip_sound_of_match); diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 0a0a95b4f520..64c90316fa02 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c @@ -127,52 +127,52 @@ static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) unsigned int val = 0; int ret = 0; - spin_lock(&i2s->lock); - if (on) { - ret = regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_TDE_ENABLE, - I2S_DMACR_TDE_ENABLE); - if (ret < 0) - goto end; - ret = regmap_update_bits(i2s->regmap, I2S_XFER, - I2S_XFER_TXS_START | I2S_XFER_RXS_START, - I2S_XFER_TXS_START | I2S_XFER_RXS_START); - if (ret < 0) - goto end; - i2s->tx_start = true; - } else { - i2s->tx_start = false; - - ret = regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_TDE_ENABLE, - I2S_DMACR_TDE_DISABLE); - if (ret < 0) - goto end; - - if (!i2s->rx_start) { + scoped_guard(spinlock, &i2s->lock) { + if (on) { + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, + I2S_DMACR_TDE_ENABLE, + I2S_DMACR_TDE_ENABLE); + if (ret < 0) + break; ret = regmap_update_bits(i2s->regmap, I2S_XFER, I2S_XFER_TXS_START | I2S_XFER_RXS_START, - I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP); + I2S_XFER_TXS_START | I2S_XFER_RXS_START); if (ret < 0) - goto end; - udelay(150); - ret = regmap_update_bits(i2s->regmap, I2S_CLR, - I2S_CLR_TXC | I2S_CLR_RXC, + break; + i2s->tx_start = true; + } else { + i2s->tx_start = false; + + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, + I2S_DMACR_TDE_ENABLE, + I2S_DMACR_TDE_DISABLE); + if (ret < 0) + break; + + if (!i2s->rx_start) { + ret = regmap_update_bits(i2s->regmap, I2S_XFER, + I2S_XFER_TXS_START | I2S_XFER_RXS_START, + I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP); + if (ret < 0) + break; + udelay(150); + ret = regmap_update_bits(i2s->regmap, I2S_CLR, + I2S_CLR_TXC | I2S_CLR_RXC, I2S_CLR_TXC | I2S_CLR_RXC); - if (ret < 0) - goto end; - ret = regmap_read_poll_timeout_atomic(i2s->regmap, - I2S_CLR, - val, - val == 0, - 20, - 200); - if (ret < 0) - dev_warn(i2s->dev, "fail to clear: %d\n", ret); + if (ret < 0) + break; + ret = regmap_read_poll_timeout_atomic(i2s->regmap, + I2S_CLR, + val, + val == 0, + 20, + 200); + if (ret < 0) + dev_warn(i2s->dev, "fail to clear: %d\n", ret); + } } } -end: - spin_unlock(&i2s->lock); + if (ret < 0) dev_err(i2s->dev, "lrclk update failed\n"); @@ -184,53 +184,53 @@ static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) unsigned int val = 0; int ret = 0; - spin_lock(&i2s->lock); - if (on) { - ret = regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_RDE_ENABLE, - I2S_DMACR_RDE_ENABLE); - if (ret < 0) - goto end; + scoped_guard(spinlock, &i2s->lock) { + if (on) { + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, + I2S_DMACR_RDE_ENABLE, + I2S_DMACR_RDE_ENABLE); + if (ret < 0) + break; - ret = regmap_update_bits(i2s->regmap, I2S_XFER, - I2S_XFER_TXS_START | I2S_XFER_RXS_START, - I2S_XFER_TXS_START | I2S_XFER_RXS_START); - if (ret < 0) - goto end; - i2s->rx_start = true; - } else { - i2s->rx_start = false; - - ret = regmap_update_bits(i2s->regmap, I2S_DMACR, - I2S_DMACR_RDE_ENABLE, - I2S_DMACR_RDE_DISABLE); - if (ret < 0) - goto end; - - if (!i2s->tx_start) { ret = regmap_update_bits(i2s->regmap, I2S_XFER, I2S_XFER_TXS_START | I2S_XFER_RXS_START, - I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP); + I2S_XFER_TXS_START | I2S_XFER_RXS_START); if (ret < 0) - goto end; - udelay(150); - ret = regmap_update_bits(i2s->regmap, I2S_CLR, - I2S_CLR_TXC | I2S_CLR_RXC, - I2S_CLR_TXC | I2S_CLR_RXC); + break; + i2s->rx_start = true; + } else { + i2s->rx_start = false; + + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, + I2S_DMACR_RDE_ENABLE, + I2S_DMACR_RDE_DISABLE); if (ret < 0) - goto end; - ret = regmap_read_poll_timeout_atomic(i2s->regmap, - I2S_CLR, - val, - val == 0, - 20, - 200); - if (ret < 0) - dev_warn(i2s->dev, "fail to clear: %d\n", ret); + break; + + if (!i2s->tx_start) { + ret = regmap_update_bits(i2s->regmap, I2S_XFER, + I2S_XFER_TXS_START | I2S_XFER_RXS_START, + I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP); + if (ret < 0) + break; + udelay(150); + ret = regmap_update_bits(i2s->regmap, I2S_CLR, + I2S_CLR_TXC | I2S_CLR_RXC, + I2S_CLR_TXC | I2S_CLR_RXC); + if (ret < 0) + break; + ret = regmap_read_poll_timeout_atomic(i2s->regmap, + I2S_CLR, + val, + val == 0, + 20, + 200); + if (ret < 0) + dev_warn(i2s->dev, "fail to clear: %d\n", ret); + } } } -end: - spin_unlock(&i2s->lock); + if (ret < 0) dev_err(i2s->dev, "lrclk update failed\n"); @@ -662,6 +662,15 @@ static const struct of_device_id rockchip_i2s_match[] __maybe_unused = { { .compatible = "rockchip,rv1126-i2s", }, {}, }; +MODULE_DEVICE_TABLE(of, rockchip_i2s_match); + +static void rockchip_i2s_suspend(void *data) +{ + struct device *dev = data; + + if (!pm_runtime_status_suspended(dev)) + i2s_runtime_suspend(dev); +} static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res, struct snd_soc_dai_driver **dp) @@ -757,37 +766,28 @@ static int rockchip_i2s_probe(struct platform_device *pdev) } /* try to prepare related clocks */ - i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); + i2s->hclk = devm_clk_get_enabled(&pdev->dev, "i2s_hclk"); if (IS_ERR(i2s->hclk)) { dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n"); return PTR_ERR(i2s->hclk); } - ret = clk_prepare_enable(i2s->hclk); - if (ret) { - dev_err(i2s->dev, "hclock enable failed %d\n", ret); - return ret; - } i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk"); if (IS_ERR(i2s->mclk)) { dev_err(&pdev->dev, "Can't retrieve i2s master clock\n"); - ret = PTR_ERR(i2s->mclk); - goto err_clk; + return PTR_ERR(i2s->mclk); } regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); - if (IS_ERR(regs)) { - ret = PTR_ERR(regs); - goto err_clk; - } + if (IS_ERR(regs)) + return PTR_ERR(regs); i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &rockchip_i2s_regmap_config); if (IS_ERR(i2s->regmap)) { dev_err(&pdev->dev, "Failed to initialise managed register map\n"); - ret = PTR_ERR(i2s->regmap); - goto err_clk; + return PTR_ERR(i2s->regmap); } i2s->bclk_ratio = 64; @@ -798,8 +798,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev) i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl, "bclk_off"); if (IS_ERR_OR_NULL(i2s->bclk_off)) { dev_err(&pdev->dev, "failed to find i2s bclk_off\n"); - ret = -EINVAL; - goto err_clk; + return -EINVAL; } } } else { @@ -810,16 +809,23 @@ static int rockchip_i2s_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, i2s); - pm_runtime_enable(&pdev->dev); + ret = devm_add_action(&pdev->dev, rockchip_i2s_suspend, &pdev->dev); + if (ret) + return ret; + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + if (!pm_runtime_enabled(&pdev->dev)) { ret = i2s_runtime_resume(&pdev->dev); if (ret) - goto err_pm_disable; + return ret; } ret = rockchip_i2s_init_dai(i2s, res, &dai); if (ret) - goto err_pm_disable; + return ret; ret = devm_snd_soc_register_component(&pdev->dev, &rockchip_i2s_component, @@ -827,36 +833,16 @@ static int rockchip_i2s_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Could not register DAI\n"); - goto err_suspend; + return ret; } ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); if (ret) { dev_err(&pdev->dev, "Could not register PCM\n"); - goto err_suspend; + return ret; } return 0; - -err_suspend: - if (!pm_runtime_status_suspended(&pdev->dev)) - i2s_runtime_suspend(&pdev->dev); -err_pm_disable: - pm_runtime_disable(&pdev->dev); -err_clk: - clk_disable_unprepare(i2s->hclk); - return ret; -} - -static void rockchip_i2s_remove(struct platform_device *pdev) -{ - struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev); - - pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - i2s_runtime_suspend(&pdev->dev); - - clk_disable_unprepare(i2s->hclk); } static const struct dev_pm_ops rockchip_i2s_pm_ops = { @@ -865,7 +851,6 @@ static const struct dev_pm_ops rockchip_i2s_pm_ops = { static struct platform_driver rockchip_i2s_driver = { .probe = rockchip_i2s_probe, - .remove = rockchip_i2s_remove, .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(rockchip_i2s_match), @@ -878,4 +863,3 @@ MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); MODULE_AUTHOR("jianqun "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, rockchip_i2s_match); diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c index fc52149ed6ae..e6229a325ffe 100644 --- a/sound/soc/rockchip/rockchip_i2s_tdm.c +++ b/sound/soc/rockchip/rockchip_i2s_tdm.c @@ -285,9 +285,8 @@ static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, int on) { struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); - unsigned long flags; - spin_lock_irqsave(&i2s_tdm->lock, flags); + guard(spinlock_irqsave)(&i2s_tdm->lock); if (on) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) rockchip_enable_tde(i2s_tdm->regmap); @@ -313,7 +312,6 @@ static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream, I2S_CLR_TXC | I2S_CLR_RXC); } } - spin_unlock_irqrestore(&i2s_tdm->lock, flags); } static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on) @@ -587,12 +585,11 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream, unsigned int fmt) { struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai); - unsigned long flags; if (!i2s_tdm->clk_trcm) return 0; - spin_lock_irqsave(&i2s_tdm->lock, flags); + guard(spinlock_irqsave)(&i2s_tdm->lock); if (i2s_tdm->refcount) rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm); @@ -614,7 +611,6 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream, if (i2s_tdm->refcount) rockchip_i2s_tdm_xfer_resume(substream, i2s_tdm); - spin_unlock_irqrestore(&i2s_tdm->lock, flags); return 0; } @@ -1040,6 +1036,7 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = { { .compatible = "rockchip,rv1126-i2s-tdm", .data = &rv1126_i2s_soc_data }, {}, }; +MODULE_DEVICE_TABLE(of, rockchip_i2s_tdm_match); static const struct snd_soc_dai_driver i2s_tdm_dai = { .ops = &rockchip_i2s_tdm_dai_ops, @@ -1442,4 +1439,3 @@ MODULE_DESCRIPTION("ROCKCHIP I2S/TDM ASoC Interface"); MODULE_AUTHOR("Sugar Zhang "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, rockchip_i2s_tdm_match); diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index c69cdd6f2499..115e90d3bbfe 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -321,6 +321,7 @@ static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai, { struct rk_pdm_dev *pdm = to_info(cpu_dai); unsigned int mask = 0, val = 0; + int ret; mask = PDM_CKP_MSK; switch (fmt & SND_SOC_DAIFMT_INV_MASK) { @@ -334,7 +335,10 @@ static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } - pm_runtime_get_sync(cpu_dai->dev); + ret = pm_runtime_resume_and_get(cpu_dai->dev); + if (ret) + return ret; + regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val); pm_runtime_put(cpu_dai->dev); @@ -422,16 +426,16 @@ static int rockchip_pdm_runtime_resume(struct device *dev) struct rk_pdm_dev *pdm = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(pdm->clk); + ret = clk_prepare_enable(pdm->hclk); if (ret) { - dev_err(pdm->dev, "clock enable failed %d\n", ret); + dev_err(pdm->dev, "hclock enable failed %d\n", ret); return ret; } - ret = clk_prepare_enable(pdm->hclk); + ret = clk_prepare_enable(pdm->clk); if (ret) { - clk_disable_unprepare(pdm->clk); - dev_err(pdm->dev, "hclock enable failed %d\n", ret); + clk_disable_unprepare(pdm->hclk); + dev_err(pdm->dev, "clock enable failed %d\n", ret); return ret; } diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index ed393e5034a4..a195e96fed0a 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -18,7 +18,6 @@ #include #include #include - #include "rockchip_sai.h" #define DRV_NAME "rockchip-sai" @@ -216,14 +215,12 @@ static void rockchip_sai_xfer_clk_stop_and_wait(struct rk_sai_dev *sai, unsigned static int rockchip_sai_runtime_suspend(struct device *dev) { struct rk_sai_dev *sai = dev_get_drvdata(dev); - unsigned long flags; rockchip_sai_fsync_lost_detect(sai, 0); rockchip_sai_fsync_err_detect(sai, 0); - spin_lock_irqsave(&sai->xfer_lock, flags); - rockchip_sai_xfer_clk_stop_and_wait(sai, NULL); - spin_unlock_irqrestore(&sai->xfer_lock, flags); + scoped_guard(spinlock_irqsave, &sai->xfer_lock) + rockchip_sai_xfer_clk_stop_and_wait(sai, NULL); regcache_cache_only(sai->regmap, true); /* @@ -483,7 +480,6 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai); unsigned int mask = 0, val = 0; unsigned int clk_gates; - unsigned long flags; int ret = 0; pm_runtime_get_sync(dai->dev); @@ -499,56 +495,56 @@ static int rockchip_sai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) sai->is_master_mode = false; break; default: - ret = -EINVAL; - goto err_pm_put; + pm_runtime_put(dai->dev); + return -EINVAL; } - spin_lock_irqsave(&sai->xfer_lock, flags); - rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); - if (sai->initialized) { - if (sai->has_capture && sai->has_playback) - rockchip_sai_xfer_stop(sai, -1); - else if (sai->has_capture) - rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_CAPTURE); - else - rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_PLAYBACK); - } else { - rockchip_sai_clear(sai, 0); - sai->initialized = true; + scoped_guard(spinlock_irqsave, &sai->xfer_lock) { + rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); + if (sai->initialized) { + if (sai->has_capture && sai->has_playback) + rockchip_sai_xfer_stop(sai, -1); + else if (sai->has_capture) + rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_CAPTURE); + else + rockchip_sai_xfer_stop(sai, SNDRV_PCM_STREAM_PLAYBACK); + } else { + rockchip_sai_clear(sai, 0); + sai->initialized = true; + } + + regmap_update_bits(sai->regmap, SAI_CKR, mask, val); + + mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK; + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL; + break; + case SND_SOC_DAIFMT_NB_IF: + val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED; + break; + case SND_SOC_DAIFMT_IB_NF: + val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL; + break; + case SND_SOC_DAIFMT_IB_IF: + val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED; + break; + default: + ret = -EINVAL; + break; + } + + if (ret == 0) { + regmap_update_bits(sai->regmap, SAI_CKR, mask, val); + rockchip_sai_fmt_create(sai, fmt); + } + + if (clk_gates) + regmap_update_bits(sai->regmap, SAI_XFER, + SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, + clk_gates); } - regmap_update_bits(sai->regmap, SAI_CKR, mask, val); - - mask = SAI_CKR_CKP_MASK | SAI_CKR_FSP_MASK; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_NORMAL; - break; - case SND_SOC_DAIFMT_NB_IF: - val = SAI_CKR_CKP_NORMAL | SAI_CKR_FSP_INVERTED; - break; - case SND_SOC_DAIFMT_IB_NF: - val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_NORMAL; - break; - case SND_SOC_DAIFMT_IB_IF: - val = SAI_CKR_CKP_INVERTED | SAI_CKR_FSP_INVERTED; - break; - default: - ret = -EINVAL; - goto err_xfer_unlock; - } - - regmap_update_bits(sai->regmap, SAI_CKR, mask, val); - - rockchip_sai_fmt_create(sai, fmt); - -err_xfer_unlock: - if (clk_gates) - regmap_update_bits(sai->regmap, SAI_XFER, - SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, - clk_gates); - spin_unlock_irqrestore(&sai->xfer_lock, flags); -err_pm_put: pm_runtime_put(dai->dev); return ret; @@ -564,7 +560,6 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, unsigned int ch_per_lane, slot_width; unsigned int val, fscr, reg; unsigned int lanes, req_lanes; - unsigned long flags; int ret = 0; if (!rockchip_sai_stream_valid(substream, dai)) @@ -591,8 +586,8 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, dev_err(sai->dev, "not enough lanes (%d) for requested number of %s channels (%d)\n", lanes, reg == SAI_TXCR ? "playback" : "capture", params_channels(params)); - ret = -EINVAL; - goto err_pm_put; + pm_runtime_put(sai->dev); + return -EINVAL; } else { lanes = req_lanes; } @@ -618,84 +613,88 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, val = SAI_XCR_VDW(32); break; default: - ret = -EINVAL; - goto err_pm_put; + pm_runtime_put(sai->dev); + return -EINVAL; } val |= SAI_XCR_CSR(lanes); - spin_lock_irqsave(&sai->xfer_lock, flags); + scoped_guard(spinlock_irqsave, &sai->xfer_lock) { - regmap_update_bits(sai->regmap, reg, SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK, val); + regmap_update_bits(sai->regmap, reg, SAI_XCR_VDW_MASK | SAI_XCR_CSR_MASK, val); - if (!sai->is_tdm) - regmap_update_bits(sai->regmap, reg, SAI_XCR_SBW_MASK, - SAI_XCR_SBW(params_physical_width(params))); + if (!sai->is_tdm) + regmap_update_bits(sai->regmap, reg, SAI_XCR_SBW_MASK, + SAI_XCR_SBW(params_physical_width(params))); - regmap_read(sai->regmap, reg, &val); + regmap_read(sai->regmap, reg, &val); - slot_width = SAI_XCR_SBW_V(val); - ch_per_lane = params_channels(params) / lanes; + slot_width = SAI_XCR_SBW_V(val); + ch_per_lane = params_channels(params) / lanes; - regmap_update_bits(sai->regmap, reg, SAI_XCR_SNB_MASK, - SAI_XCR_SNB(ch_per_lane)); + regmap_update_bits(sai->regmap, reg, SAI_XCR_SNB_MASK, + SAI_XCR_SNB(ch_per_lane)); - fscr = SAI_FSCR_FW(sai->fw_ratio * slot_width * ch_per_lane); + fscr = SAI_FSCR_FW(sai->fw_ratio * slot_width * ch_per_lane); - switch (sai->fpw) { - case FPW_ONE_BCLK_WIDTH: - fscr |= SAI_FSCR_FPW(1); - break; - case FPW_ONE_SLOT_WIDTH: - fscr |= SAI_FSCR_FPW(slot_width); - break; - case FPW_HALF_FRAME_WIDTH: - fscr |= SAI_FSCR_FPW(sai->fw_ratio * slot_width * ch_per_lane / 2); - break; - default: - dev_err(sai->dev, "Invalid Frame Pulse Width %d\n", sai->fpw); - ret = -EINVAL; - goto err_xfer_unlock; + switch (sai->fpw) { + case FPW_ONE_BCLK_WIDTH: + fscr |= SAI_FSCR_FPW(1); + break; + case FPW_ONE_SLOT_WIDTH: + fscr |= SAI_FSCR_FPW(slot_width); + break; + case FPW_HALF_FRAME_WIDTH: + fscr |= SAI_FSCR_FPW(sai->fw_ratio * slot_width * ch_per_lane / 2); + break; + default: + dev_err(sai->dev, "Invalid Frame Pulse Width %d\n", sai->fpw); + ret = -EINVAL; + break; + } + + if (ret == 0) { + regmap_update_bits(sai->regmap, SAI_FSCR, + SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK, fscr); + + if (sai->is_master_mode) { + bclk_rate = sai->fw_ratio * slot_width * + ch_per_lane * params_rate(params); + ret = clk_set_rate(sai->mclk, sai->mclk_rate); + if (ret) + dev_err(sai->dev, "Failed to set mclk to %u: %pe\n", + sai->mclk_rate, ERR_PTR(ret)); + else { + mclk_rate = clk_get_rate(sai->mclk); + if (mclk_rate < bclk_rate) { + dev_err(sai->dev, "Mismatch mclk: %u, at least %u\n", + mclk_rate, bclk_rate); + ret = -EINVAL; + } else { + + div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); + mclk_req_rate = bclk_rate * div_bclk; + + if (mclk_rate < + mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX || + mclk_rate > + mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) { + dev_err(sai->dev, + "Mismatch mclk: %u, expected %u (+/- %dHz)\n", + mclk_rate, mclk_req_rate, + CLK_SHIFT_RATE_HZ_MAX); + ret = -EINVAL; + } else + regmap_update_bits(sai->regmap, + SAI_CKR, + SAI_CKR_MDIV_MASK, + SAI_CKR_MDIV(div_bclk)); + } + } + } + } } - regmap_update_bits(sai->regmap, SAI_FSCR, - SAI_FSCR_FW_MASK | SAI_FSCR_FPW_MASK, fscr); - - if (sai->is_master_mode) { - bclk_rate = sai->fw_ratio * slot_width * ch_per_lane * params_rate(params); - ret = clk_set_rate(sai->mclk, sai->mclk_rate); - if (ret) { - dev_err(sai->dev, "Failed to set mclk to %u: %pe\n", - sai->mclk_rate, ERR_PTR(ret)); - goto err_xfer_unlock; - } - - mclk_rate = clk_get_rate(sai->mclk); - if (mclk_rate < bclk_rate) { - dev_err(sai->dev, "Mismatch mclk: %u, at least %u\n", - mclk_rate, bclk_rate); - ret = -EINVAL; - goto err_xfer_unlock; - } - - div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); - mclk_req_rate = bclk_rate * div_bclk; - - if (mclk_rate < mclk_req_rate - CLK_SHIFT_RATE_HZ_MAX || - mclk_rate > mclk_req_rate + CLK_SHIFT_RATE_HZ_MAX) { - dev_err(sai->dev, "Mismatch mclk: %u, expected %u (+/- %dHz)\n", - mclk_rate, mclk_req_rate, CLK_SHIFT_RATE_HZ_MAX); - ret = -EINVAL; - goto err_xfer_unlock; - } - - regmap_update_bits(sai->regmap, SAI_CKR, SAI_CKR_MDIV_MASK, - SAI_CKR_MDIV(div_bclk)); - } - -err_xfer_unlock: - spin_unlock_irqrestore(&sai->xfer_lock, flags); -err_pm_put: pm_runtime_put(sai->dev); return ret; @@ -705,7 +704,6 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai); - unsigned long flags; if (!rockchip_sai_stream_valid(substream, dai)) return 0; @@ -726,13 +724,12 @@ static int rockchip_sai_prepare(struct snd_pcm_substream *substream, * udelay falls short. */ udelay(20); - spin_lock_irqsave(&sai->xfer_lock, flags); - regmap_update_bits(sai->regmap, SAI_XFER, - SAI_XFER_CLK_MASK | - SAI_XFER_FSS_MASK, - SAI_XFER_CLK_EN | - SAI_XFER_FSS_EN); - spin_unlock_irqrestore(&sai->xfer_lock, flags); + scoped_guard(spinlock_irqsave, &sai->xfer_lock) + regmap_update_bits(sai->regmap, SAI_XFER, + SAI_XFER_CLK_MASK | + SAI_XFER_FSS_MASK, + SAI_XFER_CLK_EN | + SAI_XFER_FSS_EN); } rockchip_sai_fsync_lost_detect(sai, 1); @@ -915,7 +912,6 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai, int slots, int slot_width) { struct rk_sai_dev *sai = snd_soc_dai_get_drvdata(dai); - unsigned long flags; unsigned int clk_gates; int sw = slot_width; @@ -931,16 +927,16 @@ static int rockchip_sai_set_tdm_slot(struct snd_soc_dai *dai, return -EINVAL; pm_runtime_get_sync(dai->dev); - spin_lock_irqsave(&sai->xfer_lock, flags); - rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); - regmap_update_bits(sai->regmap, SAI_TXCR, SAI_XCR_SBW_MASK, - SAI_XCR_SBW(sw)); - regmap_update_bits(sai->regmap, SAI_RXCR, SAI_XCR_SBW_MASK, - SAI_XCR_SBW(sw)); - regmap_update_bits(sai->regmap, SAI_XFER, - SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, - clk_gates); - spin_unlock_irqrestore(&sai->xfer_lock, flags); + scoped_guard(spinlock_irqsave, &sai->xfer_lock) { + rockchip_sai_xfer_clk_stop_and_wait(sai, &clk_gates); + regmap_update_bits(sai->regmap, SAI_TXCR, SAI_XCR_SBW_MASK, + SAI_XCR_SBW(sw)); + regmap_update_bits(sai->regmap, SAI_RXCR, SAI_XCR_SBW_MASK, + SAI_XCR_SBW(sw)); + regmap_update_bits(sai->regmap, SAI_XFER, + SAI_XFER_CLK_MASK | SAI_XFER_FSS_MASK, + clk_gates); + } pm_runtime_put(dai->dev); return 0; diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c index 581624f2682e..7f15bc7f8f35 100644 --- a/sound/soc/rockchip/rockchip_spdif.c +++ b/sound/soc/rockchip/rockchip_spdif.c @@ -76,16 +76,16 @@ static int rk_spdif_runtime_resume(struct device *dev) struct rk_spdif_dev *spdif = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(spdif->mclk); + ret = clk_prepare_enable(spdif->hclk); if (ret) { - dev_err(spdif->dev, "mclk clock enable failed %d\n", ret); + dev_err(spdif->dev, "hclk clock enable failed %d\n", ret); return ret; } - ret = clk_prepare_enable(spdif->hclk); + ret = clk_prepare_enable(spdif->mclk); if (ret) { - clk_disable_unprepare(spdif->mclk); - dev_err(spdif->dev, "hclk clock enable failed %d\n", ret); + clk_disable_unprepare(spdif->hclk); + dev_err(spdif->dev, "mclk clock enable failed %d\n", ret); return ret; } @@ -94,6 +94,7 @@ static int rk_spdif_runtime_resume(struct device *dev) ret = regcache_sync(spdif->regmap); if (ret) { + regcache_cache_only(spdif->regmap, true); clk_disable_unprepare(spdif->mclk); clk_disable_unprepare(spdif->hclk); } diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 140907a41a70..f80f697a5d55 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -510,14 +510,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off; unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off; u32 mod, mask, val = 0; - unsigned long flags; int ret = 0; pm_runtime_get_sync(dai->dev); - spin_lock_irqsave(&priv->lock, flags); - mod = readl(priv->addr + I2SMOD); - spin_unlock_irqrestore(&priv->lock, flags); + scoped_guard(spinlock_irqsave, &priv->lock) + mod = readl(priv->addr + I2SMOD); + switch (clk_id) { case SAMSUNG_I2S_OPCLK: @@ -612,11 +611,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs, goto err; } - spin_lock_irqsave(&priv->lock, flags); - mod = readl(priv->addr + I2SMOD); - mod = (mod & ~mask) | val; - writel(mod, priv->addr + I2SMOD); - spin_unlock_irqrestore(&priv->lock, flags); + scoped_guard(spinlock_irqsave, &priv->lock) { + mod = readl(priv->addr + I2SMOD); + mod = (mod & ~mask) | val; + writel(mod, priv->addr + I2SMOD); + } done: pm_runtime_put(dai->dev); @@ -729,7 +728,6 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, struct i2s_dai *i2s = to_info(dai); u32 mod, mask = 0, val = 0; struct clk *rclksrc; - unsigned long flags; WARN_ON(!pm_runtime_active(dai->dev)); @@ -801,11 +799,11 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - spin_lock_irqsave(&priv->lock, flags); - mod = readl(priv->addr + I2SMOD); - mod = (mod & ~mask) | val; - writel(mod, priv->addr + I2SMOD); - spin_unlock_irqrestore(&priv->lock, flags); + scoped_guard(spinlock_irqsave, &priv->lock) { + mod = readl(priv->addr + I2SMOD); + mod = (mod & ~mask) | val; + writel(mod, priv->addr + I2SMOD); + } snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture); @@ -825,11 +823,10 @@ static int i2s_startup(struct snd_pcm_substream *substream, struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); struct i2s_dai *i2s = to_info(dai); struct i2s_dai *other = get_other_dai(i2s); - unsigned long flags; pm_runtime_get_sync(dai->dev); - spin_lock_irqsave(&priv->pcm_lock, flags); + guard(spinlock_irqsave)(&priv->pcm_lock); i2s->mode |= DAI_OPENED; @@ -841,8 +838,6 @@ static int i2s_startup(struct snd_pcm_substream *substream, if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR)) writel(CON_RSTCLR, i2s->priv->addr + I2SCON); - spin_unlock_irqrestore(&priv->pcm_lock, flags); - return 0; } @@ -852,21 +847,18 @@ static void i2s_shutdown(struct snd_pcm_substream *substream, struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); struct i2s_dai *i2s = to_info(dai); struct i2s_dai *other = get_other_dai(i2s); - unsigned long flags; - spin_lock_irqsave(&priv->pcm_lock, flags); + scoped_guard(spinlock_irqsave, &priv->pcm_lock) { + i2s->mode &= ~DAI_OPENED; + i2s->mode &= ~DAI_MANAGER; - i2s->mode &= ~DAI_OPENED; - i2s->mode &= ~DAI_MANAGER; + if (is_opened(other)) + other->mode |= DAI_MANAGER; - if (is_opened(other)) - other->mode |= DAI_MANAGER; - - /* Reset any constraint on RFS and BFS */ - i2s->rfs = 0; - i2s->bfs = 0; - - spin_unlock_irqrestore(&priv->pcm_lock, flags); + /* Reset any constraint on RFS and BFS */ + i2s->rfs = 0; + i2s->bfs = 0; + } pm_runtime_put(dai->dev); } @@ -939,7 +931,6 @@ static int i2s_trigger(struct snd_pcm_substream *substream, int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0)); - unsigned long flags; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -950,37 +941,31 @@ static int i2s_trigger(struct snd_pcm_substream *substream, if (priv->fixup_early) priv->fixup_early(substream, dai); - spin_lock_irqsave(&priv->lock, flags); + scoped_guard(spinlock_irqsave, &priv->lock) { + if (config_setup(i2s)) + return -EINVAL; - if (config_setup(i2s)) { - spin_unlock_irqrestore(&priv->lock, flags); - return -EINVAL; + if (priv->fixup_late) + priv->fixup_late(substream, dai); + + if (capture) + i2s_rxctrl(i2s, 1); + else + i2s_txctrl(i2s, 1); } - - if (priv->fixup_late) - priv->fixup_late(substream, dai); - - if (capture) - i2s_rxctrl(i2s, 1); - else - i2s_txctrl(i2s, 1); - - spin_unlock_irqrestore(&priv->lock, flags); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(&priv->lock, flags); - - if (capture) { - i2s_rxctrl(i2s, 0); - i2s_fifo(i2s, FIC_RXFLUSH); - } else { - i2s_txctrl(i2s, 0); - i2s_fifo(i2s, FIC_TXFLUSH); + scoped_guard(spinlock_irqsave, &priv->lock) { + if (capture) { + i2s_rxctrl(i2s, 0); + i2s_fifo(i2s, FIC_RXFLUSH); + } else { + i2s_txctrl(i2s, 0); + i2s_fifo(i2s, FIC_TXFLUSH); + } } - - spin_unlock_irqrestore(&priv->lock, flags); pm_runtime_put(dai->dev); break; } @@ -1056,7 +1041,6 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); struct i2s_dai *i2s = to_info(dai); struct i2s_dai *other = get_other_dai(i2s); - unsigned long flags; pm_runtime_get_sync(dai->dev); @@ -1079,13 +1063,13 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai) i2s->rfs = 0; i2s->bfs = 0; - spin_lock_irqsave(&priv->lock, flags); - i2s_txctrl(i2s, 0); - i2s_rxctrl(i2s, 0); - i2s_fifo(i2s, FIC_TXFLUSH); - i2s_fifo(other, FIC_TXFLUSH); - i2s_fifo(i2s, FIC_RXFLUSH); - spin_unlock_irqrestore(&priv->lock, flags); + scoped_guard(spinlock_irqsave, &priv->lock) { + i2s_txctrl(i2s, 0); + i2s_rxctrl(i2s, 0); + i2s_fifo(i2s, FIC_TXFLUSH); + i2s_fifo(other, FIC_TXFLUSH); + i2s_fifo(i2s, FIC_RXFLUSH); + } /* Gate CDCLK by default */ if (!is_opened(other)) @@ -1100,15 +1084,13 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai) { struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai); struct i2s_dai *i2s = to_info(dai); - unsigned long flags; pm_runtime_get_sync(dai->dev); if (!is_secondary(i2s)) { if (priv->quirks & QUIRK_NEED_RSTCLR) { - spin_lock_irqsave(&priv->lock, flags); - writel(0, priv->addr + I2SCON); - spin_unlock_irqrestore(&priv->lock, flags); + scoped_guard(spinlock_irqsave, &priv->lock) + writel(0, priv->addr + I2SCON); } } diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c index cb455ddce253..d362136e1069 100644 --- a/sound/soc/samsung/idma.c +++ b/sound/soc/samsung/idma.c @@ -67,9 +67,8 @@ static int idma_enqueue(struct snd_pcm_substream *substream) struct idma_ctrl *prtd = substream->runtime->private_data; u32 val; - spin_lock(&prtd->lock); - prtd->token = (void *) substream; - spin_unlock(&prtd->lock); + scoped_guard(spinlock, &prtd->lock) + prtd->token = (void *) substream; /* Internal DMA Level0 Interrupt Address */ val = idma.lp_tx_addr + prtd->periodsz; @@ -101,16 +100,15 @@ static void idma_setcallbk(struct snd_pcm_substream *substream, { struct idma_ctrl *prtd = substream->runtime->private_data; - spin_lock(&prtd->lock); + guard(spinlock)(&prtd->lock); prtd->cb = cb; - spin_unlock(&prtd->lock); } static void idma_control(int op) { u32 val = readl(idma.regs + I2SAHB); - spin_lock(&idma.lock); + guard(spinlock)(&idma.lock); switch (op) { case LPAM_DMA_START: @@ -120,12 +118,10 @@ static void idma_control(int op) val &= ~(AHB_INTENLVL0 | AHB_DMAEN); break; default: - spin_unlock(&idma.lock); return; } writel(val, idma.regs + I2SAHB); - spin_unlock(&idma.lock); } static void idma_done(void *id, int bytes_xfer) @@ -192,7 +188,7 @@ static int idma_trigger(struct snd_soc_component *component, struct idma_ctrl *prtd = substream->runtime->private_data; int ret = 0; - spin_lock(&prtd->lock); + guard(spinlock)(&prtd->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: @@ -214,8 +210,6 @@ static int idma_trigger(struct snd_soc_component *component, break; } - spin_unlock(&prtd->lock); - return ret; } @@ -228,12 +222,10 @@ idma_pointer(struct snd_soc_component *component, dma_addr_t src; unsigned long res; - spin_lock(&prtd->lock); - - idma_getpos(&src); - res = src - prtd->start; - - spin_unlock(&prtd->lock); + scoped_guard(spinlock, &prtd->lock) { + idma_getpos(&src); + res = src - prtd->start; + } return bytes_to_frames(substream->runtime, res); } diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c index ab3398f39f4a..5c5ecbea5331 100644 --- a/sound/soc/samsung/odroid.c +++ b/sound/soc/samsung/odroid.c @@ -36,15 +36,12 @@ static int odroid_card_fe_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); - unsigned long flags; - int ret = 0; - spin_lock_irqsave(&priv->lock, flags); + guard(spinlock_irqsave)(&priv->lock); if (priv->be_active && priv->be_sample_rate != params_rate(params)) - ret = -EINVAL; - spin_unlock_irqrestore(&priv->lock, flags); + return -EINVAL; - return ret; + return 0; } static const struct snd_soc_ops odroid_card_fe_ops = { @@ -58,7 +55,6 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); unsigned int pll_freq, rclk_freq, rfs; - unsigned long flags; int ret; switch (params_rate(params)) { @@ -105,10 +101,8 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream, return ret; } - spin_lock_irqsave(&priv->lock, flags); - priv->be_sample_rate = params_rate(params); - spin_unlock_irqrestore(&priv->lock, flags); - + scoped_guard(spinlock_irqsave, &priv->lock) + priv->be_sample_rate = params_rate(params); return 0; } @@ -116,9 +110,8 @@ static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card); - unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); + guard(spinlock_irqsave)(&priv->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -134,8 +127,6 @@ static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd) break; } - spin_unlock_irqrestore(&priv->lock, flags); - return 0; } diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index a03ba9374c2e..309f024bf2a4 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -218,7 +218,6 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd, { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); - unsigned long flags; dev_dbg(pcm->dev, "Entered %s\n", __func__); @@ -226,27 +225,23 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock_irqsave(&pcm->lock, flags); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - s3c_pcm_snd_rxctrl(pcm, 1); - else - s3c_pcm_snd_txctrl(pcm, 1); - - spin_unlock_irqrestore(&pcm->lock, flags); + scoped_guard(spinlock_irqsave, &pcm->lock) { + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + s3c_pcm_snd_rxctrl(pcm, 1); + else + s3c_pcm_snd_txctrl(pcm, 1); + } break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(&pcm->lock, flags); - - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - s3c_pcm_snd_rxctrl(pcm, 0); - else - s3c_pcm_snd_txctrl(pcm, 0); - - spin_unlock_irqrestore(&pcm->lock, flags); + scoped_guard(spinlock_irqsave, &pcm->lock) { + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + s3c_pcm_snd_rxctrl(pcm, 0); + else + s3c_pcm_snd_txctrl(pcm, 0); + } break; default: @@ -265,7 +260,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, void __iomem *regs = pcm->regs; struct clk *clk; int sclk_div, sync_div; - unsigned long flags; u32 clkctl; dev_dbg(pcm->dev, "Entered %s\n", __func__); @@ -278,36 +272,33 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - spin_lock_irqsave(&pcm->lock, flags); + scoped_guard(spinlock_irqsave, &pcm->lock) { + /* Get hold of the PCMSOURCE_CLK */ + clkctl = readl(regs + S3C_PCM_CLKCTL); + if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK) + clk = pcm->pclk; + else + clk = pcm->cclk; - /* Get hold of the PCMSOURCE_CLK */ - clkctl = readl(regs + S3C_PCM_CLKCTL); - if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK) - clk = pcm->pclk; - else - clk = pcm->cclk; + /* Set the SCLK divider */ + sclk_div = clk_get_rate(clk) / pcm->sclk_per_fs / + params_rate(params) / 2 - 1; - /* Set the SCLK divider */ - sclk_div = clk_get_rate(clk) / pcm->sclk_per_fs / - params_rate(params) / 2 - 1; + clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK + << S3C_PCM_CLKCTL_SCLKDIV_SHIFT); + clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK) + << S3C_PCM_CLKCTL_SCLKDIV_SHIFT); - clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK - << S3C_PCM_CLKCTL_SCLKDIV_SHIFT); - clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK) - << S3C_PCM_CLKCTL_SCLKDIV_SHIFT); + /* Set the SYNC divider */ + sync_div = pcm->sclk_per_fs - 1; - /* Set the SYNC divider */ - sync_div = pcm->sclk_per_fs - 1; - - clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK - << S3C_PCM_CLKCTL_SYNCDIV_SHIFT); - clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK) - << S3C_PCM_CLKCTL_SYNCDIV_SHIFT); - - writel(clkctl, regs + S3C_PCM_CLKCTL); - - spin_unlock_irqrestore(&pcm->lock, flags); + clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK + << S3C_PCM_CLKCTL_SYNCDIV_SHIFT); + clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK) + << S3C_PCM_CLKCTL_SYNCDIV_SHIFT); + writel(clkctl, regs + S3C_PCM_CLKCTL); + } dev_dbg(pcm->dev, "PCMSOURCE_CLK-%lu SCLK=%ufs SCLK_DIV=%d SYNC_DIV=%d\n", clk_get_rate(clk), pcm->sclk_per_fs, sclk_div, sync_div); @@ -320,13 +311,11 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, { struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai); void __iomem *regs = pcm->regs; - unsigned long flags; - int ret = 0; u32 ctl; dev_dbg(pcm->dev, "Entered %s\n", __func__); - spin_lock_irqsave(&pcm->lock, flags); + guard(spinlock_irqsave)(&pcm->lock); ctl = readl(regs + S3C_PCM_CTL); @@ -336,8 +325,7 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, break; default: dev_err(pcm->dev, "Unsupported clock inversion!\n"); - ret = -EINVAL; - goto exit; + return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { @@ -346,8 +334,7 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, break; default: dev_err(pcm->dev, "Unsupported master/slave format!\n"); - ret = -EINVAL; - goto exit; + return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { @@ -359,8 +346,7 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, break; default: dev_err(pcm->dev, "Invalid Clock gating request!\n"); - ret = -EINVAL; - goto exit; + return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -374,16 +360,11 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, break; default: dev_err(pcm->dev, "Unsupported data format!\n"); - ret = -EINVAL; - goto exit; + return -EINVAL; } writel(ctl, regs + S3C_PCM_CTL); - -exit: - spin_unlock_irqrestore(&pcm->lock, flags); - - return ret; + return 0; } static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index fb30f6b637a0..7fc46d55c522 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c @@ -143,7 +143,6 @@ static int spdif_trigger(struct snd_pcm_substream *substream, int cmd, { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct samsung_spdif_info *spdif = to_info(snd_soc_rtd_to_cpu(rtd, 0)); - unsigned long flags; dev_dbg(spdif->dev, "Entered %s\n", __func__); @@ -151,16 +150,14 @@ static int spdif_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - spin_lock_irqsave(&spdif->lock, flags); - spdif_snd_txctrl(spdif, 1); - spin_unlock_irqrestore(&spdif->lock, flags); + scoped_guard(spinlock_irqsave, &spdif->lock) + spdif_snd_txctrl(spdif, 1); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - spin_lock_irqsave(&spdif->lock, flags); - spdif_snd_txctrl(spdif, 0); - spin_unlock_irqrestore(&spdif->lock, flags); + scoped_guard(spinlock_irqsave, &spdif->lock) + spdif_snd_txctrl(spdif, 0); break; default: return -EINVAL; @@ -182,7 +179,6 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, void __iomem *regs = spdif->regs; struct snd_dmaengine_dai_dma_data *dma_data; u32 con, clkcon, cstas; - unsigned long flags; int i, ratio; dev_dbg(spdif->dev, "Entered %s\n", __func__); @@ -196,7 +192,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, snd_soc_dai_set_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream, dma_data); - spin_lock_irqsave(&spdif->lock, flags); + guard(spinlock_irqsave)(&spdif->lock); con = readl(regs + CON) & CON_MASK; cstas = readl(regs + CSTAS) & CSTAS_MASK; @@ -214,7 +210,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, break; default: dev_err(spdif->dev, "Unsupported data size.\n"); - goto err; + return -EINVAL; } ratio = spdif->clk_rate / params_rate(params); @@ -224,7 +220,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, if (i == ARRAY_SIZE(spdif_sysclk_ratios)) { dev_err(spdif->dev, "Invalid clock ratio %ld/%d\n", spdif->clk_rate, params_rate(params)); - goto err; + return -EINVAL; } con &= ~CON_MCLKDIV_MASK; @@ -257,7 +253,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, default: dev_err(spdif->dev, "Invalid sampling rate %d\n", params_rate(params)); - goto err; + return -EINVAL; } cstas &= ~CSTAS_CATEGORY_MASK; @@ -268,12 +264,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream, writel(cstas, regs + CSTAS); writel(clkcon, regs + CLKCON); - spin_unlock_irqrestore(&spdif->lock, flags); - return 0; -err: - spin_unlock_irqrestore(&spdif->lock, flags); - return -EINVAL; } static void spdif_shutdown(struct snd_pcm_substream *substream, diff --git a/sound/soc/sdca/Kconfig b/sound/soc/sdca/Kconfig index 87ab2895096c..4c0dcb9ff3b9 100644 --- a/sound/soc/sdca/Kconfig +++ b/sound/soc/sdca/Kconfig @@ -2,7 +2,7 @@ menu "SoundWire (SDCA)" config SND_SOC_SDCA - tristate + tristate "SDCA core support" depends on ACPI select AUXILIARY_BUS help diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c index 2bfc8e5aee31..e76afa396b0a 100644 --- a/sound/soc/sdca/sdca_asoc.c +++ b/sound/soc/sdca/sdca_asoc.c @@ -359,15 +359,77 @@ static int entity_parse_ot(struct device *dev, return 0; } +/** + * sdca_asoc_pde_poll_actual_ps - Verify PDE power state reached target state + * @dev: Pointer to the device for error logging. + * @regmap: Register map for reading ACTUAL_PS register. + * @function_id: SDCA function identifier. + * @entity_id: SDCA entity identifier for the power domain. + * @from_ps: Source power state (SDCA_PDE_PSn value). + * @to_ps: Target power state (SDCA_PDE_PSn value). + * @pde_delays: Pointer to array of PDE delay specifications for this device, + * or NULL to use default polling interval. + * @num_delays: Number of entries in pde_delays array. + * + * This function polls the ACTUAL_PS register to verify that a PDE power state + * transition has completed. Per SDCA specification, after writing REQUESTED_PS, + * the caller must poll ACTUAL_PS until it reflects the requested state. + * + * This function implements the polling logic but does NOT modify the power state. + * The caller is responsible for writing REQUESTED_PS before invoking this function. + * + * If a delay table is provided, appropriate polling intervals are extracted based + * on the from_ps and to_ps transition. If no table is provided or no matching entry + * is found, a default polling interval is used. + * + * Return: Returns zero when ACTUAL_PS reaches the target state, -ETIMEDOUT if the + * polling times out before reaching the target state, or a negative error code if + * a register read fails. + */ +int sdca_asoc_pde_poll_actual_ps(struct device *dev, struct regmap *regmap, + int function_id, int entity_id, + int from_ps, int to_ps, + const struct sdca_pde_delay *pde_delays, + int num_delays) +{ + static const int polls = 100; + static const int default_poll_us = 1000; + unsigned int reg, val; + int i, poll_us = default_poll_us; + int ret; + + if (pde_delays && num_delays > 0) { + for (i = 0; i < num_delays; i++) { + if (pde_delays[i].from_ps == from_ps && pde_delays[i].to_ps == to_ps) { + poll_us = pde_delays[i].us / polls; + break; + } + } + } + + reg = SDW_SDCA_CTL(function_id, entity_id, SDCA_CTL_PDE_ACTUAL_PS, 0); + + for (i = 0; i < polls; i++) { + if (i) + fsleep(poll_us); + + ret = regmap_read(regmap, reg, &val); + if (ret) + return ret; + else if (val == to_ps) + return 0; + } + + return -ETIMEDOUT; +} +EXPORT_SYMBOL_NS(sdca_asoc_pde_poll_actual_ps, "SND_SOC_SDCA"); + static int entity_pde_event(struct snd_soc_dapm_widget *widget, struct snd_kcontrol *kctl, int event) { struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); struct sdca_entity *entity = widget->priv; - static const int polls = 100; - unsigned int reg, val; - int from, to, i; - int poll_us; + int from, to; int ret; if (!component) @@ -386,33 +448,17 @@ static int entity_pde_event(struct snd_soc_dapm_widget *widget, return 0; } - for (i = 0; i < entity->pde.num_max_delay; i++) { - struct sdca_pde_delay *delay = &entity->pde.max_delay[i]; + ret = sdca_asoc_pde_poll_actual_ps(component->dev, component->regmap, + SDW_SDCA_CTL_FUNC(widget->reg), + SDW_SDCA_CTL_ENT(widget->reg), + from, to, + entity->pde.max_delay, + entity->pde.num_max_delay); + if (ret) + dev_err(component->dev, "%s: PDE transition %x -> %x failed, err=%d\n", + entity->label, from, to, ret); - if (delay->from_ps == from && delay->to_ps == to) { - poll_us = delay->us / polls; - break; - } - } - - reg = SDW_SDCA_CTL(SDW_SDCA_CTL_FUNC(widget->reg), - SDW_SDCA_CTL_ENT(widget->reg), - SDCA_CTL_PDE_ACTUAL_PS, 0); - - for (i = 0; i < polls; i++) { - if (i) - fsleep(poll_us); - - ret = regmap_read(component->regmap, reg, &val); - if (ret) - return ret; - else if (val == to) - return 0; - } - - dev_err(component->dev, "%s: power transition failed: %x\n", - entity->label, val); - return -ETIMEDOUT; + return ret; } static int entity_parse_pde(struct device *dev, diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c index 6e9b66f71801..6937a91ddfb9 100644 --- a/sound/soc/sdca/sdca_class.c +++ b/sound/soc/sdca/sdca_class.c @@ -38,35 +38,8 @@ static int class_read_prop(struct sdw_slave *sdw) return 0; } -static int class_sdw_update_status(struct sdw_slave *sdw, enum sdw_slave_status status) -{ - struct sdca_class_drv *drv = dev_get_drvdata(&sdw->dev); - - switch (status) { - case SDW_SLAVE_ATTACHED: - dev_dbg(drv->dev, "device attach\n"); - - drv->attached = true; - - complete(&drv->device_attach); - break; - case SDW_SLAVE_UNATTACHED: - dev_dbg(drv->dev, "device detach\n"); - - drv->attached = false; - - reinit_completion(&drv->device_attach); - break; - default: - break; - } - - return 0; -} - static const struct sdw_slave_ops class_sdw_ops = { .read_prop = class_read_prop, - .update_status = class_sdw_update_status, }; static void class_regmap_lock(void *data) @@ -83,24 +56,6 @@ static void class_regmap_unlock(void *data) mutex_unlock(lock); } -static int class_wait_for_attach(struct sdca_class_drv *drv) -{ - if (!drv->attached) { - unsigned long timeout = msecs_to_jiffies(CLASS_SDW_ATTACH_TIMEOUT_MS); - unsigned long time; - - time = wait_for_completion_timeout(&drv->device_attach, timeout); - if (!time) { - dev_err(drv->dev, "timed out waiting for device re-attach\n"); - return -ETIMEDOUT; - } - } - - regcache_cache_only(drv->dev_regmap, false); - - return 0; -} - static bool class_dev_regmap_volatile(struct device *dev, unsigned int reg) { switch (reg) { @@ -151,10 +106,12 @@ static void class_boot_work(struct work_struct *work) boot_work); int ret; - ret = class_wait_for_attach(drv); + ret = sdw_slave_wait_for_init(drv->sdw, CLASS_SDW_ATTACH_TIMEOUT_MS); if (ret) goto err; + regcache_cache_only(drv->dev_regmap, false); + drv->irq_info = sdca_irq_allocate(drv->dev, drv->dev_regmap, drv->sdw->irq); if (IS_ERR(drv->irq_info)) @@ -183,7 +140,6 @@ static void class_boot_work(struct work_struct *work) static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id) { struct device *dev = &sdw->dev; - struct sdca_device_data *data = &sdw->sdca_data; struct regmap_config *dev_config; struct sdca_class_drv *drv; int ret; @@ -199,12 +155,6 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id if (!dev_config) return -ENOMEM; - drv->functions = devm_kcalloc(dev, data->num_functions, - sizeof(*drv->functions), - GFP_KERNEL); - if (!drv->functions) - return -ENOMEM; - drv->dev = dev; drv->sdw = sdw; mutex_init(&drv->regmap_lock); @@ -213,7 +163,6 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id dev_set_drvdata(drv->dev, drv); INIT_WORK(&drv->boot_work, class_boot_work); - init_completion(&drv->device_attach); dev_config->lock_arg = &drv->regmap_lock; @@ -297,10 +246,11 @@ static int class_runtime_resume(struct device *dev) struct sdca_class_drv *drv = dev_get_drvdata(dev); int ret; - ret = class_wait_for_attach(drv); + ret = sdw_slave_wait_for_init(drv->sdw, CLASS_SDW_ATTACH_TIMEOUT_MS); if (ret) goto err; + regcache_cache_only(drv->dev_regmap, false); regcache_mark_dirty(drv->dev_regmap); ret = regcache_sync(drv->dev_regmap); diff --git a/sound/soc/sdca/sdca_class.h b/sound/soc/sdca/sdca_class.h index 6f24ea2bbd38..57f7f8d08f49 100644 --- a/sound/soc/sdca/sdca_class.h +++ b/sound/soc/sdca/sdca_class.h @@ -24,16 +24,12 @@ struct sdca_class_drv { struct regmap *dev_regmap; struct sdw_slave *sdw; - struct sdca_function_data *functions; struct sdca_interrupt_info *irq_info; struct mutex regmap_lock; /* Serialise function initialisations */ struct mutex init_lock; struct work_struct boot_work; - struct completion device_attach; - - bool attached; }; #endif /* __SDCA_CLASS_H__ */ diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c index 31fc08d51307..1496a15f7d2a 100644 --- a/sound/soc/sdca/sdca_class_function.c +++ b/sound/soc/sdca/sdca_class_function.c @@ -27,6 +27,7 @@ #include #include #include "sdca_class.h" +#include "sdca_function_device.h" struct class_function_drv { struct device *dev; @@ -294,8 +295,7 @@ static int class_function_probe(struct auxiliary_device *auxdev, { struct device *dev = &auxdev->dev; struct sdca_class_drv *core = dev_get_drvdata(dev->parent); - struct sdca_device_data *data = &core->sdw->sdca_data; - struct sdca_function_desc *desc; + struct sdca_dev *sdev = auxiliary_dev_to_sdca_dev(auxdev); struct snd_soc_component_driver *cmp_drv; struct snd_soc_dai_driver *dais; struct class_function_drv *drv; @@ -305,7 +305,6 @@ static int class_function_probe(struct auxiliary_device *auxdev, int ndefaults; int num_dais; int ret; - int i; drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); if (!drv) @@ -328,21 +327,9 @@ static int class_function_probe(struct auxiliary_device *auxdev, drv->dev = dev; drv->core = core; + drv->function = &sdev->function; - for (i = 0; i < data->num_functions; i++) { - desc = &data->function[i]; - - if (desc->type == aux_dev_id->driver_data) - break; - } - if (i == core->sdw->sdca_data.num_functions) { - dev_err(dev, "failed to locate function\n"); - return -EINVAL; - } - - drv->function = &core->functions[i]; - - ret = sdca_parse_function(dev, core->sdw, desc, drv->function); + ret = sdca_parse_function(dev, core->sdw, drv->function); if (ret) return ret; @@ -377,7 +364,7 @@ static int class_function_probe(struct auxiliary_device *auxdev, return dev_err_probe(dev, PTR_ERR(drv->regmap), "failed to create regmap"); - switch (desc->type) { + switch (drv->function->desc->type) { case SDCA_FUNCTION_TYPE_UAJ: case SDCA_FUNCTION_TYPE_RJ: cmp_drv->set_jack = class_function_set_jack; diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index 196bade11ab5..77940bd6b33c 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -98,7 +98,7 @@ static int find_sdca_function(struct acpi_device *adev, void *data) u32 function_type; int function_index; u64 addr; - int ret; + int i, ret; if (sdca_data->num_functions >= SDCA_MAX_FUNCTION_COUNT) { dev_err(dev, "maximum number of functions exceeded\n"); @@ -159,6 +159,14 @@ static int find_sdca_function(struct acpi_device *adev, void *data) /* store results */ function_index = sdca_data->num_functions; + + for (i = 0; i < function_index; i++) { + if (sdca_data->function[i].type == function_type) { + sdca_data->function[function_index].duplicate = true; + break; + } + } + sdca_data->function[function_index].adr = addr; sdca_data->function[function_index].type = function_type; sdca_data->function[function_index].name = function_name; @@ -1466,6 +1474,7 @@ static int find_sdca_entity_xu(struct device *dev, } static int find_sdca_entity(struct device *dev, struct sdw_slave *sdw, + struct sdca_function_data *function, struct fwnode_handle *function_node, struct fwnode_handle *entity_node, struct sdca_entity *entity) @@ -1481,6 +1490,13 @@ static int find_sdca_entity(struct device *dev, struct sdw_slave *sdw, return ret; } + if (function->desc->duplicate) { + entity->label = devm_kasprintf(dev, GFP_KERNEL, "%d %s", + function->desc->adr, entity->label); + if (!entity->label) + return -ENOMEM; + } + ret = fwnode_property_read_u32(entity_node, "mipi-sdca-entity-type", &tmp); if (ret) { dev_err(dev, "%s: type missing: %d\n", entity->label, ret); @@ -1578,7 +1594,7 @@ static int find_sdca_entities(struct device *dev, struct sdw_slave *sdw, return -EINVAL; } - ret = find_sdca_entity(dev, sdw, function_node, + ret = find_sdca_entity(dev, sdw, function, function_node, entity_node, &entities[i]); fwnode_handle_put(entity_node); if (ret) @@ -1605,8 +1621,14 @@ static struct sdca_entity *find_sdca_entity_by_label(struct sdca_function_data * const char *entity_label) { struct sdca_entity *entity = NULL; + char tmp[64]; int i; + if (function->desc->duplicate) { + snprintf(tmp, sizeof(tmp), "%d %s", function->desc->adr, entity_label); + entity_label = tmp; + } + for (i = 0; i < function->num_entities; i++) { entity = &function->entities[i]; @@ -2158,27 +2180,22 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw, * sdca_parse_function - parse ACPI DisCo for a Function * @dev: Pointer to device against which function data will be allocated. * @sdw: SoundWire slave device to be processed. - * @function_desc: Pointer to the Function short descriptor. * @function: Pointer to the Function information, to be populated. * * Return: Returns 0 for success. */ int sdca_parse_function(struct device *dev, struct sdw_slave *sdw, - struct sdca_function_desc *function_desc, struct sdca_function_data *function) { + struct fwnode_handle *node = function->desc->node; u32 tmp; int ret; - function->desc = function_desc; - - ret = fwnode_property_read_u32(function_desc->node, - "mipi-sdca-function-busy-max-delay", &tmp); + ret = fwnode_property_read_u32(node, "mipi-sdca-function-busy-max-delay", &tmp); if (!ret) function->busy_max_delay = tmp; - ret = fwnode_property_read_u32(function_desc->node, - "mipi-sdca-function-reset-max-delay", &tmp); + ret = fwnode_property_read_u32(node, "mipi-sdca-function-reset-max-delay", &tmp); if (ret || tmp == 0) { dev_dbg(dev, "reset delay missing, defaulting to 100mS\n"); function->reset_max_delay = 100000; @@ -2187,26 +2204,26 @@ int sdca_parse_function(struct device *dev, struct sdw_slave *sdw, } dev_dbg(dev, "%pfwP: name %s busy delay %dus reset delay %dus\n", - function->desc->node, function->desc->name, - function->busy_max_delay, function->reset_max_delay); + node, function->desc->name, function->busy_max_delay, + function->reset_max_delay); - ret = find_sdca_init_table(dev, function_desc->node, function); + ret = find_sdca_init_table(dev, node, function); if (ret) return ret; - ret = find_sdca_entities(dev, sdw, function_desc->node, function); + ret = find_sdca_entities(dev, sdw, node, function); if (ret) return ret; - ret = find_sdca_connections(dev, function_desc->node, function); + ret = find_sdca_connections(dev, node, function); if (ret) return ret; - ret = find_sdca_clusters(dev, function_desc->node, function); + ret = find_sdca_clusters(dev, node, function); if (ret < 0) return ret; - ret = find_sdca_filesets(dev, sdw, function_desc->node, function); + ret = find_sdca_filesets(dev, sdw, node, function); if (ret) return ret; diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c index 6e10b4e660d9..4539a52a8e32 100644 --- a/sound/soc/sdca/sdca_interrupts.c +++ b/sound/soc/sdca/sdca_interrupts.c @@ -375,8 +375,7 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap, if (!dev) return -ENODEV; - name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name, - entity->label, control->label); + name = kasprintf(GFP_KERNEL, "%s %s", entity->label, control->label); if (!name) return -ENOMEM; diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c index 49d317d3b8c8..ae9636622a84 100644 --- a/sound/soc/sdca/sdca_jack.c +++ b/sound/soc/sdca/sdca_jack.c @@ -145,6 +145,32 @@ int sdca_jack_alloc_state(struct sdca_interrupt *interrupt) } EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA"); +static int type_get_mask(enum sdca_terminal_type type) +{ + switch (type) { + case SDCA_TERM_TYPE_LINEIN_STEREO: + case SDCA_TERM_TYPE_LINEIN_FRONT_LR: + case SDCA_TERM_TYPE_LINEIN_CENTER_LFE: + case SDCA_TERM_TYPE_LINEIN_SURROUND_LR: + case SDCA_TERM_TYPE_LINEIN_REAR_LR: + return SND_JACK_LINEIN; + case SDCA_TERM_TYPE_LINEOUT_STEREO: + case SDCA_TERM_TYPE_LINEOUT_FRONT_LR: + case SDCA_TERM_TYPE_LINEOUT_CENTER_LFE: + case SDCA_TERM_TYPE_LINEOUT_SURROUND_LR: + case SDCA_TERM_TYPE_LINEOUT_REAR_LR: + return SND_JACK_LINEOUT; + case SDCA_TERM_TYPE_MIC_JACK: + return SND_JACK_MICROPHONE; + case SDCA_TERM_TYPE_HEADPHONE_JACK: + return SND_JACK_HEADPHONE; + case SDCA_TERM_TYPE_HEADSET_JACK: + return SND_JACK_HEADSET; + default: + return 0; + } +} + /** * sdca_jack_set_jack - attach an ASoC jack to SDCA * @info: SDCA interrupt information. @@ -154,7 +180,8 @@ EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA"); */ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack) { - int i, ret; + int i, j; + int ret; guard(mutex)(&info->irq_lock); @@ -162,6 +189,7 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja struct sdca_interrupt *interrupt = &info->irqs[i]; struct sdca_control *control = interrupt->control; struct sdca_entity *entity = interrupt->entity; + struct sdca_control_range *range; struct jack_state *jack_state; if (!interrupt->irq) @@ -169,7 +197,22 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja switch (SDCA_CTL_TYPE(entity->type, control->sel)) { case SDCA_CTL_TYPE_S(GE, DETECTED_MODE): + range = sdca_selector_find_range(interrupt->dev, entity, + SDCA_CTL_GE_SELECTED_MODE, + SDCA_SELECTED_MODE_NCOLS, 0); + if (!range) + return -EINVAL; + jack_state = interrupt->priv; + + for (j = 0; j < range->rows; j++) { + enum sdca_terminal_type type; + + type = sdca_range(range, SDCA_SELECTED_MODE_TERM_TYPE, j); + + jack_state->mask |= type_get_mask(type); + } + jack_state->jack = jack; /* Report initial state in case IRQ was already handled */ @@ -191,7 +234,6 @@ int sdca_jack_report(struct sdca_interrupt *interrupt) struct jack_state *jack_state = interrupt->priv; struct sdca_control_range *range; enum sdca_terminal_type type; - unsigned int report = 0; unsigned int reg, val; int ret; @@ -213,35 +255,7 @@ int sdca_jack_report(struct sdca_interrupt *interrupt) type = sdca_range_search(range, SDCA_SELECTED_MODE_INDEX, val, SDCA_SELECTED_MODE_TERM_TYPE); - switch (type) { - case SDCA_TERM_TYPE_LINEIN_STEREO: - case SDCA_TERM_TYPE_LINEIN_FRONT_LR: - case SDCA_TERM_TYPE_LINEIN_CENTER_LFE: - case SDCA_TERM_TYPE_LINEIN_SURROUND_LR: - case SDCA_TERM_TYPE_LINEIN_REAR_LR: - report = SND_JACK_LINEIN; - break; - case SDCA_TERM_TYPE_LINEOUT_STEREO: - case SDCA_TERM_TYPE_LINEOUT_FRONT_LR: - case SDCA_TERM_TYPE_LINEOUT_CENTER_LFE: - case SDCA_TERM_TYPE_LINEOUT_SURROUND_LR: - case SDCA_TERM_TYPE_LINEOUT_REAR_LR: - report = SND_JACK_LINEOUT; - break; - case SDCA_TERM_TYPE_MIC_JACK: - report = SND_JACK_MICROPHONE; - break; - case SDCA_TERM_TYPE_HEADPHONE_JACK: - report = SND_JACK_HEADPHONE; - break; - case SDCA_TERM_TYPE_HEADSET_JACK: - report = SND_JACK_HEADSET; - break; - default: - break; - } - - snd_soc_jack_report(jack_state->jack, report, 0xFFFF); + snd_soc_jack_report(jack_state->jack, type_get_mask(type), jack_state->mask); return 0; } diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile index a8d091fd374b..5ae8c69b8b98 100644 --- a/sound/soc/sdw_utils/Makefile +++ b/sound/soc/sdw_utils/Makefile @@ -8,6 +8,7 @@ snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \ soc_sdw_cs42l45.o \ soc_sdw_cs47l47.o \ soc_sdw_cs_amp.o \ + soc_sdw_es9356.o \ soc_sdw_maxim.o \ soc_sdw_ti_amp.o obj-$(CONFIG_SND_SOC_SDW_UTILS) += snd-soc-sdw-utils.o diff --git a/sound/soc/sdw_utils/soc_sdw_es9356.c b/sound/soc/sdw_utils/soc_sdw_es9356.c new file mode 100644 index 000000000000..aa405e7dad99 --- /dev/null +++ b/sound/soc/sdw_utils/soc_sdw_es9356.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Based on sof_sdw_rt5682.c +// This file incorporates work covered by the following copyright notice: +// Copyright (c) 2023 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. +// Copyright (c) 2025 Everest Semiconductor Co., Ltd + +/* + * soc_sdw_es9356 - Helpers to handle ES9356 from generic machine driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 es9356_add_codec_device_props(struct device *sdw_dev, unsigned long quirk) +{ + struct property_entry props[SOC_SDW_MAX_NO_PROPS] = {}; + struct fwnode_handle *fwnode; + int ret; + + if (!SOC_SDW_JACK_JDSRC(quirk)) + return 0; + props[0] = PROPERTY_ENTRY_U32("everest,jd-src", SOC_SDW_JACK_JDSRC(quirk)); + + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + + ret = device_add_software_node(sdw_dev, to_software_node(fwnode)); + + fwnode_handle_put(fwnode); + + return ret; +} + +static const struct snd_soc_dapm_route es9356_map[] = { + /* Headphones */ + { "Headphone", NULL, "es9356 HP" }, + { "es9356 MIC1", NULL, "Headset Mic" }, +}; + +static const struct snd_soc_dapm_route es9356_spk_map[] = { + /* Speaker */ + { "Speaker", NULL, "es9356 SPK" }, +}; + +static const struct snd_soc_dapm_route es9356_dmic_map[] = { + /* DMIC */ + { "es9356 PDM_DIN", NULL, "DMIC" }, +}; + +static struct snd_soc_jack_pin es9356_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +int asoc_sdw_es9356_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:es9356-spk", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_dapm_add_routes(dapm, es9356_spk_map, + ARRAY_SIZE(es9356_spk_map)); + if (ret) + dev_err(card->dev, "es9356 map addition failed: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_NS(asoc_sdw_es9356_spk_rtd_init, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_es9356_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:es9356-dmic", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_dapm_add_routes(dapm, es9356_dmic_map, + ARRAY_SIZE(es9356_dmic_map)); + if (ret) + dev_err(card->dev, "es9356 map addition failed: %d\n", ret); + + return ret; +} +EXPORT_SYMBOL_NS(asoc_sdw_es9356_dmic_rtd_init, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_es9356_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_component *component; + struct snd_soc_jack *jack; + int ret; + + component = dai->component; + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s hs:es9356", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_dapm_add_routes(dapm, es9356_map, + ARRAY_SIZE(es9356_map)); + + if (ret) { + dev_err(card->dev, "es9356 map addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3 | SND_JACK_BTN_4, + &ctx->sdw_headset, + es9356_jack_pins, + ARRAY_SIZE(es9356_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_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_NEXTSONG); + snd_jack_set_key(jack->jack, SND_JACK_BTN_4, KEY_PREVIOUSSONG); + + 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; +} +EXPORT_SYMBOL_NS(asoc_sdw_es9356_rtd_init, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_es9356_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) +{ + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + + if (!ctx->headset_codec_dev) + return 0; + + device_remove_software_node(ctx->headset_codec_dev); + put_device(ctx->headset_codec_dev); + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_es9356_exit, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_es9356_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) +{ + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct device *sdw_dev; + int ret; + + /* + * headset should be initialized once. + * Do it with dai link for playback. + */ + if (!playback) + return 0; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name); + if (!sdw_dev) + return -EPROBE_DEFER; + + ret = es9356_add_codec_device_props(sdw_dev, ctx->mc_quirk); + if (ret < 0) { + put_device(sdw_dev); + return ret; + } + ctx->headset_codec_dev = sdw_dev; + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_es9356_init, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_es9356_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) +{ + if (!playback) + return 0; + + info->amp_num++; + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_es9356_amp_init, "SND_SOC_SDW_UTILS"); diff --git a/sound/soc/sdw_utils/soc_sdw_ti_amp.c b/sound/soc/sdw_utils/soc_sdw_ti_amp.c index 488ef2ef45d4..d0ae5d7efe8f 100644 --- a/sound/soc/sdw_utils/soc_sdw_ti_amp.c +++ b/sound/soc/sdw_utils/soc_sdw_ti_amp.c @@ -7,12 +7,15 @@ #include #include -#include +#include +#include #include #include +#include #include #define TIAMP_SPK_VOLUME_0DB 200 +#define TAC5XX2_WIDGET_NAME_MAX 32 int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card, const char *name_prefix) @@ -95,3 +98,132 @@ int asoc_sdw_ti_amp_init(struct snd_soc_card *card, return 0; } EXPORT_SYMBOL_NS(asoc_sdw_ti_amp_init, "SND_SOC_SDW_UTILS"); + +static int asoc_sdw_ti_add_tac5xx2_routes(struct snd_soc_dapm_context *dapm, + const char *name_prefix) +{ + struct snd_soc_dapm_route routes[2]; + char left_widget[TAC5XX2_WIDGET_NAME_MAX]; + char right_widget[TAC5XX2_WIDGET_NAME_MAX]; + + if (strlen(name_prefix) > (TAC5XX2_WIDGET_NAME_MAX - 7)) + return -ENAMETOOLONG; + + scnprintf(left_widget, sizeof(left_widget), "%s SPK_L", name_prefix); + scnprintf(right_widget, sizeof(right_widget), "%s SPK_R", name_prefix); + + routes[0] = (struct snd_soc_dapm_route){"Left Spk", NULL, left_widget}; + routes[1] = (struct snd_soc_dapm_route){"Right Spk", NULL, right_widget}; + + return snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes)); +} + +int asoc_sdw_ti_tac5xx2_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + int ret, i; + struct snd_soc_dai *codec_dai; + const char *prefix; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (!strstr(codec_dai->name, "tac5") && + !strstr(codec_dai->name, "tas2883")) + continue; + + prefix = codec_dai->component->name_prefix; + if (!prefix) { + dev_warn(card->dev, + "No name prefix found for codec DAI: %s\n", + codec_dai->name); + continue; + } + ret = asoc_sdw_ti_add_tac5xx2_routes(dapm, prefix); + if (ret) { + dev_err(card->dev, "Failed to add routes for %s: %d\n", + prefix, ret); + return ret; + } + } + + dev_dbg(card->dev, "Added TAC5XX2 speaker routes\n"); + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_tac5xx2_spk_rtd_init, "SND_SOC_SDW_UTILS"); + +int asoc_sdw_ti_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_component *component; + + component = dai->component; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:%s", card->components, + component->name_prefix); + if (!card->components) + return -ENOMEM; + + dev_dbg(card->dev, "card->components: %s\n", card->components); + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_dmic_rtd_init, "SND_SOC_SDW_UTILS"); + +static struct snd_soc_jack_pin ti_sdca_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +int asoc_sdw_ti_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +{ + struct snd_soc_card *card = rtd->card; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_component *component; + struct snd_soc_jack *jack; + int ret; + + component = dai->component; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s hs:%s", card->components, + component->name_prefix); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3 | SND_JACK_BTN_4, + &ctx->sdw_headset, + ti_sdca_jack_pins, + ARRAY_SIZE(ti_sdca_jack_pins)); + if (ret) { + dev_err(rtd->card->dev, "Jack create 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); + snd_jack_set_key(jack->jack, SND_JACK_BTN_4, KEY_NEXTSONG); + + 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; +} +EXPORT_SYMBOL_NS(asoc_sdw_ti_sdca_jack_rtd_init, "SND_SOC_SDW_UTILS"); diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index e440c2327100..d8db8fc5313e 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -72,14 +72,167 @@ static const struct snd_kcontrol_new rt700_controls[] = { }; struct asoc_sdw_codec_info codec_info_list[] = { + { + .vendor_id = 0x0102, + .part_id = 0x5572, + .name_prefix = "tac5572", + .dais = { + { + /* speaker */ + .direction = {true, false}, + .dai_name = "tac5xx2-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_ti_amp_init, + .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init, + .controls = lr_spk_controls, + .num_controls = ARRAY_SIZE(lr_spk_controls), + .widgets = lr_spk_widgets, + .num_widgets = ARRAY_SIZE(lr_spk_widgets), + }, + { + /* mic */ + .direction = {false, true}, + .dai_name = "tac5xx2-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_ti_dmic_rtd_init, + }, + { + /* UAJ */ + .direction = {true, true}, + .dai_name = "tac5xx2-aif3", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + .rtd_init = asoc_sdw_ti_sdca_jack_rtd_init, + }, + }, + .dai_num = 3, + }, + { + .vendor_id = 0x0102, + .part_id = 0x5672, + .name_prefix = "tac5672", + .dais = { + { + /* speaker with IV sense feedback */ + .direction = {true, true}, + .dai_name = "tac5xx2-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + .init = asoc_sdw_ti_amp_init, + .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init, + .controls = lr_spk_controls, + .num_controls = ARRAY_SIZE(lr_spk_controls), + .widgets = lr_spk_widgets, + .num_widgets = ARRAY_SIZE(lr_spk_widgets), + }, + { + /* mic */ + .direction = {false, true}, + .dai_name = "tac5xx2-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_ti_dmic_rtd_init, + }, + { + /* UAJ */ + .direction = {true, true}, + .dai_name = "tac5xx2-aif3", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + .rtd_init = asoc_sdw_ti_sdca_jack_rtd_init, + }, + }, + .dai_num = 3, + }, + { + .vendor_id = 0x0102, + .part_id = 0x5682, + .name_prefix = "tac5682", + .dais = { + { + /* speaker with echo reference feedback */ + .direction = {true, true}, + .dai_name = "tac5xx2-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + .init = asoc_sdw_ti_amp_init, + .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init, + .controls = lr_spk_controls, + .num_controls = ARRAY_SIZE(lr_spk_controls), + .widgets = lr_spk_widgets, + .num_widgets = ARRAY_SIZE(lr_spk_widgets), + }, + { + /* mic */ + .direction = {false, true}, + .dai_name = "tac5xx2-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_ti_dmic_rtd_init, + }, + { + /* UAJ */ + .direction = {true, true}, + .dai_name = "tac5xx2-aif3", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + .rtd_init = asoc_sdw_ti_sdca_jack_rtd_init, + }, + }, + .dai_num = 3, + }, + { + .vendor_id = 0x0102, + .part_id = 0x2883, + .name_prefix = "tas2883", + .dais = { + { + .direction = {true, false}, + .dai_name = "tac5xx2-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_ti_amp_init, + .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init, + .controls = lr_spk_controls, + .num_controls = ARRAY_SIZE(lr_spk_controls), + .widgets = lr_spk_widgets, + .num_widgets = ARRAY_SIZE(lr_spk_widgets), + }, + { + /* mic */ + .direction = {false, true}, + .dai_name = "tac5xx2-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_ti_dmic_rtd_init, + }, + }, + .dai_num = 2, + }, { .vendor_id = 0x0102, .part_id = 0x0000, /* TAS2783A */ .name_prefix = "tas2783", + .is_amp = true, .dais = { { .direction = {true, true}, .dai_name = "tas2783-codec", + .component_name = "tas2783", .dai_type = SOC_SDW_DAI_TYPE_AMP, .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, .init = asoc_sdw_ti_amp_init, @@ -266,6 +419,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .part_id = 0x1308, .name_prefix = "rt1308", .acpi_id = "10EC1308", + .is_amp = true, .dais = { { .direction = {true, false}, @@ -289,6 +443,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x025d, .part_id = 0x1316, .name_prefix = "rt1316", + .is_amp = true, .dais = { { .direction = {true, true}, @@ -311,6 +466,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x025d, .part_id = 0x1318, .name_prefix = "rt1318", + .is_amp = true, .dais = { { .direction = {true, true}, @@ -561,6 +717,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x019f, .part_id = 0x8373, .name_prefix = "Left", + .is_amp = true, .dais = { { .direction = {true, true}, @@ -582,6 +739,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x019f, .part_id = 0x8363, .name_prefix = "Left", + .is_amp = true, .dais = { { .direction = {true, false}, @@ -622,6 +780,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x01fa, .part_id = 0x3556, .name_prefix = "AMP", + .is_amp = true, .dais = { { .direction = {true, false}, @@ -650,6 +809,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x01fa, .part_id = 0x3557, .name_prefix = "AMP", + .is_amp = true, .dais = { { .direction = {true, false}, @@ -678,6 +838,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x01fa, .part_id = 0x3563, .name_prefix = "AMP", + .is_amp = true, .dais = { { .direction = {true, false}, @@ -818,6 +979,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { { .direction = {true, false}, .codec_name = "cs42l43-codec", + .component_name = "cs42l43-spk", .dai_name = "cs42l43-dp6", .dai_type = SOC_SDW_DAI_TYPE_AMP, .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, @@ -943,6 +1105,56 @@ struct asoc_sdw_codec_info codec_info_list[] = { }, .aux_num = 1, }, + { + .vendor_id = 0x04b3, + .part_id = 0x9356, + .name_prefix = "es9356", + .version_id = 3, + .dais = { + { + .direction = {true, false}, + .dai_name = "es9356-sdp-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_es9356_init, + .exit = asoc_sdw_es9356_exit, + .rtd_init = asoc_sdw_es9356_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + }, + { + .direction = {false, true}, + .dai_name = "es9356-sdp-aif4", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_es9356_dmic_rtd_init, + .widgets = generic_dmic_widgets, + .num_widgets = ARRAY_SIZE(generic_dmic_widgets), + }, + { + .direction = {false, true}, + .dai_name = "es9356-sdp-aif2", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + }, + { + .direction = {true, false}, + .dai_name = "es9356-sdp-aif3", + .component_name = "es9356", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_es9356_amp_init, + .rtd_init = asoc_sdw_es9356_spk_rtd_init, + .controls = generic_spk_controls, + .num_controls = ARRAY_SIZE(generic_spk_controls), + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), + }, + }, + .dai_num = 4, + }, { .vendor_id = 0x0105, .part_id = 0xaaaa, /* generic codec mockup */ @@ -989,6 +1201,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { .vendor_id = 0x0105, .part_id = 0x55aa, /* amplifier mockup */ .name_prefix = "sdw_mockup_amp1", + .is_amp = true, .version_id = 0, .dais = { { @@ -1428,7 +1641,9 @@ const char *asoc_sdw_get_codec_name(struct device *dev, __func__, component->name, dai_info->codec_name); return devm_kstrdup(dev, component->name, GFP_KERNEL); } else { - return devm_kstrdup(dev, dai_info->codec_name, GFP_KERNEL); + dev_dbg(dev, "%s component %s is not registered yet\n", + __func__, dai_info->codec_name); + return ERR_PTR(-EPROBE_DEFER); } } @@ -1559,6 +1774,63 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d } EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, "SND_SOC_SDW_UTILS"); +/** + * is_sdca_aux_dev_present - Check if an SDCA aux device is present on the SDW peripheral + * @dev: Device pointer + * @aux_codec_name: Aux codec name from the codec info (e.g. "snd_soc_sdca.HID.2") + * @adr_link: ACPI link address + * @adr_index: Index of the ACPI link address + * + * Return: 1 if the aux is present, 0 if the aux is not present, or negative error code. + */ +static int is_sdca_aux_dev_present(struct device *dev, + const char *aux_codec_name, + const struct snd_soc_acpi_link_adr *adr_link, + int adr_index) +{ + struct sdw_slave *slave; + struct device *sdw_dev; + const char *sdw_codec_name; + int ret = 0; + int i; + + if (!aux_codec_name) + return 0; + + sdw_codec_name = _asoc_sdw_get_codec_name(dev, adr_link, adr_index); + if (!sdw_codec_name) + return -ENOMEM; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_codec_name); + if (!sdw_dev) { + dev_err(dev, "codec %s not found\n", sdw_codec_name); + return -EINVAL; + } + + slave = dev_to_sdw_dev(sdw_dev); + + if (!slave->sdca_data.interface_revision) { + dev_warn(dev, "No SDCA properties, assuming aux '%s' present\n", aux_codec_name); + ret = 1; + goto put_dev; + } + + for (i = 0; i < slave->sdca_data.num_functions; i++) { + const char *fname = slave->sdca_data.function[i].name; + + if (fname && strstr(aux_codec_name, fname)) { + ret = 1; + goto put_dev; + } + } + + dev_dbg(dev, "SDCA function for aux '%s' NOT FOUND on slave, skipping\n", aux_codec_name); + +put_dev: + put_device(sdw_dev); + return ret; +} + int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends, int *num_aux) { @@ -1566,7 +1838,7 @@ int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; const struct snd_soc_acpi_link_adr *adr_link; - int i; + int i, j, ret; for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { *num_devs += adr_link->num_adr; @@ -1581,7 +1853,14 @@ int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, if (!codec_info) return -EINVAL; - *num_aux += codec_info->aux_num; + for (j = 0; j < codec_info->aux_num; j++) { + ret = is_sdca_aux_dev_present(dev, codec_info->auxs[j].codec_name, + adr_link, i); + if (ret < 0) + return ret; + if (ret) + (*num_aux)++; + } } } @@ -1630,20 +1909,16 @@ int asoc_sdw_get_dai_type(u32 type) } EXPORT_SYMBOL_NS(asoc_sdw_get_dai_type, "SND_SOC_SDW_UTILS"); -/* - * Check if the SDCA endpoint is present by the SDW peripheral - * +/** + * is_sdca_endpoint_present - Check if an SDCA endpoint is present on the SDW peripheral * @dev: Device pointer * @codec_info: Codec info pointer * @adr_link: ACPI link address * @adr_index: Index of the ACPI link address * @end_index: Index of the endpoint * - * Return: 1 if the endpoint is present, - * 0 if the endpoint is not present, - * negative error code. + * Return: 1 if the endpoint is present, 0 if the endpoint is not present, or negative error code. */ - static int is_sdca_endpoint_present(struct device *dev, struct asoc_sdw_codec_info *codec_info, const struct snd_soc_acpi_link_adr *adr_link, @@ -1745,6 +2020,14 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card, for (j = 0; j < codec_info->aux_num; j++) { struct snd_soc_component *component; + ret = is_sdca_aux_dev_present(dev, codec_info->auxs[j].codec_name, + adr_link, i); + if (ret < 0) + return ret; + + if (ret == 0) + continue; + component = snd_soc_lookup_component_by_name(codec_info->auxs[j].codec_name); if (component) { dev_dbg(dev, "%s found component %s for aux name %s\n", @@ -1752,7 +2035,9 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card, codec_info->auxs[j].codec_name); soc_aux->dlc.name = component->name; } else { - soc_aux->dlc.name = codec_info->auxs[j].codec_name; + dev_dbg(dev, "%s the aux component %s is not registered yet\n", + __func__, codec_info->auxs[j].codec_name); + return -EPROBE_DEFER; } soc_aux++; } @@ -1852,6 +2137,8 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card, codec_name = asoc_sdw_get_codec_name(dev, dai_info, adr_link, i); + if (IS_ERR(codec_name)) + return PTR_ERR(codec_name); if (!codec_name) return -ENOMEM; diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 235427d69061..282d666dae9e 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -246,3 +246,16 @@ void snd_soc_card_remove_dai_link(struct snd_soc_card *card, card->remove_dai_link(card, dai_link); } EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link); + +void snd_soc_card_set_topology_name(struct snd_soc_card *card, const char *prefix) +{ + if (!prefix || !card->name) + return; + + if (!card->topology_shortname) + card->topology_shortname = devm_kasprintf(card->dev, GFP_KERNEL, + "%s-%s", prefix, card->name); + + card->name = card->topology_shortname; +} +EXPORT_SYMBOL_GPL(snd_soc_card_set_topology_name); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 3fecf9fc903c..86b6c752a56b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -136,11 +136,11 @@ static void soc_init_component_debugfs(struct snd_soc_component *component) if (!component->card->debugfs_card_root) return; - if (component->debugfs_prefix) { + if (component->driver->debugfs_prefix) { char *name; name = kasprintf(GFP_KERNEL, "%s:%s", - component->debugfs_prefix, component->name); + component->driver->debugfs_prefix, component->name); if (name) { component->debugfs_root = debugfs_create_dir(name, component->card->debugfs_card_root); @@ -194,9 +194,6 @@ static void soc_init_card_debugfs(struct snd_soc_card *card) card->debugfs_card_root = debugfs_create_dir(card->name, snd_soc_debugfs_root); - debugfs_create_u32("dapm_pop_time", 0644, card->debugfs_card_root, - &card->pop_time); - snd_soc_dapm_debugfs_init(snd_soc_card_to_dapm(card), card->debugfs_card_root); } @@ -215,6 +212,8 @@ static void snd_soc_debugfs_init(void) debugfs_create_file("components", 0444, snd_soc_debugfs_root, NULL, &component_list_fops); + + snd_soc_dapm_debugfs_pop_time(snd_soc_debugfs_root); } static void snd_soc_debugfs_exit(void) @@ -1285,163 +1284,6 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, } EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtimes); -static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_dai_link *dai_link = rtd->dai_link; - struct snd_soc_dai *dai, *not_used; - u64 pos, possible_fmt; - unsigned int mask = 0, dai_fmt = 0; - int i, j, priority, pri, until; - - /* - * Get selectable format from each DAIs. - * - **************************** - * NOTE - * Using .auto_selectable_formats is not mandatory, - * we can select format manually from Sound Card. - * When use it, driver should list well tested format only. - **************************** - * - * ex) - * auto_selectable_formats (= SND_SOC_POSSIBLE_xxx) - * (A) (B) (C) - * DAI0_: { 0x000F, 0x00F0, 0x0F00 }; - * DAI1 : { 0xF000, 0x0F00 }; - * (X) (Y) - * - * "until" will be 3 in this case (MAX array size from DAI0 and DAI1) - * Here is dev_dbg() message and comments - * - * priority = 1 - * DAI0: (pri, fmt) = (1, 000000000000000F) // 1st check (A) DAI1 is not selected - * DAI1: (pri, fmt) = (0, 0000000000000000) // Necessary Waste - * DAI0: (pri, fmt) = (1, 000000000000000F) // 2nd check (A) - * DAI1: (pri, fmt) = (1, 000000000000F000) // (X) - * priority = 2 - * DAI0: (pri, fmt) = (2, 00000000000000FF) // 3rd check (A) + (B) - * DAI1: (pri, fmt) = (1, 000000000000F000) // (X) - * DAI0: (pri, fmt) = (2, 00000000000000FF) // 4th check (A) + (B) - * DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y) - * priority = 3 - * DAI0: (pri, fmt) = (3, 0000000000000FFF) // 5th check (A) + (B) + (C) - * DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y) - * found auto selected format: 0000000000000F00 - */ - until = snd_soc_dai_get_fmt_max_priority(rtd); - for (priority = 1; priority <= until; priority++) { - for_each_rtd_dais(rtd, j, not_used) { - - possible_fmt = ULLONG_MAX; - for_each_rtd_dais(rtd, i, dai) { - u64 fmt = 0; - - pri = (j >= i) ? priority : priority - 1; - fmt = snd_soc_dai_get_fmt(dai, pri); - possible_fmt &= fmt; - } - if (possible_fmt) - goto found; - } - } - /* Not Found */ - return; -found: - /* - * convert POSSIBLE_DAIFMT to DAIFMT - * - * Some basic/default settings on each is defined as 0. - * see - * SND_SOC_DAIFMT_NB_NF - * SND_SOC_DAIFMT_GATED - * - * SND_SOC_DAIFMT_xxx_MASK can't notice it if Sound Card specify - * these value, and will be overwrite to auto selected value. - * - * To avoid such issue, loop from 63 to 0 here. - * Small number of SND_SOC_POSSIBLE_xxx will be Hi priority. - * Basic/Default settings of each part and above are defined - * as Hi priority (= small number) of SND_SOC_POSSIBLE_xxx. - */ - for (i = 63; i >= 0; i--) { - pos = 1ULL << i; - switch (possible_fmt & pos) { - /* - * for format - */ - case SND_SOC_POSSIBLE_DAIFMT_I2S: - case SND_SOC_POSSIBLE_DAIFMT_RIGHT_J: - case SND_SOC_POSSIBLE_DAIFMT_LEFT_J: - case SND_SOC_POSSIBLE_DAIFMT_DSP_A: - case SND_SOC_POSSIBLE_DAIFMT_DSP_B: - case SND_SOC_POSSIBLE_DAIFMT_AC97: - case SND_SOC_POSSIBLE_DAIFMT_PDM: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | i; - break; - /* - * for clock - */ - case SND_SOC_POSSIBLE_DAIFMT_CONT: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_CONT; - break; - case SND_SOC_POSSIBLE_DAIFMT_GATED: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_GATED; - break; - /* - * for clock invert - */ - case SND_SOC_POSSIBLE_DAIFMT_NB_NF: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_NF; - break; - case SND_SOC_POSSIBLE_DAIFMT_NB_IF: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_IF; - break; - case SND_SOC_POSSIBLE_DAIFMT_IB_NF: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_NF; - break; - case SND_SOC_POSSIBLE_DAIFMT_IB_IF: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_IF; - break; - /* - * for clock provider / consumer - */ - case SND_SOC_POSSIBLE_DAIFMT_CBP_CFP: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBP_CFP; - break; - case SND_SOC_POSSIBLE_DAIFMT_CBC_CFP: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBC_CFP; - break; - case SND_SOC_POSSIBLE_DAIFMT_CBP_CFC: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBP_CFC; - break; - case SND_SOC_POSSIBLE_DAIFMT_CBC_CFC: - dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBC_CFC; - break; - } - } - - /* - * Some driver might have very complex limitation. - * In such case, user want to auto-select non-limitation part, - * and want to manually specify complex part. - * - * Or for example, if both CPU and Codec can be clock provider, - * but because of its quality, user want to specify it manually. - * - * Use manually specified settings if sound card did. - */ - if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK)) - mask |= SND_SOC_DAIFMT_FORMAT_MASK; - if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_MASK)) - mask |= SND_SOC_DAIFMT_CLOCK_MASK; - if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_INV_MASK)) - mask |= SND_SOC_DAIFMT_INV_MASK; - if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) - mask |= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; - - dai_link->dai_fmt |= (dai_fmt & mask); -} - /** * snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime * @rtd: The runtime for which the DAI link format should be changed @@ -1520,8 +1362,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, if (ret < 0) return ret; - snd_soc_runtime_get_dai_fmt(rtd); - ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); + ret = snd_soc_runtime_set_dai_fmt(rtd, snd_soc_dai_auto_select_format(rtd)); if (ret) goto err; @@ -1881,12 +1722,12 @@ static int is_dmi_valid(const char *field) } /* - * Append a string to card->dmi_longname with character cleanups. + * Append a string to dmi_longname with character cleanups. */ -static void append_dmi_string(struct snd_soc_card *card, const char *str) +#define DMI_LONGNAME_LEN 80 +static void append_dmi_string(char *dst, const char *str) { - char *dst = card->dmi_longname; - size_t dst_len = sizeof(card->dmi_longname); + size_t dst_len = DMI_LONGNAME_LEN; size_t len; len = strlen(dst); @@ -1930,6 +1771,7 @@ static void append_dmi_string(struct snd_soc_card *card, const char *str) static int snd_soc_set_dmi_name(struct snd_soc_card *card) { const char *vendor, *product, *board; + char *dmi_longname; if (card->long_name) return 0; /* long name already set by driver or from DMI */ @@ -1944,27 +1786,31 @@ static int snd_soc_set_dmi_name(struct snd_soc_card *card) return 0; } - snprintf(card->dmi_longname, sizeof(card->dmi_longname), "%s", vendor); - cleanup_dmi_name(card->dmi_longname); + dmi_longname = devm_kzalloc(card->dev, DMI_LONGNAME_LEN, GFP_KERNEL); + if (!dmi_longname) + return -ENOMEM; + + snprintf(dmi_longname, DMI_LONGNAME_LEN, "%s", vendor); + cleanup_dmi_name(dmi_longname); product = dmi_get_system_info(DMI_PRODUCT_NAME); if (product && is_dmi_valid(product)) { const char *product_version = dmi_get_system_info(DMI_PRODUCT_VERSION); - append_dmi_string(card, product); + append_dmi_string(dmi_longname, product); /* * some vendors like Lenovo may only put a self-explanatory * name in the product version field */ if (product_version && is_dmi_valid(product_version)) - append_dmi_string(card, product_version); + append_dmi_string(dmi_longname, product_version); } board = dmi_get_system_info(DMI_BOARD_NAME); if (board && is_dmi_valid(board)) { if (!product || strcasecmp(board, product)) - append_dmi_string(card, board); + append_dmi_string(dmi_longname, board); } else if (!product) { /* fall back to using legacy name */ dev_warn(card->dev, "ASoC: no DMI board/product name!\n"); @@ -1972,7 +1818,7 @@ static int snd_soc_set_dmi_name(struct snd_soc_card *card) } /* set the card long name */ - card->long_name = card->dmi_longname; + card->long_name = dmi_longname; return 0; } @@ -1986,7 +1832,6 @@ static inline int snd_soc_set_dmi_name(struct snd_soc_card *card) static void soc_check_tplg_fes(struct snd_soc_card *card) { struct snd_soc_component *component; - const struct snd_soc_component_driver *comp_drv; struct snd_soc_dai_link *dai_link; int i; @@ -2047,21 +1892,7 @@ static void soc_check_tplg_fes(struct snd_soc_card *card) } /* Inform userspace we are using alternate topology */ - if (component->driver->topology_name_prefix) { - - /* topology shortname created? */ - if (!card->topology_shortname_created) { - comp_drv = component->driver; - - snprintf(card->topology_shortname, 32, "%s-%s", - comp_drv->topology_name_prefix, - card->name); - card->topology_shortname_created = true; - } - - /* use topology shortname */ - card->name = card->topology_shortname; - } + snd_soc_card_set_topology_name(card, component->driver->topology_name_prefix); } } @@ -2149,10 +1980,29 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card) } } +static void snd_soc_remove_device_links(struct snd_soc_card *card, + struct snd_soc_component *stop_at) +{ + struct snd_soc_component *component; + + for_each_card_components(card, component) { + if (card->dev == component->dev) + continue; + + device_link_remove(card->dev, component->dev); + + if (component == stop_at) + return; + } +} + static void snd_soc_unbind_card(struct snd_soc_card *card) { if (snd_soc_card_is_instantiated(card)) { card->instantiated = false; + + snd_soc_remove_device_links(card, NULL); + soc_cleanup_card_resources(card); } } @@ -2162,12 +2012,14 @@ static int snd_soc_bind_card(struct snd_soc_card *card) struct snd_soc_pcm_runtime *rtd; struct snd_soc_component *component; struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); + struct snd_soc_component *last_devlinked_component = NULL; int ret; snd_soc_card_mutex_lock_root(card); snd_soc_fill_dummy_dai(card); snd_soc_dapm_init(dapm, card, NULL); + list_del_init(&card->list); /* check whether any platform is ignore machine FE and using topology */ soc_check_tplg_fes(card); @@ -2285,10 +2137,33 @@ static int snd_soc_bind_card(struct snd_soc_card *card) } } + /* + * Add device_link from card to component so that system_suspend + * will be done in the correct order. The card must suspend first + * to stop audio activity before the components suspend. + */ + for_each_card_components(card, component) { + if (card->dev == component->dev) + continue; + + if (!device_link_add(card->dev, component->dev, DL_FLAG_STATELESS)) { + dev_warn(card->dev, "Failed to create device link to %s\n", + dev_name(component->dev)); + ret = -EINVAL; + goto probe_end; + } + + last_devlinked_component = component; + } + ret = snd_soc_card_late_probe(card); if (ret < 0) goto probe_end; + ret = snd_soc_dapm_ignore_suspend_widgets(card); + if (ret < 0) + goto probe_end; + snd_soc_dapm_new_widgets(card); snd_soc_card_fixup_controls(card); @@ -2309,8 +2184,17 @@ static int snd_soc_bind_card(struct snd_soc_card *card) pinctrl_pm_select_sleep_state(component->dev); probe_end: - if (ret < 0) + if (ret < 0) { + if (last_devlinked_component) + snd_soc_remove_device_links(card, last_devlinked_component); + soc_cleanup_card_resources(card); + } + + if (ret == -EPROBE_DEFER) { + list_add(&card->list, &unbind_card_list); + ret = 0; + } snd_soc_card_mutex_unlock(card); return ret; @@ -2326,12 +2210,15 @@ static int devm_snd_soc_bind_card(struct device *dev, struct snd_soc_card *card) struct snd_soc_card **ptr; int ret; + /* The procedure may be called many times during the lifetime of the card. */ + devres_destroy(dev, devm_card_bind_release, NULL, NULL); + ptr = devres_alloc(devm_card_bind_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) return -ENOMEM; ret = snd_soc_bind_card(card); - if (ret == 0 || ret == -EPROBE_DEFER) { + if (ret == 0) { *ptr = card; devres_add(dev, ptr); } else { @@ -2341,21 +2228,11 @@ static int devm_snd_soc_bind_card(struct device *dev, struct snd_soc_card *card) return ret; } -static int snd_soc_rebind_card(struct snd_soc_card *card) +static int call_soc_bind_card(struct snd_soc_card *card) { - int ret; - - if (card->devres_dev) { - devres_destroy(card->devres_dev, devm_card_bind_release, NULL, NULL); - ret = devm_snd_soc_bind_card(card->devres_dev, card); - } else { - ret = snd_soc_bind_card(card); - } - - if (ret != -EPROBE_DEFER) - list_del_init(&card->list); - - return ret; + if (card->devres_dev) + return devm_snd_soc_bind_card(card->devres_dev, card); + return snd_soc_bind_card(card); } /* probes a new socdev */ @@ -2553,8 +2430,6 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls); */ int snd_soc_register_card(struct snd_soc_card *card) { - int ret; - if (!card->name || !card->dev) return -EINVAL; @@ -2580,17 +2455,7 @@ int snd_soc_register_card(struct snd_soc_card *card) guard(mutex)(&client_mutex); - if (card->devres_dev) { - ret = devm_snd_soc_bind_card(card->devres_dev, card); - if (ret == -EPROBE_DEFER) { - list_add(&card->list, &unbind_card_list); - ret = 0; - } - } else { - ret = snd_soc_bind_card(card); - } - - return ret; + return call_soc_bind_card(card); } EXPORT_SYMBOL_GPL(snd_soc_register_card); @@ -2868,11 +2733,6 @@ int snd_soc_component_initialize(struct snd_soc_component *component, component->dev = dev; component->driver = driver; -#ifdef CONFIG_DEBUG_FS - if (!component->debugfs_prefix) - component->debugfs_prefix = driver->debugfs_prefix; -#endif - return 0; } EXPORT_SYMBOL_GPL(snd_soc_component_initialize); @@ -2910,7 +2770,7 @@ int snd_soc_add_component(struct snd_soc_component *component, list_add(&component->list, &component_list); list_for_each_entry_safe(card, c, &unbind_card_list, list) - snd_soc_rebind_card(card); + call_soc_bind_card(card); err_cleanup: if (ret < 0) @@ -3294,6 +3154,45 @@ int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname) } EXPORT_SYMBOL_GPL(snd_soc_of_parse_aux_devs); +int snd_soc_of_parse_ignore_suspend_widgets(struct snd_soc_card *card, + const char *propname) +{ + struct device_node *np = card->dev->of_node; + int num_widgets; + const char **widgets; + int i; + + num_widgets = of_property_count_strings(np, propname); + if (num_widgets < 0) { + dev_err(card->dev, + "ASoC: Property '%s' does not exist\n", propname); + return -EINVAL; + } + + widgets = devm_kcalloc(card->dev, num_widgets, sizeof(char *), GFP_KERNEL); + if (!widgets) + return -ENOMEM; + + for (i = 0; i < num_widgets; i++) { + const char *name; + int ret = of_property_read_string_index(np, propname, i, &name); + + if (ret) { + dev_err(card->dev, + "ASoC: Property '%s' could not be read: %d\n", + propname, ret); + return -EINVAL; + } + widgets[i] = name; + } + + card->num_of_ignore_suspend_widgets = num_widgets; + card->of_ignore_suspend_widgets = widgets; + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_of_parse_ignore_suspend_widgets); + unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt) { unsigned int inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 2f370fda1266..b098d1100b4b 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -116,72 +116,207 @@ int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) dai->driver->ops->set_bclk_ratio) ret = dai->driver->ops->set_bclk_ratio(dai, ratio); + if (!ret) + dai->bclk_ratio = ratio; + return soc_dai_ret(dai, ret); } EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); -int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd) +/** + * snd_soc_dai_set_bclk_clk - set the BCLK clock for shared clock detection + * @dai: DAI + * @bclk: BCLK clock pointer (or NULL to clear) + * + * When multiple DAIs share the same physical BCLK (detected via + * clk_is_match()), the ASoC core will automatically constrain their + * hw_params so that the resulting BCLK rates are compatible. + */ +void snd_soc_dai_set_bclk_clk(struct snd_soc_dai *dai, struct clk *bclk) { - struct snd_soc_dai *dai; - int i, max = 0; + dai->bclk = bclk; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_clk); - /* - * return max num if *ALL* DAIs have .auto_selectable_formats - */ - for_each_rtd_dais(rtd, i, dai) { - if (dai->driver->ops && - dai->driver->ops->num_auto_selectable_formats) - max = max(max, dai->driver->ops->num_auto_selectable_formats); - else - return 0; - } +static int soc_dai_fmt_match_cnt(u64 fmt) +{ + int cnt = 0; - return max; + if (fmt & SND_SOC_POSSIBLE_DAIFMT_FORMAT_MASK) + cnt++; + if (fmt & SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK) + cnt++; + if (fmt & SND_SOC_POSSIBLE_DAIFMT_INV_MASK) + cnt++; + + return cnt; } -/** - * snd_soc_dai_get_fmt - get supported audio format. - * @dai: DAI - * @priority: priority level of supported audio format. - * - * This should return only formats implemented with high - * quality by the DAI so that the core can configure a - * format which will work well with other devices. - * For example devices which don't support both edges of the - * LRCLK signal in I2S style formats should only list DSP - * modes. This will mean that sometimes fewer formats - * are reported here than are supported by set_fmt(). - */ -u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority) +static void soc_dai_auto_select_format(u64 fmt, const struct snd_soc_pcm_runtime *rtd, + int idx, u64 *best_fmt) { - const struct snd_soc_dai_ops *ops = dai->driver->ops; - u64 fmt = 0; - int i, max = 0, until = priority; + struct snd_soc_dai *dai; + const struct snd_soc_dai_ops *ops; + int max_idx = rtd->dai_link->num_cpus + rtd->dai_link->num_codecs; + u64 available_fmt; /* - * Collect auto_selectable_formats until priority + * NOTE + * It doesn't support Multi CPU/Codec for now + */ + if (rtd->dai_link->num_cpus != 1 || + rtd->dai_link->num_codecs != 1) + return; + + if (idx >= max_idx) + return; + + dai = rtd->dais[idx]; + ops = dai->driver->ops; + + /* zero chance of auto select format */ + if (!ops || !ops->num_auto_selectable_formats) + return; + + /* + **************************** + * NOTE + **************************** + * Using .auto_selectable_formats is not mandatory, + * It try to find best formats as much as possible, but automatically selecting the + * perfect format is impossible. So you can select full or missing format manually + * from Sound Card. * * ex) - * auto_selectable_formats[] = { A, B, C }; - * (A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx) + * CPU Codec + * (A)[0] I2S/LEFT_J : IB_NF/IB_IF (X)[0] I2S/DSP_A: NB_NF : GATED + * (B)[1] DSP_A/DSP_B: NB_NF/IB_NF (Y)[1] LEFT_J: NB_NF : GATED + * (C)[2] ... * - * priority = 1 : A - * priority = 2 : A | B - * priority = 3 : A | B | C - * priority = 4 : A | B | C + * 1. (A) -> (X) : I2S :update best format + * 2. (A) -> (Y) : LEFT_J + * 3. (B) -> (X) : DSP_A/NB_NF :update best format + * 4. (B) -> (Y) : NB_NF + * 5. (C) -> (X) ... + * 6. (C) -> (Y) ... * ... + * + * In above case GATED will not be selected */ - if (ops) - max = ops->num_auto_selectable_formats; - if (max < until) - until = max; + /* find best formats */ + for (int i = 0; i < ops->num_auto_selectable_formats; i++) { + available_fmt = fmt & ops->auto_selectable_formats[i]; - if (ops && ops->auto_selectable_formats) - for (i = 0; i < until; i++) - fmt |= ops->auto_selectable_formats[i]; + /* In case of last DAI */ + if (idx + 1 >= max_idx) { + int cnt1 = soc_dai_fmt_match_cnt(*best_fmt); + int cnt2 = soc_dai_fmt_match_cnt(available_fmt); - return fmt; + if (cnt1 < cnt2) + *best_fmt = available_fmt; + } + /* parse with next DAI */ + else { + soc_dai_auto_select_format(available_fmt, rtd, idx + 1, best_fmt); + } + } +} + +static unsigned int soc_dai_convert_possiblefmt_to_daifmt(u64 possible_fmt, unsigned int configured_fmt) +{ + unsigned int fmt = 0; + unsigned int mask = 0; + + /* + * convert POSSIBLE_DAIFMT to DAIFMT + * + * Some basic/default settings on each is defined as 0. + * see + * SND_SOC_DAIFMT_NB_NF + * SND_SOC_DAIFMT_GATED + * + * SND_SOC_DAIFMT_xxx_MASK can't notice it if Sound Card specify + * these value, and will be overwrite to auto selected value. + * + * To avoid such issue, loop from 63 to 0 here. + * Small number of SND_SOC_POSSIBLE_xxx will be Hi priority. + * Basic/Default settings of each part and above are defined + * as Hi priority (= small number) of SND_SOC_POSSIBLE_xxx. + */ + for (int i = 63; i >= 0; i--) { + u64 pos = 1ULL << i; + + switch (possible_fmt & pos) { + /* + * for format + */ + case SND_SOC_POSSIBLE_DAIFMT_I2S: + case SND_SOC_POSSIBLE_DAIFMT_RIGHT_J: + case SND_SOC_POSSIBLE_DAIFMT_LEFT_J: + case SND_SOC_POSSIBLE_DAIFMT_DSP_A: + case SND_SOC_POSSIBLE_DAIFMT_DSP_B: + case SND_SOC_POSSIBLE_DAIFMT_AC97: + case SND_SOC_POSSIBLE_DAIFMT_PDM: + fmt = (fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | i; + break; + /* + * for clock + */ + case SND_SOC_POSSIBLE_DAIFMT_CONT: + fmt = (fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_CONT; + break; + case SND_SOC_POSSIBLE_DAIFMT_GATED: + fmt = (fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_GATED; + break; + /* + * for clock invert + */ + case SND_SOC_POSSIBLE_DAIFMT_NB_NF: + fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_NF; + break; + case SND_SOC_POSSIBLE_DAIFMT_NB_IF: + fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_IF; + break; + case SND_SOC_POSSIBLE_DAIFMT_IB_NF: + fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_NF; + break; + case SND_SOC_POSSIBLE_DAIFMT_IB_IF: + fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_IF; + break; + } + } + + /* + * Some driver might have very complex limitation. + * In such case, user want to auto-select non-limitation part, + * and want to manually specify complex part. + * + * Or for example, if both CPU and Codec can be clock provider, + * but because of its quality, user want to specify it manually. + * + * Ignore already configured format if exist + */ + if (!(configured_fmt & SND_SOC_DAIFMT_FORMAT_MASK)) + mask |= SND_SOC_DAIFMT_FORMAT_MASK; + if (!(configured_fmt & SND_SOC_DAIFMT_CLOCK_MASK)) + mask |= SND_SOC_DAIFMT_CLOCK_MASK; + if (!(configured_fmt & SND_SOC_DAIFMT_INV_MASK)) + mask |= SND_SOC_DAIFMT_INV_MASK; + if (!(configured_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) + mask |= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; + + return configured_fmt | (fmt & mask); +} + +unsigned int snd_soc_dai_auto_select_format(const struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_dai_link *dai_link = rtd->dai_link; + u64 possible_fmt = 0; + + soc_dai_auto_select_format(~0, rtd, 0, &possible_fmt); + + return soc_dai_convert_possiblefmt_to_daifmt(possible_fmt, dai_link->dai_fmt); } /** diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d6192204e613..4ad126bd4f70 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -40,6 +40,8 @@ #include +static u32 pop_time; + /* DAPM context */ struct snd_soc_dapm_context { enum snd_soc_bias_level bias_level; @@ -161,14 +163,14 @@ static void dapm_assert_locked(struct snd_soc_dapm_context *dapm) snd_soc_dapm_mutex_assert_held(dapm); } -static void dapm_pop_wait(u32 pop_time) +static void dapm_pop_wait(void) { if (pop_time) schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); } -__printf(3, 4) -static void dapm_pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...) +__printf(2, 3) +static void dapm_pop_dbg(struct device *dev, const char *fmt, ...) { va_list args; char *buf; @@ -1872,8 +1874,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card, if (w->event && (w->event_flags & event)) { int ret; - dapm_pop_dbg(dev, card->pop_time, "pop test : %s %s\n", - w->name, ev_name); + dapm_pop_dbg(dev, "pop test : %s %s\n", w->name, ev_name); dapm_async_complete(w->dapm); trace_snd_soc_dapm_widget_event_start(w, event); ret = w->event(w, NULL, event); @@ -1909,7 +1910,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, else value |= w->off_val << w->shift; - dapm_pop_dbg(dev, card->pop_time, + dapm_pop_dbg(dev, "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", w->name, reg, value, mask); @@ -1923,10 +1924,10 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card, * same register. */ - dapm_pop_dbg(dev, card->pop_time, + dapm_pop_dbg(dev, "pop test : Applying 0x%x/0x%x to %x in %dms\n", - value, mask, reg, card->pop_time); - dapm_pop_wait(card->pop_time); + value, mask, reg, pop_time); + dapm_pop_wait(); dapm_update_bits(dapm, reg, mask, value); } @@ -2392,9 +2393,9 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event, return ret; } - dapm_pop_dbg(card->dev, card->pop_time, - "DAPM sequencing finished, waiting %dms\n", card->pop_time); - dapm_pop_wait(card->pop_time); + dapm_pop_dbg(card->dev, + "DAPM sequencing finished, waiting %dms\n", pop_time); + dapm_pop_wait(); trace_snd_soc_dapm_done(card, event); @@ -2561,6 +2562,11 @@ static const struct file_operations dapm_bias_fops = { .llseek = default_llseek, }; +void snd_soc_dapm_debugfs_pop_time(struct dentry *parent) +{ + debugfs_create_u32("dapm_pop_time", 0644, parent, &pop_time); +} + void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent) { @@ -2906,20 +2912,18 @@ static struct snd_soc_dapm_widget *dapm_find_widget( { struct snd_soc_dapm_widget *w; struct snd_soc_dapm_widget *fallback = NULL; - char prefixed_pin[80]; - const char *pin_name; - const char *prefix = dapm_prefix(dapm); - - if (prefix) { - snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s", - prefix, pin); - pin_name = prefixed_pin; - } else { - pin_name = pin; - } + bool pin_has_prefix = snd_soc_dapm_pin_has_prefix(dapm->card, pin); + bool match; for_each_card_widgets(dapm->card, w) { - if (!strcmp(w->name, pin_name)) { + match = false; + + if (!strcmp(pin, w->name)) + match = true; + else if (!pin_has_prefix && !snd_soc_dapm_widget_name_cmp(w, pin)) + match = true; + + if (match) { if (w->dapm == dapm) return w; else @@ -4606,6 +4610,36 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card) } } +int snd_soc_dapm_ignore_suspend_widgets(struct snd_soc_card *card) +{ + struct snd_soc_dapm_widget *w; + int i; + + for (i = 0; i < card->num_ignore_suspend_widgets; i++) { + w = dapm_find_widget(snd_soc_card_to_dapm(card), + card->ignore_suspend_widgets[i], true); + if (!w) { + dev_err(card->dev, "ASoC: DAPM unknown ignore suspend widget %s\n", + card->ignore_suspend_widgets[i]); + return -EINVAL; + } + w->ignore_suspend = 1; + } + + for (i = 0; i < card->num_of_ignore_suspend_widgets; i++) { + w = dapm_find_widget(snd_soc_card_to_dapm(card), + card->of_ignore_suspend_widgets[i], true); + if (!w) { + dev_err(card->dev, "ASoC: DAPM unknown ignore suspend widget %s\n", + card->of_ignore_suspend_widgets[i]); + return -EINVAL; + } + w->ignore_suspend = 1; + } + + return 0; +} + static void dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int event) { struct snd_soc_dai *dai; @@ -4872,6 +4906,33 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, } EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend); +/** + * snd_soc_dapm_pin_has_prefix - check if given pin has a known prefix + * @card: card to be checked + * @pin: pin name + * + * Returns true if given pin has a known prefix + */ +bool snd_soc_dapm_pin_has_prefix(struct snd_soc_card *card, const char *pin) +{ + struct snd_soc_component *component; + const char *prefix; + size_t prefix_len; + + for_each_card_components(card, component) { + prefix = component->name_prefix; + if (!prefix) + continue; + + prefix_len = strlen(prefix); + if (!strncmp(pin, prefix, prefix_len) && pin[prefix_len] == ' ') + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_pin_has_prefix); + /** * snd_soc_dapm_free - free dapm resources * @dapm: DAPM context diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index d33f83ec24f2..718165ba84ac 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c @@ -49,11 +49,6 @@ int devm_snd_soc_register_component(struct device *dev, } EXPORT_SYMBOL_GPL(devm_snd_soc_register_component); -static void devm_card_release(struct device *dev, void *res) -{ - snd_soc_unregister_card(*(struct snd_soc_card **)res); -} - /** * devm_snd_soc_register_card - resource managed card registration * @dev: Device used to manage card @@ -63,32 +58,11 @@ static void devm_card_release(struct device *dev, void *res) * unregistered. */ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) -{ - struct snd_soc_card **ptr; - int ret; - - ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return -ENOMEM; - - ret = snd_soc_register_card(card); - if (ret == 0) { - *ptr = card; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } - - return ret; -} -EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); - -int devm_snd_soc_register_deferrable_card(struct device *dev, struct snd_soc_card *card) { card->devres_dev = dev; return snd_soc_register_card(card); } -EXPORT_SYMBOL_GPL(devm_snd_soc_register_deferrable_card); +EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); #ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 6b8c65763c82..467426d2b5e4 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -334,6 +334,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component = { .pointer = dmaengine_pcm_pointer, .pcm_new = dmaengine_pcm_new, .sync_stop = dmaengine_pcm_sync_stop, + .debugfs_prefix = "dma", }; static const struct snd_soc_component_driver dmaengine_pcm_component_process = { @@ -347,6 +348,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component_process = { .copy = dmaengine_copy, .pcm_new = dmaengine_pcm_new, .sync_stop = dmaengine_pcm_sync_stop, + .debugfs_prefix = "dma", }; static const char * const dmaengine_pcm_dma_channel_names[] = { @@ -441,9 +443,6 @@ int snd_dmaengine_pcm_register(struct device *dev, if (!pcm) return -ENOMEM; -#ifdef CONFIG_DEBUG_FS - pcm->component.debugfs_prefix = "dma"; -#endif if (!config) config = &snd_dmaengine_pcm_default_config; pcm->config = config; diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index bbf277670718..c935571d43e9 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -461,6 +461,10 @@ int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max) mc->platform_max = max; ret = snd_soc_clip_to_platform_max(kctl); } + } else { + /* Some cards blindly add limits for multiple variants. */ + dev_dbg(card->dev, "Volume limit for unknown control '%s'\n", + name); } return ret; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 9b12eedb77c3..0e49290a8c90 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,9 @@ #include #include + +DEFINE_GUARD(snd_soc_card_mutex, struct snd_soc_card *, + snd_soc_card_mutex_lock(_T), snd_soc_card_mutex_unlock(_T)) #define soc_pcm_ret(rtd, ret) _soc_pcm_ret(rtd, __func__, ret) static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd, const char *func, int ret) @@ -467,6 +471,114 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, return 0; } +/* + * Shared BCLK constraint: when multiple DAIs share the same physical BCLK, + * constrain hw_params so that the BCLK rate (rate * channels * sample_bits, + * or rate * slots * slot_width for TDM) remains consistent. + */ + +static int soc_pcm_shared_bclk_rule_rate(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_soc_dai *dai = rule->private; + struct snd_soc_card *card = dai->component->card; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dai *other_dai; + unsigned long active_bclk_rate = 0; + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval constraint = { .empty = 1 }; + unsigned int target_rate; + int i; + + /* Protect the rtd list traversal with the ASoC card mutex helper. */ + guard(snd_soc_card_mutex)(card); + + /* Scan all DAIs on the card for an active peer sharing the same BCLK */ + for_each_card_rtds(card, rtd) { + for_each_rtd_cpu_dais(rtd, i, other_dai) { + if (other_dai == dai) + continue; + if (!other_dai->bclk) + continue; + if (!snd_soc_dai_active(other_dai)) + continue; + /* + * Skip peers whose hw_params hasn't run yet. + * symmetric_rate is set by soc_pcm_set_dai_params() + * after snd_soc_dai_hw_params(), so non-zero means + * the DAI's clk_set_rate() has already executed. + */ + if (!other_dai->symmetric_rate) + continue; + if (!clk_is_match(dai->bclk, other_dai->bclk)) + continue; + + active_bclk_rate = clk_get_rate(other_dai->bclk); + if (active_bclk_rate) + goto found; + } + } + + return 0; + +found: + if (dai->bclk_ratio) { + /* + * Driver has set an explicit BCLK ratio (e.g. for TDM where + * BCLK = rate * slots * slot_width). The only valid rate is + * active_bclk_rate / bclk_ratio. + */ + target_rate = active_bclk_rate / dai->bclk_ratio; + + constraint.min = target_rate; + constraint.max = target_rate; + } else { + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_interval *sample_bits = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS); + + /* + * Default: BCLK = rate * channels * sample_bits. + * Calculate the range of valid rates given the current + * channel and sample_bits intervals. + */ + if (!channels->min || !sample_bits->min) + return 0; + + constraint.max = active_bclk_rate / + ((unsigned long)channels->min * sample_bits->min); + + if (channels->max && sample_bits->max) + constraint.min = active_bclk_rate / + ((unsigned long)channels->max * sample_bits->max); + else + constraint.min = constraint.max; + } + + constraint.integer = 1; + constraint.empty = 0; + + return snd_interval_refine(rate, &constraint); +} + +static int soc_pcm_apply_shared_bclk(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + if (!dai->bclk) + return 0; + + dev_dbg(dai->dev, + "ASoC: registering shared BCLK rate constraint\n"); + + return snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + soc_pcm_shared_bclk_rule_rate, dai, + SNDRV_PCM_HW_PARAM_CHANNELS, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + -1); +} + static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -903,6 +1015,13 @@ static int __soc_pcm_open(struct snd_soc_pcm_runtime *rtd, if (ret != 0) goto err; } + + /* Shared BCLK constraint across DAIs on the same card */ + for_each_rtd_cpu_dais(rtd, i, dai) { + ret = soc_pcm_apply_shared_bclk(substream, dai); + if (ret != 0) + goto err; + } dynamic: snd_soc_runtime_activate(rtd, substream->stream); ret = 0; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 85679c8e0229..35cbe29d2275 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1326,9 +1326,24 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg) return ret; } +static int soc_tplg_check_name(const char *name) +{ + if (strnlen(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) == + SNDRV_CTL_ELEM_ID_NAME_MAXLEN) + return -EINVAL; + + return 0; +} + static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream, struct snd_soc_tplg_stream_caps *caps) { + int ret; + + ret = soc_tplg_check_name(caps->name); + if (ret) + return ret; + stream->stream_name = devm_kstrdup(tplg->dev, caps->name, GFP_KERNEL); if (!stream->stream_name) return -ENOMEM; @@ -1380,7 +1395,11 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, if (dai_drv == NULL) return -ENOMEM; - if (strlen(pcm->dai_name)) { + ret = soc_tplg_check_name(pcm->dai_name); + if (ret) + goto err; + + if (pcm->dai_name[0]) { dai_drv->name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); if (!dai_drv->name) { ret = -ENOMEM; @@ -1486,7 +1505,11 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, if (tplg->ops) link->dobj.unload = tplg->ops->link_unload; - if (strlen(pcm->pcm_name)) { + ret = soc_tplg_check_name(pcm->pcm_name); + if (ret) + goto err; + + if (pcm->pcm_name[0]) { link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); link->stream_name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL); if (!link->name || !link->stream_name) { @@ -1496,7 +1519,11 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg, } link->id = le32_to_cpu(pcm->pcm_id); - if (strlen(pcm->dai_name)) { + ret = soc_tplg_check_name(pcm->dai_name); + if (ret) + goto err; + + if (pcm->dai_name[0]) { link->cpus->dai_name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL); if (!link->cpus->dai_name) { ret = -ENOMEM; @@ -1848,6 +1875,10 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg, memset(&dai_component, 0, sizeof(dai_component)); + ret = soc_tplg_check_name(d->dai_name); + if (ret) + return ret; + dai_component.dai_name = d->dai_name; dai = snd_soc_find_dai(&dai_component); if (!dai) { diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 9cb7567e263e..87e9c86ca4f8 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -183,13 +183,6 @@ static const struct snd_soc_component_driver dummy_codec = { SNDRV_PCM_FMTBIT_U32_LE | \ SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE) -/* - * Select these from Sound Card Manually - * SND_SOC_POSSIBLE_DAIFMT_CBP_CFP - * SND_SOC_POSSIBLE_DAIFMT_CBP_CFC - * SND_SOC_POSSIBLE_DAIFMT_CBC_CFP - * SND_SOC_POSSIBLE_DAIFMT_CBC_CFC - */ static const u64 dummy_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S | SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index 0c3a92f5f942..df656cdc1527 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -149,7 +149,8 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev * break; } if (i == acp_data->info.count || !link->num_adr) - break; + if (!mach->machine_check || mach->machine_check(acp_data->sdw)) + break; } if (mach && mach->link_mask) { mach->mach_params.subsystem_rev = acp_data->pci_rev; diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index e31f4c4061d8..915abbef398d 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -266,10 +266,8 @@ config SND_SOC_SOF_METEORLAKE config SND_SOC_SOF_INTEL_LNL tristate - select SOUNDWIRE_INTEL if SND_SOC_SOF_INTEL_SOUNDWIRE != n select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE - select SND_SOF_SOF_HDA_SDW_BPT if SND_SOC_SOF_INTEL_SOUNDWIRE != n select SND_SOC_SOF_IPC4 select SND_SOC_SOF_INTEL_MTL @@ -329,8 +327,10 @@ config SND_SOC_SOF_HDA_GENERIC select SND_INTEL_DSP_CONFIG select SND_SOC_SOF_HDA_LINK_BASELINE select SND_SOC_SOF_HDA_PROBES - select SND_SOC_SDW_UTILS if SND_SOC_SOF_INTEL_SOUNDWIRE + select SND_SOC_SDW_UTILS if SND_SOC_SOF_INTEL_SOUNDWIRE !=n select SND_SOC_SOF_HDA_MLINK if SND_SOC_SOF_HDA_LINK + select SND_SOF_SOF_HDA_SDW_BPT if SND_SOC_SOF_INTEL_LNL != n && \ + SND_SOC_SOF_INTEL_SOUNDWIRE !=n help This option is not user-selectable but automagically handled by 'select' statements at a higher level. diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index ce603a2343de..92314e3b568a 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -988,24 +988,19 @@ struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus) } EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_get_hlink, "SND_SOC_SOF_HDA_MLINK"); -int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) +void hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable) { struct hdac_ext2_link *h2link; struct hdac_ext_link *hlink; h2link = find_ext2_link(bus, alt, elid); - if (!h2link) - return -ENODEV; - - if (!h2link->ofls) - return 0; + if (!h2link || !h2link->ofls) + return; hlink = &h2link->hext_link; scoped_guard(mutex, &h2link->eml_lock) hdaml_lctl_offload_enable(hlink->ml_addr + AZX_REG_ML_LCTL, enable); - - return 0; } EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, "SND_SOC_SOF_HDA_MLINK"); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 8662b422eb80..dc85903b8d46 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1159,7 +1159,6 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev, struct snd_soc_acpi_adr_device *adr_dev; const char *name_prefix = ""; int index = link->num_adr; - bool is_amp = true; /* Set it to false if the codec wiah any NON-AMP DAI type */ int ep_index = 0; int i, j; @@ -1216,7 +1215,6 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev, endpoints[ep_index].aggregated = 0; endpoints[ep_index].group_id = 0; endpoints[ep_index].group_position = 0; - is_amp = false; } ep_index++; } @@ -1230,16 +1228,6 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev, return NULL; } - /* - * codec_info_list[].is_amp is a codec-level override: for multi-function - * codecs we must treat the whole codec as an AMP when it is described as - * such in the codec info table, even if some endpoints were detected as - * non-AMP above. Callers/UCM rely on this to keep name_prefix and AMP - * indexing stable and backwards compatible. - */ - if (codec_info_list[i].is_amp) - is_amp = true; - adr_dev[index].adr = ((u64)sdw_device->id.class_id & 0xFF) | ((u64)sdw_device->id.part_id & 0xFFFF) << 8 | ((u64)sdw_device->id.mfg_id & 0xFFFF) << 24 | @@ -1247,7 +1235,7 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev, ((u64)(sdw_device->id.sdw_version & 0xF) << 44) | ((u64)(sdw_device->bus->link_id & 0xF) << 48); - if (!is_amp) { + if (!codec_info_list[i].is_amp) { /* For non-amp codecs, get name_prefix from codec_info_list[] */ adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s", name_prefix); goto done_name_prefix; diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index c01ea7e731aa..83703ebc6385 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -20,22 +20,12 @@ #include "lnl.h" #include -/* this helps allows the DSP to setup DMIC/SSP */ -static int hdac_bus_offload_dmic_ssp(struct hdac_bus *bus, bool enable) +/* Configure DSP offload for DMIC/SSP/UAOL */ +static void hdac_bus_set_dsp_offload(struct hdac_bus *bus, bool enable) { - int ret; - - ret = hdac_bus_eml_enable_offload(bus, true, - AZX_REG_ML_LEPTR_ID_INTEL_SSP, enable); - if (ret < 0) - return ret; - - ret = hdac_bus_eml_enable_offload(bus, true, - AZX_REG_ML_LEPTR_ID_INTEL_DMIC, enable); - if (ret < 0) - return ret; - - return 0; + hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_SSP, enable); + hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_DMIC, enable); + hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_UAOL, enable); } static int lnl_hda_dsp_probe(struct snd_sof_dev *sdev) @@ -46,18 +36,14 @@ static int lnl_hda_dsp_probe(struct snd_sof_dev *sdev) if (ret < 0) return ret; - return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true); + hdac_bus_set_dsp_offload(sof_to_bus(sdev), true); + + return 0; } static void lnl_hda_dsp_remove(struct snd_sof_dev *sdev) { - int ret; - - ret = hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), false); - if (ret < 0) - dev_warn(sdev->dev, - "Failed to disable offload for DMIC/SSP: %d\n", ret); - + hdac_bus_set_dsp_offload(sof_to_bus(sdev), false); hda_dsp_remove(sdev); } @@ -69,7 +55,9 @@ static int lnl_hda_dsp_resume(struct snd_sof_dev *sdev) if (ret < 0) return ret; - return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true); + hdac_bus_set_dsp_offload(sof_to_bus(sdev), true); + + return 0; } static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev) @@ -80,7 +68,9 @@ static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev) if (ret < 0) return ret; - return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true); + hdac_bus_set_dsp_offload(sof_to_bus(sdev), true); + + return 0; } static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 2b1befad6d5c..d1697401b1da 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -315,10 +315,13 @@ static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol, } /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ - if (data->size > scontrol->max_size - sizeof(*data)) { + if (data->size > scontrol->max_size - sizeof(*cdata) - + sizeof(*data)) { dev_err_ratelimited(scomp->dev, "%u bytes of control data is invalid, max is %zu\n", - data->size, scontrol->max_size - sizeof(*data)); + data->size, + scontrol->max_size - sizeof(*cdata) - + sizeof(*data)); return -EINVAL; } @@ -336,6 +339,8 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol, struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; struct snd_soc_component *scomp = scontrol->scomp; struct sof_abi_hdr *data = cdata->data; + const struct sof_abi_hdr *new_hdr = + (const struct sof_abi_hdr *)ucontrol->value.bytes.data; size_t size; if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { @@ -344,14 +349,18 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol, return -EINVAL; } - /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ - if (data->size > scontrol->max_size - sizeof(*data)) { - dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n", - data->size, scontrol->max_size - sizeof(*data)); + /* Validate the new data's size, not the old one */ + if (new_hdr->size > scontrol->max_size - sizeof(*cdata) - + sizeof(*new_hdr)) { + dev_err_ratelimited(scomp->dev, + "data size too big %u bytes max is %zu\n", + new_hdr->size, + scontrol->max_size - sizeof(*cdata) - + sizeof(*new_hdr)); return -EINVAL; } - size = data->size + sizeof(*data); + size = new_hdr->size + sizeof(*new_hdr); /* copy from kcontrol */ memcpy(data, ucontrol->value.bytes.data, size); @@ -389,9 +398,17 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, } /* be->max is coming from topology */ - if (header.length > scontrol->max_size) { - dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n", - header.length, scontrol->max_size); + if (header.length > scontrol->max_size - sizeof(*cdata)) { + dev_err_ratelimited(scomp->dev, "Bytes data size %u exceeds max %zu\n", + header.length, scontrol->max_size - sizeof(*cdata)); + return -EINVAL; + } + + /* Ensure the data is large enough to contain the ABI header */ + if (header.length < sizeof(struct sof_abi_hdr)) { + dev_err_ratelimited(scomp->dev, + "Bytes data size %u less than ABI header %zu\n", + header.length, sizeof(struct sof_abi_hdr)); return -EINVAL; } @@ -427,7 +444,7 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, } /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ - if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { + if (cdata->data->size > scontrol->max_size - sizeof(*cdata) - sizeof(struct sof_abi_hdr)) { dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n"); goto err_restore; } @@ -443,7 +460,7 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, err_restore: /* If we have an issue, we restore the old, valid bytes control data */ if (scontrol->old_ipc_control_data) { - memcpy(cdata->data, scontrol->old_ipc_control_data, scontrol->max_size); + memcpy(cdata, scontrol->old_ipc_control_data, scontrol->max_size); kfree(scontrol->old_ipc_control_data); scontrol->old_ipc_control_data = NULL; } @@ -482,10 +499,13 @@ static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, } /* check data size doesn't exceed max coming from topology */ - if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { - dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", + if (cdata->data->size > scontrol->max_size - sizeof(*cdata) - + sizeof(struct sof_abi_hdr)) { + dev_err_ratelimited(scomp->dev, + "User data size %u exceeds max size %zu\n", cdata->data->size, - scontrol->max_size - sizeof(struct sof_abi_hdr)); + scontrol->max_size - sizeof(*cdata) - + sizeof(struct sof_abi_hdr)); return -EINVAL; } @@ -535,6 +555,15 @@ static void snd_sof_update_control(struct snd_sof_control *scontrol, return; } + /* Verify the size fits within the allocation */ + if (cdata->num_elems > scontrol->max_size - sizeof(*local_cdata) - + sizeof(*local_cdata->data)) { + dev_err(scomp->dev, + "cdata binary size %u exceeds buffer\n", + cdata->num_elems); + return; + } + /* copy the new binary data */ memcpy(local_cdata->data, cdata->data, cdata->num_elems); } else if (cdata->num_elems != scontrol->num_channels) { @@ -626,16 +655,28 @@ static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_ return; } - expected_size = sizeof(struct sof_ipc_ctrl_data); switch (cdata->type) { case SOF_CTRL_TYPE_VALUE_CHAN_GET: case SOF_CTRL_TYPE_VALUE_CHAN_SET: - expected_size += cdata->num_elems * - sizeof(struct sof_ipc_ctrl_value_chan); + if (check_mul_overflow((size_t)cdata->num_elems, + sizeof(struct sof_ipc_ctrl_value_chan), + &expected_size)) + return; + if (check_add_overflow(expected_size, + sizeof(struct sof_ipc_ctrl_data), + &expected_size)) + return; break; case SOF_CTRL_TYPE_DATA_GET: case SOF_CTRL_TYPE_DATA_SET: - expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr); + if (check_add_overflow((size_t)cdata->num_elems, + sizeof(struct sof_abi_hdr), + &expected_size)) + return; + if (check_add_overflow(expected_size, + sizeof(struct sof_ipc_ctrl_data), + &expected_size)) + return; break; default: return; diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 8006777f2f64..4e066bbded91 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -519,6 +519,7 @@ static int sof_ipc3_widget_setup_comp_mixer(struct snd_sof_widget *swidget) static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) { struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_sof_pipeline *spipe = swidget->spipe; struct sof_ipc_pipe_new *pipeline; struct snd_sof_widget *comp_swidget; @@ -559,8 +560,15 @@ static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) if (ret < 0) goto err; - if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) + if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) { pipeline->core = SOF_DSP_PRIMARY_CORE; + } else if (pipeline->core > sdev->num_cores - 1) { + dev_info(scomp->dev, + "out of range core id for %s, moving it %d -> %d\n", + swidget->widget->name, pipeline->core, + SOF_DSP_PRIMARY_CORE); + pipeline->core = SOF_DSP_PRIMARY_CORE; + } if (sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_OVERRIDE)) swidget->dynamic_pipeline_widget = diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index 596c3d77a34e..8d86d32a16ca 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -13,13 +13,12 @@ #include "ipc4-topology.h" static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control *scontrol, + struct sof_ipc4_msg *msg, bool set, bool lock) { - struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); const struct sof_ipc_ops *iops = sdev->ipc->ops; - struct sof_ipc4_msg *msg = &cdata->msg; struct snd_sof_widget *swidget; bool widget_found = false; int ret = 0; @@ -88,9 +87,9 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge { struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; struct sof_ipc4_gain *gain = swidget->private; - struct sof_ipc4_msg *msg = &cdata->msg; struct sof_ipc4_gain_params params; bool all_channels_equal = true; + struct sof_ipc4_msg msg; u32 value; int ret, i; @@ -107,6 +106,7 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge * notify DSP with a single IPC message if all channel values are equal. Otherwise send * a separate IPC for each channel. */ + memcpy(&msg, &cdata->msg, sizeof(msg)); for (i = 0; i < scontrol->num_channels; i++) { if (all_channels_equal) { params.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK; @@ -121,12 +121,10 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge params.curve_duration_h = gain->data.params.curve_duration_h; params.curve_type = gain->data.params.curve_type; - msg->data_ptr = ¶ms; - msg->data_size = sizeof(params); + msg.data_ptr = ¶ms; + msg.data_size = sizeof(params); - ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock); - msg->data_ptr = NULL; - msg->data_size = 0; + ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, true, lock); if (ret < 0) { dev_err(sdev->dev, "Failed to set volume update for %s\n", scontrol->name); @@ -208,7 +206,7 @@ sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev, { struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; struct sof_ipc4_control_msg_payload *data; - struct sof_ipc4_msg *msg = &cdata->msg; + struct sof_ipc4_msg msg; size_t data_size; unsigned int i; int ret; @@ -225,12 +223,11 @@ sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev, data->chanv[i].value = cdata->chanv[i].value; } - msg->data_ptr = data; - msg->data_size = data_size; + memcpy(&msg, &cdata->msg, sizeof(msg)); + msg.data_ptr = data; + msg.data_size = data_size; - ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock); - msg->data_ptr = NULL; - msg->data_size = 0; + ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, true, lock); if (ret < 0) dev_err(sdev->dev, "Failed to set control update for %s\n", scontrol->name); @@ -245,7 +242,7 @@ static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol) struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc4_control_msg_payload *data; - struct sof_ipc4_msg *msg = &cdata->msg; + struct sof_ipc4_msg msg; size_t data_size; unsigned int i; int ret; @@ -263,13 +260,13 @@ static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol) data->id = cdata->index; data->num_elems = scontrol->num_channels; - msg->data_ptr = data; - msg->data_size = data_size; + + memcpy(&msg, &cdata->msg, sizeof(msg)); + msg.data_ptr = data; + msg.data_size = data_size; scontrol->comp_data_dirty = false; - ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, true); - msg->data_ptr = NULL; - msg->data_size = 0; + ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, false, true); if (!ret) { for (i = 0; i < scontrol->num_channels; i++) { cdata->chanv[i].channel = data->chanv[i].channel; @@ -291,7 +288,7 @@ sof_ipc4_set_bytes_control_data(struct snd_sof_control *scontrol, bool lock) struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc4_control_msg_payload *msg_data; struct sof_abi_hdr *data = cdata->data; - struct sof_ipc4_msg *msg = &cdata->msg; + struct sof_ipc4_msg msg; size_t data_size; int ret; @@ -304,14 +301,13 @@ sof_ipc4_set_bytes_control_data(struct snd_sof_control *scontrol, bool lock) msg_data->num_elems = data->size; memcpy(msg_data->data, data->data, data->size); - msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); + memcpy(&msg, &cdata->msg, sizeof(msg)); + msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); - msg->data_ptr = msg_data; - msg->data_size = data_size; + msg.data_ptr = msg_data; + msg.data_size = data_size; - ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock); - msg->data_ptr = NULL; - msg->data_size = 0; + ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, true, lock); if (ret < 0) dev_err(scomp->dev, "%s: Failed to set control update for %s\n", __func__, scontrol->name); @@ -328,7 +324,7 @@ sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock) struct snd_soc_component *scomp = scontrol->scomp; struct sof_ipc4_control_msg_payload *msg_data; struct sof_abi_hdr *data = cdata->data; - struct sof_ipc4_msg *msg = &cdata->msg; + struct sof_ipc4_msg msg; size_t data_size; int ret = 0; @@ -346,29 +342,30 @@ sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock) if (!msg_data) return -ENOMEM; - msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); + memcpy(&msg, &cdata->msg, sizeof(msg)); + msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); msg_data->id = cdata->index; msg_data->num_elems = 0; /* ignored for bytes */ - msg->data_ptr = msg_data; - msg->data_size = data_size; + msg.data_ptr = msg_data; + msg.data_size = data_size; scontrol->comp_data_dirty = false; - ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, lock); + ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, false, lock); if (!ret) { - if (msg->data_size > scontrol->max_size - sizeof(*data)) { + if (msg.data_size > scontrol->max_size - sizeof(*data)) { dev_err(scomp->dev, "%s: no space for data in %s (%zu, %zu)\n", - __func__, scontrol->name, msg->data_size, + __func__, scontrol->name, msg.data_size, scontrol->max_size - sizeof(*data)); ret = -EINVAL; goto out; } - data->size = msg->data_size; + data->size = msg.data_size; scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size; - memcpy(data->data, msg->data_ptr, data->size); + memcpy(data->data, msg.data_ptr, data->size); } else { dev_err(scomp->dev, "Failed to read control data for %s\n", scontrol->name); @@ -376,9 +373,6 @@ sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock) } out: - msg->data_ptr = NULL; - msg->data_size = 0; - kfree(msg_data); return ret; @@ -508,7 +502,7 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, { struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; struct sof_abi_hdr *data = cdata->data; - struct sof_ipc4_msg *msg = &cdata->msg; + struct sof_ipc4_msg msg; int ret = 0; /* Send the new data to the firmware only if it is powered up */ @@ -530,28 +524,26 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev, return sof_ipc4_refresh_bytes_control(scontrol, lock); } - msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); + memcpy(&msg, &cdata->msg, sizeof(msg)); + msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); - msg->data_ptr = data->data; + msg.data_ptr = data->data; if (set) - msg->data_size = data->size; + msg.data_size = data->size; else - msg->data_size = scontrol->max_size - sizeof(*data); + msg.data_size = scontrol->max_size - sizeof(*data); - ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock); + ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, set, lock); if (ret < 0) { dev_err(sdev->dev, "Failed to %s for %s\n", set ? "set bytes update" : "get bytes", scontrol->name); } else if (!set) { /* Update the sizes according to the received payload data */ - data->size = msg->data_size; + data->size = msg.data_size; scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size; } - msg->data_ptr = NULL; - msg->data_size = 0; - return ret; } @@ -562,6 +554,8 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol, struct snd_soc_component *scomp = scontrol->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_abi_hdr *data = cdata->data; + const struct sof_abi_hdr *new_hdr = + (const struct sof_abi_hdr *)ucontrol->value.bytes.data; size_t size; int ret; @@ -572,15 +566,16 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol, return -EINVAL; } - /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ - if (data->size > scontrol->max_size - sizeof(*data)) { + /* Validate the new data's size, not the old one */ + if (new_hdr->size > scontrol->max_size - sizeof(*new_hdr)) { dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n", - data->size, scontrol->max_size - sizeof(*data)); + new_hdr->size, + scontrol->max_size - sizeof(*new_hdr)); return -EINVAL; } - size = data->size + sizeof(*data); + size = new_hdr->size + sizeof(*new_hdr); /* copy from kcontrol */ memcpy(data, ucontrol->value.bytes.data, size); @@ -880,6 +875,16 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message) */ if (type == SND_SOC_TPLG_TYPE_BYTES) { struct sof_abi_hdr *data = cdata->data; + size_t source_size = struct_size(msg_data, data, msg_data->num_elems); + + if (source_size > ndata->event_data_size) { + dev_warn(sdev->dev, + "%s: invalid bytes notification size for %s (%zu, %u)\n", + __func__, scontrol->name, source_size, + ndata->event_data_size); + scontrol->comp_data_dirty = true; + goto notify; + } if (msg_data->num_elems > scontrol->max_size - sizeof(*data)) { dev_warn(sdev->dev, @@ -892,6 +897,17 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message) scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size; } } else { + size_t source_size = struct_size(msg_data, chanv, msg_data->num_elems); + + if (source_size > ndata->event_data_size) { + dev_warn(sdev->dev, + "%s: invalid channel notification size for %s (%zu, %u)\n", + __func__, scontrol->name, source_size, + ndata->event_data_size); + scontrol->comp_data_dirty = true; + goto notify; + } + for (i = 0; i < msg_data->num_elems; i++) { u32 channel = msg_data->chanv[i].channel; @@ -919,6 +935,8 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message) scontrol->comp_data_dirty = true; } +notify: + /* * Look up the ALSA kcontrol of the scontrol to be able to send a * notification to user space diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 76812d8fb567..95ad5266b0c6 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -238,6 +238,23 @@ struct snd_sof_widget *sof_ipc4_find_swidget_by_ids(struct snd_sof_dev *sdev, return NULL; } +static u32 sof_ipc4_fmt_cfg_to_type(u32 fmt_cfg) +{ + /* Fetch the sample type from the fmt for 8 and 32 bit formats */ + u32 __bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt_cfg); + + if (__bits == 8 || __bits == 32) + return SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt_cfg); + + /* + * Return LSB integer type for 16, 20 and 24 formats as the firmware is + * handling the LSB/MSB alignment internally, for the kernel this + * should not be taken into account, we treat them as LSB to match with + * the format we support on the PCM side. + */ + return SOF_IPC4_TYPE_LSB_INTEGER; +} + static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_format *pin_fmt, int num_formats) { @@ -246,8 +263,9 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo for (i = 0; i < num_formats; i++) { struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt; dev_dbg(dev, - "Pin #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", + "Pin #%d: %uHz, %ubit (type: %u), %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n", pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth, + sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg), SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg), fmt->ch_map, fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg, pin_fmt[i].buffer_size); @@ -624,6 +642,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) struct sof_ipc4_available_audio_format *available_fmt; struct snd_soc_component *scomp = swidget->scomp; struct sof_ipc4_copier *ipc4_copier; + struct snd_sof_pcm_stream *sps; struct snd_sof_pcm *spcm; int node_type = 0; int ret, dir; @@ -668,24 +687,23 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (ret) goto free_available_fmt; - if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - struct snd_sof_pcm_stream *sps = &spcm->stream[dir]; + sps = &spcm->stream[dir]; + sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms, + SOF_COPIER_DEEP_BUFFER_TOKENS, + swidget->tuples, + swidget->num_tuples, sizeof(u32), 1); - sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms, - SOF_COPIER_DEEP_BUFFER_TOKENS, - swidget->tuples, - swidget->num_tuples, sizeof(u32), 1); - /* Set default DMA buffer size if it is not specified in topology */ - if (!sps->dsp_max_burst_size_in_ms) { - struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; - struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + /* Set default DMA buffer size if it is not specified in topology */ + if (!sps->dsp_max_burst_size_in_ms) { + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + if (dir == SNDRV_PCM_STREAM_PLAYBACK) sps->dsp_max_burst_size_in_ms = pipeline->use_chain_dma ? SOF_IPC4_CHAIN_DMA_BUFFER_SIZE : SOF_IPC4_MIN_DMA_BUFFER_SIZE; - } - } else { - /* Capture data is copied from DSP to host in 1ms bursts */ - spcm->stream[dir].dsp_max_burst_size_in_ms = 1; + else + /* Capture data is copied from DSP to host in 1ms bursts */ + sps->dsp_max_burst_size_in_ms = 1; } skip_gtw_cfg: @@ -927,6 +945,7 @@ static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget) static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) { struct snd_soc_component *scomp = swidget->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_pipeline *pipeline; struct snd_sof_pipeline *spipe = swidget->spipe; int ret; @@ -942,6 +961,16 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget) goto err; } + if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) { + pipeline->core_id = SOF_DSP_PRIMARY_CORE; + } else if (pipeline->core_id > sdev->num_cores - 1) { + dev_info(scomp->dev, + "out of range core id for %s, moving it %d -> %d\n", + swidget->widget->name, pipeline->core_id, + SOF_DSP_PRIMARY_CORE); + pipeline->core_id = SOF_DSP_PRIMARY_CORE; + } + swidget->core = pipeline->core_id; spipe->core_mask |= BIT(pipeline->core_id); if (pipeline->direction_valid) { @@ -1092,6 +1121,15 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget) if (ret) goto err; + if (!src->available_fmt.num_input_formats || + !src->available_fmt.num_output_formats) { + dev_err(scomp->dev, + "Invalid number of formats: input: %d, output: %d\n", + src->available_fmt.num_input_formats, + src->available_fmt.num_output_formats); + goto err; + } + ret = sof_update_ipc_object(scomp, &src->data, SOF_SRC_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*src), 1); if (ret) { @@ -1135,6 +1173,15 @@ static int sof_ipc4_widget_setup_comp_asrc(struct snd_sof_widget *swidget) if (ret) goto err; + if (!asrc->available_fmt.num_input_formats || + !asrc->available_fmt.num_output_formats) { + dev_err(scomp->dev, + "Invalid number of formats: input: %d, output: %d\n", + asrc->available_fmt.num_input_formats, + asrc->available_fmt.num_output_formats); + goto err; + } + ret = sof_update_ipc_object(scomp, &asrc->data, SOF_ASRC_TOKENS, swidget->tuples, swidget->num_tuples, sizeof(*asrc), 1); if (ret) { @@ -1353,23 +1400,6 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev, return 0; } -static u32 sof_ipc4_fmt_cfg_to_type(u32 fmt_cfg) -{ - /* Fetch the sample type from the fmt for 8 and 32 bit formats */ - u32 __bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt_cfg); - - if (__bits == 8 || __bits == 32) - return SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt_cfg); - - /* - * Return LSB integer type for 20 and 24 formats as the firmware is - * handling the LSB/MSB alignment internally, for the kernel this - * should not be taken into account, we treat them as LSB to match with - * the format we support on the PCM side. - */ - return SOF_IPC4_TYPE_LSB_INTEGER; -} - /* update hw_params based on the audio stream format */ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params, struct sof_ipc4_audio_format *fmt, u32 param_to_update) @@ -2430,10 +2460,19 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, copier_data->gtw_cfg.dma_buffer_size); break; case snd_soc_dapm_dai_out: - case snd_soc_dapm_aif_out: copier_data->gtw_cfg.dma_buffer_size = SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.obs; break; + case snd_soc_dapm_aif_out: + copier_data->gtw_cfg.dma_buffer_size = + max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms) * + copier_data->base_config.obs; + dev_dbg(sdev->dev, "copier %s, dma buffer%s: %u ms (%u bytes)", + swidget->widget->name, + deep_buffer_dma_ms ? " (using Deep Buffer)" : "", + max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms), + copier_data->gtw_cfg.dma_buffer_size); + break; default: break; } @@ -2610,16 +2649,6 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, if (input_fmt_index < 0) return input_fmt_index; - /* - * For playback, the SRC sink rate will be configured based on the requested output - * format, which is restricted to only deal with DAI's with a single format for now. - */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK && available_fmt->num_output_formats > 1) { - dev_err(sdev->dev, "Invalid number of output formats: %d for SRC %s\n", - available_fmt->num_output_formats, swidget->widget->name); - return -EINVAL; - } - /* * SRC does not perform format conversion, so the output channels and valid bit depth must * be the same as that of the input. @@ -2629,12 +2658,36 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg); out_ref_type = sof_ipc4_fmt_cfg_to_type(in_audio_fmt->fmt_cfg); - /* - * For capture, the SRC module should convert the rate to match the rate requested by the - * PCM hw_params. Set the reference params based on the fe_params unconditionally as it - * will be ignored for playback anyway. - */ - out_ref_rate = params_rate(fe_params); + if (src->data.sink_rate) { + /* Use the sink rate as reference */ + out_ref_rate = src->data.sink_rate; + } else if (dir == SNDRV_PCM_STREAM_CAPTURE) { + /* + * Use the fe rate as reference for capture if the sink rate is + * not set since we need to convert to the rate the PCM device + * is openned with + */ + out_ref_rate = params_rate(fe_params); + } else { + /* + * Otherwise try to guess what the rate should be: + * The output formats must have single rate specified if the + * sink rate is not set for an SRC in playback path. + */ + int i; + + out_audio_fmt = &available_fmt->output_pin_fmts[0].audio_fmt; + out_ref_rate = out_audio_fmt->sampling_frequency; + for (i = 1; i < available_fmt->num_output_formats; i++) { + out_audio_fmt = &available_fmt->output_pin_fmts[i].audio_fmt; + if (out_ref_rate != out_audio_fmt->sampling_frequency) { + dev_err(sdev->dev, + "Cannot determine the output rate for SRC: %s\n", + swidget->widget->name); + return -EINVAL; + } + } + } output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget, &src->data.base_config, diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index c0c906a78eba..11a95dba3c9c 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -15,7 +15,6 @@ static struct snd_soc_card sof_nocodec_card = { .name = "nocodec", /* the sof- prefix is added by the core */ - .topology_shortname = "sof-nocodec", .owner = THIS_MODULE }; @@ -89,9 +88,10 @@ static int sof_nocodec_probe(struct platform_device *pdev) int ret; card->dev = &pdev->dev; - card->topology_shortname_created = true; mach = pdev->dev.platform_data; + snd_soc_card_set_topology_name(card, "sof"); + ret = sof_nocodec_setup(card->dev, mach->mach_params.num_dai_drivers, mach->mach_params.dai_drivers); if (ret < 0) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 63d582c65891..42a2d90bb705 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -23,6 +23,13 @@ static bool disable_function_topology; module_param(disable_function_topology, bool, 0444); MODULE_PARM_DESC(disable_function_topology, "Disable function topology loading"); +#define MAX_FEATURE_TPLG_COUNT 16 + +static char *feature_topologies[MAX_FEATURE_TPLG_COUNT]; +static int feature_tplg_cnt; +module_param_array(feature_topologies, charp, &feature_tplg_cnt, 0444); +MODULE_PARM_DESC(feature_topologies, "Topology list for virtual loop DAI link"); + #define COMP_ID_UNASSIGNED 0xffffffff /* * Constants used in the computation of linear volume gain @@ -733,10 +740,13 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp, int ret; while (array_size > 0 && total < count * token_instance_num) { + if (array_size < (int)sizeof(*array)) + return -EINVAL; + asize = le32_to_cpu(array->size); /* validate asize */ - if (asize < sizeof(*array)) { + if (asize < (int)sizeof(*array)) { dev_err(scomp->dev, "error: invalid array size 0x%x\n", asize); return -EINVAL; @@ -1567,8 +1577,15 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, int core = sof_get_token_value(SOF_TKN_COMP_CORE_ID, swidget->tuples, swidget->num_tuples); - if (core >= 0) + if (core >= 0) { + if (core > sdev->num_cores - 1) { + dev_info(scomp->dev, + "out of range core id for %s, moving it %d -> %d\n", + swidget->widget->name, core, SOF_DSP_PRIMARY_CORE); + core = SOF_DSP_PRIMARY_CORE; + } swidget->core = core; + } } /* bind widget to external event */ @@ -2534,6 +2551,8 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) if (strstr(file, "dummy")) { dev_err(scomp->dev, "Function topology is required, please upgrade sof-firmware\n"); + + kfree(tplg_files); return -EINVAL; } tplg_files[0] = file; @@ -2575,6 +2594,54 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) } } + /* Loading user defined topologies */ + for (i = 0; i < feature_tplg_cnt; i++) { + const char *feature_topology = devm_kasprintf(scomp->dev, GFP_KERNEL, "%s/%s", + tplg_filename_prefix, + feature_topologies[i]); + + if (!feature_topology) { + ret = -ENOMEM; + goto out; + } + dev_info(scomp->dev, "loading feature topology %d: %s\n", i, feature_topology); + ret = request_firmware(&fw, feature_topology, scomp->dev); + if (ret < 0) { + /* + * snd_soc_tplg_component_remove(scomp) will be called + * if snd_soc_tplg_component_load(scomp) failed and all + * objects in the scomp will be removed. No need to call + * snd_soc_tplg_component_remove(scomp) here. + */ + dev_warn(scomp->dev, "feature tplg request firmware %s failed err: %d\n", + feature_topologies[i], ret); + /* + * We don't return error here because we can still have the basic + * audio feature when the function topology load complete. No need + * to convert the error code because we will get new 'ret' out of the + * loop. + */ + continue; + } + + if (sdev->dspless_mode_selected) + ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw); + else + ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw); + + release_firmware(fw); + + if (ret < 0) { + dev_err(scomp->dev, "feature tplg %s component load failed %d\n", + feature_topologies[i], ret); + /* + * We need to return error here because it may lead to kernel NULL pointer + * dereference if we continue the remaining tasks. + */ + goto out; + } + } + /* call sof_complete when topologies are loaded successfully */ ret = sof_complete(scomp); diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c index 5420ca2aefbd..8871fc15b29c 100644 --- a/sound/soc/spacemit/k1_i2s.c +++ b/sound/soc/spacemit/k1_i2s.c @@ -53,6 +53,9 @@ struct spacemit_i2s_dev { struct clk *sysclk; struct clk *bclk; struct clk *sspa_clk; + struct clk *sysclk_div; + struct clk *c_sysclk; + struct clk *c_bclk; struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; @@ -206,6 +209,14 @@ static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream, params_rate(params) * data_bits; + ret = clk_set_rate(i2s->c_sysclk, bclk_rate * 2); + if (ret) + return ret; + + ret = clk_set_rate(i2s->c_bclk, bclk_rate); + if (ret) + return ret; + ret = clk_set_rate(i2s->bclk, bclk_rate); if (ret) return ret; @@ -217,10 +228,17 @@ static int spacemit_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev); + int ret; if (freq == 0) return 0; + if (i2s->sysclk_div) { + ret = clk_set_rate(i2s->sysclk_div, freq); + if (ret) + return ret; + } + return clk_set_rate(i2s->sysclk, freq); } @@ -436,6 +454,21 @@ static int spacemit_i2s_probe(struct platform_device *pdev) return dev_err_probe(i2s->dev, PTR_ERR(i2s->sspa_clk), "failed to enable sspa clock\n"); + i2s->sysclk_div = devm_clk_get_optional_enabled(i2s->dev, "sysclk_div"); + if (IS_ERR(i2s->sysclk_div)) + return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk_div), + "failed to enable sysclk_div clock\n"); + + i2s->c_sysclk = devm_clk_get_optional_enabled(i2s->dev, "c_sysclk"); + if (IS_ERR(i2s->c_sysclk)) + return dev_err_probe(i2s->dev, PTR_ERR(i2s->c_sysclk), + "failed to enable c_sysclk clock\n"); + + i2s->c_bclk = devm_clk_get_optional_enabled(i2s->dev, "c_bclk"); + if (IS_ERR(i2s->c_bclk)) + return dev_err_probe(i2s->dev, PTR_ERR(i2s->c_bclk), + "failed to enable c_bclk clock\n"); + i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(i2s->base)) return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n"); @@ -462,6 +495,7 @@ static int spacemit_i2s_probe(struct platform_device *pdev) static const struct of_device_id spacemit_i2s_of_match[] = { { .compatible = "spacemit,k1-i2s", }, + { .compatible = "spacemit,k3-i2s", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, spacemit_i2s_of_match); @@ -476,4 +510,4 @@ static struct platform_driver spacemit_i2s_driver = { module_platform_driver(spacemit_i2s_driver); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1 SoC"); +MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1/K3 SoC"); diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c index 814a1cde1d35..5f3a2a7bce31 100644 --- a/sound/soc/sprd/sprd-mcdt.c +++ b/sound/soc/sprd/sprd-mcdt.c @@ -524,7 +524,7 @@ static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id) struct sprd_mcdt_dev *mcdt = (struct sprd_mcdt_dev *)dev_id; int i; - spin_lock(&mcdt->lock); + guard(spinlock)(&mcdt->lock); for (i = 0; i < MCDT_ADC_CHANNEL_NUM; i++) { if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_ADC_FIFO_AF_INT)) { @@ -547,8 +547,6 @@ static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id) } } - spin_unlock(&mcdt->lock); - return IRQ_HANDLED; } @@ -569,22 +567,19 @@ static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id) int sprd_mcdt_chan_write(struct sprd_mcdt_chan *chan, char *tx_buf, u32 size) { struct sprd_mcdt_dev *mcdt = chan->mcdt; - unsigned long flags; int avail, i = 0, words = size / 4; u32 *buf = (u32 *)tx_buf; - spin_lock_irqsave(&mcdt->lock, flags); + guard(spinlock_irqsave)(&mcdt->lock); if (chan->dma_enable) { dev_err(mcdt->dev, "Can not write data when DMA mode enabled\n"); - spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL; } if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_DAC_FIFO_REAL_FULL)) { dev_err(mcdt->dev, "Channel fifo is full now\n"); - spin_unlock_irqrestore(&mcdt->lock, flags); return -EBUSY; } @@ -592,14 +587,12 @@ int sprd_mcdt_chan_write(struct sprd_mcdt_chan *chan, char *tx_buf, u32 size) if (size > avail) { dev_err(mcdt->dev, "Data size is larger than the available fifo size\n"); - spin_unlock_irqrestore(&mcdt->lock, flags); return -EBUSY; } while (i++ < words) sprd_mcdt_dac_write_fifo(mcdt, chan->id, *buf++); - spin_unlock_irqrestore(&mcdt->lock, flags); return 0; } EXPORT_SYMBOL_GPL(sprd_mcdt_chan_write); @@ -620,21 +613,18 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_write); int sprd_mcdt_chan_read(struct sprd_mcdt_chan *chan, char *rx_buf, u32 size) { struct sprd_mcdt_dev *mcdt = chan->mcdt; - unsigned long flags; int i = 0, avail, words = size / 4; u32 *buf = (u32 *)rx_buf; - spin_lock_irqsave(&mcdt->lock, flags); + guard(spinlock_irqsave)(&mcdt->lock); if (chan->dma_enable) { dev_err(mcdt->dev, "Can not read data when DMA mode enabled\n"); - spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL; } if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_ADC_FIFO_REAL_EMPTY)) { dev_err(mcdt->dev, "Channel fifo is empty\n"); - spin_unlock_irqrestore(&mcdt->lock, flags); return -EBUSY; } @@ -645,7 +635,6 @@ int sprd_mcdt_chan_read(struct sprd_mcdt_chan *chan, char *rx_buf, u32 size) while (i++ < words) sprd_mcdt_adc_read_fifo(mcdt, chan->id, buf++); - spin_unlock_irqrestore(&mcdt->lock, flags); return words * 4; } EXPORT_SYMBOL_GPL(sprd_mcdt_chan_read); @@ -672,14 +661,12 @@ int sprd_mcdt_chan_int_enable(struct sprd_mcdt_chan *chan, u32 water_mark, struct sprd_mcdt_chan_callback *cb) { struct sprd_mcdt_dev *mcdt = chan->mcdt; - unsigned long flags; int ret = 0; - spin_lock_irqsave(&mcdt->lock, flags); + guard(spinlock_irqsave)(&mcdt->lock); if (chan->dma_enable || chan->int_enable) { dev_err(mcdt->dev, "Failed to set interrupt mode.\n"); - spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL; } @@ -712,8 +699,6 @@ int sprd_mcdt_chan_int_enable(struct sprd_mcdt_chan *chan, u32 water_mark, chan->int_enable = true; } - spin_unlock_irqrestore(&mcdt->lock, flags); - return ret; } EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_enable); @@ -725,14 +710,12 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_enable); void sprd_mcdt_chan_int_disable(struct sprd_mcdt_chan *chan) { struct sprd_mcdt_dev *mcdt = chan->mcdt; - unsigned long flags; - spin_lock_irqsave(&mcdt->lock, flags); + guard(spinlock_irqsave)(&mcdt->lock); - if (!chan->int_enable) { - spin_unlock_irqrestore(&mcdt->lock, flags); + if (!chan->int_enable) return; - } + switch (chan->type) { case SPRD_MCDT_ADC_CHAN: @@ -754,7 +737,6 @@ void sprd_mcdt_chan_int_disable(struct sprd_mcdt_chan *chan) } chan->int_enable = false; - spin_unlock_irqrestore(&mcdt->lock, flags); } EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_disable); @@ -775,15 +757,13 @@ int sprd_mcdt_chan_dma_enable(struct sprd_mcdt_chan *chan, u32 water_mark) { struct sprd_mcdt_dev *mcdt = chan->mcdt; - unsigned long flags; int ret = 0; - spin_lock_irqsave(&mcdt->lock, flags); + guard(spinlock_irqsave)(&mcdt->lock); if (chan->dma_enable || chan->int_enable || dma_chan > SPRD_MCDT_DMA_CH4) { dev_err(mcdt->dev, "Failed to set DMA mode\n"); - spin_unlock_irqrestore(&mcdt->lock, flags); return -EINVAL; } @@ -814,8 +794,6 @@ int sprd_mcdt_chan_dma_enable(struct sprd_mcdt_chan *chan, if (!ret) chan->dma_enable = true; - spin_unlock_irqrestore(&mcdt->lock, flags); - return ret; } EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_enable); @@ -827,14 +805,11 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_enable); void sprd_mcdt_chan_dma_disable(struct sprd_mcdt_chan *chan) { struct sprd_mcdt_dev *mcdt = chan->mcdt; - unsigned long flags; - spin_lock_irqsave(&mcdt->lock, flags); + guard(spinlock_irqsave)(&mcdt->lock); - if (!chan->dma_enable) { - spin_unlock_irqrestore(&mcdt->lock, flags); + if (!chan->dma_enable) return; - } switch (chan->type) { case SPRD_MCDT_ADC_CHAN: @@ -852,7 +827,6 @@ void sprd_mcdt_chan_dma_disable(struct sprd_mcdt_chan *chan) } chan->dma_enable = false; - spin_unlock_irqrestore(&mcdt->lock, flags); } EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable); @@ -868,7 +842,7 @@ struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, { struct sprd_mcdt_chan *temp; - mutex_lock(&sprd_mcdt_list_mutex); + guard(mutex)(&sprd_mcdt_list_mutex); list_for_each_entry(temp, &sprd_mcdt_chan_list, list) { if (temp->type == type && temp->id == channel) { @@ -880,8 +854,6 @@ struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel, if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list)) temp = NULL; - mutex_unlock(&sprd_mcdt_list_mutex); - return temp; } EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan); @@ -897,17 +869,14 @@ void sprd_mcdt_free_chan(struct sprd_mcdt_chan *chan) sprd_mcdt_chan_dma_disable(chan); sprd_mcdt_chan_int_disable(chan); - mutex_lock(&sprd_mcdt_list_mutex); + guard(mutex)(&sprd_mcdt_list_mutex); list_for_each_entry(temp, &sprd_mcdt_chan_list, list) { - if (temp == chan) { - mutex_unlock(&sprd_mcdt_list_mutex); + if (temp == chan) return; - } } list_add_tail(&chan->list, &sprd_mcdt_chan_list); - mutex_unlock(&sprd_mcdt_list_mutex); } EXPORT_SYMBOL_GPL(sprd_mcdt_free_chan); @@ -933,9 +902,8 @@ static void sprd_mcdt_init_chans(struct sprd_mcdt_dev *mcdt, chan->mcdt = mcdt; INIT_LIST_HEAD(&chan->list); - mutex_lock(&sprd_mcdt_list_mutex); - list_add_tail(&chan->list, &sprd_mcdt_chan_list); - mutex_unlock(&sprd_mcdt_list_mutex); + scoped_guard(mutex, &sprd_mcdt_list_mutex) + list_add_tail(&chan->list, &sprd_mcdt_chan_list); } } @@ -977,12 +945,10 @@ static void sprd_mcdt_remove(struct platform_device *pdev) { struct sprd_mcdt_chan *chan, *temp; - mutex_lock(&sprd_mcdt_list_mutex); + guard(mutex)(&sprd_mcdt_list_mutex); list_for_each_entry_safe(chan, temp, &sprd_mcdt_chan_list, list) list_del(&chan->list); - - mutex_unlock(&sprd_mcdt_list_mutex); } static const struct of_device_id sprd_mcdt_of_match[] = { diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c index 45d35b887e4e..e4b9799ad9b2 100644 --- a/sound/soc/sti/uniperif_player.c +++ b/sound/soc/sti/uniperif_player.c @@ -65,13 +65,15 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) unsigned int status; unsigned int tmp; - spin_lock(&player->irq_lock); + guard(spinlock)(&player->irq_lock); if (!player->substream) - goto irq_spin_unlock; + return ret; snd_pcm_stream_lock(player->substream); - if (player->state == UNIPERIF_STATE_STOPPED) - goto stream_unlock; + if (player->state == UNIPERIF_STATE_STOPPED) { + snd_pcm_stream_unlock(player->substream); + return ret; + } /* Get interrupt status & clear them immediately */ status = GET_UNIPERIF_ITS(player); @@ -116,7 +118,8 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) dev_err(player->dev, "unexpected Underflow recovering\n"); ret = -EPERM; - goto stream_unlock; + snd_pcm_stream_unlock(player->substream); + return ret; } /* Read the underflow recovery duration */ tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player); @@ -143,10 +146,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id) ret = IRQ_HANDLED; } -stream_unlock: snd_pcm_stream_unlock(player->substream); -irq_spin_unlock: - spin_unlock(&player->irq_lock); return ret; } @@ -363,10 +363,10 @@ static int uni_player_prepare_iec958(struct uniperif *player, SET_UNIPERIF_CTRL_ZERO_STUFF_HW(player); - mutex_lock(&player->ctrl_lock); /* Update the channel status */ - uni_player_set_channel_status(player, runtime); - mutex_unlock(&player->ctrl_lock); + scoped_guard(mutex, &player->ctrl_lock) + uni_player_set_channel_status(player, runtime); + /* Clear the user validity user bits */ SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(player, 0); @@ -546,11 +546,11 @@ static int uni_player_prepare_tdm(struct uniperif *player, /* set unip clk rate (not done vai set_sysclk ops) */ freq = runtime->rate * tdm_frame_size * 8; - mutex_lock(&player->ctrl_lock); - ret = uni_player_clk_set_rate(player, freq); - if (!ret) - player->mclk = freq; - mutex_unlock(&player->ctrl_lock); + scoped_guard(mutex, &player->ctrl_lock) { + ret = uni_player_clk_set_rate(player, freq); + if (!ret) + player->mclk = freq; + } return 0; } @@ -575,12 +575,11 @@ static int uni_player_ctl_iec958_get(struct snd_kcontrol *kcontrol, struct uniperif *player = priv->dai_data.uni; struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; - mutex_lock(&player->ctrl_lock); + guard(mutex)(&player->ctrl_lock); ucontrol->value.iec958.status[0] = iec958->status[0]; ucontrol->value.iec958.status[1] = iec958->status[1]; ucontrol->value.iec958.status[2] = iec958->status[2]; ucontrol->value.iec958.status[3] = iec958->status[3]; - mutex_unlock(&player->ctrl_lock); return 0; } @@ -591,23 +590,20 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol, struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958; - unsigned long flags; - mutex_lock(&player->ctrl_lock); + guard(mutex)(&player->ctrl_lock); iec958->status[0] = ucontrol->value.iec958.status[0]; iec958->status[1] = ucontrol->value.iec958.status[1]; iec958->status[2] = ucontrol->value.iec958.status[2]; iec958->status[3] = ucontrol->value.iec958.status[3]; - spin_lock_irqsave(&player->irq_lock, flags); - if (player->substream && player->substream->runtime) - uni_player_set_channel_status(player, - player->substream->runtime); - else - uni_player_set_channel_status(player, NULL); - - spin_unlock_irqrestore(&player->irq_lock, flags); - mutex_unlock(&player->ctrl_lock); + scoped_guard(spinlock_irqsave, &player->irq_lock) { + if (player->substream && player->substream->runtime) + uni_player_set_channel_status(player, + player->substream->runtime); + else + uni_player_set_channel_status(player, NULL); + } return 0; } @@ -642,9 +638,8 @@ static int snd_sti_clk_adjustment_get(struct snd_kcontrol *kcontrol, struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; - mutex_lock(&player->ctrl_lock); + guard(mutex)(&player->ctrl_lock); ucontrol->value.integer.value[0] = player->clk_adj; - mutex_unlock(&player->ctrl_lock); return 0; } @@ -661,12 +656,11 @@ static int snd_sti_clk_adjustment_put(struct snd_kcontrol *kcontrol, (ucontrol->value.integer.value[0] > UNIPERIF_PLAYER_CLK_ADJ_MAX)) return -EINVAL; - mutex_lock(&player->ctrl_lock); + guard(mutex)(&player->ctrl_lock); player->clk_adj = ucontrol->value.integer.value[0]; if (player->mclk) ret = uni_player_clk_set_rate(player, player->mclk); - mutex_unlock(&player->ctrl_lock); return ret; } @@ -693,12 +687,10 @@ static int uni_player_startup(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; - unsigned long flags; int ret; - spin_lock_irqsave(&player->irq_lock, flags); - player->substream = substream; - spin_unlock_irqrestore(&player->irq_lock, flags); + scoped_guard(spinlock_irqsave, &player->irq_lock) + player->substream = substream; player->clk_adj = 0; @@ -734,11 +726,10 @@ static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id, if (clk_id != 0) return -EINVAL; - mutex_lock(&player->ctrl_lock); + guard(mutex)(&player->ctrl_lock); ret = uni_player_clk_set_rate(player, freq); if (!ret) player->mclk = freq; - mutex_unlock(&player->ctrl_lock); return ret; } @@ -996,15 +987,13 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *player = priv->dai_data.uni; - unsigned long flags; - spin_lock_irqsave(&player->irq_lock, flags); + guard(spinlock_irqsave)(&player->irq_lock); if (player->state != UNIPERIF_STATE_STOPPED) /* Stop the player */ uni_player_stop(player); player->substream = NULL; - spin_unlock_irqrestore(&player->irq_lock, flags); } static int uni_player_parse_dt_audio_glue(struct platform_device *pdev, diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c index 05ea2b794eb9..45d7613f595c 100644 --- a/sound/soc/sti/uniperif_reader.c +++ b/sound/soc/sti/uniperif_reader.c @@ -46,15 +46,16 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) struct uniperif *reader = dev_id; unsigned int status; - spin_lock(&reader->irq_lock); + guard(spinlock)(&reader->irq_lock); if (!reader->substream) - goto irq_spin_unlock; + return ret; snd_pcm_stream_lock(reader->substream); if (reader->state == UNIPERIF_STATE_STOPPED) { /* Unexpected IRQ: do nothing */ dev_warn(reader->dev, "unexpected IRQ\n"); - goto stream_unlock; + snd_pcm_stream_unlock(reader->substream); + return ret; } /* Get interrupt status & clear them immediately */ @@ -70,10 +71,7 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id) ret = IRQ_HANDLED; } -stream_unlock: snd_pcm_stream_unlock(reader->substream); -irq_spin_unlock: - spin_unlock(&reader->irq_lock); return ret; } @@ -355,12 +353,10 @@ static int uni_reader_startup(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *reader = priv->dai_data.uni; - unsigned long flags; int ret; - spin_lock_irqsave(&reader->irq_lock, flags); - reader->substream = substream; - spin_unlock_irqrestore(&reader->irq_lock, flags); + scoped_guard(spinlock_irqsave, &reader->irq_lock) + reader->substream = substream; if (!UNIPERIF_TYPE_IS_TDM(reader)) return 0; @@ -386,15 +382,13 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream, { struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai); struct uniperif *reader = priv->dai_data.uni; - unsigned long flags; - spin_lock_irqsave(&reader->irq_lock, flags); + guard(spinlock_irqsave)(&reader->irq_lock); if (reader->state != UNIPERIF_STATE_STOPPED) { /* Stop the reader */ uni_reader_stop(reader); } reader->substream = NULL; - spin_unlock_irqrestore(&reader->irq_lock, flags); } static const struct snd_soc_dai_ops uni_reader_dai_ops = { diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 0f6d32814c22..66efb9a0acb9 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -62,12 +62,11 @@ static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream, { struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); - mutex_lock(&priv->lock); + guard(mutex)(&priv->lock); if (priv->iio_active) { iio_channel_stop_all_cb(priv->iio_cb); priv->iio_active = false; } - mutex_unlock(&priv->lock); } static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, @@ -76,7 +75,7 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); int ret; - mutex_lock(&priv->lock); + guard(mutex)(&priv->lock); if (priv->iio_active) { iio_channel_stop_all_cb(priv->iio_cb); priv->iio_active = false; @@ -88,7 +87,7 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, if (ret < 0) { dev_err(dai->dev, "%s: Failed to set %d sampling rate\n", __func__, substream->runtime->rate); - goto out; + return ret; } if (!priv->iio_active) { @@ -100,9 +99,6 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, __func__, ret); } -out: - mutex_unlock(&priv->lock); - return ret; } @@ -316,6 +312,7 @@ static const struct snd_soc_component_driver stm32_adfsdm_soc_platform = { .trigger = stm32_adfsdm_trigger, .pointer = stm32_adfsdm_pcm_pointer, .pcm_new = stm32_adfsdm_pcm_new, + .debugfs_prefix = "pcm", }; static const struct of_device_id stm32_adfsdm_of_match[] = { @@ -327,7 +324,6 @@ MODULE_DEVICE_TABLE(of, stm32_adfsdm_of_match); static int stm32_adfsdm_probe(struct platform_device *pdev) { struct stm32_adfsdm_priv *priv; - struct snd_soc_component *component; int ret; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); @@ -361,20 +357,9 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) return ret; } - component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL); - if (!component) - return -ENOMEM; - - ret = snd_soc_component_initialize(component, - &stm32_adfsdm_soc_platform, - &pdev->dev); - if (ret < 0) - return ret; -#ifdef CONFIG_DEBUG_FS - component->debugfs_prefix = "pcm"; -#endif - - ret = snd_soc_add_component(component, NULL, 0); + ret = devm_snd_soc_register_component(&pdev->dev, + &stm32_adfsdm_soc_platform, + NULL, 0); if (ret < 0) { dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", __func__); diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 6ca21780f21d..ae9e25657f3f 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -615,10 +615,10 @@ static irqreturn_t stm32_i2s_isr(int irq, void *devid) if (flags & I2S_SR_TIFRE) dev_dbg(&pdev->dev, "Frame error\n"); - spin_lock(&i2s->irq_lock); - if (err && i2s->substream) - snd_pcm_stop_xrun(i2s->substream); - spin_unlock(&i2s->irq_lock); + scoped_guard(spinlock, &i2s->irq_lock) { + if (err && i2s->substream) + snd_pcm_stop_xrun(i2s->substream); + } return IRQ_HANDLED; } @@ -905,12 +905,10 @@ static int stm32_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; int ret; - spin_lock_irqsave(&i2s->irq_lock, flags); - i2s->substream = substream; - spin_unlock_irqrestore(&i2s->irq_lock, flags); + scoped_guard(spinlock_irqsave, &i2s->irq_lock) + i2s->substream = substream; if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_DSP_A) snd_pcm_hw_constraint_single(substream->runtime, @@ -982,19 +980,19 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, regmap_write_bits(i2s->regmap, STM32_I2S_IFCR_REG, I2S_IFCR_MASK, I2S_IFCR_MASK); - spin_lock(&i2s->lock_fd); - i2s->refcount++; - if (playback_flg) { - ier = I2S_IER_UDRIE; - } else { - ier = I2S_IER_OVRIE; + scoped_guard(spinlock, &i2s->lock_fd) { + i2s->refcount++; + if (playback_flg) { + ier = I2S_IER_UDRIE; + } else { + ier = I2S_IER_OVRIE; - if (STM32_I2S_IS_MASTER(i2s) && i2s->refcount == 1) - /* dummy write to gate bus clocks */ - regmap_write(i2s->regmap, - STM32_I2S_TXDR_REG, 0); + if (STM32_I2S_IS_MASTER(i2s) && i2s->refcount == 1) + /* dummy write to gate bus clocks */ + regmap_write(i2s->regmap, + STM32_I2S_TXDR_REG, 0); + } } - spin_unlock(&i2s->lock_fd); if (STM32_I2S_IS_SLAVE(i2s)) ier |= I2S_IER_TIFREIE; @@ -1016,21 +1014,18 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, I2S_IER_OVRIE, (unsigned int)~I2S_IER_OVRIE); - spin_lock(&i2s->lock_fd); - i2s->refcount--; - if (i2s->refcount) { - spin_unlock(&i2s->lock_fd); - break; - } + scoped_guard(spinlock, &i2s->lock_fd) { + i2s->refcount--; + if (i2s->refcount) + return 0; - ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG, - I2S_CR1_SPE, 0); - if (ret < 0) { - dev_err(cpu_dai->dev, "Error %d disabling I2S\n", ret); - spin_unlock(&i2s->lock_fd); - return ret; + ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG, + I2S_CR1_SPE, 0); + if (ret < 0) { + dev_err(cpu_dai->dev, "Error %d disabling I2S\n", ret); + return ret; + } } - spin_unlock(&i2s->lock_fd); cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN; regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG, @@ -1047,7 +1042,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; clk_disable_unprepare(i2s->i2sclk); @@ -1059,9 +1053,8 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream, if (!i2s->i2smclk && i2s->put_i2s_clk_rate) i2s->put_i2s_clk_rate(i2s); - spin_lock_irqsave(&i2s->irq_lock, flags); - i2s->substream = NULL; - spin_unlock_irqrestore(&i2s->irq_lock, flags); + scoped_guard(spinlock_irqsave, &i2s->irq_lock) + i2s->substream = NULL; } static int stm32_i2s_dai_probe(struct snd_soc_dai *cpu_dai) diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 3e82fa90e719..ea9e8bddd63f 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -280,9 +280,8 @@ static int snd_pcm_iec958_get(struct snd_kcontrol *kcontrol, { struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol); - mutex_lock(&sai->ctrl_lock); + guard(mutex)(&sai->ctrl_lock); memcpy(uctl->value.iec958.status, sai->iec958.status, 4); - mutex_unlock(&sai->ctrl_lock); return 0; } @@ -292,9 +291,8 @@ static int snd_pcm_iec958_put(struct snd_kcontrol *kcontrol, { struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol); - mutex_lock(&sai->ctrl_lock); + guard(mutex)(&sai->ctrl_lock); memcpy(sai->iec958.status, uctl->value.iec958.status, 4); - mutex_unlock(&sai->ctrl_lock); return 0; } @@ -658,10 +656,10 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid) status = SNDRV_PCM_STATE_XRUN; } - spin_lock(&sai->irq_lock); - if (status != SNDRV_PCM_STATE_RUNNING && sai->substream) - snd_pcm_stop_xrun(sai->substream); - spin_unlock(&sai->irq_lock); + scoped_guard(spinlock, &sai->irq_lock) { + if (status != SNDRV_PCM_STATE_RUNNING && sai->substream) + snd_pcm_stop_xrun(sai->substream); + } return IRQ_HANDLED; } @@ -894,11 +892,9 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream, { struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); int imr, cr2, ret; - unsigned long flags; - spin_lock_irqsave(&sai->irq_lock, flags); - sai->substream = substream; - spin_unlock_irqrestore(&sai->irq_lock, flags); + scoped_guard(spinlock_irqsave, &sai->irq_lock) + sai->substream = substream; if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) { snd_pcm_hw_constraint_mask64(substream->runtime, @@ -1083,7 +1079,7 @@ static void stm32_sai_set_iec958_status(struct stm32_sai_sub_data *sai, return; /* Force the sample rate according to runtime rate */ - mutex_lock(&sai->ctrl_lock); + guard(mutex)(&sai->ctrl_lock); switch (runtime->rate) { case 22050: sai->iec958.status[3] = IEC958_AES3_CON_FS_22050; @@ -1116,7 +1112,6 @@ static void stm32_sai_set_iec958_status(struct stm32_sai_sub_data *sai, sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID; break; } - mutex_unlock(&sai->ctrl_lock); } static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai, @@ -1284,7 +1279,6 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; stm32_sai_sub_reg_up(sai, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0); @@ -1298,9 +1292,8 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream, if (!sai->sai_mclk && sai->put_sai_ck_rate) sai->put_sai_ck_rate(sai); - spin_lock_irqsave(&sai->irq_lock, flags); - sai->substream = NULL; - spin_unlock_irqrestore(&sai->irq_lock, flags); + scoped_guard(spinlock_irqsave, &sai->irq_lock) + sai->substream = NULL; } static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd, diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index 57b711c44278..2f83ca989e68 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -322,7 +322,6 @@ static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx) static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) { int cr, cr_mask, imr, ret; - unsigned long flags; /* Enable IRQs */ imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE; @@ -330,7 +329,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) if (ret) return ret; - spin_lock_irqsave(&spdifrx->lock, flags); + guard(spinlock_irqsave)(&spdifrx->lock); spdifrx->refcount++; @@ -365,22 +364,17 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) "Failed to start synchronization\n"); } - spin_unlock_irqrestore(&spdifrx->lock, flags); - return ret; } static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) { int cr, cr_mask, reg; - unsigned long flags; - spin_lock_irqsave(&spdifrx->lock, flags); + guard(spinlock_irqsave)(&spdifrx->lock); - if (--spdifrx->refcount) { - spin_unlock_irqrestore(&spdifrx->lock, flags); + if (--spdifrx->refcount) return; - } cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); cr_mask = SPDIFRX_CR_SPDIFEN_MASK | SPDIFRX_CR_RXDMAEN; @@ -396,8 +390,6 @@ static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) /* dummy read to clear CSRNE and RXNE in status register */ regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, ®); regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, ®); - - spin_unlock_irqrestore(&spdifrx->lock, flags); } static int stm32_spdifrx_dma_ctrl_register(struct device *dev, @@ -744,19 +736,19 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) return IRQ_HANDLED; } - spin_lock(&spdifrx->irq_lock); - if (spdifrx->substream) - snd_pcm_stop(spdifrx->substream, - SNDRV_PCM_STATE_DISCONNECTED); - spin_unlock(&spdifrx->irq_lock); + scoped_guard(spinlock, &spdifrx->irq_lock) { + if (spdifrx->substream) + snd_pcm_stop(spdifrx->substream, + SNDRV_PCM_STATE_DISCONNECTED); + } return IRQ_HANDLED; } - spin_lock(&spdifrx->irq_lock); - if (err_xrun && spdifrx->substream) - snd_pcm_stop_xrun(spdifrx->substream); - spin_unlock(&spdifrx->irq_lock); + scoped_guard(spinlock, &spdifrx->irq_lock) { + if (err_xrun && spdifrx->substream) + snd_pcm_stop_xrun(spdifrx->substream); + } return IRQ_HANDLED; } @@ -765,12 +757,10 @@ static int stm32_spdifrx_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; int ret; - spin_lock_irqsave(&spdifrx->irq_lock, flags); - spdifrx->substream = substream; - spin_unlock_irqrestore(&spdifrx->irq_lock, flags); + scoped_guard(spinlock_irqsave, &spdifrx->irq_lock) + spdifrx->substream = substream; ret = clk_prepare_enable(spdifrx->kclk); if (ret) @@ -846,11 +836,9 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); - unsigned long flags; - spin_lock_irqsave(&spdifrx->irq_lock, flags); - spdifrx->substream = NULL; - spin_unlock_irqrestore(&spdifrx->irq_lock, flags); + scoped_guard(spinlock_irqsave, &spdifrx->irq_lock) + spdifrx->substream = NULL; clk_disable_unprepare(spdifrx->kclk); } diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 08c58e8f3c22..0df1fc64f532 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -441,6 +441,7 @@ static const struct of_device_id tegra20_ac97_of_match[] = { { .compatible = "nvidia,tegra20-ac97", }, {}, }; +MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match); static struct platform_driver tegra20_ac97_driver = { .driver = { @@ -456,4 +457,3 @@ MODULE_AUTHOR("Lucas Stach"); MODULE_DESCRIPTION("Tegra20 AC97 ASoC driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match); diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index c620ab0c601f..b48cc4a6967b 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -188,6 +188,7 @@ static const struct of_device_id tegra20_das_of_match[] = { { .compatible = "nvidia,tegra20-das", }, {}, }; +MODULE_DEVICE_TABLE(of, tegra20_das_of_match); static struct platform_driver tegra20_das_driver = { .probe = tegra20_das_probe, @@ -202,4 +203,3 @@ MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra20 DAS driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra20_das_of_match); diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 51df0835ce3e..d9ab210ad69a 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -485,6 +485,7 @@ static const struct of_device_id tegra20_i2s_of_match[] = { { .compatible = "nvidia,tegra20-i2s", }, {}, }; +MODULE_DEVICE_TABLE(of, tegra20_i2s_of_match); static const struct dev_pm_ops tegra20_i2s_pm_ops = { RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend, @@ -507,4 +508,3 @@ MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra20 I2S ASoC driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra20_i2s_of_match); diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c index a1c2757a3932..7299c6bfcf15 100644 --- a/sound/soc/tegra/tegra210_admaif.c +++ b/sound/soc/tegra/tegra210_admaif.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include "tegra_isomgr_bw.h" @@ -912,35 +913,26 @@ MODULE_DEVICE_TABLE(of, tegra_admaif_of_match); static int tegra_admaif_probe(struct platform_device *pdev) { + const struct tegra_admaif_soc_data *soc_data; struct tegra_admaif *admaif; void __iomem *regs; struct resource *res; + size_t alloc_size; int err, i; - admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL); + soc_data = of_device_get_match_data(&pdev->dev); + + alloc_size = struct_size(admaif, capture_dma_data, soc_data->num_ch); + alloc_size += sizeof(*admaif->playback_dma_data) * soc_data->num_ch; + admaif = devm_kzalloc(&pdev->dev, alloc_size, GFP_KERNEL); if (!admaif) return -ENOMEM; - admaif->soc_data = of_device_get_match_data(&pdev->dev); + admaif->playback_dma_data = admaif->capture_dma_data + soc_data->num_ch; + admaif->soc_data = soc_data; dev_set_drvdata(&pdev->dev, admaif); - admaif->capture_dma_data = - devm_kcalloc(&pdev->dev, - admaif->soc_data->num_ch, - sizeof(struct snd_dmaengine_dai_dma_data), - GFP_KERNEL); - if (!admaif->capture_dma_data) - return -ENOMEM; - - admaif->playback_dma_data = - devm_kcalloc(&pdev->dev, - admaif->soc_data->num_ch, - sizeof(struct snd_dmaengine_dai_dma_data), - GFP_KERNEL); - if (!admaif->playback_dma_data) - return -ENOMEM; - for (i = 0; i < ADMAIF_PATHS; i++) { admaif->mono_to_stereo[i] = devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch, diff --git a/sound/soc/tegra/tegra210_admaif.h b/sound/soc/tegra/tegra210_admaif.h index 304d45c76a9a..fd9877aa95d3 100644 --- a/sound/soc/tegra/tegra210_admaif.h +++ b/sound/soc/tegra/tegra210_admaif.h @@ -229,13 +229,13 @@ struct tegra_admaif_soc_data { }; struct tegra_admaif { - struct snd_dmaengine_dai_dma_data *capture_dma_data; struct snd_dmaengine_dai_dma_data *playback_dma_data; const struct tegra_admaif_soc_data *soc_data; unsigned int *mono_to_stereo[ADMAIF_PATHS]; unsigned int *stereo_to_mono[ADMAIF_PATHS]; struct regmap *regmap; struct tegra_adma_isomgr *adma_isomgr; + struct snd_dmaengine_dai_dma_data capture_dma_data[]; }; #endif diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index d2f742ffc59d..9b662fcee66f 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -4,6 +4,7 @@ // // tegra210_adx.c - Tegra210 ADX driver +#include #include #include #include @@ -47,18 +48,36 @@ static const struct reg_default tegra264_adx_reg_defaults[] = { static void tegra210_adx_write_map_ram(struct tegra210_adx *adx) { + const unsigned int bits_per_mask = BITS_PER_TYPE(*adx->byte_mask); int i; + memset(adx->byte_mask, 0, + adx->soc_data->byte_mask_size * sizeof(*adx->byte_mask)); + regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL + adx->soc_data->cya_offset, TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN | TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN | TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE); - for (i = 0; i < adx->soc_data->ram_depth; i++) + for (i = 0; i < adx->soc_data->ram_depth; i++) { + u32 word = 0; + int b; + + for (b = 0; b < TEGRA_ADX_SLOTS_PER_WORD; b++) { + unsigned int slot = i * TEGRA_ADX_SLOTS_PER_WORD + b; + u16 val = adx->map[slot]; + + if (val >= 256) + continue; + + word |= (u32)val << (b * BITS_PER_BYTE); + adx->byte_mask[slot / bits_per_mask] |= + 1U << (slot % bits_per_mask); + } regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA + - adx->soc_data->cya_offset, - adx->map[i]); + adx->soc_data->cya_offset, word); + } for (i = 0; i < adx->soc_data->byte_mask_size; i++) regmap_write(adx->regmap, @@ -192,27 +211,10 @@ static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol, { struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt); - struct soc_mixer_control *mc; - unsigned char *bytes_map = (unsigned char *)adx->map; - int enabled; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; - mc = (struct soc_mixer_control *)kcontrol->private_value; - enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32)); - - /* - * TODO: Simplify this logic to just return from bytes_map[] - * - * Presently below is required since bytes_map[] is - * tightly packed and cannot store the control value of 256. - * Byte mask state is used to know if 256 needs to be returned. - * Note that for control value of 256, the put() call stores 0 - * in the bytes_map[] and disables the corresponding bit in - * byte_mask[]. - */ - if (enabled) - ucontrol->value.integer.value[0] = bytes_map[mc->reg]; - else - ucontrol->value.integer.value[0] = 256; + ucontrol->value.integer.value[0] = adx->map[mc->reg]; return 0; } @@ -222,23 +224,22 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol, { struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt); - unsigned char *bytes_map = (unsigned char *)adx->map; - int value = ucontrol->value.integer.value[0]; struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - unsigned int mask_val = adx->byte_mask[mc->reg / 32]; + unsigned int value = ucontrol->value.integer.value[0]; - if (value >= 0 && value <= 255) - mask_val |= (1 << (mc->reg % 32)); - else - mask_val &= ~(1 << (mc->reg % 32)); + /* + * Match the previous behaviour: any value outside [0, 255] is + * treated as the "disabled" sentinel (256). Negative values from + * userspace fold in through the unsigned cast and are caught here. + */ + if (value > 255) + value = 256; - if (mask_val == adx->byte_mask[mc->reg / 32]) + if (adx->map[mc->reg] == value) return 0; - /* Update byte map and slot */ - bytes_map[mc->reg] = value % 256; - adx->byte_mask[mc->reg / 32] = mask_val; + adx->map[mc->reg] = value; return 1; } @@ -676,17 +677,15 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct tegra210_adx *adx; - const struct of_device_id *match; - struct tegra210_adx_soc_data *soc_data; + const struct tegra210_adx_soc_data *soc_data; void __iomem *regs; - int err; + int err, i; adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL); if (!adx) return -ENOMEM; - match = of_match_device(tegra210_adx_of_match, dev); - soc_data = (struct tegra210_adx_soc_data *)match->data; + soc_data = of_device_get_match_data(dev); adx->soc_data = soc_data; dev_set_drvdata(dev, adx); @@ -703,17 +702,21 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev) regcache_cache_only(adx->regmap, true); - adx->map = devm_kzalloc(dev, soc_data->ram_depth * sizeof(*adx->map), - GFP_KERNEL); + adx->map = devm_kcalloc(dev, + soc_data->ram_depth * TEGRA_ADX_SLOTS_PER_WORD, + sizeof(*adx->map), GFP_KERNEL); if (!adx->map) return -ENOMEM; - adx->byte_mask = devm_kzalloc(dev, - soc_data->byte_mask_size * sizeof(*adx->byte_mask), - GFP_KERNEL); + adx->byte_mask = devm_kcalloc(dev, soc_data->byte_mask_size, + sizeof(*adx->byte_mask), GFP_KERNEL); if (!adx->byte_mask) return -ENOMEM; + /* Initialise all byte map slots as disabled (value 256). */ + for (i = 0; i < soc_data->ram_depth * TEGRA_ADX_SLOTS_PER_WORD; i++) + adx->map[i] = 256; + tegra210_adx_dais[TEGRA_ADX_IN_DAI_ID].playback.channels_max = adx->soc_data->max_ch; diff --git a/sound/soc/tegra/tegra210_adx.h b/sound/soc/tegra/tegra210_adx.h index 176a4e40de0a..a6298c3dcca5 100644 --- a/sound/soc/tegra/tegra210_adx.h +++ b/sound/soc/tegra/tegra210_adx.h @@ -8,6 +8,8 @@ #ifndef __TEGRA210_ADX_H__ #define __TEGRA210_ADX_H__ +#include + /* Register offsets from TEGRA210_ADX*_BASE */ #define TEGRA210_ADX_RX_STATUS 0x0c #define TEGRA210_ADX_RX_INT_STATUS 0x10 @@ -61,6 +63,7 @@ #define TEGRA210_ADX_SOFT_RESET_SOFT_DEFAULT (0 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT) #define TEGRA210_ADX_AUDIOCIF_CH_STRIDE 4 +#define TEGRA_ADX_SLOTS_PER_WORD 4 #define TEGRA210_ADX_RAM_DEPTH 16 #define TEGRA210_ADX_MAP_STREAM_NUMBER_SHIFT 6 #define TEGRA210_ADX_MAP_WORD_NUMBER_SHIFT 2 @@ -88,8 +91,8 @@ struct tegra210_adx_soc_data { struct tegra210_adx { struct regmap *regmap; - unsigned int *map; unsigned int *byte_mask; + u16 *map; const struct tegra210_adx_soc_data *soc_data; }; diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c index ece33b7ff190..efc8f3388668 100644 --- a/sound/soc/tegra/tegra210_ahub.c +++ b/sound/soc/tegra/tegra210_ahub.c @@ -62,13 +62,15 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, struct snd_soc_dapm_update update[TEGRA_XBAR_UPDATE_MAX_REG] = { }; int val_bytes = snd_soc_component_regmap_val_bytes(cmpnt); unsigned int *item = uctl->value.enumerated.item; - unsigned int value = e->values[item[0]]; + unsigned int value; unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; int change = 0; if (item[0] >= e->items) return -EINVAL; + value = e->values[item[0]]; + if (value) { /* Get the register index and value to set */ reg_idx = (value - 1) / (8 * val_bytes); diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c index d635046bbe81..930b080aec0a 100644 --- a/sound/soc/tegra/tegra210_amx.c +++ b/sound/soc/tegra/tegra210_amx.c @@ -4,6 +4,7 @@ // // tegra210_amx.c - Tegra210 AMX driver +#include #include #include #include @@ -60,16 +61,35 @@ static const struct reg_default tegra264_amx_reg_defaults[] = { static void tegra210_amx_write_map_ram(struct tegra210_amx *amx) { + const unsigned int bits_per_mask = BITS_PER_TYPE(*amx->byte_mask); int i; + memset(amx->byte_mask, 0, + amx->soc_data->byte_mask_size * sizeof(*amx->byte_mask)); + regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_CTRL + amx->soc_data->reg_offset, TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN | TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN | TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE); - for (i = 0; i < amx->soc_data->ram_depth; i++) + for (i = 0; i < amx->soc_data->ram_depth; i++) { + u32 word = 0; + int b; + + for (b = 0; b < TEGRA_AMX_SLOTS_PER_WORD; b++) { + unsigned int slot = i * TEGRA_AMX_SLOTS_PER_WORD + b; + u16 val = amx->map[slot]; + + if (val >= 256) + continue; + + word |= (u32)val << (b * BITS_PER_BYTE); + amx->byte_mask[slot / bits_per_mask] |= + 1U << (slot % bits_per_mask); + } regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_DATA + amx->soc_data->reg_offset, - amx->map[i]); + word); + } for (i = 0; i < amx->soc_data->byte_mask_size; i++) regmap_write(amx->regmap, @@ -214,26 +234,8 @@ static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt); - unsigned char *bytes_map = (unsigned char *)amx->map; - int reg = mc->reg; - int enabled; - enabled = amx->byte_mask[reg / 32] & (1 << (reg % 32)); - - /* - * TODO: Simplify this logic to just return from bytes_map[] - * - * Presently below is required since bytes_map[] is - * tightly packed and cannot store the control value of 256. - * Byte mask state is used to know if 256 needs to be returned. - * Note that for control value of 256, the put() call stores 0 - * in the bytes_map[] and disables the corresponding bit in - * byte_mask[]. - */ - if (enabled) - ucontrol->value.integer.value[0] = bytes_map[reg]; - else - ucontrol->value.integer.value[0] = 256; + ucontrol->value.integer.value[0] = amx->map[mc->reg]; return 0; } @@ -245,22 +247,20 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt); - unsigned char *bytes_map = (unsigned char *)amx->map; - int reg = mc->reg; - int value = ucontrol->value.integer.value[0]; - unsigned int mask_val = amx->byte_mask[reg / 32]; + unsigned int value = ucontrol->value.integer.value[0]; - if (value >= 0 && value <= 255) - mask_val |= (1 << (reg % 32)); - else - mask_val &= ~(1 << (reg % 32)); + /* + * Match the previous behaviour: any value outside [0, 255] is + * treated as the "disabled" sentinel (256). Negative values from + * userspace fold in through the unsigned cast and are caught here. + */ + if (value > 255) + value = 256; - if (mask_val == amx->byte_mask[reg / 32]) + if (amx->map[mc->reg] == value) return 0; - /* Update byte map and slot */ - bytes_map[reg] = value % 256; - amx->byte_mask[reg / 32] = mask_val; + amx->map[mc->reg] = value; return 1; } @@ -729,7 +729,7 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct tegra210_amx *amx; void __iomem *regs; - int err; + int err, i; amx = devm_kzalloc(dev, sizeof(*amx), GFP_KERNEL); if (!amx) @@ -751,17 +751,21 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev) regcache_cache_only(amx->regmap, true); - amx->map = devm_kzalloc(dev, amx->soc_data->ram_depth * sizeof(*amx->map), - GFP_KERNEL); + amx->map = devm_kcalloc(dev, + amx->soc_data->ram_depth * TEGRA_AMX_SLOTS_PER_WORD, + sizeof(*amx->map), GFP_KERNEL); if (!amx->map) return -ENOMEM; - amx->byte_mask = devm_kzalloc(dev, - amx->soc_data->byte_mask_size * sizeof(*amx->byte_mask), - GFP_KERNEL); + amx->byte_mask = devm_kcalloc(dev, amx->soc_data->byte_mask_size, + sizeof(*amx->byte_mask), GFP_KERNEL); if (!amx->byte_mask) return -ENOMEM; + /* Initialise all byte map slots as disabled (value 256). */ + for (i = 0; i < amx->soc_data->ram_depth * TEGRA_AMX_SLOTS_PER_WORD; i++) + amx->map[i] = 256; + tegra210_amx_dais[TEGRA_AMX_OUT_DAI_ID].capture.channels_max = amx->soc_data->max_ch; diff --git a/sound/soc/tegra/tegra210_amx.h b/sound/soc/tegra/tegra210_amx.h index 50a237b197ba..420b62f0cf35 100644 --- a/sound/soc/tegra/tegra210_amx.h +++ b/sound/soc/tegra/tegra210_amx.h @@ -8,6 +8,8 @@ #ifndef __TEGRA210_AMX_H__ #define __TEGRA210_AMX_H__ +#include + /* Register offsets from TEGRA210_AMX*_BASE */ #define TEGRA210_AMX_RX_STATUS 0x0c #define TEGRA210_AMX_RX_INT_STATUS 0x10 @@ -73,6 +75,7 @@ #define TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK TEGRA210_AMX_SOFT_RESET_SOFT_EN #define TEGRA210_AMX_AUDIOCIF_CH_STRIDE 4 +#define TEGRA_AMX_SLOTS_PER_WORD 4 #define TEGRA210_AMX_RAM_DEPTH 16 #define TEGRA210_AMX_MAP_STREAM_NUM_SHIFT 6 #define TEGRA210_AMX_MAP_WORD_NUM_SHIFT 2 @@ -105,8 +108,8 @@ struct tegra210_amx_soc_data { struct tegra210_amx { const struct tegra210_amx_soc_data *soc_data; - unsigned int *map; unsigned int *byte_mask; + u16 *map; struct regmap *regmap; }; diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c index ce44117a0b9c..c237ba7531de 100644 --- a/sound/soc/tegra/tegra210_mixer.c +++ b/sound/soc/tegra/tegra210_mixer.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -149,12 +150,19 @@ static int tegra210_mixer_configure_gain(struct snd_soc_component *cmpnt, /* Write duration parameters */ for (i = 0; i < NUM_DURATION_PARMS; i++) { - int val; + u32 val; - if (instant_gain) + if (instant_gain) { val = 1; - else - val = gain_params.duration[i]; + } else { + if (i == DURATION_N3_ID) + val = mixer->duration[id]; + else if (i == DURATION_INV_N3_ID) + val = div_u64(BIT_ULL(31 + TEGRA210_MIXER_PRESCALAR), + mixer->duration[id]); + else + val = gain_params.duration[i]; + } err = tegra210_mixer_write_ram(mixer, REG_DURATION_PARAM(reg, i), @@ -173,6 +181,216 @@ static int tegra210_mixer_configure_gain(struct snd_soc_component *cmpnt, return err; } +static int tegra210_mixer_fade_duration_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = TEGRA210_MIXER_FADE_DURATION_MIN; + uinfo->value.integer.max = TEGRA210_MIXER_FADE_DURATION_MAX; + + return 0; +} + +static int tegra210_mixer_get_fade_duration(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); + struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); + + ucontrol->value.integer.value[0] = mixer->duration[mc->reg]; + + return 0; +} + +static int tegra210_mixer_put_fade_duration(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); + struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); + unsigned int id = mc->reg; + long duration = ucontrol->value.integer.value[0]; + + if (duration < (long)TEGRA210_MIXER_FADE_DURATION_MIN || + duration > TEGRA210_MIXER_FADE_DURATION_MAX) + return -EINVAL; + + if (mixer->duration[id] == duration) + return 0; + + mixer->duration[id] = duration; + mixer->fade_pending[id] = true; + + return 1; +} + +static int tegra210_mixer_get_fade_gain(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); + struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); + + ucontrol->value.integer.value[0] = mixer->fade_gain[mc->reg]; + + return 0; +} + +static int tegra210_mixer_put_fade_gain(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); + struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); + unsigned int id = mc->reg; + + if (ucontrol->value.integer.value[0] < 0 || + ucontrol->value.integer.value[0] > TEGRA210_MIXER_GAIN_MAX) + return -EINVAL; + + if (mixer->fade_gain[id] == ucontrol->value.integer.value[0]) + return 0; + + mixer->fade_gain[id] = ucontrol->value.integer.value[0]; + mixer->fade_pending[id] = true; + + return 1; +} + +static int tegra210_mixer_get_fade_switch(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = 0; + + return 0; +} + +static int tegra210_mixer_put_fade_switch(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); + struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); + int id, err, changed = 0; + + err = pm_runtime_resume_and_get(cmpnt->dev); + if (err < 0) + return err; + + /* Switch off: disable sample count for all active fades */ + if (!ucontrol->value.integer.value[0]) { + for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) { + if (!mixer->in_fade[id]) + continue; + + regmap_update_bits(mixer->regmap, + MIXER_REG(TEGRA210_MIXER_RX1_CTRL, + id), + TEGRA210_MIXER_SAMPLE_COUNT_ENABLE, + 0); + mixer->in_fade[id] = false; + changed = 1; + } + + pm_runtime_put(cmpnt->dev); + return changed; + } + + /* Stop active fades on pending streams before reconfiguring */ + for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) { + if (!mixer->fade_pending[id]) + continue; + + if (mixer->in_fade[id]) { + regmap_update_bits(mixer->regmap, + MIXER_REG(TEGRA210_MIXER_RX1_CTRL, + id), + TEGRA210_MIXER_SAMPLE_COUNT_ENABLE, + 0); + mixer->in_fade[id] = false; + } + + mixer->gain_value[id] = mixer->fade_gain[id]; + err = tegra210_mixer_configure_gain(cmpnt, id, false); + if (err) { + dev_err(cmpnt->dev, + "Failed to configure fade for RX%d\n", id + 1); + pm_runtime_put(cmpnt->dev); + return err; + } + + changed = 1; + } + + if (!changed) { + pm_runtime_put(cmpnt->dev); + return 0; + } + + /* Enable sample count for all pending streams */ + for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) { + if (!mixer->fade_pending[id]) + continue; + + err = regmap_update_bits(mixer->regmap, + MIXER_REG(TEGRA210_MIXER_RX1_CTRL, id), + TEGRA210_MIXER_SAMPLE_COUNT_ENABLE, + TEGRA210_MIXER_SAMPLE_COUNT_ENABLE); + if (err) { + dev_err(cmpnt->dev, + "Failed to enable sample count for RX%d\n", + id + 1); + pm_runtime_put(cmpnt->dev); + return err; + } + + mixer->in_fade[id] = true; + mixer->fade_pending[id] = false; + } + + pm_runtime_put(cmpnt->dev); + + return 1; +} + +static int tegra210_mixer_get_fade_status(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol); + struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); + u32 count; + int id, err; + + err = pm_runtime_resume_and_get(cmpnt->dev); + if (err < 0) + return err; + + for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) { + if (!mixer->in_fade[id]) { + ucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_IDLE; + continue; + } + + regmap_read(mixer->regmap, + MIXER_REG(TEGRA210_MIXER_RX1_SAMPLE_COUNT, id), + &count); + + if (count >= mixer->duration[id]) + ucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_IDLE; + else + ucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_ACTIVE; + } + + pm_runtime_put(cmpnt->dev); + + return 0; +} + static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -396,14 +614,44 @@ ADDER_CTRL_DECL(adder3, TEGRA210_MIXER_TX3_ADDER_CONFIG); ADDER_CTRL_DECL(adder4, TEGRA210_MIXER_TX4_ADDER_CONFIG); ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG); +static int tegra210_mixer_fade_status_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = TEGRA210_MIXER_RX_MAX; + uinfo->value.integer.min = TEGRA210_MIXER_FADE_IDLE; + uinfo->value.integer.max = TEGRA210_MIXER_FADE_ACTIVE; + + return 0; +} + +#define FADE_CTRL(id) \ + { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = "RX" #id " Fade Duration", \ + .info = tegra210_mixer_fade_duration_info, \ + .get = tegra210_mixer_get_fade_duration, \ + .put = tegra210_mixer_put_fade_duration, \ + .private_value = SOC_SINGLE_VALUE((id) - 1, 0, \ + TEGRA210_MIXER_FADE_DURATION_MIN, \ + TEGRA210_MIXER_FADE_DURATION_MAX, \ + 0, 0), \ + }, \ + SOC_SINGLE_EXT("RX" #id " Fade Gain", (id) - 1, 0, \ + TEGRA210_MIXER_GAIN_MAX, 0, \ + tegra210_mixer_get_fade_gain, \ + tegra210_mixer_put_fade_gain), + #define GAIN_CTRL(id) \ SOC_SINGLE_EXT("RX" #id " Gain Volume", \ MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \ - 0x20000, 0, tegra210_mixer_get_gain, \ + TEGRA210_MIXER_GAIN_MAX, 0, \ + tegra210_mixer_get_gain, \ tegra210_mixer_put_gain), \ SOC_SINGLE_EXT("RX" #id " Instant Gain Volume", \ MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \ - 0x20000, 0, tegra210_mixer_get_gain, \ + TEGRA210_MIXER_GAIN_MAX, 0, \ + tegra210_mixer_get_gain, \ tegra210_mixer_put_instant_gain), /* Volume controls for all MIXER inputs */ @@ -418,6 +666,28 @@ static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = { GAIN_CTRL(8) GAIN_CTRL(9) GAIN_CTRL(10) + + FADE_CTRL(1) + FADE_CTRL(2) + FADE_CTRL(3) + FADE_CTRL(4) + FADE_CTRL(5) + FADE_CTRL(6) + FADE_CTRL(7) + FADE_CTRL(8) + FADE_CTRL(9) + FADE_CTRL(10) + SOC_SINGLE_EXT("Fade Switch", SND_SOC_NOPM, 0, 1, 0, + tegra210_mixer_get_fade_switch, + tegra210_mixer_put_fade_switch), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Fade Status", + .info = tegra210_mixer_fade_status_info, + .access = SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .get = tegra210_mixer_get_fade_status, + }, }; static const struct snd_soc_dapm_widget tegra210_mixer_widgets[] = { @@ -579,6 +849,7 @@ static bool tegra210_mixer_volatile_reg(struct device *dev, case TEGRA210_MIXER_GAIN_CFG_RAM_DATA: case TEGRA210_MIXER_PEAKM_RAM_CTRL: case TEGRA210_MIXER_PEAKM_RAM_DATA: + case TEGRA210_MIXER_RX1_SAMPLE_COUNT: return true; default: return false; @@ -632,8 +903,11 @@ static int tegra210_mixer_platform_probe(struct platform_device *pdev) dev_set_drvdata(dev, mixer); /* Use default gain value for all MIXER inputs */ - for (i = 0; i < TEGRA210_MIXER_RX_MAX; i++) + for (i = 0; i < TEGRA210_MIXER_RX_MAX; i++) { mixer->gain_value[i] = gain_params.gain_value; + mixer->fade_gain[i] = gain_params.gain_value; + mixer->duration[i] = gain_params.duration[DURATION_N3_ID]; + } regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) diff --git a/sound/soc/tegra/tegra210_mixer.h b/sound/soc/tegra/tegra210_mixer.h index a330530fbc61..d9c8fa6124de 100644 --- a/sound/soc/tegra/tegra210_mixer.h +++ b/sound/soc/tegra/tegra210_mixer.h @@ -79,12 +79,27 @@ #define TEGRA210_MIXER_RX_LIMIT (TEGRA210_MIXER_RX_MAX * TEGRA210_MIXER_REG_STRIDE) #define TEGRA210_MIXER_TX_MAX 5 #define TEGRA210_MIXER_TX_LIMIT (TEGRA210_MIXER_RX_LIMIT + (TEGRA210_MIXER_TX_MAX * TEGRA210_MIXER_REG_STRIDE)) +#define TEGRA210_MIXER_SAMPLE_COUNT_SHIFT 24 +#define TEGRA210_MIXER_SAMPLE_COUNT_ENABLE BIT(TEGRA210_MIXER_SAMPLE_COUNT_SHIFT) #define REG_CFG_DONE_TRIGGER 0xf #define VAL_CFG_DONE_TRIGGER 0x1 #define NUM_GAIN_POLY_COEFFS 9 -#define NUM_DURATION_PARMS 4 +#define TEGRA210_MIXER_GAIN_MAX 0x20000 + +#define TEGRA210_MIXER_PRESCALAR 6 +#define TEGRA210_MIXER_FADE_DURATION_MIN \ + (BIT(TEGRA210_MIXER_PRESCALAR - 1) + 1) +#define TEGRA210_MIXER_FADE_DURATION_MAX 0x7fffffff +#define TEGRA210_MIXER_FADE_IDLE 0 +#define TEGRA210_MIXER_FADE_ACTIVE 1 + +enum { + DURATION_N3_ID = 2, + DURATION_INV_N3_ID, + NUM_DURATION_PARMS, +}; struct tegra210_mixer_gain_params { int poly_coeff[NUM_GAIN_POLY_COEFFS]; @@ -94,6 +109,10 @@ struct tegra210_mixer_gain_params { struct tegra210_mixer { int gain_value[TEGRA210_MIXER_RX_MAX]; + int fade_gain[TEGRA210_MIXER_RX_MAX]; + u32 duration[TEGRA210_MIXER_RX_MAX]; + bool in_fade[TEGRA210_MIXER_RX_MAX]; + bool fade_pending[TEGRA210_MIXER_RX_MAX]; struct regmap *regmap; }; diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c index 2c299704ef4f..b55f8142c4a4 100644 --- a/sound/soc/tegra/tegra210_mvc.c +++ b/sound/soc/tegra/tegra210_mvc.c @@ -438,6 +438,9 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc, channels = params_channels(params); switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + audio_bits = TEGRA_ACIF_BITS_8; + break; case SNDRV_PCM_FORMAT_S16_LE: audio_bits = TEGRA_ACIF_BITS_16; break; diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 51e5ab6c276b..ee68f28852c4 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -509,6 +509,7 @@ static const struct of_device_id tegra30_ahub_of_match[] = { { .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 }, {}, }; +MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match); static int tegra30_ahub_probe(struct platform_device *pdev) { @@ -684,4 +685,3 @@ MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra30 AHUB driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match); diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index b121af9ef8ed..1d7b3aed51fd 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -402,6 +402,7 @@ static const struct of_device_id tegra30_i2s_of_match[] = { { .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config }, {}, }; +MODULE_DEVICE_TABLE(of, tegra30_i2s_of_match); static int tegra30_i2s_platform_probe(struct platform_device *pdev) { @@ -567,4 +568,3 @@ MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra30 I2S ASoC driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra30_i2s_of_match); diff --git a/sound/soc/tegra/tegra_isomgr_bw.c b/sound/soc/tegra/tegra_isomgr_bw.c index fa979960bc09..1c007f870759 100644 --- a/sound/soc/tegra/tegra_isomgr_bw.c +++ b/sound/soc/tegra/tegra_isomgr_bw.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include "tegra_isomgr_bw.h" @@ -55,19 +56,18 @@ int tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream, sample_bytes; } - mutex_lock(&adma_isomgr->mutex); + scoped_guard(mutex, &adma_isomgr->mutex) { + if (is_running) { + if (bandwidth + adma_isomgr->current_bandwidth > adma_isomgr->max_bw) + bandwidth = adma_isomgr->max_bw - adma_isomgr->current_bandwidth; - if (is_running) { - if (bandwidth + adma_isomgr->current_bandwidth > adma_isomgr->max_bw) - bandwidth = adma_isomgr->max_bw - adma_isomgr->current_bandwidth; - - adma_isomgr->current_bandwidth += bandwidth; - } else { - adma_isomgr->current_bandwidth -= adma_isomgr->bw_per_dev[type][pcm->device]; + adma_isomgr->current_bandwidth += bandwidth; + } else { + adma_isomgr->current_bandwidth -= + adma_isomgr->bw_per_dev[type][pcm->device]; + } } - mutex_unlock(&adma_isomgr->mutex); - adma_isomgr->bw_per_dev[type][pcm->device] = bandwidth; dev_dbg(dev, "Setting up bandwidth to %d KBps\n", adma_isomgr->current_bandwidth); diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index ba173d9fcba9..61252359d5cb 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -93,7 +93,7 @@ static unsigned short ams_delta_audio_agc; * Used for passing a codec structure pointer * from the board initialization code to the tty line discipline. */ -static struct snd_soc_component *cx20442_codec; +static struct cx20442_codec cx20442_codec; static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -105,7 +105,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, int pin, changed = 0; /* Refuse any mode changes if we are not able to control the codec. */ - if (!cx20442_codec->card->pop_time) + if (!cx20442_codec.ready) return -EUNATCH; if (ucontrol->value.enumerated.item[0] >= control->items) @@ -264,10 +264,10 @@ static void cx81801_timeout(struct timer_list *unused) { int muted; - spin_lock(&ams_delta_lock); - cx81801_cmd_pending = 0; - muted = ams_delta_muted; - spin_unlock(&ams_delta_lock); + scoped_guard(spinlock, &ams_delta_lock) { + cx81801_cmd_pending = 0; + muted = ams_delta_muted; + } /* Reconnect the codec DAI back from the modem to the CPU DAI * only if digital mute still off */ @@ -280,14 +280,14 @@ static int cx81801_open(struct tty_struct *tty) { int ret; - if (!cx20442_codec) + if (!cx20442_codec.component) return -ENODEV; /* * Pass the codec structure pointer for use by other ldisc callbacks, * both the card and the codec specific parts. */ - tty->disc_data = cx20442_codec; + tty->disc_data = &cx20442_codec; ret = v253_ops.open(tty); @@ -300,9 +300,12 @@ static int cx81801_open(struct tty_struct *tty) /* Line discipline .close() */ static void cx81801_close(struct tty_struct *tty) { - struct snd_soc_component *component = tty->disc_data; + struct snd_soc_component *component = cx20442_codec.component; struct snd_soc_dapm_context *dapm; + if (WARN_ON(tty->disc_data != &cx20442_codec)) + return; + timer_delete_sync(&cx81801_timer); /* Prevent the hook switch from further changing the DAPM pins */ @@ -339,14 +342,14 @@ static void cx81801_hangup(struct tty_struct *tty) static void cx81801_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp, size_t count) { - struct snd_soc_component *component = tty->disc_data; + struct snd_soc_component *component = cx20442_codec.component; const unsigned char *c; int apply, ret; - if (!component) + if (WARN_ON(tty->disc_data != &cx20442_codec)) return; - if (!component->card->pop_time) { + if (!cx20442_codec.ready) { /* First modem response, complete setup procedure */ /* Initialize timer used for config pulse generation */ @@ -373,11 +376,11 @@ static void cx81801_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp, continue; /* Complete modem response received, apply config to codec */ - spin_lock_bh(&ams_delta_lock); - mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150)); - apply = !ams_delta_muted && !cx81801_cmd_pending; - cx81801_cmd_pending = 1; - spin_unlock_bh(&ams_delta_lock); + scoped_guard(spinlock_bh, &ams_delta_lock) { + mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150)); + apply = !ams_delta_muted && !cx81801_cmd_pending; + cx81801_cmd_pending = 1; + } /* Apply config pulse by connecting the codec to the modem * if not already done */ @@ -426,10 +429,10 @@ static int ams_delta_mute(struct snd_soc_dai *dai, int mute, int direction) if (ams_delta_muted == mute) return 0; - spin_lock_bh(&ams_delta_lock); - ams_delta_muted = mute; - apply = !cx81801_cmd_pending; - spin_unlock_bh(&ams_delta_lock); + scoped_guard(spinlock_bh, &ams_delta_lock) { + ams_delta_muted = mute; + apply = !cx81801_cmd_pending; + } if (apply) gpiod_set_value(gpiod_modem_codec, !!mute); @@ -467,7 +470,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd) /* Codec is ready, now add/activate board specific controls */ /* Store a pointer to the codec structure for tty ldisc use */ - cx20442_codec = snd_soc_rtd_to_codec(rtd, 0)->component; + cx20442_codec.component = snd_soc_rtd_to_codec(rtd, 0)->component; /* Add hook switch - can be used to control the codec from userspace * even if line discipline fails */ diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index f229f847eaf4..79239131b659 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,14 @@ struct davinci_mcasp_ruledata { int stream; }; +enum mcasp_graph_mode { + MCASP_GRAPH_NONE, /* 1:1, simple-audio-card, no of-graph endpoints */ + MCASP_GRAPH_PORT, /* 1:1, audio-graph-card: port { endpoint } */ + MCASP_GRAPH_PORTS, /* 1:N, audio-graph-card2 non-DPCM: ports { port@0; ... } */ + MCASP_GRAPH_DPCM, /* N:M, audio-graph-card2 DPCM: N FE DAIs, detected via */ + /* remote "dpcm" node in the sound card DT */ +}; + struct davinci_mcasp { struct snd_dmaengine_dai_dma_data dma_data[2]; struct davinci_mcasp_pdata *pdata; @@ -124,6 +133,10 @@ struct davinci_mcasp { int max_format_width; u8 active_serializers[2]; + /* Audio graph support */ + enum mcasp_graph_mode graph_mode; + int num_dais; + #ifdef CONFIG_GPIOLIB struct gpio_chip gpio_chip; #endif @@ -1486,7 +1499,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + unsigned int cpu_fmt; + + if (mcasp->graph_mode != MCASP_GRAPH_NONE && rtd->dai_link->dai_fmt) + /* clock provider bits stored separately in ext_fmt */ + cpu_fmt = snd_soc_daifmt_clock_provider_flipped( + rtd->dai_link->dai_fmt) | + rtd->dai_link->cpus[0].ext_fmt; + else + cpu_fmt = mcasp->dai_fmt; + + ret = davinci_mcasp_set_dai_fmt(cpu_dai, cpu_fmt); if (ret) return ret; @@ -2029,8 +2053,31 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { }; +/* Translate of-graph endpoint to DAI ID (DPCM: port reg; else 0). */ +static int davinci_mcasp_of_xlate_dai_id(struct snd_soc_component *component, + struct device_node *endpoint) +{ + struct davinci_mcasp *mcasp = snd_soc_component_get_drvdata(component); + struct device_node *port; + u32 port_reg = 0; + + if (mcasp->graph_mode != MCASP_GRAPH_DPCM) + return 0; + + /* endpoint is inside mcasp/ports/port@N — read port's reg */ + port = of_get_parent(endpoint); + if (!port) + return -EINVAL; + + of_property_read_u32(port, "reg", &port_reg); + of_node_put(port); + + return port_reg; +} + static const struct snd_soc_component_driver davinci_mcasp_component = { .name = "davinci-mcasp", + .of_xlate_dai_id = davinci_mcasp_of_xlate_dai_id, .legacy_dai_naming = 1, }; @@ -2138,6 +2185,88 @@ static bool davinci_mcasp_have_gpiochip(struct davinci_mcasp *mcasp) return device_property_present(mcasp->dev, "gpio-controller"); } +/* Return true if the remote sound card uses a "dpcm" container. */ +static bool mcasp_detect_dpcm(struct device_node *np) +{ + struct device_node *ep, *remote_ep; + struct device_node *port, *container, *parent; + bool is_dpcm = false; + + /* Grab the first endpoint under this McASP node */ + ep = of_graph_get_next_endpoint(np, NULL); + if (!ep) + return false; + + /* Follow remote-endpoint phandle into the card node */ + remote_ep = of_graph_get_remote_endpoint(ep); + of_node_put(ep); + if (!remote_ep) + return false; + + /* Traverse the remote: remote_ep -> port -> ports@N -> dpcm */ + port = of_get_parent(remote_ep); + of_node_put(remote_ep); + if (!port) + return false; + + container = of_get_parent(port); + of_node_put(port); + if (!container) + return false; + + if (of_node_name_eq(container, "ports")) { + parent = of_get_parent(container); + of_node_put(container); + if (parent) { + is_dpcm = of_node_name_eq(parent, "dpcm"); + of_node_put(parent); + } + } else { + of_node_put(container); + } + + return is_dpcm; +} + +/* Detect audio-graph topology and return the number of DAIs to register. */ +static int davinci_mcasp_parse_of_graph(struct davinci_mcasp *mcasp, + struct device_node *np) +{ + struct device_node *port, *ports; + int num_dais = 0; + + mcasp->graph_mode = MCASP_GRAPH_NONE; + + /* audio-graph-card2: ports { port@0 ... }; DPCM -> N DAIs, else 1 */ + ports = of_get_child_by_name(np, "ports"); + if (ports) { + int port_count = of_get_child_count(ports); + + of_node_put(ports); + + if (mcasp_detect_dpcm(np)) { + num_dais = port_count; + mcasp->graph_mode = MCASP_GRAPH_DPCM; + } else { + num_dais = 1; + mcasp->graph_mode = MCASP_GRAPH_PORTS; + } + + return num_dais; + } + + /* audio-graph-card: single port { endpoint } */ + port = of_get_child_by_name(np, "port"); + if (port) { + num_dais = of_graph_get_endpoint_count(port); + if (num_dais > 0) + mcasp->graph_mode = MCASP_GRAPH_PORT; + of_node_put(port); + } + + return num_dais ? num_dais : 1; +} + static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp, struct platform_device *pdev) { @@ -2555,6 +2684,53 @@ static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp) } #endif /* CONFIG_GPIOLIB */ +static int davinci_mcasp_register_component(struct davinci_mcasp *mcasp, + struct platform_device *pdev) +{ + struct snd_soc_dai_driver *dais; + int i; + + if (mcasp->graph_mode == MCASP_GRAPH_NONE || mcasp->num_dais <= 1) + return devm_snd_soc_register_component(&pdev->dev, + &davinci_mcasp_component, + &davinci_mcasp_dai[mcasp->op_mode], 1); + + dais = devm_kcalloc(&pdev->dev, mcasp->num_dais, sizeof(*dais), + GFP_KERNEL); + if (!dais) + return -ENOMEM; + + for (i = 0; i < mcasp->num_dais; i++) { + memcpy(&dais[i], &davinci_mcasp_dai[mcasp->op_mode], + sizeof(*dais)); + dais[i].id = i; + dais[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "davinci-mcasp.%d", i); + if (!dais[i].name) + return -ENOMEM; + + /* Unique stream names per DAI */ + if (dais[i].playback.channels_min) { + dais[i].playback.stream_name = + devm_kasprintf(&pdev->dev, GFP_KERNEL, + "Playback Port %d", i); + if (!dais[i].playback.stream_name) + return -ENOMEM; + } + if (dais[i].capture.channels_min) { + dais[i].capture.stream_name = + devm_kasprintf(&pdev->dev, GFP_KERNEL, + "Capture Port %d", i); + if (!dais[i].capture.stream_name) + return -ENOMEM; + } + } + + return devm_snd_soc_register_component(&pdev->dev, + &davinci_mcasp_component, + dais, mcasp->num_dais); +} + static int davinci_mcasp_probe(struct platform_device *pdev) { struct snd_dmaengine_dai_dma_data *dma_data; @@ -2760,9 +2936,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev) goto err; } - ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, - &davinci_mcasp_dai[mcasp->op_mode], 1); + /* Parse audio-graph structure and register DAIs */ + mcasp->num_dais = davinci_mcasp_parse_of_graph(mcasp, pdev->dev.of_node); + ret = davinci_mcasp_register_component(mcasp, pdev); if (ret != 0) goto err; diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c index faa62c1a9b8e..c214ae0d7b95 100644 --- a/sound/soc/ti/j721e-evm.c +++ b/sound/soc/ti/j721e-evm.c @@ -74,7 +74,6 @@ struct j721e_audio_domain { struct j721e_priv { struct device *dev; struct snd_soc_card card; - struct snd_soc_dai_link *dai_links; struct snd_soc_codec_conf codec_conf[J721E_CODEC_CONF_COUNT]; struct snd_interval rate_range; const struct j721e_audio_match_data *match_data; @@ -84,6 +83,7 @@ struct j721e_priv { struct j721e_audio_domain audio_domains[J721E_AUDIO_DOMAIN_LAST]; struct mutex mutex; + struct snd_soc_dai_link dai_links[]; }; static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets[] = { @@ -263,7 +263,7 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream) int ret = 0; int i; - mutex_lock(&priv->mutex); + guard(mutex)(&priv->mutex); domain->active++; @@ -303,7 +303,6 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream) out: if (ret) domain->active--; - mutex_unlock(&priv->mutex); return ret; } @@ -323,30 +322,28 @@ static int j721e_audio_hw_params(struct snd_pcm_substream *substream, int ret; int i; - mutex_lock(&priv->mutex); + guard(mutex)(&priv->mutex); - if (domain->rate && domain->rate != params_rate(params)) { - ret = -EINVAL; - goto out; - } + if (domain->rate && domain->rate != params_rate(params)) + return -EINVAL; if (params_width(params) == 16) slot_width = 16; ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, slot_width); if (ret && ret != -ENOTSUPP) - goto out; + return ret; for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, slot_width); if (ret && ret != -ENOTSUPP) - goto out; + return ret; } ret = j721e_configure_refclk(priv, domain_id, params_rate(params)); if (ret) - goto out; + return ret; sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id]; for_each_rtd_codec_dais(rtd, i, codec_dai) { @@ -356,7 +353,7 @@ static int j721e_audio_hw_params(struct snd_pcm_substream *substream, dev_err(priv->dev, "codec set_sysclk failed for %u Hz\n", sysclk_rate); - goto out; + return ret; } } @@ -371,8 +368,6 @@ static int j721e_audio_hw_params(struct snd_pcm_substream *substream, ret = 0; } -out: - mutex_unlock(&priv->mutex); return ret; } @@ -383,15 +378,13 @@ static void j721e_audio_shutdown(struct snd_pcm_substream *substream) unsigned int domain_id = rtd->dai_link->id; struct j721e_audio_domain *domain = &priv->audio_domains[domain_id]; - mutex_lock(&priv->mutex); + guard(mutex)(&priv->mutex); domain->active--; if (!domain->active) { domain->rate = 0; domain->active_link = 0; } - - mutex_unlock(&priv->mutex); } static const struct snd_soc_ops j721e_audio_ops = { @@ -844,33 +837,23 @@ static int j721e_soc_probe_ivi(struct j721e_priv *priv, int *link_idx, static int j721e_soc_probe(struct platform_device *pdev) { - struct device_node *node = pdev->dev.of_node; + const struct j721e_audio_match_data *match; struct snd_soc_card *card; - const struct of_device_id *match; struct j721e_priv *priv; int link_cnt, conf_cnt, ret, i; - if (!node) { - dev_err(&pdev->dev, "of node is missing.\n"); - return -ENODEV; - } - - match = of_match_node(j721e_audio_of_match, node); + match = of_device_get_match_data(&pdev->dev); if (!match) { dev_err(&pdev->dev, "No compatible match found\n"); return -ENODEV; } - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, + struct_size(priv, dai_links, match->num_links), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->match_data = match->data; - - priv->dai_links = devm_kcalloc(&pdev->dev, priv->match_data->num_links, - sizeof(*priv->dai_links), GFP_KERNEL); - if (!priv->dai_links) - return -ENOMEM; + priv->match_data = match; for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++) priv->audio_domains[i].parent_clk_id = -1; diff --git a/sound/soc/ti/omap-dmic.c b/sound/soc/ti/omap-dmic.c index f6c393c9489d..7ca46c57566d 100644 --- a/sound/soc/ti/omap-dmic.c +++ b/sound/soc/ti/omap-dmic.c @@ -91,18 +91,14 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - int ret = 0; - mutex_lock(&dmic->mutex); + guard(mutex)(&dmic->mutex); - if (!snd_soc_dai_active(dai)) - dmic->active = 1; - else - ret = -EBUSY; + if (snd_soc_dai_active(dai)) + return -EBUSY; - mutex_unlock(&dmic->mutex); - - return ret; + dmic->active = 1; + return 0; } static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream, @@ -110,14 +106,12 @@ static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream, { struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); - mutex_lock(&dmic->mutex); + guard(mutex)(&dmic->mutex); cpu_latency_qos_remove_request(&dmic->pm_qos_req); if (!snd_soc_dai_active(dai)) dmic->active = 0; - - mutex_unlock(&dmic->mutex); } static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate) @@ -334,26 +328,24 @@ static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id, return -ENODEV; } - mutex_lock(&dmic->mutex); - if (dmic->active) { - /* disable clock while reparenting */ - pm_runtime_put_sync(dmic->dev); - ret = clk_set_parent(mux, parent_clk); - pm_runtime_get_sync(dmic->dev); - } else { - ret = clk_set_parent(mux, parent_clk); + scoped_guard(mutex, &dmic->mutex) { + if (dmic->active) { + /* disable clock while reparenting */ + pm_runtime_put_sync(dmic->dev); + ret = clk_set_parent(mux, parent_clk); + pm_runtime_get_sync(dmic->dev); + } else { + ret = clk_set_parent(mux, parent_clk); + } } - mutex_unlock(&dmic->mutex); if (ret < 0) { dev_err(dmic->dev, "re-parent failed\n"); - goto err_busy; + } else { + dmic->sysclk = clk_id; + dmic->fclk_freq = freq; } - dmic->sysclk = clk_id; - dmic->fclk_freq = freq; - -err_busy: clk_put(mux); clk_put(parent_clk); diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index 55e7cb96858f..e60f5b483fc5 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -49,7 +49,7 @@ static void hdmi_dai_abort(struct device *dev) { struct hdmi_audio_data *ad = dev_get_drvdata(dev); - mutex_lock(&ad->current_stream_lock); + guard(mutex)(&ad->current_stream_lock); if (ad->current_stream && ad->current_stream->runtime && snd_pcm_running(ad->current_stream)) { dev_err(dev, "HDMI display disabled, aborting playback\n"); @@ -57,7 +57,6 @@ static void hdmi_dai_abort(struct device *dev) snd_pcm_stop(ad->current_stream, SNDRV_PCM_STATE_DISCONNECTED); snd_pcm_stream_unlock_irq(ad->current_stream); } - mutex_unlock(&ad->current_stream_lock); } static int hdmi_dai_startup(struct snd_pcm_substream *substream, @@ -86,16 +85,14 @@ static int hdmi_dai_startup(struct snd_pcm_substream *substream, snd_soc_dai_set_dma_data(dai, substream, &ad->dma_data); - mutex_lock(&ad->current_stream_lock); - ad->current_stream = substream; - mutex_unlock(&ad->current_stream_lock); + scoped_guard(mutex, &ad->current_stream_lock) + ad->current_stream = substream; ret = ad->ops->audio_startup(ad->dssdev, hdmi_dai_abort); if (ret) { - mutex_lock(&ad->current_stream_lock); - ad->current_stream = NULL; - mutex_unlock(&ad->current_stream_lock); + scoped_guard(mutex, &ad->current_stream_lock) + ad->current_stream = NULL; } return ret; @@ -261,9 +258,8 @@ static void hdmi_dai_shutdown(struct snd_pcm_substream *substream, ad->ops->audio_shutdown(ad->dssdev); - mutex_lock(&ad->current_stream_lock); - ad->current_stream = NULL; - mutex_unlock(&ad->current_stream_lock); + scoped_guard(mutex, &ad->current_stream_lock) + ad->current_stream = NULL; } static const struct snd_soc_dai_ops hdmi_dai_ops = { diff --git a/sound/soc/ti/omap-mcbsp-st.c b/sound/soc/ti/omap-mcbsp-st.c index 901578896ef3..b762d5d3e33b 100644 --- a/sound/soc/ti/omap-mcbsp-st.c +++ b/sound/soc/ti/omap-mcbsp-st.c @@ -156,7 +156,7 @@ static int omap_mcbsp_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, if (!st_data) return -ENOENT; - spin_lock_irq(&mcbsp->lock); + guard(spinlock_irq)(&mcbsp->lock); if (channel == 0) st_data->ch0gain = chgain; else if (channel == 1) @@ -166,7 +166,6 @@ static int omap_mcbsp_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, if (st_data->enabled) omap_mcbsp_st_chgain(mcbsp); - spin_unlock_irq(&mcbsp->lock); return ret; } @@ -180,14 +179,13 @@ static int omap_mcbsp_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, if (!st_data) return -ENOENT; - spin_lock_irq(&mcbsp->lock); + guard(spinlock_irq)(&mcbsp->lock); if (channel == 0) *chgain = st_data->ch0gain; else if (channel == 1) *chgain = st_data->ch1gain; else ret = -EINVAL; - spin_unlock_irq(&mcbsp->lock); return ret; } @@ -199,10 +197,9 @@ static int omap_mcbsp_st_enable(struct omap_mcbsp *mcbsp) if (!st_data) return -ENODEV; - spin_lock_irq(&mcbsp->lock); + guard(spinlock_irq)(&mcbsp->lock); st_data->enabled = 1; omap_mcbsp_st_start(mcbsp); - spin_unlock_irq(&mcbsp->lock); return 0; } @@ -215,10 +212,9 @@ static int omap_mcbsp_st_disable(struct omap_mcbsp *mcbsp) if (!st_data) return -ENODEV; - spin_lock_irq(&mcbsp->lock); + guard(spinlock_irq)(&mcbsp->lock); omap_mcbsp_st_stop(mcbsp); st_data->enabled = 0; - spin_unlock_irq(&mcbsp->lock); return ret; } @@ -241,13 +237,12 @@ static ssize_t st_taps_show(struct device *dev, ssize_t status = 0; int i; - spin_lock_irq(&mcbsp->lock); + guard(spinlock_irq)(&mcbsp->lock); for (i = 0; i < st_data->nr_taps; i++) status += sysfs_emit_at(buf, status, (i ? ", %d" : "%d"), st_data->taps[i]); if (i) status += sysfs_emit_at(buf, status, "\n"); - spin_unlock_irq(&mcbsp->lock); return status; } @@ -260,19 +255,17 @@ static ssize_t st_taps_store(struct device *dev, struct omap_mcbsp_st_data *st_data = mcbsp->st_data; int val, tmp, status, i = 0; - spin_lock_irq(&mcbsp->lock); + guard(spinlock_irq)(&mcbsp->lock); memset(st_data->taps, 0, sizeof(st_data->taps)); st_data->nr_taps = 0; do { status = sscanf(buf, "%d%n", &val, &tmp); if (status < 0 || status == 0) { - size = -EINVAL; - goto out; + return -EINVAL; } if (val < -32768 || val > 32767) { - size = -EINVAL; - goto out; + return -EINVAL; } st_data->taps[i++] = val; buf += tmp; @@ -283,9 +276,6 @@ static ssize_t st_taps_store(struct device *dev, st_data->nr_taps = i; -out: - spin_unlock_irq(&mcbsp->lock); - return size; } diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 411970399271..26af616c33f5 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -290,25 +290,24 @@ static u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp) static int omap_mcbsp_request(struct omap_mcbsp *mcbsp) { - void *reg_cache; + void *reg_cache __free(kfree) = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL); int err; - reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL); if (!reg_cache) return -ENOMEM; - spin_lock(&mcbsp->lock); - if (!mcbsp->free) { - dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id); - err = -EBUSY; - goto err_kfree; + scoped_guard(spinlock, &mcbsp->lock) { + if (!mcbsp->free) { + dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id); + return -EBUSY; + } + + mcbsp->free = false; + mcbsp->reg_cache = reg_cache; + reg_cache = NULL; } - mcbsp->free = false; - mcbsp->reg_cache = reg_cache; - spin_unlock(&mcbsp->lock); - - if(mcbsp->pdata->ops && mcbsp->pdata->ops->request) + if (mcbsp->pdata->ops && mcbsp->pdata->ops->request) mcbsp->pdata->ops->request(mcbsp->id - 1); /* @@ -323,43 +322,40 @@ static int omap_mcbsp_request(struct omap_mcbsp *mcbsp) "McBSP", (void *)mcbsp); if (err != 0) { dev_err(mcbsp->dev, "Unable to request IRQ\n"); - goto err_clk_disable; } } else { err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0, "McBSP TX", (void *)mcbsp); if (err != 0) { dev_err(mcbsp->dev, "Unable to request TX IRQ\n"); - goto err_clk_disable; - } - - err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0, - "McBSP RX", (void *)mcbsp); - if (err != 0) { - dev_err(mcbsp->dev, "Unable to request RX IRQ\n"); - goto err_free_irq; + } else { + err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0, + "McBSP RX", (void *)mcbsp); + if (err != 0) { + dev_err(mcbsp->dev, "Unable to request RX IRQ\n"); + free_irq(mcbsp->tx_irq, (void *)mcbsp); + } } } + if (err != 0) { + if (mcbsp->pdata->ops && mcbsp->pdata->ops->free) + mcbsp->pdata->ops->free(mcbsp->id - 1); + + /* Disable wakeup behavior */ + if (mcbsp->pdata->has_wakeup) + MCBSP_WRITE(mcbsp, WAKEUPEN, 0); + + scoped_guard(spinlock, &mcbsp->lock) { + reg_cache = mcbsp->reg_cache; + mcbsp->free = true; + mcbsp->reg_cache = NULL; + } + + return err; + } + return 0; -err_free_irq: - free_irq(mcbsp->tx_irq, (void *)mcbsp); -err_clk_disable: - if(mcbsp->pdata->ops && mcbsp->pdata->ops->free) - mcbsp->pdata->ops->free(mcbsp->id - 1); - - /* Disable wakeup behavior */ - if (mcbsp->pdata->has_wakeup) - MCBSP_WRITE(mcbsp, WAKEUPEN, 0); - - spin_lock(&mcbsp->lock); - mcbsp->free = true; - mcbsp->reg_cache = NULL; -err_kfree: - spin_unlock(&mcbsp->lock); - kfree(reg_cache); - - return err; } static void omap_mcbsp_free(struct omap_mcbsp *mcbsp) @@ -395,13 +391,13 @@ static void omap_mcbsp_free(struct omap_mcbsp *mcbsp) if (!mcbsp_omap1()) omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC); - spin_lock(&mcbsp->lock); - if (mcbsp->free) - dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); - else - mcbsp->free = true; - mcbsp->reg_cache = NULL; - spin_unlock(&mcbsp->lock); + scoped_guard(spinlock, &mcbsp->lock) { + if (mcbsp->free) + dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); + else + mcbsp->free = true; + mcbsp->reg_cache = NULL; + } kfree(reg_cache); } @@ -581,16 +577,12 @@ static ssize_t dma_op_mode_store(struct device *dev, if (i < 0) return i; - spin_lock_irq(&mcbsp->lock); + guard(spinlock_irq)(&mcbsp->lock); if (!mcbsp->free) { - size = -EBUSY; - goto unlock; + return -EBUSY; } mcbsp->dma_op_mode = i; -unlock: - spin_unlock_irq(&mcbsp->lock); - return size; } diff --git a/sound/soc/ti/omap-mcpdm.c b/sound/soc/ti/omap-mcpdm.c index 1a5d19937c64..c7d7b502f120 100644 --- a/sound/soc/ti/omap-mcpdm.c +++ b/sound/soc/ti/omap-mcpdm.c @@ -251,13 +251,11 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); - mutex_lock(&mcpdm->mutex); + guard(mutex)(&mcpdm->mutex); if (!snd_soc_dai_active(dai)) omap_mcpdm_open_streams(mcpdm); - mutex_unlock(&mcpdm->mutex); - return 0; } @@ -269,7 +267,7 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - mutex_lock(&mcpdm->mutex); + guard(mutex)(&mcpdm->mutex); if (!snd_soc_dai_active(dai)) { if (omap_mcpdm_active(mcpdm)) { @@ -287,8 +285,6 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, cpu_latency_qos_remove_request(&mcpdm->pm_qos_req); mcpdm->latency[stream1] = 0; - - mutex_unlock(&mcpdm->mutex); } static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, diff --git a/sound/soc/ti/omap3pandora.c b/sound/soc/ti/omap3pandora.c index f11b1d8a1306..6c9c184cd9d6 100644 --- a/sound/soc/ti/omap3pandora.c +++ b/sound/soc/ti/omap3pandora.c @@ -11,12 +11,12 @@ #include #include #include +#include #include #include #include -#include #include #include "omap-mcbsp.h" @@ -225,7 +225,8 @@ static int __init omap3pandora_soc_init(void) { int ret; - if (!machine_is_omap3_pandora()) + if (!of_machine_is_compatible("openpandora,omap3-pandora-600mhz") && + !of_machine_is_compatible("openpandora,omap3-pandora-1ghz")) return -ENODEV; pr_info("OMAP3 Pandora SoC init\n"); diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 7eeb12e5066c..cfc23e0838c2 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -19,8 +19,6 @@ #include #include -#include - #include "omap-mcbsp.h" enum { @@ -364,7 +362,7 @@ static int rx51_soc_probe(struct platform_device *pdev) struct snd_soc_card *card = &rx51_sound_card; int err; - if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900")) + if (!of_machine_is_compatible("nokia,omap3-n900")) return -ENODEV; card->dev = &pdev->dev; diff --git a/sound/soc/uniphier/aio-compress.c b/sound/soc/uniphier/aio-compress.c index b18af98a552b..57247a03b5c9 100644 --- a/sound/soc/uniphier/aio-compress.c +++ b/sound/soc/uniphier/aio-compress.c @@ -183,18 +183,16 @@ static int uniphier_aio_compr_prepare(struct snd_soc_component *component, struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; int bytes = runtime->fragment_size; - unsigned long flags; int ret; ret = aiodma_ch_set_param(sub); if (ret) return ret; - spin_lock_irqsave(&sub->lock, flags); - ret = aiodma_rb_set_buffer(sub, sub->compr_addr, - sub->compr_addr + sub->compr_bytes, - bytes); - spin_unlock_irqrestore(&sub->lock, flags); + scoped_guard(spinlock_irqsave, &sub->lock) + ret = aiodma_rb_set_buffer(sub, sub->compr_addr, + sub->compr_addr + sub->compr_bytes, + bytes); if (ret) return ret; @@ -223,9 +221,8 @@ static int uniphier_aio_compr_trigger(struct snd_soc_component *component, struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; struct device *dev = &aio->chip->pdev->dev; int bytes = runtime->fragment_size, ret = 0; - unsigned long flags; - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); @@ -242,7 +239,6 @@ static int uniphier_aio_compr_trigger(struct snd_soc_component *component, dev_warn(dev, "Unknown trigger(%d)\n", cmd); ret = -EINVAL; } - spin_unlock_irqrestore(&sub->lock, flags); return ret; } @@ -256,10 +252,9 @@ static int uniphier_aio_compr_pointer(struct snd_soc_component *component, struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0)); struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; int bytes = runtime->fragment_size; - unsigned long flags; u32 pos; - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); @@ -273,8 +268,6 @@ static int uniphier_aio_compr_pointer(struct snd_soc_component *component, } tstamp->byte_offset = pos; - spin_unlock_irqrestore(&sub->lock, flags); - return 0; } @@ -332,7 +325,6 @@ static int uniphier_aio_compr_copy(struct snd_soc_component *component, struct uniphier_aio_sub *sub = &aio->sub[cstream->direction]; size_t cnt = min_t(size_t, count, aio_rb_space_to_end(sub) / 2); int bytes = runtime->fragment_size; - unsigned long flags; size_t s; int ret; @@ -360,7 +352,7 @@ static int uniphier_aio_compr_copy(struct snd_soc_component *component, if (ret) return -EFAULT; - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); sub->threshold = 2 * bytes; aiodma_rb_set_threshold(sub, sub->compr_bytes, 2 * bytes); @@ -376,8 +368,6 @@ static int uniphier_aio_compr_copy(struct snd_soc_component *component, } aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); - spin_unlock_irqrestore(&sub->lock, flags); - return cnt; } diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index c1ca55997103..c01eae55d4fc 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c @@ -32,15 +32,15 @@ static void aiodma_pcm_irq(struct uniphier_aio_sub *sub) runtime->channels * samples_to_bytes(runtime, 1); int ret; - spin_lock(&sub->lock); - ret = aiodma_rb_set_threshold(sub, runtime->dma_bytes, - sub->threshold + bytes); - if (!ret) - sub->threshold += bytes; + scoped_guard(spinlock, &sub->lock) { + ret = aiodma_rb_set_threshold(sub, runtime->dma_bytes, + sub->threshold + bytes); + if (!ret) + sub->threshold += bytes; - aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes, bytes); - aiodma_rb_clear_irq(sub); - spin_unlock(&sub->lock); + aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes, bytes); + aiodma_rb_clear_irq(sub); + } snd_pcm_period_elapsed(sub->substream); } @@ -51,15 +51,15 @@ static void aiodma_compr_irq(struct uniphier_aio_sub *sub) int bytes = runtime->fragment_size; int ret; - spin_lock(&sub->lock); - ret = aiodma_rb_set_threshold(sub, sub->compr_bytes, - sub->threshold + bytes); - if (!ret) - sub->threshold += bytes; + scoped_guard(spinlock, &sub->lock) { + ret = aiodma_rb_set_threshold(sub, sub->compr_bytes, + sub->threshold + bytes); + if (!ret) + sub->threshold += bytes; - aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); - aiodma_rb_clear_irq(sub); - spin_unlock(&sub->lock); + aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes); + aiodma_rb_clear_irq(sub); + } snd_compr_fragment_elapsed(sub->cstream); } @@ -113,18 +113,16 @@ static int uniphier_aiodma_prepare(struct snd_soc_component *component, struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; int bytes = runtime->period_size * runtime->channels * samples_to_bytes(runtime, 1); - unsigned long flags; int ret; ret = aiodma_ch_set_param(sub); if (ret) return ret; - spin_lock_irqsave(&sub->lock, flags); - ret = aiodma_rb_set_buffer(sub, runtime->dma_addr, - runtime->dma_addr + runtime->dma_bytes, - bytes); - spin_unlock_irqrestore(&sub->lock, flags); + scoped_guard(spinlock_irqsave, &sub->lock) + ret = aiodma_rb_set_buffer(sub, runtime->dma_addr, + runtime->dma_addr + runtime->dma_bytes, + bytes); if (ret) return ret; @@ -141,9 +139,8 @@ static int uniphier_aiodma_trigger(struct snd_soc_component *component, struct device *dev = &aio->chip->pdev->dev; int bytes = runtime->period_size * runtime->channels * samples_to_bytes(runtime, 1); - unsigned long flags; - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); switch (cmd) { case SNDRV_PCM_TRIGGER_START: aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes, @@ -161,7 +158,6 @@ static int uniphier_aiodma_trigger(struct snd_soc_component *component, dev_warn(dev, "Unknown trigger(%d) ignored\n", cmd); break; } - spin_unlock_irqrestore(&sub->lock, flags); return 0; } @@ -176,17 +172,15 @@ static snd_pcm_uframes_t uniphier_aiodma_pointer( struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; int bytes = runtime->period_size * runtime->channels * samples_to_bytes(runtime, 1); - unsigned long flags; snd_pcm_uframes_t pos; - spin_lock_irqsave(&sub->lock, flags); + guard(spinlock_irqsave)(&sub->lock); aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes, bytes); if (sub->swm->dir == PORT_DIR_OUTPUT) pos = bytes_to_frames(runtime, sub->rd_offs); else pos = bytes_to_frames(runtime, sub->wr_offs); - spin_unlock_irqrestore(&sub->lock, flags); return pos; } diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c index 2e6ed19a18cd..2a459267f0f9 100644 --- a/sound/soc/ux500/mop500_ab8500.c +++ b/sound/soc/ux500/mop500_ab8500.c @@ -234,19 +234,18 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream, substream->number); /* Ensure configuration consistency between DAIs */ - mutex_lock(&mop500_ab8500_params_lock); - if (mop500_ab8500_usage) { - if (mop500_ab8500_rate != params_rate(params) || - mop500_ab8500_channels != params_channels(params)) { - mutex_unlock(&mop500_ab8500_params_lock); - return -EBUSY; + scoped_guard(mutex, &mop500_ab8500_params_lock) { + if (mop500_ab8500_usage) { + if (mop500_ab8500_rate != params_rate(params) || + mop500_ab8500_channels != params_channels(params)) { + return -EBUSY; + } + } else { + mop500_ab8500_rate = params_rate(params); + mop500_ab8500_channels = params_channels(params); } - } else { - mop500_ab8500_rate = params_rate(params); - mop500_ab8500_channels = params_channels(params); + __set_bit(cpu_dai->id, &mop500_ab8500_usage); } - __set_bit(cpu_dai->id, &mop500_ab8500_usage); - mutex_unlock(&mop500_ab8500_params_lock); channels = params_channels(params); @@ -339,9 +338,8 @@ static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - mutex_lock(&mop500_ab8500_params_lock); + guard(mutex)(&mop500_ab8500_params_lock); __clear_bit(cpu_dai->id, &mop500_ab8500_usage); - mutex_unlock(&mop500_ab8500_params_lock); return 0; } diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 2ed01e9d79bb..01ad5b12b680 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c @@ -132,19 +132,15 @@ snd_emux_create_port(struct snd_emux *emu, char *name, int i, type, cap; /* Allocate structures for this channel */ - p = kzalloc_obj(*p); + p = kzalloc_flex(*p, chset.channels, max_channels); if (!p) return NULL; - p->chset.channels = kzalloc_objs(*p->chset.channels, max_channels); - if (!p->chset.channels) { - kfree(p); - return NULL; - } + p->chset.max_channels = max_channels; + for (i = 0; i < max_channels; i++) p->chset.channels[i].number = i; p->chset.private_data = p; - p->chset.max_channels = max_channels; p->emu = emu; p->chset.client = emu->client; #ifdef SNDRV_EMUX_USE_RAW_EFFECT @@ -182,7 +178,6 @@ free_port(void *private_data) #ifdef SNDRV_EMUX_USE_RAW_EFFECT snd_emux_delete_effect(p); #endif - kfree(p->chset.channels); kfree(p); } } diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index c77a21a9acd7..10104cb42165 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -582,30 +582,31 @@ int usb6fire_control_init(struct sfire_chip *chip) "Master Playback Volume", vol_elements); if (ret) { dev_err(&chip->dev->dev, "cannot add control.\n"); - kfree(rt); - return ret; + goto free_rt; } ret = usb6fire_control_add_virtual(rt, chip->card, "Master Playback Switch", mute_elements); if (ret) { dev_err(&chip->dev->dev, "cannot add control.\n"); - kfree(rt); - return ret; + goto free_rt; } i = 0; while (elements[i].name) { ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt)); if (ret < 0) { - kfree(rt); dev_err(&chip->dev->dev, "cannot add control.\n"); - return ret; + goto free_rt; } i++; } chip->control = rt; return 0; + +free_rt: + kfree(rt); + return ret; } void usb6fire_control_abort(struct sfire_chip *chip) diff --git a/sound/usb/card.c b/sound/usb/card.c index f42d72cd0378..6a3b576fb067 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -769,7 +769,6 @@ static int snd_usb_audio_create(struct usb_interface *intf, chip = card->private_data; mutex_init(&chip->mutex); - init_waitqueue_head(&chip->shutdown_wait); chip->index = idx; chip->dev = dev; chip->card = card; @@ -778,7 +777,7 @@ static int snd_usb_audio_create(struct usb_interface *intf, chip->autoclock = autoclock; chip->lowlatency = lowlatency; atomic_set(&chip->active, 1); /* avoid autopm during probing */ - atomic_set(&chip->usage_count, 0); + snd_refcount_init(&chip->usage_count); atomic_set(&chip->shutdown, 0); chip->usb_id = usb_id; @@ -1107,8 +1106,7 @@ static bool __usb_audio_disconnect(struct usb_interface *intf, /* wait until all pending tasks done; * they are protected by snd_usb_lock_shutdown() */ - wait_event(chip->shutdown_wait, - !atomic_read(&chip->usage_count)); + snd_refcount_sync(&chip->usage_count); snd_card_disconnect(card); /* release the pcm resources */ list_for_each_entry(as, &chip->pcm_list, list) { @@ -1166,7 +1164,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip) { int err; - atomic_inc(&chip->usage_count); + snd_refcount_get(&chip->usage_count); if (atomic_read(&chip->shutdown)) { err = -EIO; goto error; @@ -1177,8 +1175,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip) return 0; error: - if (atomic_dec_and_test(&chip->usage_count)) - wake_up(&chip->shutdown_wait); + snd_refcount_put(&chip->usage_count); return err; } EXPORT_SYMBOL_GPL(snd_usb_lock_shutdown); @@ -1187,8 +1184,7 @@ EXPORT_SYMBOL_GPL(snd_usb_lock_shutdown); void snd_usb_unlock_shutdown(struct snd_usb_audio *chip) { snd_usb_autosuspend(chip); - if (atomic_dec_and_test(&chip->usage_count)) - wake_up(&chip->shutdown_wait); + snd_refcount_put(&chip->usage_count); } EXPORT_SYMBOL_GPL(snd_usb_unlock_shutdown); diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 6fbcb117555c..24cd7692bd01 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1780,8 +1780,16 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep, /* * skip empty packets. At least M-Audio's Fast Track Ultra stops * streaming once it received a 0-byte OUT URB + * + * However, on devices where bytes==0 means every sync-source + * packet errored (e.g. Behringer Flow 8 returning -EXDEV bursts + * for entire capture URBs), an unconditional return starves the + * IFB-fed OUT ring permanently. Such devices set + * QUIRK_FLAG_IFB_SILENCE_ON_EMPTY to fall through and enqueue a + * packet_info with size 0 packets, so playback emits silence + * and the OUT ring keeps moving. */ - if (bytes == 0) + if (bytes == 0 && !(ep->chip->quirk_flags & QUIRK_FLAG_IFB_SILENCE_ON_EMPTY)) return; spin_lock_irqsave(&ep->lock, flags); diff --git a/sound/usb/fcp.c b/sound/usb/fcp.c index 0fc4d063c48a..ea746bdb36ff 100644 --- a/sound/usb/fcp.c +++ b/sound/usb/fcp.c @@ -191,13 +191,13 @@ static int fcp_usb(struct usb_mixer_interface *mixer, u32 opcode, struct fcp_usb_packet *req __free(kfree) = NULL; size_t req_buf_size = struct_size(req, data, req_size); - req = kmalloc(req_buf_size, GFP_KERNEL); + req = kmalloc_flex(*req, data, req_size); if (!req) return -ENOMEM; struct fcp_usb_packet *resp __free(kfree) = NULL; size_t resp_buf_size = struct_size(resp, data, resp_size); - resp = kmalloc(resp_buf_size, GFP_KERNEL); + resp = kmalloc_flex(*resp, data, resp_size); if (!resp) return -ENOMEM; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fb37bb8ad9a9..b4c855c25eef 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -434,6 +434,11 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval, *value = cval->cache_val[index]; return 0; } + + /* The current value is always provided by the cache after initialization. */ + if (cval->get_cur_broken) + return -ENXIO; + err = get_cur_mix_raw(cval, channel, value); if (err < 0) { if (!cval->head.mixer->ignore_ctl_error) @@ -665,17 +670,13 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter return 0; switch (iterm->type >> 16) { case UAC3_SELECTOR_UNIT: - strscpy(name, "Selector", maxlen); - return 8; + return strscpy(name, "Selector", maxlen); case UAC3_PROCESSING_UNIT: - strscpy(name, "Process Unit", maxlen); - return 12; + return strscpy(name, "Process Unit", maxlen); case UAC3_EXTENSION_UNIT: - strscpy(name, "Ext Unit", maxlen); - return 8; + return strscpy(name, "Ext Unit", maxlen); case UAC3_MIXER_UNIT: - strscpy(name, "Mixer", maxlen); - return 5; + return strscpy(name, "Mixer", maxlen); default: return scnprintf(name, maxlen, "Unit %d", iterm->id); } @@ -683,25 +684,18 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter switch (iterm->type & 0xff00) { case 0x0100: - strscpy(name, "PCM", maxlen); - return 3; + return strscpy(name, "PCM", maxlen); case 0x0200: - strscpy(name, "Mic", maxlen); - return 3; + return strscpy(name, "Mic", maxlen); case 0x0400: - strscpy(name, "Headset", maxlen); - return 7; + return strscpy(name, "Headset", maxlen); case 0x0500: - strscpy(name, "Phone", maxlen); - return 5; + return strscpy(name, "Phone", maxlen); } - for (names = iterm_names; names->type; names++) { - if (names->type == iterm->type) { - strscpy(name, names->name, maxlen); - return strlen(names->name); - } - } + for (names = iterm_names; names->type; names++) + if (names->type == iterm->type) + return strscpy(name, names->name, maxlen); return 0; } @@ -1234,7 +1228,7 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx) err = snd_usb_get_cur_mix_value(cval, ch, idx, &val); if (!err) return; - if (!cval->head.mixer->ignore_ctl_error) + if (!cval->head.mixer->ignore_ctl_error && !cval->get_cur_broken) usb_audio_warn(cval->head.mixer->chip, "%d:%d: failed to get current value for ch %d (%d)\n", cval->head.id, mixer_ctrl_intf(cval->head.mixer), @@ -1248,8 +1242,16 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx) * Some devices' volume control mixers are sticky, which accept SET_CUR but * do absolutely nothing. * - * Prevent sticky mixers from being registered, otherwise they confuses - * userspace and results in ineffective volume control. + * Check the return values of GET_CUR with different SET_CUR values. Consider + * the mixer as sticky if GET_CUR always returns a constant value. + * + * Some devices have effective SET_CUR despite GET_CUR being constant. Do not + * consider the mixer as sticky if a quirk flag indicates that. + * + * Gate the registration of sticky mixers to prevent confusing userspace, so + * that they won't cause ineffective volume control. However, for mixers with + * effective SET_CUR but broken GET_CUR, the registration can continue normally + * but further GET_CUR requests will be gated. */ static int check_sticky_volume_control(struct usb_mixer_elem_info *cval, int channel, int saved) @@ -1269,10 +1271,22 @@ static int check_sticky_volume_control(struct usb_mixer_elem_info *cval, return 0; } + if (cval->head.mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_GET_CUR_BROKEN) { + usb_audio_info(cval->head.mixer->chip, + "%d:%d: broken mixer GET_CUR (%d/%d/%d => %d)\n", + cval->head.id, mixer_ctrl_intf(cval->head.mixer), + cval->min, cval->max, cval->res, saved); + + cval->get_cur_broken = 1; + return -ENXIO; + } + usb_audio_err(cval->head.mixer->chip, "%d:%d: sticky mixer values (%d/%d/%d => %d), disabling\n", cval->head.id, mixer_ctrl_intf(cval->head.mixer), cval->min, cval->max, cval->res, saved); + usb_audio_info(cval->head.mixer->chip, + "check MIXER_GET_CUR_BROKEN if you believe the mixer is non-sticky"); return -ENODEV; } @@ -1315,7 +1329,7 @@ static void check_volume_control_res(struct usb_mixer_elem_info *cval, static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, int default_min, struct snd_kcontrol *kctl) { - int i, idx, ret; + int i, idx, ret = 0; /* for failsafe */ cval->min = default_min; @@ -1371,8 +1385,10 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, goto no_checks; ret = check_sticky_volume_control(cval, minchn, saved); - if (ret < 0) + if (ret == -ENODEV) goto sticky; + if (ret) + goto no_checks; if (cval->min + cval->res < cval->max) check_volume_control_res(cval, minchn, saved); @@ -1381,6 +1397,16 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval, } no_checks: + /* + * Got a non-fatal failure during sanity checks. + * + * Do not propagate mixer values written by sanity checks. + * Instead, rely on init_cur_mix_raw() to initialize the mixer + * properly. + */ + if (ret) + cval->cached = 0; + cval->initialized = 1; } @@ -1561,7 +1587,10 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, return -EINVAL; val = get_abs_value(cval, val); if (oval != val) { - snd_usb_set_cur_mix_value(cval, c + 1, cnt, val); + err = snd_usb_set_cur_mix_value(cval, c + 1, + cnt, val); + if (err < 0) + return filter_error(cval, err); changed = 1; } cnt++; @@ -1576,7 +1605,9 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { - snd_usb_set_cur_mix_value(cval, 0, 0, val); + err = snd_usb_set_cur_mix_value(cval, 0, 0, val); + if (err < 0) + return filter_error(cval, err); changed = 1; } } @@ -2013,7 +2044,9 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer, int name_len = get_term_name(mixer->chip, term, name, name_size, 0); if (name_len == 0) - strscpy(name, "Unknown", name_size); + name_len = strscpy(name, "Unknown", name_size); + if (name_len < 0) + return; /* * sound/core/ctljack.c has a convention of naming jack controls @@ -2021,9 +2054,9 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer, * indicating Input or Output after the terminal name. */ if (is_input) - strlcat(name, " - Input Jack", name_size); + strscpy(name + name_len, " - Input Jack", name_size - name_len); else - strlcat(name, " - Output Jack", name_size); + strscpy(name + name_len, " - Output Jack", name_size - name_len); } /* get connector value to "wake up" the USB audio */ @@ -2501,7 +2534,9 @@ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { - set_cur_ctl_value(cval, cval->control << 8, val); + err = set_cur_ctl_value(cval, cval->control << 8, val); + if (err < 0) + return filter_error(cval, err); return 1; } return 0; @@ -2867,7 +2902,9 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { - set_cur_ctl_value(cval, cval->control << 8, val); + err = set_cur_ctl_value(cval, cval->control << 8, val); + if (err < 0) + return filter_error(cval, err); return 1; } return 0; @@ -3538,7 +3575,8 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) continue; info = mixer_elem_list_to_info(list); /* invalidate cache, so the value is read from the device */ - info->cached = 0; + if (!info->get_cur_broken) + info->cached = 0; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &list->kctl->id); } @@ -3635,10 +3673,12 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, switch (attribute) { case UAC2_CS_CUR: /* invalidate cache, so the value is read from the device */ - if (channel) - info->cached &= ~BIT(channel); - else /* master channel */ - info->cached = 0; + if (!info->get_cur_broken) { + if (channel) + info->cached &= ~BIT(channel); + else /* master channel */ + info->cached = 0; + } snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &info->head.kctl->id); diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index afbb3dd9f177..3fa1bd96f858 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -94,6 +94,7 @@ struct usb_mixer_elem_info { int cache_val[MAX_CHANNELS]; u8 initialized; u8 min_mute; + u8 get_cur_broken; void *private_data; }; diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 1bdaa46d4fe1..628f841b04aa 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -333,6 +333,7 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, int index = kcontrol->private_value & 0xff; unsigned int value = ucontrol->value.integer.value[0]; int old_value = kcontrol->private_value >> 8; + unsigned long old_pval = kcontrol->private_value; int err; if (value > 1) @@ -341,7 +342,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, return 0; kcontrol->private_value = (value << 8) | index; err = snd_audigy2nx_led_update(mixer, value, index); - return err < 0 ? err : 1; + if (err < 0) { + kcontrol->private_value = old_pval; + return err; + } + return 1; } static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list) @@ -487,6 +492,7 @@ static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol, struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); struct usb_mixer_interface *mixer = list->mixer; unsigned int value = ucontrol->value.enumerated.item[0]; + unsigned long old_pval = kcontrol->private_value; int err; if (value > 1) @@ -497,7 +503,11 @@ static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol, kcontrol->private_value = value; err = snd_emu0204_ch_switch_update(mixer, value); - return err < 0 ? err : 1; + if (err < 0) { + kcontrol->private_value = old_pval; + return err; + } + return 1; } static int snd_emu0204_ch_switch_resume(struct usb_mixer_elem_list *list) @@ -821,7 +831,11 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, kcontrol->private_value = new_status; err = snd_xonar_u1_switch_update(list->mixer, new_status); - return err < 0 ? err : 1; + if (err < 0) { + kcontrol->private_value = old_status; + return err; + } + return 1; } static int snd_xonar_u1_switch_resume(struct usb_mixer_elem_list *list) @@ -1159,7 +1173,8 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); - u8 oldval = (kcontrol->private_value >> 24) & 0xff; + unsigned long old_pval = kcontrol->private_value; + u8 oldval = (old_pval >> 24) & 0xff; u8 newval = ucontrol->value.integer.value[0]; int err; @@ -1169,7 +1184,11 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, kcontrol->private_value &= ~(0xff << 24); kcontrol->private_value |= (unsigned int)newval << 24; err = snd_ni_update_cur_val(list); - return err < 0 ? err : 1; + if (err < 0) { + kcontrol->private_value = old_pval; + return err; + } + return 1; } static const struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { @@ -1282,7 +1301,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer, err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - pval & 0xff00, + (pval & 0xff00) | ((pval & 0xff0000) >> 16), snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8), value, 2); if (err < 0) @@ -1315,7 +1334,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list) usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - pval & 0xff00, + (pval & 0xff00) | ((pval & 0xff0000) >> 16), snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8), value, 2); } @@ -1324,7 +1343,8 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); - unsigned int pval = list->kctl->private_value; + unsigned long old_pval = list->kctl->private_value; + unsigned int pval = old_pval; int cur_val, err, new_val; cur_val = pval >> 24; @@ -1335,7 +1355,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, kctl->private_value &= ~(0xff << 24); kctl->private_value |= new_val << 24; err = snd_ftu_eff_switch_update(list); - return err < 0 ? err : 1; + if (err < 0) { + kctl->private_value = old_pval; + return err; + } + return 1; } static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, @@ -1730,6 +1754,44 @@ static int snd_c400_create_effect_ret_vol_ctls(struct usb_mixer_interface *mixer return 0; } +/* output gain knob selectively adjusts outputs as stereo pairs */ +/* reuses functions from FTU effect switch */ +static int snd_c400_knob_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static const char *const texts[8] = { + "None", "1/2", "3/4", "1/2 3/4", + "5/6", "1/2 5/6", "3/4 5/6", "1/2 3/4 5/6" + }; + + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); +} + +static int snd_c400_create_knob_switch(struct usb_mixer_interface *mixer, + int validx, int bUnitID) +{ + static struct snd_kcontrol_new template = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Output Gain Knob", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_c400_knob_switch_info, + .get = snd_ftu_eff_switch_get, + .put = snd_ftu_eff_switch_put + }; + struct usb_mixer_elem_list *list; + int err; + + err = add_single_ctl_with_resume(mixer, bUnitID, + snd_ftu_eff_switch_update, + &template, &list); + if (err < 0) + return err; + list->kctl->private_value = (validx << 8) | bUnitID; + snd_ftu_eff_switch_init(mixer, list->kctl); + return 0; +} + static int snd_c400_create_mixer(struct usb_mixer_interface *mixer) { int err; @@ -1762,6 +1824,10 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer) if (err < 0) return err; + err = snd_c400_create_knob_switch(mixer, 0x0900, 0x20); + if (err < 0) + return err; + return 0; } @@ -2114,13 +2180,18 @@ static int snd_soundblaster_e1_switch_put(struct snd_kcontrol *kcontrol, { struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); unsigned char value = !!ucontrol->value.integer.value[0]; + unsigned long old_pval = kcontrol->private_value; int err; if (kcontrol->private_value == value) return 0; kcontrol->private_value = value; err = snd_soundblaster_e1_switch_update(list->mixer, value); - return err < 0 ? err : 1; + if (err < 0) { + kcontrol->private_value = old_pval; + return err; + } + return 1; } static int snd_soundblaster_e1_switch_resume(struct usb_mixer_elem_list *list) @@ -2998,12 +3069,14 @@ static int snd_bbfpro_ctl_put(struct snd_kcontrol *kcontrol, if (val == old_value) return 0; + err = snd_bbfpro_ctl_update(mixer, reg, idx, val); + if (err < 0) + return err; + kcontrol->private_value = reg | ((idx & SND_BBFPRO_CTL_IDX_MASK) << SND_BBFPRO_CTL_IDX_SHIFT) | ((val & SND_BBFPRO_CTL_VAL_MASK) << SND_BBFPRO_CTL_VAL_SHIFT); - - err = snd_bbfpro_ctl_update(mixer, reg, idx, val); - return err < 0 ? err : 1; + return 1; } static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list) @@ -3188,11 +3261,13 @@ static int snd_bbfpro_vol_put(struct snd_kcontrol *kcontrol, new_val = uvalue & SND_BBFPRO_MIXER_VAL_MASK; + err = snd_bbfpro_vol_update(mixer, idx, new_val); + if (err < 0) + return err; + kcontrol->private_value = idx | (new_val << SND_BBFPRO_MIXER_VAL_SHIFT); - - err = snd_bbfpro_vol_update(mixer, idx, new_val); - return err < 0 ? err : 1; + return 1; } static int snd_bbfpro_vol_resume(struct usb_mixer_elem_list *list) diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c index 1bb01e827654..673eb8d8724d 100644 --- a/sound/usb/mixer_scarlett.c +++ b/sound/usb/mixer_scarlett.c @@ -680,7 +680,9 @@ static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl, val = ucontrol->value.integer.value[0]; val = val + opt->start; if (val != oval) { - snd_usb_set_cur_mix_value(elem, 0, 0, val); + err = snd_usb_set_cur_mix_value(elem, 0, 0, val); + if (err < 0) + return err; return 1; } return 0; diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c index a4fac4652201..78fb72e626ca 100644 --- a/sound/usb/mixer_scarlett2.c +++ b/sound/usb/mixer_scarlett2.c @@ -192,6 +192,9 @@ /* maximum Bluetooth volume value */ #define SCARLETT2_MAX_BLUETOOTH_VOLUME 30 +/* maximum front-panel sleep time in seconds (24 hours) */ +#define SCARLETT2_MAX_FP_SLEEP_TIME 86400 + /* mixer range from -80dB to +12dB in 0.5dB steps */ #define SCARLETT2_MIXER_MIN_DB -80 #define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2) @@ -398,6 +401,7 @@ static const char *const scarlett2_autogain_status_gen4[] = { "FailMaxGainLimit", "FailClipped", "Cancelled", + "Root", "Invalid", NULL }; @@ -567,6 +571,8 @@ enum { SCARLETT2_CONFIG_BLUETOOTH_VOLUME, SCARLETT2_CONFIG_SPDIF_MODE, SCARLETT2_CONFIG_SP_HP_MUTE, + SCARLETT2_CONFIG_FP_BRIGHTNESS, + SCARLETT2_CONFIG_FP_SLEEP_TIME, SCARLETT2_CONFIG_COUNT }; @@ -612,6 +618,20 @@ struct scarlett2_config_set { const struct scarlett2_config items[SCARLETT2_CONFIG_COUNT]; }; +/* Map firmware versions to config sets per-device. + * + * Each device lists one or more entries, sorted in ascending order of + * from_firmware_version. At probe time the running firmware version + * is looked up against this list and the last entry whose + * from_firmware_version is <= the running version is selected. + * + * The list is terminated by a sentinel entry with config_set == NULL. + */ +struct scarlett2_config_set_entry { + u16 from_firmware_version; + const struct scarlett2_config_set *config_set; +}; + /* Input gain TLV dB ranges */ static const DECLARE_TLV_DB_MINMAX( @@ -870,6 +890,42 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_solo = { } }; +/* Solo Gen 4, firmware version 2417 and above */ +static const struct scarlett2_config_set scarlett2_config_set_gen4_solo_2417 = { + .notifications = scarlett4_solo_notifications, + .param_buf_addr = 0xd8, + .items = { + [SCARLETT2_CONFIG_MSD_SWITCH] = { + .offset = 0x47, .size = 8, .activate = 4 }, + + [SCARLETT2_CONFIG_DIRECT_MONITOR] = { + .offset = 0x108, .size = 8, .activate = 12, .pbuf = 1 }, + + [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { + .offset = 0x46, .size = 8, .activate = 9, .pbuf = 1, + .mute = 1 }, + + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { + .offset = 0x3d, .size = 8, .activate = 10, .pbuf = 1, + .mute = 1 }, + + [SCARLETT2_CONFIG_AIR_SWITCH] = { + .offset = 0x3e, .size = 8, .activate = 11, .pbuf = 1 }, + + [SCARLETT2_CONFIG_PCM_INPUT_SWITCH] = { + .offset = 0x206, .size = 8, .activate = 25, .pbuf = 1 }, + + [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = { + .offset = 0x232, .size = 16, .activate = 26 }, + + [SCARLETT2_CONFIG_FP_BRIGHTNESS] = { + .offset = 0x243, .size = 8, .activate = 27, .pbuf = 1 }, + + [SCARLETT2_CONFIG_FP_SLEEP_TIME] = { + .offset = 0x248, .size = 32, .activate = 29 } + } +}; + /* 2i2 Gen 4 */ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = { .notifications = scarlett4_2i2_notifications, @@ -923,6 +979,70 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = { } }; +/* 2i2 Gen 4, firmware version 2417 and above + * + * Firmware 2417 shifted DIRECT_MONITOR_GAIN by 4 bytes and added + * front-panel brightness and sleep controls; all other offsets are + * unchanged from scarlett2_config_set_gen4_2i2. + */ +static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = { + .notifications = scarlett4_2i2_notifications, + .param_buf_addr = 0xfc, + .input_gain_tlv = db_scale_gen4_gain, + .autogain_status_texts = scarlett2_autogain_status_gen4, + .items = { + [SCARLETT2_CONFIG_MSD_SWITCH] = { + .offset = 0x49, .size = 8, .activate = 4 }, + + [SCARLETT2_CONFIG_DIRECT_MONITOR] = { + .offset = 0x14a, .size = 8, .activate = 16, .pbuf = 1 }, + + [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = { + .offset = 0x135, .size = 8, .activate = 10, .pbuf = 1 }, + + [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = { + .offset = 0x137, .size = 8 }, + + [SCARLETT2_CONFIG_AG_MEAN_TARGET] = { + .offset = 0x131, .size = 8, .activate = 29, .pbuf = 1 }, + + [SCARLETT2_CONFIG_AG_PEAK_TARGET] = { + .offset = 0x132, .size = 8, .activate = 30, .pbuf = 1 }, + + [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { + .offset = 0x48, .size = 8, .activate = 11, .pbuf = 1, + .mute = 1 }, + + [SCARLETT2_CONFIG_INPUT_GAIN] = { + .offset = 0x4b, .size = 8, .activate = 12, .pbuf = 1 }, + + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { + .offset = 0x3c, .size = 8, .activate = 13, .pbuf = 1, + .mute = 1 }, + + [SCARLETT2_CONFIG_SAFE_SWITCH] = { + .offset = 0x147, .size = 8, .activate = 14, .pbuf = 1 }, + + [SCARLETT2_CONFIG_AIR_SWITCH] = { + .offset = 0x3e, .size = 8, .activate = 15, .pbuf = 1 }, + + [SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = { + .offset = 0x14b, .size = 8, .activate = 17, .pbuf = 1 }, + + [SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = { + .offset = 0x14e, .size = 8, .activate = 18, .pbuf = 1 }, + + [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = { + .offset = 0x2a4, .size = 16, .activate = 36 }, + + [SCARLETT2_CONFIG_FP_BRIGHTNESS] = { + .offset = 0x2c7, .size = 8, .activate = 37, .pbuf = 1 }, + + [SCARLETT2_CONFIG_FP_SLEEP_TIME] = { + .offset = 0x2cc, .size = 32, .activate = 39 } + } +}; + /* 4i4 Gen 4 */ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = { .notifications = scarlett4_4i4_notifications, @@ -982,6 +1102,71 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = { } }; +/* 4i4 Gen 4, firmware version 2417 and above */ +static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4_2417 = { + .notifications = scarlett4_4i4_notifications, + .param_buf_addr = 0x130, + .input_gain_tlv = db_scale_gen4_gain, + .autogain_status_texts = scarlett2_autogain_status_gen4, + .items = { + [SCARLETT2_CONFIG_MSD_SWITCH] = { + .offset = 0x5c, .size = 8, .activate = 4 }, + + [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = { + .offset = 0x13e, .size = 8, .activate = 10, .pbuf = 1 }, + + [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = { + .offset = 0x140, .size = 8 }, + + [SCARLETT2_CONFIG_AG_MEAN_TARGET] = { + .offset = 0x13a, .size = 8, .activate = 23, .pbuf = 1 }, + + [SCARLETT2_CONFIG_AG_PEAK_TARGET] = { + .offset = 0x13b, .size = 8, .activate = 24, .pbuf = 1 }, + + [SCARLETT2_CONFIG_PHANTOM_SWITCH] = { + .offset = 0x5a, .size = 8, .activate = 11, .pbuf = 1, + .mute = 1 }, + + [SCARLETT2_CONFIG_INPUT_GAIN] = { + .offset = 0x5e, .size = 8, .activate = 12, .pbuf = 1 }, + + [SCARLETT2_CONFIG_LEVEL_SWITCH] = { + .offset = 0x4e, .size = 8, .activate = 13, .pbuf = 1, + .mute = 1 }, + + [SCARLETT2_CONFIG_SAFE_SWITCH] = { + .offset = 0x150, .size = 8, .activate = 14, .pbuf = 1 }, + + [SCARLETT2_CONFIG_AIR_SWITCH] = { + .offset = 0x50, .size = 8, .activate = 15, .pbuf = 1 }, + + [SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = { + .offset = 0x153, .size = 8, .activate = 16, .pbuf = 1 }, + + [SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = { + .offset = 0x156, .size = 8, .activate = 17, .pbuf = 1 }, + + [SCARLETT2_CONFIG_MASTER_VOLUME] = { + .offset = 0x32, .size = 16 }, + + [SCARLETT2_CONFIG_HEADPHONE_VOLUME] = { + .offset = 0x3a, .size = 16 }, + + [SCARLETT2_CONFIG_POWER_EXT] = { + .offset = 0x168, .size = 8 }, + + [SCARLETT2_CONFIG_POWER_LOW] = { + .offset = 0x16d, .size = 8 }, + + [SCARLETT2_CONFIG_FP_BRIGHTNESS] = { + .offset = 0x3a9, .size = 8, .activate = 36, .pbuf = 1 }, + + [SCARLETT2_CONFIG_FP_SLEEP_TIME] = { + .offset = 0x3ac, .size = 32, .activate = 38 } + } +}; + /* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */ static const struct scarlett2_config_set scarlett2_config_set_clarett = { .notifications = scarlett2_notifications, @@ -1100,11 +1285,8 @@ struct scarlett2_meter_entry { }; struct scarlett2_device_info { - /* which set of configuration parameters the device uses */ - const struct scarlett2_config_set *config_set; - - /* minimum firmware version required */ - u16 min_firmware_version; + /* which sets of configuration parameters the device uses */ + const struct scarlett2_config_set_entry *config_sets; /* has a downloadable device map */ u8 has_devmap; @@ -1335,6 +1517,8 @@ struct scarlett2_data { struct snd_kcontrol *talkback_ctl; struct snd_kcontrol *power_status_ctl; struct snd_kcontrol *bluetooth_volume_ctl; + u8 fp_brightness; + u32 fp_sleep_time; u8 mux[SCARLETT2_MUX_MAX]; u8 mix[SCARLETT2_MIX_MAX]; u8 monitor_mix[SCARLETT2_MONITOR_MIX_MAX]; @@ -1343,7 +1527,10 @@ struct scarlett2_data { /*** Model-specific data ***/ static const struct scarlett2_device_info s6i6_gen2_info = { - .config_set = &scarlett2_config_set_gen2a, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen2a }, + { } + }, .level_input_count = 2, .pad_input_count = 2, @@ -1393,7 +1580,10 @@ static const struct scarlett2_device_info s6i6_gen2_info = { }; static const struct scarlett2_device_info s18i8_gen2_info = { - .config_set = &scarlett2_config_set_gen2a, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen2a }, + { } + }, .level_input_count = 2, .pad_input_count = 4, @@ -1446,7 +1636,10 @@ static const struct scarlett2_device_info s18i8_gen2_info = { }; static const struct scarlett2_device_info s18i20_gen2_info = { - .config_set = &scarlett2_config_set_gen2b, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen2b }, + { } + }, .line_out_descrs = { "Monitor L", @@ -1503,7 +1696,10 @@ static const struct scarlett2_device_info s18i20_gen2_info = { }; static const struct scarlett2_device_info solo_gen3_info = { - .config_set = &scarlett2_config_set_gen3a, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen3a }, + { } + }, .level_input_count = 1, .level_input_first = 1, .air_input_count = 1, @@ -1513,7 +1709,10 @@ static const struct scarlett2_device_info solo_gen3_info = { }; static const struct scarlett2_device_info s2i2_gen3_info = { - .config_set = &scarlett2_config_set_gen3a, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen3a }, + { } + }, .level_input_count = 2, .air_input_count = 2, .phantom_count = 1, @@ -1522,7 +1721,10 @@ static const struct scarlett2_device_info s2i2_gen3_info = { }; static const struct scarlett2_device_info s4i4_gen3_info = { - .config_set = &scarlett2_config_set_gen3b, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen3b }, + { } + }, .level_input_count = 2, .pad_input_count = 2, .air_input_count = 2, @@ -1571,7 +1773,10 @@ static const struct scarlett2_device_info s4i4_gen3_info = { }; static const struct scarlett2_device_info s8i6_gen3_info = { - .config_set = &scarlett2_config_set_gen3b, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen3b }, + { } + }, .level_input_count = 2, .pad_input_count = 2, .air_input_count = 2, @@ -1637,7 +1842,10 @@ static const char * const scarlett2_spdif_s18i8_gen3_texts[] = { }; static const struct scarlett2_device_info s18i8_gen3_info = { - .config_set = &scarlett2_config_set_gen3c, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen3c }, + { } + }, .has_speaker_switching = 1, .level_input_count = 2, .pad_input_count = 4, @@ -1729,7 +1937,10 @@ static const char * const scarlett2_spdif_s18i20_gen3_texts[] = { }; static const struct scarlett2_device_info s18i20_gen3_info = { - .config_set = &scarlett2_config_set_gen3c, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_gen3c }, + { } + }, .has_speaker_switching = 1, .has_talkback = 1, .level_input_count = 2, @@ -1803,8 +2014,10 @@ static const struct scarlett2_device_info s18i20_gen3_info = { }; static const struct scarlett2_device_info vocaster_one_info = { - .config_set = &scarlett2_config_set_vocaster, - .min_firmware_version = 1769, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 1769, &scarlett2_config_set_vocaster }, + { } + }, .has_devmap = 1, .phantom_count = 1, @@ -1847,8 +2060,10 @@ static const struct scarlett2_device_info vocaster_one_info = { }; static const struct scarlett2_device_info vocaster_two_info = { - .config_set = &scarlett2_config_set_vocaster, - .min_firmware_version = 1769, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 1769, &scarlett2_config_set_vocaster }, + { } + }, .has_devmap = 1, .phantom_count = 2, @@ -1892,8 +2107,11 @@ static const struct scarlett2_device_info vocaster_two_info = { }; static const struct scarlett2_device_info solo_gen4_info = { - .config_set = &scarlett2_config_set_gen4_solo, - .min_firmware_version = 2115, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 2115, &scarlett2_config_set_gen4_solo }, + { 2417, &scarlett2_config_set_gen4_solo_2417 }, + { } + }, .has_devmap = 1, .level_input_count = 1, @@ -1947,8 +2165,11 @@ static const struct scarlett2_device_info solo_gen4_info = { }; static const struct scarlett2_device_info s2i2_gen4_info = { - .config_set = &scarlett2_config_set_gen4_2i2, - .min_firmware_version = 2115, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 2115, &scarlett2_config_set_gen4_2i2 }, + { 2417, &scarlett2_config_set_gen4_2i2_2417 }, + { } + }, .has_devmap = 1, .level_input_count = 2, @@ -2002,8 +2223,11 @@ static const struct scarlett2_device_info s2i2_gen4_info = { }; static const struct scarlett2_device_info s4i4_gen4_info = { - .config_set = &scarlett2_config_set_gen4_4i4, - .min_firmware_version = 2089, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 2089, &scarlett2_config_set_gen4_4i4 }, + { 2417, &scarlett2_config_set_gen4_4i4_2417 }, + { } + }, .has_devmap = 1, .level_input_count = 2, @@ -2051,7 +2275,10 @@ static const struct scarlett2_device_info s4i4_gen4_info = { }; static const struct scarlett2_device_info clarett_2pre_info = { - .config_set = &scarlett2_config_set_clarett, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_clarett }, + { } + }, .level_input_count = 2, .air_input_count = 2, @@ -2107,7 +2334,10 @@ static const char * const scarlett2_spdif_clarett_texts[] = { }; static const struct scarlett2_device_info clarett_4pre_info = { - .config_set = &scarlett2_config_set_clarett, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_clarett }, + { } + }, .level_input_count = 2, .air_input_count = 4, @@ -2163,7 +2393,10 @@ static const struct scarlett2_device_info clarett_4pre_info = { }; static const struct scarlett2_device_info clarett_8pre_info = { - .config_set = &scarlett2_config_set_clarett, + .config_sets = (const struct scarlett2_config_set_entry[]) { + { 0, &scarlett2_config_set_clarett }, + { } + }, .level_input_count = 2, .air_input_count = 8, @@ -2381,13 +2614,13 @@ static int scarlett2_usb( struct scarlett2_usb_packet *req __free(kfree) = NULL; size_t req_buf_size = struct_size(req, data, req_size); - req = kmalloc(req_buf_size, GFP_KERNEL); + req = kmalloc_flex(*req, data, req_size); if (!req) return -ENOMEM; struct scarlett2_usb_packet *resp __free(kfree) = NULL; size_t resp_buf_size = struct_size(resp, data, resp_size); - resp = kmalloc(resp_buf_size, GFP_KERNEL); + resp = kmalloc_flex(*resp, data, resp_size); if (!resp) return -ENOMEM; @@ -2504,27 +2737,6 @@ static int scarlett2_has_config_item( return !!private->config_set->items[config_item_num].offset; } -/* Return the configuration item's offset, applying any per-firmware - * overrides. - * - * Firmware 2417 for the 2i2 Gen 4 moved DIRECT_MONITOR_GAIN by 4 - * bytes. Apply that shift here so that the rest of the driver can - * keep using the single config set. This override can be removed - * once the multi-config-set framework lands. - */ -static int scarlett2_config_item_offset( - struct scarlett2_data *private, int config_item_num) -{ - int offset = private->config_set->items[config_item_num].offset; - - if (config_item_num == SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN && - private->info == &s2i2_gen4_info && - private->firmware_version >= 2417) - offset = 0x2a4; - - return offset; -} - /* Send a USB message to get configuration parameters; result placed in *buf */ static int scarlett2_usb_get_config( struct usb_mixer_interface *mixer, @@ -2534,7 +2746,6 @@ static int scarlett2_usb_get_config( const struct scarlett2_config *config_item = &private->config_set->items[config_item_num]; int size, err, i; - int item_offset; u8 *buf_8; u8 value; @@ -2544,15 +2755,13 @@ static int scarlett2_usb_get_config( if (!config_item->offset) return -EFAULT; - item_offset = scarlett2_config_item_offset(private, config_item_num); - /* Writes to the parameter buffer are always 1 byte */ size = config_item->size ? config_item->size : 8; /* For byte-sized parameters, retrieve directly into buf */ if (size >= 8) { size = size / 8 * count; - err = scarlett2_usb_get(mixer, item_offset, buf, size); + err = scarlett2_usb_get(mixer, config_item->offset, buf, size); if (err < 0) return err; if (config_item->size == 16) { @@ -2570,7 +2779,7 @@ static int scarlett2_usb_get_config( } /* For bit-sized parameters, retrieve into value */ - err = scarlett2_usb_get(mixer, item_offset, &value, 1); + err = scarlett2_usb_get(mixer, config_item->offset, &value, 1); if (err < 0) return err; @@ -2621,9 +2830,9 @@ static int scarlett2_usb_set_data_buf( u8 data[]; } __packed *req; int err; - int buf_size = struct_size(req, data, bytes); + size_t buf_size = struct_size(req, data, bytes); - req = kmalloc(buf_size, GFP_KERNEL); + req = kmalloc_flex(*req, data, bytes); if (!req) return -ENOMEM; @@ -2720,8 +2929,7 @@ static int scarlett2_usb_set_config( */ if (config_item->size >= 8) { size = config_item->size / 8; - offset = scarlett2_config_item_offset(private, config_item_num) + - index * size; + offset = config_item->offset + index * size; /* If updating a bit, retrieve the old value, set/clear the * bit as needed, and update value @@ -2730,7 +2938,7 @@ static int scarlett2_usb_set_config( u8 tmp; size = 1; - offset = scarlett2_config_item_offset(private, config_item_num); + offset = config_item->offset; err = scarlett2_usb_get(mixer, offset, &tmp, 1); if (err < 0) @@ -3301,7 +3509,8 @@ static int scarlett2_min_firmware_version_ctl_get( struct usb_mixer_elem_info *elem = kctl->private_data; struct scarlett2_data *private = elem->head.mixer->private_data; - ucontrol->value.integer.value[0] = private->info->min_firmware_version; + ucontrol->value.integer.value[0] = + private->info->config_sets[0].from_firmware_version; return 0; } @@ -7653,6 +7862,172 @@ static int scarlett2_add_bluetooth_volume_ctl( &private->bluetooth_volume_ctl); } +/*** Front Panel Brightness/Sleep Controls ***/ + +static int scarlett2_update_fp(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + int err; + + if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_BRIGHTNESS)) { + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_FP_BRIGHTNESS, + 1, &private->fp_brightness); + if (err < 0) + return err; + } + + if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_SLEEP_TIME)) { + err = scarlett2_usb_get_config( + mixer, SCARLETT2_CONFIG_FP_SLEEP_TIME, + 1, &private->fp_sleep_time); + if (err < 0) + return err; + } + + return 0; +} + +static const char * const scarlett2_fp_brightness_texts[] = { + "High", "Medium", "Low" +}; + +static int scarlett2_fp_brightness_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + return snd_ctl_enum_info(uinfo, 1, + ARRAY_SIZE(scarlett2_fp_brightness_texts), + scarlett2_fp_brightness_texts); +} + +static int scarlett2_fp_brightness_ctl_get( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; + + ucontrol->value.enumerated.item[0] = private->fp_brightness; + return 0; +} + +static int scarlett2_fp_brightness_ctl_put( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + int oval, val, err; + + guard(mutex)(&private->data_mutex); + + if (private->hwdep_in_use) + return -EBUSY; + + oval = private->fp_brightness; + val = min(ucontrol->value.enumerated.item[0], + ARRAY_SIZE(scarlett2_fp_brightness_texts) - 1); + + if (oval == val) + return 0; + + private->fp_brightness = val; + + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_FP_BRIGHTNESS, 0, val); + + return err < 0 ? err : 1; +} + +static const struct snd_kcontrol_new scarlett2_fp_brightness_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .name = "", + .info = scarlett2_fp_brightness_ctl_info, + .get = scarlett2_fp_brightness_ctl_get, + .put = scarlett2_fp_brightness_ctl_put, +}; + +static int scarlett2_fp_sleep_time_ctl_info( + struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = SCARLETT2_MAX_FP_SLEEP_TIME; + uinfo->value.integer.step = 1; + return 0; +} + +static int scarlett2_fp_sleep_time_ctl_get( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct scarlett2_data *private = elem->head.mixer->private_data; + + ucontrol->value.integer.value[0] = private->fp_sleep_time; + return 0; +} + +static int scarlett2_fp_sleep_time_ctl_put( + struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) +{ + struct usb_mixer_elem_info *elem = kctl->private_data; + struct usb_mixer_interface *mixer = elem->head.mixer; + struct scarlett2_data *private = mixer->private_data; + u32 oval, val; + int err; + + guard(mutex)(&private->data_mutex); + + if (private->hwdep_in_use) + return -EBUSY; + + oval = private->fp_sleep_time; + val = clamp(ucontrol->value.integer.value[0], + 0L, (long)SCARLETT2_MAX_FP_SLEEP_TIME); + + if (oval == val) + return 0; + + private->fp_sleep_time = val; + + err = scarlett2_usb_set_config( + mixer, SCARLETT2_CONFIG_FP_SLEEP_TIME, 0, val); + + return err < 0 ? err : 1; +} + +static const struct snd_kcontrol_new scarlett2_fp_sleep_time_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .name = "", + .info = scarlett2_fp_sleep_time_ctl_info, + .get = scarlett2_fp_sleep_time_ctl_get, + .put = scarlett2_fp_sleep_time_ctl_put, +}; + +static int scarlett2_add_fp_ctls(struct usb_mixer_interface *mixer) +{ + struct scarlett2_data *private = mixer->private_data; + int err; + + if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_BRIGHTNESS)) { + err = scarlett2_add_new_ctl( + mixer, &scarlett2_fp_brightness_ctl, 0, 1, + "Front Panel Brightness", NULL); + if (err < 0) + return err; + } + + if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_SLEEP_TIME)) { + err = scarlett2_add_new_ctl( + mixer, &scarlett2_fp_sleep_time_ctl, 0, 1, + "Front Panel Sleep Time", NULL); + if (err < 0) + return err; + } + + return 0; +} + /*** S/PDIF Mode Controls ***/ static int scarlett2_update_spdif_mode(struct usb_mixer_interface *mixer) @@ -8211,10 +8586,32 @@ static void scarlett2_private_suspend(struct usb_mixer_interface *mixer) /*** Initialisation ***/ +/* Select the config_set matching the running firmware version. + * + * The device info's config_sets array is ordered by ascending + * from_firmware_version; pick the last entry whose version is <= the + * running firmware version. If the running firmware is older than the + * first entry's from_firmware_version (i.e. older than the driver's + * minimum supported version for this device), the first entry's + * config_set is selected anyway so firmware updates can still be done + * (requires only the ACK handler), but the usual mixer controls + * aren't created. + */ +static void scarlett2_resolve_config_set(struct scarlett2_data *private) +{ + const struct scarlett2_config_set_entry *entry = + private->info->config_sets; + + private->config_set = entry->config_set; + for (entry++; entry->config_set; entry++) + if (entry->from_firmware_version <= private->firmware_version) + private->config_set = entry->config_set; +} + static void scarlett2_count_io(struct scarlett2_data *private) { const struct scarlett2_device_info *info = private->info; - const struct scarlett2_config_set *config_set = info->config_set; + const struct scarlett2_config_set *config_set = private->config_set; const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count; int port_type, srcs = 0, dsts = 0, i; @@ -8311,9 +8708,14 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer, mixer->private_suspend = scarlett2_private_suspend; private->info = entry->info; - private->config_set = entry->info->config_set; + + /* Set config_set to the first entry's config_set so the + * notify handler has a valid pointer while USB init runs; it + * is re-resolved once the firmware version has been read. + */ + private->config_set = entry->info->config_sets[0].config_set; + private->series_name = entry->series_name; - scarlett2_count_io(private); private->scarlett2_seq = 0; private->mixer = mixer; @@ -8503,6 +8905,7 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) { struct scarlett2_data *private = mixer->private_data; const struct scarlett2_device_info *info = private->info; + u16 min_firmware_version = info->config_sets[0].from_firmware_version; int err, i; if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_MSD_SWITCH)) { @@ -8513,13 +8916,13 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) return err; } - if (private->firmware_version < info->min_firmware_version) { + if (private->firmware_version < min_firmware_version) { usb_audio_err(mixer->chip, "Focusrite %s firmware version %d is too old; " "need %d", private->series_name, private->firmware_version, - info->min_firmware_version); + min_firmware_version); return 0; } @@ -8673,6 +9076,10 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer) if (err < 0) return err; + err = scarlett2_update_fp(mixer); + if (err < 0) + return err; + err = scarlett2_update_spdif_mode(mixer); if (err < 0) return err; @@ -8703,6 +9110,7 @@ static int snd_scarlett2_controls_create( const struct scarlett2_device_entry *entry) { struct scarlett2_data *private; + u16 min_firmware_version; int err; /* Initialise private data */ @@ -8711,12 +9119,21 @@ static int snd_scarlett2_controls_create( return err; private = mixer->private_data; + min_firmware_version = + private->info->config_sets[0].from_firmware_version; /* Send proprietary USB initialisation sequence */ err = scarlett2_usb_init(mixer); if (err < 0) return err; + /* Now that the firmware version is known, pick the matching + * config_set + */ + scarlett2_resolve_config_set(private); + + scarlett2_count_io(private); + /* Get the upgrade & settings flash segment numbers */ err = scarlett2_get_flash_segment_nums(mixer); if (err < 0) @@ -8746,7 +9163,7 @@ static int snd_scarlett2_controls_create( * old, don't create any other controls */ if (private->msd_switch || - private->firmware_version < private->info->min_firmware_version) + private->firmware_version < min_firmware_version) return 0; /* Create the analogue output controls */ @@ -8809,6 +9226,11 @@ static int snd_scarlett2_controls_create( if (err < 0) return err; + /* Create the front-panel brightness/sleep controls */ + err = scarlett2_add_fp_ctls(mixer); + if (err < 0) + return err; + /* Create the S/PDIF mode control */ err = scarlett2_add_spdif_mode_ctl(mixer); if (err < 0) @@ -9227,7 +9649,7 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw, /* Create and send the request */ len = struct_size(req, data, count); - req = kzalloc(len, GFP_KERNEL); + req = kzalloc_flex(*req, data, count); if (!req) return -ENOMEM; diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c index 8a02964e5d7b..ebff185cbd2c 100644 --- a/sound/usb/mixer_us16x08.c +++ b/sound/usb/mixer_us16x08.c @@ -224,14 +224,14 @@ static int snd_us16x08_route_put(struct snd_kcontrol *kcontrol, err = snd_us16x08_send_urb(chip, buf, sizeof(route_msg)); - if (err > 0) { - elem->cached |= 1 << index; - elem->cache_val[index] = val; - } else { + if (err < 0) { usb_audio_dbg(chip, "Failed to set routing, err:%d\n", err); + return err; } - return err > 0 ? 1 : 0; + elem->cached |= 1 << index; + elem->cache_val[index] = val; + return 1; } static int snd_us16x08_master_info(struct snd_kcontrol *kcontrol, @@ -283,14 +283,14 @@ static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol, buf[5] = index + 1; err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out)); - if (err > 0) { - elem->cached |= 1 << index; - elem->cache_val[index] = val; - } else { + if (err < 0) { usb_audio_dbg(chip, "Failed to set master, err:%d\n", err); + return err; } - return err > 0 ? 1 : 0; + elem->cached |= 1 << index; + elem->cache_val[index] = val; + return 1; } static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol, @@ -324,14 +324,14 @@ static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol, break; } - if (err > 0) { - elem->cached |= 1; - elem->cache_val[0] = val; - } else { + if (err < 0) { usb_audio_dbg(chip, "Failed to set bus parameter, err:%d\n", err); + return err; } - return err > 0 ? 1 : 0; + elem->cached |= 1; + elem->cache_val[0] = val; + return 1; } static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol, @@ -392,14 +392,14 @@ static int snd_us16x08_channel_put(struct snd_kcontrol *kcontrol, err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_in)); - if (err > 0) { - elem->cached |= 1 << index; - elem->cache_val[index] = val; - } else { + if (err < 0) { usb_audio_dbg(chip, "Failed to set channel, err:%d\n", err); + return err; } - return err > 0 ? 1 : 0; + elem->cached |= 1 << index; + elem->cache_val[index] = val; + return 1; } static int snd_us16x08_mix_info(struct snd_kcontrol *kcontrol, @@ -435,6 +435,7 @@ static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol, int index = ucontrol->id.index; char buf[sizeof(comp_msg)]; int val_idx, val; + int threshold, ratio, attack, release, gain, switch_on; int err; val = ucontrol->value.integer.value[0]; @@ -447,36 +448,61 @@ static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol, /* new control value incl. bias*/ val_idx = elem->head.id - SND_US16X08_ID_COMP_BASE; - store->val[val_idx][index] = ucontrol->value.integer.value[0]; + threshold = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)] + [index]; + ratio = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]; + attack = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index]; + release = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)] + [index]; + gain = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index]; + switch_on = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)] + [index]; + + switch (val_idx) { + case COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD): + threshold = val; + break; + case COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO): + ratio = val; + break; + case COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK): + attack = val; + break; + case COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE): + release = val; + break; + case COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN): + gain = val; + break; + case COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH): + switch_on = val; + break; + } /* prepare compressor URB message from template */ memcpy(buf, comp_msg, sizeof(comp_msg)); /* place comp values in message buffer watch bias! */ - buf[8] = store->val[ - COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][index] - - SND_US16X08_COMP_THRESHOLD_BIAS; - buf[11] = ratio_map[store->val[ - COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]]; - buf[14] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index] - + SND_US16X08_COMP_ATTACK_BIAS; - buf[17] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][index] - + SND_US16X08_COMP_RELEASE_BIAS; - buf[20] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index]; - buf[26] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][index]; + buf[8] = threshold - SND_US16X08_COMP_THRESHOLD_BIAS; + buf[11] = ratio_map[ratio]; + buf[14] = attack + SND_US16X08_COMP_ATTACK_BIAS; + buf[17] = release + SND_US16X08_COMP_RELEASE_BIAS; + buf[20] = gain; + buf[26] = switch_on; /* place channel selector in message buffer */ buf[5] = index + 1; err = snd_us16x08_send_urb(chip, buf, sizeof(comp_msg)); - if (err > 0) { - elem->cached |= 1 << index; - elem->cache_val[index] = val; - } else { + if (err < 0) { usb_audio_dbg(chip, "Failed to set compressor, err:%d\n", err); + return err; } + store->val[val_idx][index] = val; + elem->cached |= 1 << index; + elem->cache_val[index] = val; return 1; } @@ -529,13 +555,13 @@ static int snd_us16x08_eqswitch_put(struct snd_kcontrol *kcontrol, msleep(15); } - if (err > 0) { - elem->cached |= 1 << index; - elem->cache_val[index] = val; - } else { + if (err < 0) { usb_audio_dbg(chip, "Failed to set eq switch, err:%d\n", err); + return err; } + elem->cached |= 1 << index; + elem->cache_val[index] = val; return 1; } @@ -578,11 +604,10 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol, /* copy URB buffer from EQ template */ memcpy(buf, eqs_msq, sizeof(eqs_msq)); - store->val[b_idx][p_idx][index] = val; - buf[20] = store->val[b_idx][3][index]; - buf[17] = store->val[b_idx][2][index]; - buf[14] = store->val[b_idx][1][index]; - buf[11] = store->val[b_idx][0][index]; + buf[20] = p_idx == 3 ? val : store->val[b_idx][3][index]; + buf[17] = p_idx == 2 ? val : store->val[b_idx][2][index]; + buf[14] = p_idx == 1 ? val : store->val[b_idx][1][index]; + buf[11] = p_idx == 0 ? val : store->val[b_idx][0][index]; /* place channel index in URB buffer */ buf[5] = index + 1; @@ -592,14 +617,15 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol, err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq)); - if (err > 0) { - /* store new value in EQ band cache */ - elem->cached |= 1 << index; - elem->cache_val[index] = val; - } else { + if (err < 0) { usb_audio_dbg(chip, "Failed to set eq param, err:%d\n", err); + return err; } + store->val[b_idx][p_idx][index] = val; + /* store new value in EQ band cache */ + elem->cached |= 1 << index; + elem->cache_val[index] = val; return 1; } @@ -1418,4 +1444,3 @@ int snd_us16x08_controls_create(struct usb_mixer_interface *mixer) return 0; } - diff --git a/sound/usb/qcom/mixer_usb_offload.c b/sound/usb/qcom/mixer_usb_offload.c index 2adeb64f4d33..b1591361e76c 100644 --- a/sound/usb/qcom/mixer_usb_offload.c +++ b/sound/usb/qcom/mixer_usb_offload.c @@ -113,7 +113,7 @@ int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev) struct snd_usb_substream *subs; struct snd_usb_stream *as; char ctl_name[48]; - int ret; + int ret = 0; list_for_each_entry(as, &chip->pcm_list, list) { subs = &as->substream[SNDRV_PCM_STREAM_PLAYBACK]; @@ -128,7 +128,7 @@ int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev) */ chip_kctl->private_value = as->pcm_index | chip->card->number << 16; - sprintf(ctl_name, "USB Offload Playback Card Route PCM#%d", + snprintf(ctl_name, sizeof(ctl_name), "USB Offload Playback Card Route PCM#%d", as->pcm_index); chip_kctl->name = ctl_name; ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev)); @@ -143,7 +143,7 @@ int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev) */ chip_kctl->private_value = as->pcm_index | chip->card->number << 16; - sprintf(ctl_name, "USB Offload Playback PCM Route PCM#%d", + snprintf(ctl_name, sizeof(ctl_name), "USB Offload Playback PCM Route PCM#%d", as->pcm_index); chip_kctl->name = ctl_name; ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev)); diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c index a0009503b2c5..a3f90cc7c6ca 100644 --- a/sound/usb/qcom/qc_audio_offload.c +++ b/sound/usb/qcom/qc_audio_offload.c @@ -794,15 +794,23 @@ static void qmi_stop_session(void) continue; } /* Release XHCI endpoints */ - if (info->data_ep_pipe) + if (info->data_ep_pipe) { ep = usb_pipe_endpoint(uadev[pcm_card_num].udev, info->data_ep_pipe); - xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb, ep); + if (ep) + xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb, + ep); + info->data_ep_pipe = 0; + } - if (info->sync_ep_pipe) + if (info->sync_ep_pipe) { ep = usb_pipe_endpoint(uadev[pcm_card_num].udev, info->sync_ep_pipe); - xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb, ep); + if (ep) + xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb, + ep); + info->sync_ep_pipe = 0; + } disable_audio_stream(subs); } @@ -1042,8 +1050,6 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs, u32 len = xfer_buf_len; bool dma_coherent; dma_addr_t xfer_buf_dma_sysdev; - u32 remainder; - u32 mult; int ret; dma_coherent = dev_is_dma_coherent(subs->dev->bus->sysdev); @@ -1052,10 +1058,7 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs, if (!len) len = PAGE_SIZE; - mult = len / PAGE_SIZE; - remainder = len % PAGE_SIZE; - len = mult * PAGE_SIZE; - len += remainder ? PAGE_SIZE : 0; + len = PAGE_ALIGN(len); if (len > MAX_XFER_BUFF_LEN) { dev_err(uaudio_qdev->data->dev, @@ -1140,7 +1143,7 @@ uaudio_endpoint_setup(struct snd_usb_substream *subs, ret = xhci_sideband_add_endpoint(uadev[card_num].sb, ep); if (ret < 0) { dev_err(&subs->dev->dev, - "failed to add data ep to sec intr\n"); + "failed to add data ep to sec intr: %d\n", ret); ret = -ENODEV; goto exit; } @@ -1148,7 +1151,7 @@ uaudio_endpoint_setup(struct snd_usb_substream *subs, sgt = xhci_sideband_get_endpoint_buffer(uadev[card_num].sb, ep); if (!sgt) { dev_err(&subs->dev->dev, - "failed to get data ep ring address\n"); + "failed to get data ep ring address: %d\n", ret); ret = -ENODEV; goto remove_ep; } @@ -1753,7 +1756,7 @@ static int qc_usb_audio_offload_fill_avail_pcms(struct snd_usb_audio *chip, break; } - return -1; + return idx; } /** diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 4e9cfff4047f..97f28c53d201 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2131,6 +2131,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + USB_DEVICE(0x1235, 0x001e), + QUIRK_DRIVER_INFO { + /* .vendor_name = "Novation", */ + /* .product_name = "Mininova", */ + QUIRK_DATA_RAW_BYTES(0) + } +}, { USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661), QUIRK_DRIVER_INFO { diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index f4e885f96e83..30f6d572e4d1 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2357,6 +2357,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY), DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), + DEVICE_FLG(0x1377, 0x6004, /* Sennheiser MOMENTUM 3 */ + QUIRK_FLAG_MIXER_GET_CUR_BROKEN), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */ @@ -2365,6 +2367,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB), DEVICE_FLG(0x1397, 0x0509, /* Behringer UMC404HD */ QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB), + DEVICE_FLG(0x1397, 0x050c, /* Behringer Flow 8 */ + QUIRK_FLAG_IFB_SILENCE_ON_EMPTY), DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */ QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x152a, 0x880a, /* NeuralDSP Quad Cortex */ @@ -2473,6 +2477,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x2d99, 0x0026, /* HECATE G2 GAMING HEADSET */ QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), + DEVICE_FLG(0x2d99, 0xa024, /* Edifier MF200 */ + QUIRK_FLAG_MIXER_GET_CUR_BROKEN), DEVICE_FLG(0x2fc6, 0xf06b, /* MOONDROP Moonriver2 Ti */ QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x2fc6, 0xf0b7, /* iBasso DC07 Pro */ @@ -2487,6 +2493,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), DEVICE_FLG(0x3443, 0x930d, /* NexiGo N930W 60fps Webcam */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), + DEVICE_FLG(0x36f9, 0xc009, /* XIBERIA K03S */ + QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY), DEVICE_FLG(0x3c20, 0x3d21, /* AB13X USB Audio */ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY), DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ @@ -2606,6 +2614,8 @@ static const char *const snd_usb_audio_quirk_flag_names[] = { QUIRK_STRING_ENTRY(SKIP_IFACE_SETUP), QUIRK_STRING_ENTRY(MIXER_PLAYBACK_LINEAR_VOL), QUIRK_STRING_ENTRY(MIXER_CAPTURE_LINEAR_VOL), + QUIRK_STRING_ENTRY(IFB_SILENCE_ON_EMPTY), + QUIRK_STRING_ENTRY(MIXER_GET_CUR_BROKEN), NULL }; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 58fd07f8c3c9..e26f9092417e 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -7,6 +7,8 @@ * Copyright (c) 2002 by Takashi Iwai */ +#include + /* handling of USB vendor/product ID pairs as 32-bit numbers */ #define USB_ID(vendor, product) (((unsigned int)(vendor) << 16) | (product)) #define USB_ID_VENDOR(id) ((id) >> 16) @@ -41,8 +43,7 @@ struct snd_usb_audio { unsigned int system_suspend; atomic_t active; atomic_t shutdown; - atomic_t usage_count; - wait_queue_head_t shutdown_wait; + struct snd_refcount usage_count; unsigned int quirk_flags; unsigned int need_delayed_register:1; /* warn for delayed registration */ int num_interfaces; @@ -236,6 +237,23 @@ extern bool snd_usb_skip_validation; * QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL * Similar to QUIRK_FLAG_MIXER_PLAYBACK_LINEAR_VOL, but for capture streams. * Overrides QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE + * QUIRK_FLAG_IFB_SILENCE_ON_EMPTY + * In implicit feedback mode, when an entire capture URB returns with + * all iso_frame_desc[i].status != 0 (bytes==0), do not silently return + * from snd_usb_handle_sync_urb. Instead fall through and enqueue a + * packet_info containing only size-0 packets, so the OUT ring keeps + * moving (emits silence). Needed by Behringer Flow 8 (1397:050c). + * QUIRK_FLAG_MIXER_GET_CUR_BROKEN + * Some mixers are sticky, which means that setting their current volume is a + * no-op, and reading the current volume returns a constant value. The sticky + * check disables these mixers to prevent confusing userspace. However, some + * devices do have a tunable volume despite the reported current volume being + * constant. As the sticky check can't distinguish between the two categories, + * setting this flag tells that the device should fall into the second + * category when GET_CUR returns a constant value, resulting in the sticky + * check being non-fatal and only disabling GET_CUR instead of the whole mixer. + * The current volume will then be provided by the internal cache that stores + * the last set volume */ enum { @@ -268,6 +286,8 @@ enum { QUIRK_TYPE_SKIP_IFACE_SETUP = 26, QUIRK_TYPE_MIXER_PLAYBACK_LINEAR_VOL = 27, QUIRK_TYPE_MIXER_CAPTURE_LINEAR_VOL = 28, + QUIRK_TYPE_IFB_SILENCE_ON_EMPTY = 29, + QUIRK_TYPE_MIXER_GET_CUR_BROKEN = 30, /* Please also edit snd_usb_audio_quirk_flag_names */ }; @@ -302,5 +322,7 @@ enum { #define QUIRK_FLAG_SKIP_IFACE_SETUP QUIRK_FLAG(SKIP_IFACE_SETUP) #define QUIRK_FLAG_MIXER_PLAYBACK_LINEAR_VOL QUIRK_FLAG(MIXER_PLAYBACK_LINEAR_VOL) #define QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL QUIRK_FLAG(MIXER_CAPTURE_LINEAR_VOL) +#define QUIRK_FLAG_IFB_SILENCE_ON_EMPTY QUIRK_FLAG(IFB_SILENCE_ON_EMPTY) +#define QUIRK_FLAG_MIXER_GET_CUR_BROKEN QUIRK_FLAG(MIXER_GET_CUR_BROKEN) #endif /* __USBAUDIO_H */ diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index f34e78910200..4190227c5a2a 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -180,7 +180,7 @@ static void i_usx2y_in04_int(struct urb *urb) struct usx2ydev *usx2y = urb->context; struct us428ctls_sharedmem *us428ctls = usx2y->us428ctls_sharedmem; struct us428_p4out *p4out; - int i, j, n, diff, send; + int i, j, n, diff, send, len; usx2y->in04_int_calls++; @@ -222,24 +222,31 @@ static void i_usx2y_in04_int(struct urb *urb) } while (!err && usx2y->us04->submitted < usx2y->us04->len); } } else { - if (us428ctls && us428ctls->p4out_last >= 0 && us428ctls->p4out_last < N_US428_P4OUT_BUFS) { - if (us428ctls->p4out_last != us428ctls->p4out_sent) { - send = us428ctls->p4out_sent + 1; - if (send >= N_US428_P4OUT_BUFS) - send = 0; - for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) { - if (!usx2y->as04.urb[j]->status) { - p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. - usb_fill_bulk_urb(usx2y->as04.urb[j], usx2y->dev, - usb_sndbulkpipe(usx2y->dev, 0x04), &p4out->val.vol, - p4out->type == ELT_LIGHT ? sizeof(struct us428_lights) : 5, - i_usx2y_out04_int, usx2y); - err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC); + while (us428ctls && + us428ctls->p4out_last >= 0 && + us428ctls->p4out_last < N_US428_P4OUT_BUFS && + us428ctls->p4out_last != us428ctls->p4out_sent) { + for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) { + if (!usx2y->as04.urb[j]->status) { + send = us428ctls->p4out_sent + 1; + if (send >= N_US428_P4OUT_BUFS) + send = 0; + + p4out = us428ctls->p4out + send; + len = p4out->type == ELT_LIGHT ? + sizeof(struct us428_lights) : 5; + memcpy(usx2y->as04.urb[j]->transfer_buffer, + &p4out->val.vol, len); + usx2y->as04.urb[j]->transfer_buffer_length = len; + err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC); + if (!err) us428ctls->p4out_sent = send; - break; - } + + break; } } + if (j >= URBS_ASYNC_SEQ || err) + break; } } diff --git a/sound/virtio/virtio_kctl.c b/sound/virtio/virtio_kctl.c index ffb903d56297..45f7b6a5b308 100644 --- a/sound/virtio/virtio_kctl.c +++ b/sound/virtio/virtio_kctl.c @@ -18,6 +18,21 @@ static const snd_ctl_elem_type_t g_v2a_type_map[] = { [VIRTIO_SND_CTL_TYPE_IEC958] = SNDRV_CTL_ELEM_TYPE_IEC958 }; +/* Map for converting VirtIO types to maximum value counts. */ +static const unsigned int g_v2a_count_map[] = { + [VIRTIO_SND_CTL_TYPE_BOOLEAN] = + ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer), + [VIRTIO_SND_CTL_TYPE_INTEGER] = + ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer), + [VIRTIO_SND_CTL_TYPE_INTEGER64] = + ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer64), + [VIRTIO_SND_CTL_TYPE_ENUMERATED] = + ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.enumerated), + [VIRTIO_SND_CTL_TYPE_BYTES] = + ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.bytes), + [VIRTIO_SND_CTL_TYPE_IEC958] = 1 +}; + /* Map for converting VirtIO access rights to ALSA access rights. */ static const unsigned int g_v2a_access_map[] = { [VIRTIO_SND_CTL_ACCESS_READ] = SNDRV_CTL_ELEM_ACCESS_READ, @@ -36,6 +51,37 @@ static const unsigned int g_v2a_mask_map[] = { [VIRTIO_SND_CTL_EVT_MASK_TLV] = SNDRV_CTL_EVENT_MASK_TLV }; +static int virtsnd_kctl_validate_info(struct virtio_snd *snd, u32 cid, + struct virtio_snd_ctl_info *kinfo) +{ + struct virtio_device *vdev = snd->vdev; + unsigned int type = le32_to_cpu(kinfo->type); + unsigned int count = le32_to_cpu(kinfo->count); + + if (type >= ARRAY_SIZE(g_v2a_type_map)) { + dev_err(&vdev->dev, "control #%u: unknown type %u\n", + cid, type); + return -EINVAL; + } + + if (count > g_v2a_count_map[type] || + (type == VIRTIO_SND_CTL_TYPE_IEC958 && count != 1)) { + dev_err(&vdev->dev, "control #%u: invalid count %u for type %u\n", + cid, count, type); + return -EINVAL; + } + + if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED && + !le32_to_cpu(kinfo->value.enumerated.items)) { + dev_err(&vdev->dev, + "control #%u: no items for enumerated control\n", + cid); + return -EINVAL; + } + + return 0; +} + /** * virtsnd_kctl_info() - Returns information about the control. * @kcontrol: ALSA control element. @@ -385,6 +431,10 @@ int virtsnd_kctl_parse_cfg(struct virtio_snd *snd) struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[i]; unsigned int type = le32_to_cpu(kinfo->type); + rc = virtsnd_kctl_validate_info(snd, i, kinfo); + if (rc) + return rc; + if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED) { rc = virtsnd_kctl_get_enum_items(snd, i); if (rc) diff --git a/sound/virtio/virtio_pcm.c b/sound/virtio/virtio_pcm.c index eb9cc8131905..be3893de40a5 100644 --- a/sound/virtio/virtio_pcm.c +++ b/sound/virtio/virtio_pcm.c @@ -77,7 +77,8 @@ static const struct virtsnd_v2a_rate g_v2a_rate_map[] = { [VIRTIO_SND_PCM_RATE_88200] = { SNDRV_PCM_RATE_88200, 88200 }, [VIRTIO_SND_PCM_RATE_96000] = { SNDRV_PCM_RATE_96000, 96000 }, [VIRTIO_SND_PCM_RATE_176400] = { SNDRV_PCM_RATE_176400, 176400 }, - [VIRTIO_SND_PCM_RATE_192000] = { SNDRV_PCM_RATE_192000, 192000 } + [VIRTIO_SND_PCM_RATE_192000] = { SNDRV_PCM_RATE_192000, 192000 }, + [VIRTIO_SND_PCM_RATE_384000] = { SNDRV_PCM_RATE_384000, 384000 } }; /** diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c index 6297a9c61e70..1105e7ff3523 100644 --- a/sound/virtio/virtio_pcm_ops.c +++ b/sound/virtio/virtio_pcm_ops.c @@ -90,7 +90,8 @@ static const struct virtsnd_a2v_rate g_a2v_rate_map[] = { { 88200, VIRTIO_SND_PCM_RATE_88200 }, { 96000, VIRTIO_SND_PCM_RATE_96000 }, { 176400, VIRTIO_SND_PCM_RATE_176400 }, - { 192000, VIRTIO_SND_PCM_RATE_192000 } + { 192000, VIRTIO_SND_PCM_RATE_192000 }, + { 384000, VIRTIO_SND_PCM_RATE_384000 } }; static int virtsnd_pcm_sync_stop(struct snd_pcm_substream *substream); diff --git a/sound/xen/xen_snd_front_alsa.c b/sound/xen/xen_snd_front_alsa.c index dc626480123a..a6dd196f73d6 100644 --- a/sound/xen/xen_snd_front_alsa.c +++ b/sound/xen/xen_snd_front_alsa.c @@ -378,7 +378,7 @@ static int alsa_open(struct snd_pcm_substream *substream) stream_clear(stream); - xen_snd_front_evtchnl_pair_set_connected(stream->evt_pair, true); + xen_snd_front_evtchnl_set_connected(&stream->evt_pair->req, true); ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, alsa_hw_rule, stream, @@ -498,6 +498,8 @@ static int alsa_hw_free(struct snd_pcm_substream *substream) struct xen_snd_front_pcm_stream_info *stream = stream_get(substream); int ret; + xen_snd_front_evtchnl_set_connected(&stream->evt_pair->evt, false); + ret = xen_snd_front_stream_close(&stream->evt_pair->req); stream_free(stream); return ret; @@ -532,6 +534,7 @@ static int alsa_prepare(struct snd_pcm_substream *substream) return ret; stream->is_open = true; + xen_snd_front_evtchnl_set_connected(&stream->evt_pair->evt, true); } return 0; @@ -571,20 +574,24 @@ void xen_snd_front_alsa_handle_cur_pos(struct xen_snd_front_evtchnl *evtchnl, { struct snd_pcm_substream *substream = evtchnl->u.evt.substream; struct xen_snd_front_pcm_stream_info *stream = stream_get(substream); + struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t delta, new_hw_ptr, cur_frame; - cur_frame = bytes_to_frames(substream->runtime, pos_bytes); + if (!runtime->buffer_size || !runtime->period_size) + return; + + cur_frame = bytes_to_frames(runtime, pos_bytes); delta = cur_frame - stream->be_cur_frame; stream->be_cur_frame = cur_frame; new_hw_ptr = (snd_pcm_uframes_t)atomic_read(&stream->hw_ptr); - new_hw_ptr = (new_hw_ptr + delta) % substream->runtime->buffer_size; + new_hw_ptr = (new_hw_ptr + delta) % runtime->buffer_size; atomic_set(&stream->hw_ptr, (int)new_hw_ptr); stream->out_frames += delta; - if (stream->out_frames > substream->runtime->period_size) { - stream->out_frames %= substream->runtime->period_size; + if (stream->out_frames > runtime->period_size) { + stream->out_frames %= runtime->period_size; snd_pcm_period_elapsed(substream); } } diff --git a/sound/xen/xen_snd_front_evtchnl.c b/sound/xen/xen_snd_front_evtchnl.c index bc03f71bf16e..17a30452c0cc 100644 --- a/sound/xen/xen_snd_front_evtchnl.c +++ b/sound/xen/xen_snd_front_evtchnl.c @@ -94,6 +94,9 @@ static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id) guard(mutex)(&channel->ring_io_lock); + if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) + return IRQ_HANDLED; + prod = page->in_prod; /* Ensure we see ring contents up to prod. */ virt_rmb(); @@ -430,8 +433,8 @@ int xen_snd_front_evtchnl_publish_all(struct xen_snd_front_info *front_info) return ret; } -void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair, - bool is_connected) +void xen_snd_front_evtchnl_set_connected(struct xen_snd_front_evtchnl *channel, + bool is_connected) { enum xen_snd_front_evtchnl_state state; @@ -440,13 +443,16 @@ void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair else state = EVTCHNL_STATE_DISCONNECTED; - scoped_guard(mutex, &evt_pair->req.ring_io_lock) { - evt_pair->req.state = state; + scoped_guard(mutex, &channel->ring_io_lock) { + channel->state = state; } +} - scoped_guard(mutex, &evt_pair->evt.ring_io_lock) { - evt_pair->evt.state = state; - } +void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair, + bool is_connected) +{ + xen_snd_front_evtchnl_set_connected(&evt_pair->req, is_connected); + xen_snd_front_evtchnl_set_connected(&evt_pair->evt, is_connected); } void xen_snd_front_evtchnl_pair_clear(struct xen_snd_front_evtchnl_pair *evt_pair) @@ -456,7 +462,11 @@ void xen_snd_front_evtchnl_pair_clear(struct xen_snd_front_evtchnl_pair *evt_pai } scoped_guard(mutex, &evt_pair->evt.ring_io_lock) { - evt_pair->evt.evt_next_id = 0; + evt_pair->evt.evt_id = 0; + /* Drop obsolete events queued for the previous stream instance. */ + evt_pair->evt.u.evt.page->in_cons = + evt_pair->evt.u.evt.page->in_prod; + /* Ensure the consumer index is visible before stream reuse. */ + virt_wmb(); } } - diff --git a/sound/xen/xen_snd_front_evtchnl.h b/sound/xen/xen_snd_front_evtchnl.h index 3675fba70564..f6ebdb09c029 100644 --- a/sound/xen/xen_snd_front_evtchnl.h +++ b/sound/xen/xen_snd_front_evtchnl.h @@ -37,9 +37,9 @@ struct xen_snd_front_evtchnl { /* State of the event channel. */ enum xen_snd_front_evtchnl_state state; enum xen_snd_front_evtchnl_type type; - /* Either response id or incoming event id. */ + /* Current response id or next expected incoming event id. */ u16 evt_id; - /* Next request id or next expected event id. */ + /* Next request id. */ u16 evt_next_id; /* Shared ring access lock. */ struct mutex ring_io_lock; @@ -77,6 +77,8 @@ void xen_snd_front_evtchnl_free_all(struct xen_snd_front_info *front_info); int xen_snd_front_evtchnl_publish_all(struct xen_snd_front_info *front_info); void xen_snd_front_evtchnl_flush(struct xen_snd_front_evtchnl *evtchnl); +void xen_snd_front_evtchnl_set_connected(struct xen_snd_front_evtchnl *channel, + bool is_connected); void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair, bool is_connected);