diff options
104 files changed, 4002 insertions, 2423 deletions
diff --git a/Documentation/devicetree/bindings/sound/da7213.txt b/Documentation/devicetree/bindings/sound/da7213.txt deleted file mode 100644 index 94584c96c4ae..000000000000 --- a/Documentation/devicetree/bindings/sound/da7213.txt +++ /dev/null @@ -1,45 +0,0 @@ -Dialog Semiconductor DA7212/DA7213 Audio Codec bindings - -====== - -Required properties: -- compatible : Should be "dlg,da7212" or "dlg,da7213" -- reg: Specifies the I2C slave address - -Optional properties: -- clocks : phandle and clock specifier for codec MCLK. -- clock-names : Clock name string for 'clocks' attribute, should be "mclk". - -- dlg,micbias1-lvl : Voltage (mV) for Mic Bias 1 - [<1600>, <2200>, <2500>, <3000>] -- dlg,micbias2-lvl : Voltage (mV) for Mic Bias 2 - [<1600>, <2200>, <2500>, <3000>] -- dlg,dmic-data-sel : DMIC channel select based on clock edge. - ["lrise_rfall", "lfall_rrise"] -- dlg,dmic-samplephase : When to sample audio from DMIC. - ["on_clkedge", "between_clkedge"] -- dlg,dmic-clkrate : DMIC clock frequency (Hz). - [<1500000>, <3000000>] - - - VDDA-supply : Regulator phandle for Analogue power supply - - VDDMIC-supply : Regulator phandle for Mic Bias - - VDDIO-supply : Regulator phandle for I/O power supply - -====== - -Example: - - codec_i2c: da7213@1a { - compatible = "dlg,da7213"; - reg = <0x1a>; - - clocks = <&clks 201>; - clock-names = "mclk"; - - dlg,micbias1-lvl = <2500>; - dlg,micbias2-lvl = <2500>; - - dlg,dmic-data-sel = "lrise_rfall"; - dlg,dmic-samplephase = "between_clkedge"; - dlg,dmic-clkrate = <3000000>; - }; diff --git a/Documentation/devicetree/bindings/sound/dlg,da7213.yaml b/Documentation/devicetree/bindings/sound/dlg,da7213.yaml new file mode 100644 index 000000000000..c2dede1e82ff --- /dev/null +++ b/Documentation/devicetree/bindings/sound/dlg,da7213.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/dlg,da7213.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Dialog Semiconductor DA7212/DA7213 Audio Codec + +maintainers: + - Support Opensource <[email protected]> + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - dlg,da7212 + - dlg,da7213 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: mclk + + "#sound-dai-cells": + const: 0 + + dlg,micbias1-lvl: + description: Voltage (mV) for Mic Bias 1 + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 1600, 2200, 2500, 3000 ] + + dlg,micbias2-lvl: + description: Voltage (mV) for Mic Bias 2 + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 1600, 2200, 2500, 3000 ] + + dlg,dmic-data-sel: + description: DMIC channel select based on clock edge + enum: [ lrise_rfall, lfall_rrise ] + + dlg,dmic-samplephase: + description: When to sample audio from DMIC + enum: [ on_clkedge, between_clkedge ] + + dlg,dmic-clkrate: + description: DMIC clock frequency (Hz) + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 1500000, 3000000 ] + + VDDA-supply: + description: Analogue power supply + + VDDIO-supply: + description: I/O power supply + + VDDMIC-supply: + description: Mic Bias + + VDDSP-supply: + description: Speaker supply + + ports: + $ref: audio-graph-port.yaml#/definitions/ports + + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@1a { + compatible = "dlg,da7213"; + reg = <0x1a>; + + clocks = <&clks 201>; + clock-names = "mclk"; + + #sound-dai-cells = <0>; + + dlg,micbias1-lvl = <2500>; + dlg,micbias2-lvl = <2500>; + + dlg,dmic-data-sel = "lrise_rfall"; + dlg,dmic-samplephase = "between_clkedge"; + dlg,dmic-clkrate = <3000000>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-audio-es8328.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-audio-es8328.yaml new file mode 100644 index 000000000000..5eb6f5812cf2 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,imx-audio-es8328.yaml @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,imx-audio-es8328.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX audio complex with ES8328 codec + +maintainers: + - Shawn Guo <[email protected]> + - Sascha Hauer <[email protected]> + +allOf: + - $ref: sound-card-common.yaml# + +properties: + compatible: + const: fsl,imx-audio-es8328 + + model: + $ref: /schemas/types.yaml#/definitions/string + description: The user-visible name of this sound complex + + ssi-controller: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of the i.MX SSI controller + + jack-gpio: + description: Optional GPIO for headphone jack + maxItems: 1 + + audio-amp-supply: + description: Power regulator for speaker amps + + audio-codec: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle to the ES8328 audio codec + + audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: | + A list of the connections between audio components. Each entry + is a pair of strings, the first being the connection's sink, the second + being the connection's source. Valid names could be power supplies, + ES8328 pins, and the jacks on the board: + + Power supplies: + * audio-amp + + ES8328 pins: + * LOUT1 + * LOUT2 + * ROUT1 + * ROUT2 + * LINPUT1 + * LINPUT2 + * RINPUT1 + * RINPUT2 + * Mic PGA + + Board connectors: + * Headphone + * Speaker + * Mic Jack + + mux-int-port: + $ref: /schemas/types.yaml#/definitions/uint32 + description: The internal port of the i.MX audio muxer (AUDMUX) + enum: [1, 2, 7] + default: 1 + + mux-ext-port: + $ref: /schemas/types.yaml#/definitions/uint32 + description: The external port of the i.MX audio muxer (AUDMIX) + enum: [3, 4, 5, 6] + default: 3 + +required: + - compatible + - model + - ssi-controller + - jack-gpio + - audio-amp-supply + - audio-codec + - audio-routing + - mux-int-port + - mux-ext-port + +unevaluatedProperties: false + +examples: + - | + sound { + compatible = "fsl,imx-audio-es8328"; + model = "imx-audio-es8328"; + ssi-controller = <&ssi1>; + audio-codec = <&codec>; + jack-gpio = <&gpio5 15 0>; + audio-amp-supply = <®_audio_amp>; + audio-routing = + "Speaker", "LOUT2", + "Speaker", "ROUT2", + "Speaker", "audio-amp", + "Headphone", "ROUT1", + "Headphone", "LOUT1", + "LINPUT1", "Mic Jack", + "RINPUT1", "Mic Jack", + "Mic Jack", "Mic Bias"; + mux-int-port = <1>; + mux-ext-port = <3>; + }; diff --git a/Documentation/devicetree/bindings/sound/imx-audio-es8328.txt b/Documentation/devicetree/bindings/sound/imx-audio-es8328.txt deleted file mode 100644 index 07b68ab206fb..000000000000 --- a/Documentation/devicetree/bindings/sound/imx-audio-es8328.txt +++ /dev/null @@ -1,60 +0,0 @@ -Freescale i.MX audio complex with ES8328 codec - -Required properties: -- compatible : "fsl,imx-audio-es8328" -- model : The user-visible name of this sound complex -- ssi-controller : The phandle of the i.MX SSI controller -- jack-gpio : Optional GPIO for headphone jack -- audio-amp-supply : Power regulator for speaker amps -- audio-codec : The phandle of the ES8328 audio codec -- audio-routing : A list of the connections between audio components. - Each entry is a pair of strings, the first being the - connection's sink, the second being the connection's - source. Valid names could be power supplies, ES8328 - pins, and the jacks on the board: - - Power supplies: - * audio-amp - - ES8328 pins: - * LOUT1 - * LOUT2 - * ROUT1 - * ROUT2 - * LINPUT1 - * LINPUT2 - * RINPUT1 - * RINPUT2 - * Mic PGA - - Board connectors: - * Headphone - * Speaker - * Mic Jack -- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX) -- mux-ext-port : The external port of the i.MX audio muxer (AUDMIX) - -Note: The AUDMUX port numbering should start at 1, which is consistent with -hardware manual. - -Example: - -sound { - compatible = "fsl,imx-audio-es8328"; - model = "imx-audio-es8328"; - ssi-controller = <&ssi1>; - audio-codec = <&codec>; - jack-gpio = <&gpio5 15 0>; - audio-amp-supply = <®_audio_amp>; - audio-routing = - "Speaker", "LOUT2", - "Speaker", "ROUT2", - "Speaker", "audio-amp", - "Headphone", "ROUT1", - "Headphone", "LOUT1", - "LINPUT1", "Mic Jack", - "RINPUT1", "Mic Jack", - "Mic Jack", "Mic Bias"; - mux-int-port = <1>; - mux-ext-port = <3>; -}; diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt deleted file mode 100644 index 47878a6df608..000000000000 --- a/Documentation/devicetree/bindings/sound/pcm512x.txt +++ /dev/null @@ -1,53 +0,0 @@ -PCM512x and TAS575x audio CODECs/amplifiers - -These devices support both I2C and SPI (configured with pin strapping -on the board). The TAS575x devices only support I2C. - -Required properties: - - - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141", - "ti,pcm5142", "ti,pcm5242", "ti,tas5754" or "ti,tas5756" - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - - - AVDD-supply, DVDD-supply, and CPVDD-supply : power supplies for the - device, as covered in bindings/regulator/regulator.txt - -Optional properties: - - - clocks : A clock specifier for the clock connected as SCLK. If this - is absent the device will be configured to clock from BCLK. If pll-in - and pll-out are specified in addition to a clock, the device is - configured to accept clock input on a specified gpio pin. - - - pll-in, pll-out : gpio pins used to connect the pll using <1> - through <6>. The device will be configured for clock input on the - given pll-in pin and PLL output on the given pll-out pin. An - external connection from the pll-out pin to the SCLK pin is assumed. - Caution: the TAS-desvices only support gpios 1,2 and 3 - -Examples: - - pcm5122: pcm5122@4c { - compatible = "ti,pcm5122"; - reg = <0x4c>; - - AVDD-supply = <®_3v3_analog>; - DVDD-supply = <®_1v8>; - CPVDD-supply = <®_3v3>; - }; - - - pcm5142: pcm5142@4c { - compatible = "ti,pcm5142"; - reg = <0x4c>; - - AVDD-supply = <®_3v3_analog>; - DVDD-supply = <®_1v8>; - CPVDD-supply = <®_3v3>; - - clocks = <&sck>; - pll-in = <3>; - pll-out = <6>; - }; diff --git a/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml new file mode 100644 index 000000000000..6ad451549036 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc-sndcard.yaml @@ -0,0 +1,205 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,apq8016-sbc-sndcard.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm APQ8016 and similar sound cards + +maintainers: + - Srinivas Kandagatla <[email protected]> + - Stephan Gerhold <[email protected]> + +properties: + compatible: + enum: + - qcom,apq8016-sbc-sndcard + - qcom,msm8916-qdsp6-sndcard + + reg: + items: + - description: Microphone I/O mux register address + - description: Speaker I/O mux register address + + reg-names: + items: + - const: mic-iomux + - const: spkr-iomux + + audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. Valid names could be power supplies, + MicBias of codec and the jacks on the board. + + aux-devs: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + List of phandles pointing to auxiliary devices, such + as amplifiers, to be added to the sound card. + + model: + $ref: /schemas/types.yaml#/definitions/string + description: User visible long sound card name + + pin-switches: + description: List of widget names for which pin switches should be created. + $ref: /schemas/types.yaml#/definitions/string-array + + widgets: + description: User specified audio sound widgets. + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + +patternProperties: + ".*-dai-link$": + description: + Each subnode represents a dai link. Subnodes of each dai links would be + cpu/codec dais. + + type: object + + properties: + link-name: + description: Indicates dai-link name and PCM stream name. + $ref: /schemas/types.yaml#/definitions/string + maxItems: 1 + + cpu: + description: Holds subnode which indicates cpu dai. + type: object + additionalProperties: false + + properties: + sound-dai: + maxItems: 1 + + platform: + description: Holds subnode which indicates platform dai. + type: object + additionalProperties: false + + properties: + sound-dai: + maxItems: 1 + + codec: + description: Holds subnode which indicates codec dai. + type: object + additionalProperties: false + + properties: + sound-dai: + minItems: 1 + maxItems: 8 + + required: + - link-name + - cpu + + additionalProperties: false + +required: + - compatible + - reg + - reg-names + - model + +additionalProperties: false + +examples: + - | + #include <dt-bindings/sound/qcom,lpass.h> + sound@7702000 { + compatible = "qcom,apq8016-sbc-sndcard"; + reg = <0x07702000 0x4>, <0x07702004 0x4>; + reg-names = "mic-iomux", "spkr-iomux"; + + model = "DB410c"; + audio-routing = + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External1"; + + pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>; + pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>; + pinctrl-names = "default", "sleep"; + + quaternary-dai-link { + link-name = "ADV7533"; + cpu { + sound-dai = <&lpass MI2S_QUATERNARY>; + }; + codec { + sound-dai = <&adv_bridge 0>; + }; + }; + + primary-dai-link { + link-name = "WCD"; + cpu { + sound-dai = <&lpass MI2S_PRIMARY>; + }; + codec { + sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; + }; + }; + + tertiary-dai-link { + link-name = "WCD-Capture"; + cpu { + sound-dai = <&lpass MI2S_TERTIARY>; + }; + codec { + sound-dai = <&lpass_codec 1>, <&wcd_codec 1>; + }; + }; + }; + + - | + #include <dt-bindings/sound/qcom,q6afe.h> + #include <dt-bindings/sound/qcom,q6asm.h> + sound@7702000 { + compatible = "qcom,msm8916-qdsp6-sndcard"; + reg = <0x07702000 0x4>, <0x07702004 0x4>; + reg-names = "mic-iomux", "spkr-iomux"; + + model = "msm8916"; + widgets = + "Speaker", "Speaker", + "Headphone", "Headphones"; + pin-switches = "Speaker"; + audio-routing = + "Speaker", "Speaker Amp OUT", + "Speaker Amp IN", "HPH_R", + "Headphones", "HPH_L", + "Headphones", "HPH_R", + "AMIC1", "MIC BIAS Internal1", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS Internal3"; + aux-devs = <&speaker_amp>; + + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cdc_pdm_lines_act>; + pinctrl-1 = <&cdc_pdm_lines_sus>; + + mm1-dai-link { + link-name = "MultiMedia1"; + cpu { + sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; + }; + }; + + primary-dai-link { + link-name = "Primary MI2S"; + cpu { + sound-dai = <&q6afedai PRIMARY_MI2S_RX>; + }; + platform { + sound-dai = <&q6routing>; + }; + codec { + sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index c9076dcd44c1..1d3acdc0c733 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -27,9 +27,7 @@ properties: - qcom,sm8650-sndcard - const: qcom,sm8450-sndcard - enum: - - qcom,apq8016-sbc-sndcard - qcom,apq8096-sndcard - - qcom,msm8916-qdsp6-sndcard - qcom,qcm6490-idp-sndcard - qcom,qcs6490-rb3gen2-sndcard - qcom,qrb5165-rb5-sndcard @@ -58,18 +56,6 @@ properties: $ref: /schemas/types.yaml#/definitions/string description: User visible long sound card name - pin-switches: - description: List of widget names for which pin switches should be created. - $ref: /schemas/types.yaml#/definitions/string-array - - widgets: - description: User specified audio sound widgets. - $ref: /schemas/types.yaml#/definitions/non-unique-string-array - - # Only valid for some compatibles (see allOf if below) - reg: true - reg-names: true - patternProperties: ".*-dai-link$": description: @@ -122,34 +108,6 @@ required: - compatible - model -allOf: - - if: - properties: - compatible: - contains: - enum: - - qcom,apq8016-sbc-sndcard - - qcom,msm8916-qdsp6-sndcard - then: - properties: - reg: - items: - - description: Microphone I/O mux register address - - description: Speaker I/O mux register address - reg-names: - items: - - const: mic-iomux - - const: spkr-iomux - required: - - compatible - - model - - reg - - reg-names - else: - properties: - reg: false - reg-names: false - additionalProperties: false examples: @@ -231,98 +189,3 @@ examples: }; }; }; - - - | - #include <dt-bindings/sound/qcom,lpass.h> - sound@7702000 { - compatible = "qcom,apq8016-sbc-sndcard"; - reg = <0x07702000 0x4>, <0x07702004 0x4>; - reg-names = "mic-iomux", "spkr-iomux"; - - model = "DB410c"; - audio-routing = - "AMIC2", "MIC BIAS Internal2", - "AMIC3", "MIC BIAS External1"; - - pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>; - pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>; - pinctrl-names = "default", "sleep"; - - quaternary-dai-link { - link-name = "ADV7533"; - cpu { - sound-dai = <&lpass MI2S_QUATERNARY>; - }; - codec { - sound-dai = <&adv_bridge 0>; - }; - }; - - primary-dai-link { - link-name = "WCD"; - cpu { - sound-dai = <&lpass MI2S_PRIMARY>; - }; - codec { - sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; - }; - }; - - tertiary-dai-link { - link-name = "WCD-Capture"; - cpu { - sound-dai = <&lpass MI2S_TERTIARY>; - }; - codec { - sound-dai = <&lpass_codec 1>, <&wcd_codec 1>; - }; - }; - }; - - - | - #include <dt-bindings/sound/qcom,q6afe.h> - #include <dt-bindings/sound/qcom,q6asm.h> - sound@7702000 { - compatible = "qcom,msm8916-qdsp6-sndcard"; - reg = <0x07702000 0x4>, <0x07702004 0x4>; - reg-names = "mic-iomux", "spkr-iomux"; - - model = "msm8916"; - widgets = - "Speaker", "Speaker", - "Headphone", "Headphones"; - pin-switches = "Speaker"; - audio-routing = - "Speaker", "Speaker Amp OUT", - "Speaker Amp IN", "HPH_R", - "Headphones", "HPH_L", - "Headphones", "HPH_R", - "AMIC1", "MIC BIAS Internal1", - "AMIC2", "MIC BIAS Internal2", - "AMIC3", "MIC BIAS Internal3"; - aux-devs = <&speaker_amp>; - - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&cdc_pdm_lines_act>; - pinctrl-1 = <&cdc_pdm_lines_sus>; - - mm1-dai-link { - link-name = "MultiMedia1"; - cpu { - sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>; - }; - }; - - primary-dai-link { - link-name = "Primary MI2S"; - cpu { - sound-dai = <&q6afedai PRIMARY_MI2S_RX>; - }; - platform { - sound-dai = <&q6routing>; - }; - codec { - sound-dai = <&lpass_codec 0>, <&wcd_codec 0>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml index 8b9695f5decc..f4610eaed1e1 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml @@ -87,6 +87,10 @@ properties: '#sound-dai-cells': const: 0 + port: + $ref: audio-graph-port.yaml#/definitions/port-base + description: Connection to controller providing I2S signals + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/sound/ti,pcm512x.yaml b/Documentation/devicetree/bindings/sound/ti,pcm512x.yaml new file mode 100644 index 000000000000..21ea9ff5a2bb --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,pcm512x.yaml @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,pcm512x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PCM512x and TAS575x audio CODECs/amplifiers + +maintainers: + - Animesh Agarwal <[email protected]> + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - ti,pcm5121 + - ti,pcm5122 + - ti,pcm5141 + - ti,pcm5142 + - ti,pcm5242 + - ti,tas5754 + - ti,tas5756 + + reg: + maxItems: 1 + + AVDD-supply: true + + DVDD-supply: true + + CPVDD-supply: true + + clocks: + maxItems: 1 + description: A clock specifier for the clock connected as SCLK. If this is + absent the device will be configured to clock from BCLK. If pll-in and + pll-out are specified in addition to a clock, the device is configured to + accept clock input on a specified gpio pin. + + '#sound-dai-cells': + const: 0 + + pll-in: + description: GPIO pin used to connect the pll using <1> through <6>. The + device will be configured for clock input on the given pll-in pin. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 6 + + pll-out: + description: GPIO pin used to connect the pll using <1> through <6>. The + device will be configured for PLL output on the given pll-out pin. An + external connection from the pll-out pin to the SCLK pin is assumed. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 6 + +required: + - compatible + - reg + - AVDD-supply + - DVDD-supply + - CPVDD-supply + +if: + properties: + compatible: + contains: + enum: + - ti,tas5754 + - ti,tas5756 + +then: + properties: + pll-in: + maximum: 3 + + pll-out: + maximum: 3 + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@4c { + compatible = "ti,pcm5142"; + reg = <0x4c>; + AVDD-supply = <®_3v3_analog>; + DVDD-supply = <®_1v8>; + CPVDD-supply = <®_3v3>; + #sound-dai-cells = <0>; + clocks = <&sck>; + pll-in = <3>; + pll-out = <6>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 42decde38320..88a40557db32 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6500,6 +6500,7 @@ F: Documentation/devicetree/bindings/regulator/da92*.txt F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml F: Documentation/devicetree/bindings/regulator/dlg,slg51000.yaml F: Documentation/devicetree/bindings/sound/da[79]*.txt +F: Documentation/devicetree/bindings/sound/dlg,da7213.yaml F: Documentation/devicetree/bindings/thermal/dlg,da9062-thermal.yaml F: Documentation/devicetree/bindings/watchdog/dlg,da9062-watchdog.yaml F: Documentation/hwmon/da90??.rst diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h index 4843b57798f6..daed7123df9d 100644 --- a/include/sound/soc-acpi-intel-match.h +++ b/include/sound/soc-acpi-intel-match.h @@ -33,6 +33,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[]; @@ -44,6 +45,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[]; /* * generic table used for HDA codec-based platforms, possibly with diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 38ccec4e3fcd..b6d301946244 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -70,6 +70,7 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) * @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode * @subsystem_vendor: optional PCI SSID vendor value * @subsystem_device: optional PCI SSID device value + * @subsystem_rev: optional PCI SSID revision value * @subsystem_id_set: true if a value has been written to * subsystem_vendor and subsystem_device. */ @@ -86,6 +87,7 @@ struct snd_soc_acpi_mach_params { struct snd_soc_dai_driver *dai_drivers; unsigned short subsystem_vendor; unsigned short subsystem_device; + unsigned short subsystem_rev; bool subsystem_id_set; }; diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index bbb72ad4c951..ab4e109fe71d 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -240,8 +240,6 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd, int rollback); -int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd); void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay); @@ -345,8 +343,7 @@ struct snd_soc_dai_ops { */ int (*trigger)(struct snd_pcm_substream *, int, struct snd_soc_dai *); - int (*bespoke_trigger)(struct snd_pcm_substream *, int, - struct snd_soc_dai *); + /* * For hardware based FIFO caused delay reporting. * Optional. diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index ebd24753dd00..773f2db8c31c 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -58,7 +58,6 @@ enum snd_soc_dpcm_state { enum snd_soc_dpcm_trigger { SND_SOC_DPCM_TRIGGER_PRE = 0, SND_SOC_DPCM_TRIGGER_POST, - SND_SOC_DPCM_TRIGGER_BESPOKE, }; /* diff --git a/include/sound/soc.h b/include/sound/soc.h index a8e66bbf932b..e844f6afc5b5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1209,8 +1209,9 @@ struct snd_soc_pcm_runtime { bool initialized; + /* CPU/Codec/Platform */ int num_components; - struct snd_soc_component *components[]; /* CPU/Codec/Platform */ + struct snd_soc_component *components[] __counted_by(num_components); }; /* see soc_new_pcm_runtime() */ diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h new file mode 100644 index 000000000000..e366b7968c2d --- /dev/null +++ b/include/sound/soc_sdw_utils.h @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * This file incorporates work covered by the following copyright notice: + * Copyright (c) 2020 Intel Corporation + * Copyright(c) 2024 Advanced Micro Devices, Inc. + * + */ + +#ifndef SOC_SDW_UTILS_H +#define SOC_SDW_UTILS_H + +#include <sound/soc.h> +#include <sound/soc-acpi.h> + +#define SOC_SDW_MAX_DAI_NUM 8 +#define SOC_SDW_MAX_NO_PROPS 2 +#define SOC_SDW_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) + +/* If a CODEC has an optional speaker output, this quirk will enable it */ +#define SOC_SDW_CODEC_SPKR BIT(15) +/* + * If the CODEC has additional devices attached directly to it. + * + * For the cs42l43: + * - 0 - No speaker output + * - SOC_SDW_CODEC_SPKR - CODEC internal speaker + * - SOC_SDW_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker + * - SOC_SDW_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported + */ +#define SOC_SDW_SIDECAR_AMPS BIT(16) + +#define SOC_SDW_UNUSED_DAI_ID -1 +#define SOC_SDW_JACK_OUT_DAI_ID 0 +#define SOC_SDW_JACK_IN_DAI_ID 1 +#define SOC_SDW_AMP_OUT_DAI_ID 2 +#define SOC_SDW_AMP_IN_DAI_ID 3 +#define SOC_SDW_DMIC_DAI_ID 4 + +#define SOC_SDW_DAI_TYPE_JACK 0 +#define SOC_SDW_DAI_TYPE_AMP 1 +#define SOC_SDW_DAI_TYPE_MIC 2 + +struct asoc_sdw_codec_info; + +struct asoc_sdw_dai_info { + const bool direction[2]; /* playback & capture support */ + const char *dai_name; + const int dai_type; + const int dailink[2]; /* dailink id for each direction */ + const struct snd_kcontrol_new *controls; + const int num_controls; + const struct snd_soc_dapm_widget *widgets; + const int num_widgets; + int (*init)(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + int (*rtd_init)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); + bool rtd_init_done; /* Indicate that the rtd_init callback is done */ + unsigned long quirk; +}; + +struct asoc_sdw_codec_info { + const int part_id; + const int version_id; + const char *codec_name; + int amp_num; + const u8 acpi_id[ACPI_ID_LEN]; + const bool ignore_internal_dmic; + const struct snd_soc_ops *ops; + struct asoc_sdw_dai_info dais[SOC_SDW_MAX_DAI_NUM]; + const int dai_num; + + int (*codec_card_late_probe)(struct snd_soc_card *card); + + int (*count_sidecar)(struct snd_soc_card *card, + int *num_dais, int *num_devs); + int (*add_sidecar)(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf); +}; + +struct asoc_sdw_mc_private { + struct snd_soc_card card; + struct snd_soc_jack sdw_headset; + struct device *headset_codec_dev; /* only one headset per card */ + struct device *amp_dev1, *amp_dev2; + bool append_dai_type; + bool ignore_internal_dmic; + void *private; + unsigned long mc_quirk; + int codec_info_list_count; +}; + +extern struct asoc_sdw_codec_info codec_info_list[]; +int asoc_sdw_get_codec_info_list_count(void); + +int asoc_sdw_startup(struct snd_pcm_substream *substream); +int asoc_sdw_prepare(struct snd_pcm_substream *substream); +int asoc_sdw_prepare(struct snd_pcm_substream *substream); +int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd); +int asoc_sdw_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +int asoc_sdw_hw_free(struct snd_pcm_substream *substream); +void asoc_sdw_shutdown(struct snd_pcm_substream *substream); + +const char *asoc_sdw_get_codec_name(struct device *dev, + const struct asoc_sdw_codec_info *codec_info, + const struct snd_soc_acpi_link_adr *adr_link, + int adr_index); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, + int *dai_index); + +struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card, + const char *dai_name); + +void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card); + +int asoc_sdw_card_late_probe(struct snd_soc_card *card); + +void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, + int *be_id, char *name, int playback, int capture, + struct snd_soc_dai_link_component *cpus, int cpus_num, + struct snd_soc_dai_link_component *platform_component, + int num_platforms, struct snd_soc_dai_link_component *codecs, + int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd), + const struct snd_soc_ops *ops); + +int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, + int *be_id, char *name, int playback, int capture, + const char *cpu_dai_name, const char *platform_comp_name, + int num_platforms, const char *codec_name, + const char *codec_dai_name, + int (*init)(struct snd_soc_pcm_runtime *rtd), + const struct snd_soc_ops *ops); + +int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd); + +/* DMIC support */ +int asoc_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd); + +/* RT711 support */ +int asoc_sdw_rt711_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + +/* RT711-SDCA support */ +int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + +/* RT1308 I2S support */ +extern const struct snd_soc_ops soc_sdw_rt1308_i2s_ops; + +/* generic amp support */ +int asoc_sdw_rt_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_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + +/* CS42L43 support */ +int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + +/* CS AMP support */ +int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card, + int *num_dais, int *num_devs); +int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf); +int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + +int asoc_sdw_cs_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + +/* MAXIM codec support */ +int asoc_sdw_maxim_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + +/* dai_link init callbacks */ +int asoc_sdw_rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); + +#endif diff --git a/include/sound/tas2563-tlv.h b/include/sound/tas2563-tlv.h new file mode 100644 index 000000000000..faa3e194f73b --- /dev/null +++ b/include/sound/tas2563-tlv.h @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments TAS2563 Audio Smart Amplifier +// +// Copyright (C) 2022 - 2024 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS2563 driver implements a flexible and configurable +// algo coefficient setting for one, two, or even multiple +// TAS2563 chips. +// +// Author: Shenghao Ding <[email protected]> +// + +#ifndef __TAS2563_TLV_H__ +#define __TAS2563_TLV_H__ + +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2563_dvc_tlv, -12150, 50, 1); + +/* pow(10, db/20) * pow(2,30) */ +static const unsigned char tas2563_dvc_table[][4] = { + { 0X00, 0X00, 0X00, 0X00 }, /* -121.5db */ + { 0X00, 0X00, 0X03, 0XBC }, /* -121.0db */ + { 0X00, 0X00, 0X03, 0XF5 }, /* -120.5db */ + { 0X00, 0X00, 0X04, 0X31 }, /* -120.0db */ + { 0X00, 0X00, 0X04, 0X71 }, /* -119.5db */ + { 0X00, 0X00, 0X04, 0XB4 }, /* -119.0db */ + { 0X00, 0X00, 0X04, 0XFC }, /* -118.5db */ + { 0X00, 0X00, 0X05, 0X47 }, /* -118.0db */ + { 0X00, 0X00, 0X05, 0X97 }, /* -117.5db */ + { 0X00, 0X00, 0X05, 0XEC }, /* -117.0db */ + { 0X00, 0X00, 0X06, 0X46 }, /* -116.5db */ + { 0X00, 0X00, 0X06, 0XA5 }, /* -116.0db */ + { 0X00, 0X00, 0X07, 0X0A }, /* -115.5db */ + { 0X00, 0X00, 0X07, 0X75 }, /* -115.0db */ + { 0X00, 0X00, 0X07, 0XE6 }, /* -114.5db */ + { 0X00, 0X00, 0X08, 0X5E }, /* -114.0db */ + { 0X00, 0X00, 0X08, 0XDD }, /* -113.5db */ + { 0X00, 0X00, 0X09, 0X63 }, /* -113.0db */ + { 0X00, 0X00, 0X09, 0XF2 }, /* -112.5db */ + { 0X00, 0X00, 0X0A, 0X89 }, /* -112.0db */ + { 0X00, 0X00, 0X0B, 0X28 }, /* -111.5db */ + { 0X00, 0X00, 0X0B, 0XD2 }, /* -111.0db */ + { 0X00, 0X00, 0X0C, 0X85 }, /* -110.5db */ + { 0X00, 0X00, 0X0D, 0X43 }, /* -110.0db */ + { 0X00, 0X00, 0X0E, 0X0C }, /* -109.5db */ + { 0X00, 0X00, 0X0E, 0XE1 }, /* -109.0db */ + { 0X00, 0X00, 0X0F, 0XC3 }, /* -108.5db */ + { 0X00, 0X00, 0X10, 0XB2 }, /* -108.0db */ + { 0X00, 0X00, 0X11, 0XAF }, /* -107.5db */ + { 0X00, 0X00, 0X12, 0XBC }, /* -107.0db */ + { 0X00, 0X00, 0X13, 0XD8 }, /* -106.5db */ + { 0X00, 0X00, 0X15, 0X05 }, /* -106.0db */ + { 0X00, 0X00, 0X16, 0X44 }, /* -105.5db */ + { 0X00, 0X00, 0X17, 0X96 }, /* -105.0db */ + { 0X00, 0X00, 0X18, 0XFB }, /* -104.5db */ + { 0X00, 0X00, 0X1A, 0X76 }, /* -104.0db */ + { 0X00, 0X00, 0X1C, 0X08 }, /* -103.5db */ + { 0X00, 0X00, 0X1D, 0XB1 }, /* -103.0db */ + { 0X00, 0X00, 0X1F, 0X73 }, /* -102.5db */ + { 0X00, 0X00, 0X21, 0X51 }, /* -102.0db */ + { 0X00, 0X00, 0X23, 0X4A }, /* -101.5db */ + { 0X00, 0X00, 0X25, 0X61 }, /* -101.0db */ + { 0X00, 0X00, 0X27, 0X98 }, /* -100.5db */ + { 0X00, 0X00, 0X29, 0XF1 }, /* -100.0db */ + { 0X00, 0X00, 0X2C, 0X6D }, /* -99.5db */ + { 0X00, 0X00, 0X2F, 0X0F }, /* -99.0db */ + { 0X00, 0X00, 0X31, 0XD9 }, /* -98.5db */ + { 0X00, 0X00, 0X34, 0XCD }, /* -98.0db */ + { 0X00, 0X00, 0X37, 0XEE }, /* -97.5db */ + { 0X00, 0X00, 0X3B, 0X3F }, /* -97.0db */ + { 0X00, 0X00, 0X3E, 0XC1 }, /* -96.5db */ + { 0X00, 0X00, 0X42, 0X79 }, /* -96.0db */ + { 0X00, 0X00, 0X46, 0X6A }, /* -95.5db */ + { 0X00, 0X00, 0X4A, 0X96 }, /* -95.0db */ + { 0X00, 0X00, 0X4F, 0X01 }, /* -94.5db */ + { 0X00, 0X00, 0X53, 0XAF }, /* -94.0db */ + { 0X00, 0X00, 0X58, 0XA5 }, /* -93.5db */ + { 0X00, 0X00, 0X5D, 0XE6 }, /* -93.0db */ + { 0X00, 0X00, 0X63, 0X76 }, /* -92.5db */ + { 0X00, 0X00, 0X69, 0X5B }, /* -92.0db */ + { 0X00, 0X00, 0X6F, 0X99 }, /* -91.5db */ + { 0X00, 0X00, 0X76, 0X36 }, /* -91.0db */ + { 0X00, 0X00, 0X7D, 0X37 }, /* -90.5db */ + { 0X00, 0X00, 0X84, 0XA2 }, /* -90.0db */ + { 0X00, 0X00, 0X8C, 0X7E }, /* -89.5db */ + { 0X00, 0X00, 0X94, 0XD1 }, /* -89.0db */ + { 0X00, 0X00, 0X9D, 0XA3 }, /* -88.5db */ + { 0X00, 0X00, 0XA6, 0XFA }, /* -88.0db */ + { 0X00, 0X00, 0XB0, 0XDF }, /* -87.5db */ + { 0X00, 0X00, 0XBB, 0X5A }, /* -87.0db */ + { 0X00, 0X00, 0XC6, 0X74 }, /* -86.5db */ + { 0X00, 0X00, 0XD2, 0X36 }, /* -86.0db */ + { 0X00, 0X00, 0XDE, 0XAB }, /* -85.5db */ + { 0X00, 0X00, 0XEB, 0XDC }, /* -85.0db */ + { 0X00, 0X00, 0XF9, 0XD6 }, /* -84.5db */ + { 0X00, 0X01, 0X08, 0XA4 }, /* -84.0db */ + { 0X00, 0X01, 0X18, 0X52 }, /* -83.5db */ + { 0X00, 0X01, 0X28, 0XEF }, /* -83.0db */ + { 0X00, 0X01, 0X3A, 0X87 }, /* -82.5db */ + { 0X00, 0X01, 0X4D, 0X2A }, /* -82.0db */ + { 0X00, 0X01, 0X60, 0XE8 }, /* -81.5db */ + { 0X00, 0X01, 0X75, 0XD1 }, /* -81.0db */ + { 0X00, 0X01, 0X8B, 0XF7 }, /* -80.5db */ + { 0X00, 0X01, 0XA3, 0X6E }, /* -80.0db */ + { 0X00, 0X01, 0XBC, 0X48 }, /* -79.5db */ + { 0X00, 0X01, 0XD6, 0X9B }, /* -79.0db */ + { 0X00, 0X01, 0XF2, 0X7E }, /* -78.5db */ + { 0X00, 0X02, 0X10, 0X08 }, /* -78.0db */ + { 0X00, 0X02, 0X2F, 0X51 }, /* -77.5db */ + { 0X00, 0X02, 0X50, 0X76 }, /* -77.0db */ + { 0X00, 0X02, 0X73, 0X91 }, /* -76.5db */ + { 0X00, 0X02, 0X98, 0XC0 }, /* -76.0db */ + { 0X00, 0X02, 0XC0, 0X24 }, /* -75.5db */ + { 0X00, 0X02, 0XE9, 0XDD }, /* -75.0db */ + { 0X00, 0X03, 0X16, 0X0F }, /* -74.5db */ + { 0X00, 0X03, 0X44, 0XDF }, /* -74.0db */ + { 0X00, 0X03, 0X76, 0X76 }, /* -73.5db */ + { 0X00, 0X03, 0XAA, 0XFC }, /* -73.0db */ + { 0X00, 0X03, 0XE2, 0XA0 }, /* -72.5db */ + { 0X00, 0X04, 0X1D, 0X8F }, /* -72.0db */ + { 0X00, 0X04, 0X5B, 0XFD }, /* -71.5db */ + { 0X00, 0X04, 0X9E, 0X1D }, /* -71.0db */ + { 0X00, 0X04, 0XE4, 0X29 }, /* -70.5db */ + { 0X00, 0X05, 0X2E, 0X5A }, /* -70.0db */ + { 0X00, 0X05, 0X7C, 0XF2 }, /* -69.5db */ + { 0X00, 0X05, 0XD0, 0X31 }, /* -69.0db */ + { 0X00, 0X06, 0X28, 0X60 }, /* -68.5db */ + { 0X00, 0X06, 0X85, 0XC8 }, /* -68.0db */ + { 0X00, 0X06, 0XE8, 0XB9 }, /* -67.5db */ + { 0X00, 0X07, 0X51, 0X86 }, /* -67.0db */ + { 0X00, 0X07, 0XC0, 0X8A }, /* -66.5db */ + { 0X00, 0X08, 0X36, 0X21 }, /* -66.0db */ + { 0X00, 0X08, 0XB2, 0XB0 }, /* -65.5db */ + { 0X00, 0X09, 0X36, 0XA1 }, /* -65.0db */ + { 0X00, 0X09, 0XC2, 0X63 }, /* -64.5db */ + { 0X00, 0X0A, 0X56, 0X6D }, /* -64.0db */ + { 0X00, 0X0A, 0XF3, 0X3C }, /* -63.5db */ + { 0X00, 0X0B, 0X99, 0X56 }, /* -63.0db */ + { 0X00, 0X0C, 0X49, 0X48 }, /* -62.5db */ + { 0X00, 0X0D, 0X03, 0XA7 }, /* -62.0db */ + { 0X00, 0X0D, 0XC9, 0X11 }, /* -61.5db */ + { 0X00, 0X0E, 0X9A, 0X2D }, /* -61.0db */ + { 0X00, 0X0F, 0X77, 0XAD }, /* -60.5db */ + { 0X00, 0X10, 0X62, 0X4D }, /* -60.0db */ + { 0X00, 0X11, 0X5A, 0XD5 }, /* -59.5db */ + { 0X00, 0X12, 0X62, 0X16 }, /* -59.0db */ + { 0X00, 0X13, 0X78, 0XF0 }, /* -58.5db */ + { 0X00, 0X14, 0XA0, 0X50 }, /* -58.0db */ + { 0X00, 0X15, 0XD9, 0X31 }, /* -57.5db */ + { 0X00, 0X17, 0X24, 0X9C }, /* -57.0db */ + { 0X00, 0X18, 0X83, 0XAA }, /* -56.5db */ + { 0X00, 0X19, 0XF7, 0X86 }, /* -56.0db */ + { 0X00, 0X1B, 0X81, 0X6A }, /* -55.5db */ + { 0X00, 0X1D, 0X22, 0XA4 }, /* -55.0db */ + { 0X00, 0X1E, 0XDC, 0X98 }, /* -54.5db */ + { 0X00, 0X20, 0XB0, 0XBC }, /* -54.0db */ + { 0X00, 0X22, 0XA0, 0X9D }, /* -53.5db */ + { 0X00, 0X24, 0XAD, 0XE0 }, /* -53.0db */ + { 0X00, 0X26, 0XDA, 0X43 }, /* -52.5db */ + { 0X00, 0X29, 0X27, 0X9D }, /* -52.0db */ + { 0X00, 0X2B, 0X97, 0XE3 }, /* -51.5db */ + { 0X00, 0X2E, 0X2D, 0X27 }, /* -51.0db */ + { 0X00, 0X30, 0XE9, 0X9A }, /* -50.5db */ + { 0X00, 0X33, 0XCF, 0X8D }, /* -50.0db */ + { 0X00, 0X36, 0XE1, 0X78 }, /* -49.5db */ + { 0X00, 0X3A, 0X21, 0XF3 }, /* -49.0db */ + { 0X00, 0X3D, 0X93, 0XC3 }, /* -48.5db */ + { 0X00, 0X41, 0X39, 0XD3 }, /* -48.0db */ + { 0X00, 0X45, 0X17, 0X3B }, /* -47.5db */ + { 0X00, 0X49, 0X2F, 0X44 }, /* -47.0db */ + { 0X00, 0X4D, 0X85, 0X66 }, /* -46.5db */ + { 0X00, 0X52, 0X1D, 0X50 }, /* -46.0db */ + { 0X00, 0X56, 0XFA, 0XE8 }, /* -45.5db */ + { 0X00, 0X5C, 0X22, 0X4E }, /* -45.0db */ + { 0X00, 0X61, 0X97, 0XE1 }, /* -44.5db */ + { 0X00, 0X67, 0X60, 0X44 }, /* -44.0db */ + { 0X00, 0X6D, 0X80, 0X60 }, /* -43.5db */ + { 0X00, 0X73, 0XFD, 0X65 }, /* -43.0db */ + { 0X00, 0X7A, 0XDC, 0XD7 }, /* -42.5db */ + { 0X00, 0X82, 0X24, 0X8A }, /* -42.0db */ + { 0X00, 0X89, 0XDA, 0XAB }, /* -41.5db */ + { 0X00, 0X92, 0X05, 0XC6 }, /* -41.0db */ + { 0X00, 0X9A, 0XAC, 0XC8 }, /* -40.5db */ + { 0X00, 0XA3, 0XD7, 0X0A }, /* -40.0db */ + { 0X00, 0XAD, 0X8C, 0X52 }, /* -39.5db */ + { 0X00, 0XB7, 0XD4, 0XDD }, /* -39.0db */ + { 0X00, 0XC2, 0XB9, 0X65 }, /* -38.5db */ + { 0X00, 0XCE, 0X43, 0X28 }, /* -38.0db */ + { 0X00, 0XDA, 0X7B, 0XF1 }, /* -37.5db */ + { 0X00, 0XE7, 0X6E, 0X1E }, /* -37.0db */ + { 0X00, 0XF5, 0X24, 0XAC }, /* -36.5db */ + { 0X01, 0X03, 0XAB, 0X3D }, /* -36.0db */ + { 0X01, 0X13, 0X0E, 0X24 }, /* -35.5db */ + { 0X01, 0X23, 0X5A, 0X71 }, /* -35.0db */ + { 0X01, 0X34, 0X9D, 0XF8 }, /* -34.5db */ + { 0X01, 0X46, 0XE7, 0X5D }, /* -34.0db */ + { 0X01, 0X5A, 0X46, 0X27 }, /* -33.5db */ + { 0X01, 0X6E, 0XCA, 0XC5 }, /* -33.0db */ + { 0X01, 0X84, 0X86, 0X9F }, /* -32.5db */ + { 0X01, 0X9B, 0X8C, 0X27 }, /* -32.0db */ + { 0X01, 0XB3, 0XEE, 0XE5 }, /* -31.5db */ + { 0X01, 0XCD, 0XC3, 0X8C }, /* -31.0db */ + { 0X01, 0XE9, 0X20, 0X05 }, /* -30.5db */ + { 0X02, 0X06, 0X1B, 0X89 }, /* -30.0db */ + { 0X02, 0X24, 0XCE, 0XB0 }, /* -29.5db */ + { 0X02, 0X45, 0X53, 0X85 }, /* -29.0db */ + { 0X02, 0X67, 0XC5, 0XA2 }, /* -28.5db */ + { 0X02, 0X8C, 0X42, 0X3F }, /* -28.0db */ + { 0X02, 0XB2, 0XE8, 0X55 }, /* -27.5db */ + { 0X02, 0XDB, 0XD8, 0XAD }, /* -27.0db */ + { 0X03, 0X07, 0X36, 0X05 }, /* -26.5db */ + { 0X03, 0X35, 0X25, 0X29 }, /* -26.0db */ + { 0X03, 0X65, 0XCD, 0X13 }, /* -25.5db */ + { 0X03, 0X99, 0X57, 0X0C }, /* -25.0db */ + { 0X03, 0XCF, 0XEE, 0XCF }, /* -24.5db */ + { 0X04, 0X09, 0XC2, 0XB0 }, /* -24.0db */ + { 0X04, 0X47, 0X03, 0XC1 }, /* -23.5db */ + { 0X04, 0X87, 0XE5, 0XFB }, /* -23.0db */ + { 0X04, 0XCC, 0XA0, 0X6D }, /* -22.5db */ + { 0X05, 0X15, 0X6D, 0X68 }, /* -22.0db */ + { 0X05, 0X62, 0X8A, 0XB3 }, /* -21.5db */ + { 0X05, 0XB4, 0X39, 0XBC }, /* -21.0db */ + { 0X06, 0X0A, 0XBF, 0XD4 }, /* -20.5db */ + { 0X06, 0X66, 0X66, 0X66 }, /* -20.0db */ + { 0X06, 0XC7, 0X7B, 0X36 }, /* -19.5db */ + { 0X07, 0X2E, 0X50, 0XA6 }, /* -19.0db */ + { 0X07, 0X9B, 0X3D, 0XF6 }, /* -18.5db */ + { 0X08, 0X0E, 0X9F, 0X96 }, /* -18.0db */ + { 0X08, 0X88, 0XD7, 0X6D }, /* -17.5db */ + { 0X09, 0X0A, 0X4D, 0X2F }, /* -17.0db */ + { 0X09, 0X93, 0X6E, 0XB8 }, /* -16.5db */ + { 0X0A, 0X24, 0XB0, 0X62 }, /* -16.0db */ + { 0X0A, 0XBE, 0X8D, 0X70 }, /* -15.5db */ + { 0X0B, 0X61, 0X88, 0X71 }, /* -15.0db */ + { 0X0C, 0X0E, 0X2B, 0XB0 }, /* -14.5db */ + { 0X0C, 0XC5, 0X09, 0XAB }, /* -14.0db */ + { 0X0D, 0X86, 0XBD, 0X8D }, /* -13.5db */ + { 0X0E, 0X53, 0XEB, 0XB3 }, /* -13.0db */ + { 0X0F, 0X2D, 0X42, 0X38 }, /* -12.5db */ + { 0X10, 0X13, 0X79, 0X87 }, /* -12.0db */ + { 0X11, 0X07, 0X54, 0XF9 }, /* -11.5db */ + { 0X12, 0X09, 0XA3, 0X7A }, /* -11.0db */ + { 0X13, 0X1B, 0X40, 0X39 }, /* -10.5db */ + { 0X14, 0X3D, 0X13, 0X62 }, /* -10.0db */ + { 0X15, 0X70, 0X12, 0XE1 }, /* -9.5db */ + { 0X16, 0XB5, 0X43, 0X37 }, /* -9.0db */ + { 0X18, 0X0D, 0XB8, 0X54 }, /* -8.5db */ + { 0X19, 0X7A, 0X96, 0X7F }, /* -8.0db */ + { 0X1A, 0XFD, 0X13, 0X54 }, /* -7.5db */ + { 0X1C, 0X96, 0X76, 0XC6 }, /* -7.0db */ + { 0X1E, 0X48, 0X1C, 0X37 }, /* -6.5db */ + { 0X20, 0X13, 0X73, 0X9E }, /* -6.0db */ + { 0X21, 0XFA, 0X02, 0XBF }, /* -5.5db */ + { 0X23, 0XFD, 0X66, 0X78 }, /* -5.0db */ + { 0X26, 0X1F, 0X54, 0X1C }, /* -4.5db */ + { 0X28, 0X61, 0X9A, 0XE9 }, /* -4.0db */ + { 0X2A, 0XC6, 0X25, 0X91 }, /* -3.5db */ + { 0X2D, 0X4E, 0XFB, 0XD5 }, /* -3.0db */ + { 0X2F, 0XFE, 0X44, 0X48 }, /* -2.5db */ + { 0X32, 0XD6, 0X46, 0X17 }, /* -2.0db */ + { 0X35, 0XD9, 0X6B, 0X02 }, /* -1.5db */ + { 0X39, 0X0A, 0X41, 0X5F }, /* -1.0db */ + { 0X3C, 0X6B, 0X7E, 0X4F }, /* -0.5db */ + { 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */ + { 0X43, 0XCA, 0XD0, 0X22 }, /* 0.5db */ + { 0X47, 0XCF, 0X26, 0X7D }, /* 1.0db */ + { 0X4C, 0X10, 0X6B, 0XA5 }, /* 1.5db */ + { 0X50, 0X92, 0X3B, 0XE3 }, /* 2.0db */ + { 0X55, 0X58, 0X6A, 0X46 }, /* 2.5db */ + { 0X5A, 0X67, 0X03, 0XDF }, /* 3.0db */ + { 0X5F, 0XC2, 0X53, 0X32 }, /* 3.5db */ + { 0X65, 0X6E, 0XE3, 0XDB }, /* 4.0db */ + { 0X6B, 0X71, 0X86, 0X68 }, /* 4.5db */ + { 0X71, 0XCF, 0X54, 0X71 }, /* 5.0db */ + { 0X78, 0X8D, 0XB4, 0XE9 }, /* 5.5db */ + { 0X7F, 0XFF, 0XFF, 0XFF }, /* 6.0db */ +}; +#endif diff --git a/include/sound/tas2781-tlv.h b/include/sound/tas2781-tlv.h index 00fd4d449ff3..d87263e43fdb 100644 --- a/include/sound/tas2781-tlv.h +++ b/include/sound/tas2781-tlv.h @@ -17,265 +17,5 @@ static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0); static const __maybe_unused DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0); -static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2563_dvc_tlv, -12150, 50, 1); -/* pow(10, db/20) * pow(2,30) */ -static const __maybe_unused unsigned char tas2563_dvc_table[][4] = { - { 0X00, 0X00, 0X00, 0X00 }, /* -121.5db */ - { 0X00, 0X00, 0X03, 0XBC }, /* -121.0db */ - { 0X00, 0X00, 0X03, 0XF5 }, /* -120.5db */ - { 0X00, 0X00, 0X04, 0X31 }, /* -120.0db */ - { 0X00, 0X00, 0X04, 0X71 }, /* -119.5db */ - { 0X00, 0X00, 0X04, 0XB4 }, /* -119.0db */ - { 0X00, 0X00, 0X04, 0XFC }, /* -118.5db */ - { 0X00, 0X00, 0X05, 0X47 }, /* -118.0db */ - { 0X00, 0X00, 0X05, 0X97 }, /* -117.5db */ - { 0X00, 0X00, 0X05, 0XEC }, /* -117.0db */ - { 0X00, 0X00, 0X06, 0X46 }, /* -116.5db */ - { 0X00, 0X00, 0X06, 0XA5 }, /* -116.0db */ - { 0X00, 0X00, 0X07, 0X0A }, /* -115.5db */ - { 0X00, 0X00, 0X07, 0X75 }, /* -115.0db */ - { 0X00, 0X00, 0X07, 0XE6 }, /* -114.5db */ - { 0X00, 0X00, 0X08, 0X5E }, /* -114.0db */ - { 0X00, 0X00, 0X08, 0XDD }, /* -113.5db */ - { 0X00, 0X00, 0X09, 0X63 }, /* -113.0db */ - { 0X00, 0X00, 0X09, 0XF2 }, /* -112.5db */ - { 0X00, 0X00, 0X0A, 0X89 }, /* -112.0db */ - { 0X00, 0X00, 0X0B, 0X28 }, /* -111.5db */ - { 0X00, 0X00, 0X0B, 0XD2 }, /* -111.0db */ - { 0X00, 0X00, 0X0C, 0X85 }, /* -110.5db */ - { 0X00, 0X00, 0X0D, 0X43 }, /* -110.0db */ - { 0X00, 0X00, 0X0E, 0X0C }, /* -109.5db */ - { 0X00, 0X00, 0X0E, 0XE1 }, /* -109.0db */ - { 0X00, 0X00, 0X0F, 0XC3 }, /* -108.5db */ - { 0X00, 0X00, 0X10, 0XB2 }, /* -108.0db */ - { 0X00, 0X00, 0X11, 0XAF }, /* -107.5db */ - { 0X00, 0X00, 0X12, 0XBC }, /* -107.0db */ - { 0X00, 0X00, 0X13, 0XD8 }, /* -106.5db */ - { 0X00, 0X00, 0X15, 0X05 }, /* -106.0db */ - { 0X00, 0X00, 0X16, 0X44 }, /* -105.5db */ - { 0X00, 0X00, 0X17, 0X96 }, /* -105.0db */ - { 0X00, 0X00, 0X18, 0XFB }, /* -104.5db */ - { 0X00, 0X00, 0X1A, 0X76 }, /* -104.0db */ - { 0X00, 0X00, 0X1C, 0X08 }, /* -103.5db */ - { 0X00, 0X00, 0X1D, 0XB1 }, /* -103.0db */ - { 0X00, 0X00, 0X1F, 0X73 }, /* -102.5db */ - { 0X00, 0X00, 0X21, 0X51 }, /* -102.0db */ - { 0X00, 0X00, 0X23, 0X4A }, /* -101.5db */ - { 0X00, 0X00, 0X25, 0X61 }, /* -101.0db */ - { 0X00, 0X00, 0X27, 0X98 }, /* -100.5db */ - { 0X00, 0X00, 0X29, 0XF1 }, /* -100.0db */ - { 0X00, 0X00, 0X2C, 0X6D }, /* -99.5db */ - { 0X00, 0X00, 0X2F, 0X0F }, /* -99.0db */ - { 0X00, 0X00, 0X31, 0XD9 }, /* -98.5db */ - { 0X00, 0X00, 0X34, 0XCD }, /* -98.0db */ - { 0X00, 0X00, 0X37, 0XEE }, /* -97.5db */ - { 0X00, 0X00, 0X3B, 0X3F }, /* -97.0db */ - { 0X00, 0X00, 0X3E, 0XC1 }, /* -96.5db */ - { 0X00, 0X00, 0X42, 0X79 }, /* -96.0db */ - { 0X00, 0X00, 0X46, 0X6A }, /* -95.5db */ - { 0X00, 0X00, 0X4A, 0X96 }, /* -95.0db */ - { 0X00, 0X00, 0X4F, 0X01 }, /* -94.5db */ - { 0X00, 0X00, 0X53, 0XAF }, /* -94.0db */ - { 0X00, 0X00, 0X58, 0XA5 }, /* -93.5db */ - { 0X00, 0X00, 0X5D, 0XE6 }, /* -93.0db */ - { 0X00, 0X00, 0X63, 0X76 }, /* -92.5db */ - { 0X00, 0X00, 0X69, 0X5B }, /* -92.0db */ - { 0X00, 0X00, 0X6F, 0X99 }, /* -91.5db */ - { 0X00, 0X00, 0X76, 0X36 }, /* -91.0db */ - { 0X00, 0X00, 0X7D, 0X37 }, /* -90.5db */ - { 0X00, 0X00, 0X84, 0XA2 }, /* -90.0db */ - { 0X00, 0X00, 0X8C, 0X7E }, /* -89.5db */ - { 0X00, 0X00, 0X94, 0XD1 }, /* -89.0db */ - { 0X00, 0X00, 0X9D, 0XA3 }, /* -88.5db */ - { 0X00, 0X00, 0XA6, 0XFA }, /* -88.0db */ - { 0X00, 0X00, 0XB0, 0XDF }, /* -87.5db */ - { 0X00, 0X00, 0XBB, 0X5A }, /* -87.0db */ - { 0X00, 0X00, 0XC6, 0X74 }, /* -86.5db */ - { 0X00, 0X00, 0XD2, 0X36 }, /* -86.0db */ - { 0X00, 0X00, 0XDE, 0XAB }, /* -85.5db */ - { 0X00, 0X00, 0XEB, 0XDC }, /* -85.0db */ - { 0X00, 0X00, 0XF9, 0XD6 }, /* -84.5db */ - { 0X00, 0X01, 0X08, 0XA4 }, /* -84.0db */ - { 0X00, 0X01, 0X18, 0X52 }, /* -83.5db */ - { 0X00, 0X01, 0X28, 0XEF }, /* -83.0db */ - { 0X00, 0X01, 0X3A, 0X87 }, /* -82.5db */ - { 0X00, 0X01, 0X4D, 0X2A }, /* -82.0db */ - { 0X00, 0X01, 0X60, 0XE8 }, /* -81.5db */ - { 0X00, 0X01, 0X75, 0XD1 }, /* -81.0db */ - { 0X00, 0X01, 0X8B, 0XF7 }, /* -80.5db */ - { 0X00, 0X01, 0XA3, 0X6E }, /* -80.0db */ - { 0X00, 0X01, 0XBC, 0X48 }, /* -79.5db */ - { 0X00, 0X01, 0XD6, 0X9B }, /* -79.0db */ - { 0X00, 0X01, 0XF2, 0X7E }, /* -78.5db */ - { 0X00, 0X02, 0X10, 0X08 }, /* -78.0db */ - { 0X00, 0X02, 0X2F, 0X51 }, /* -77.5db */ - { 0X00, 0X02, 0X50, 0X76 }, /* -77.0db */ - { 0X00, 0X02, 0X73, 0X91 }, /* -76.5db */ - { 0X00, 0X02, 0X98, 0XC0 }, /* -76.0db */ - { 0X00, 0X02, 0XC0, 0X24 }, /* -75.5db */ - { 0X00, 0X02, 0XE9, 0XDD }, /* -75.0db */ - { 0X00, 0X03, 0X16, 0X0F }, /* -74.5db */ - { 0X00, 0X03, 0X44, 0XDF }, /* -74.0db */ - { 0X00, 0X03, 0X76, 0X76 }, /* -73.5db */ - { 0X00, 0X03, 0XAA, 0XFC }, /* -73.0db */ - { 0X00, 0X03, 0XE2, 0XA0 }, /* -72.5db */ - { 0X00, 0X04, 0X1D, 0X8F }, /* -72.0db */ - { 0X00, 0X04, 0X5B, 0XFD }, /* -71.5db */ - { 0X00, 0X04, 0X9E, 0X1D }, /* -71.0db */ - { 0X00, 0X04, 0XE4, 0X29 }, /* -70.5db */ - { 0X00, 0X05, 0X2E, 0X5A }, /* -70.0db */ - { 0X00, 0X05, 0X7C, 0XF2 }, /* -69.5db */ - { 0X00, 0X05, 0XD0, 0X31 }, /* -69.0db */ - { 0X00, 0X06, 0X28, 0X60 }, /* -68.5db */ - { 0X00, 0X06, 0X85, 0XC8 }, /* -68.0db */ - { 0X00, 0X06, 0XE8, 0XB9 }, /* -67.5db */ - { 0X00, 0X07, 0X51, 0X86 }, /* -67.0db */ - { 0X00, 0X07, 0XC0, 0X8A }, /* -66.5db */ - { 0X00, 0X08, 0X36, 0X21 }, /* -66.0db */ - { 0X00, 0X08, 0XB2, 0XB0 }, /* -65.5db */ - { 0X00, 0X09, 0X36, 0XA1 }, /* -65.0db */ - { 0X00, 0X09, 0XC2, 0X63 }, /* -64.5db */ - { 0X00, 0X0A, 0X56, 0X6D }, /* -64.0db */ - { 0X00, 0X0A, 0XF3, 0X3C }, /* -63.5db */ - { 0X00, 0X0B, 0X99, 0X56 }, /* -63.0db */ - { 0X00, 0X0C, 0X49, 0X48 }, /* -62.5db */ - { 0X00, 0X0D, 0X03, 0XA7 }, /* -62.0db */ - { 0X00, 0X0D, 0XC9, 0X11 }, /* -61.5db */ - { 0X00, 0X0E, 0X9A, 0X2D }, /* -61.0db */ - { 0X00, 0X0F, 0X77, 0XAD }, /* -60.5db */ - { 0X00, 0X10, 0X62, 0X4D }, /* -60.0db */ - { 0X00, 0X11, 0X5A, 0XD5 }, /* -59.5db */ - { 0X00, 0X12, 0X62, 0X16 }, /* -59.0db */ - { 0X00, 0X13, 0X78, 0XF0 }, /* -58.5db */ - { 0X00, 0X14, 0XA0, 0X50 }, /* -58.0db */ - { 0X00, 0X15, 0XD9, 0X31 }, /* -57.5db */ - { 0X00, 0X17, 0X24, 0X9C }, /* -57.0db */ - { 0X00, 0X18, 0X83, 0XAA }, /* -56.5db */ - { 0X00, 0X19, 0XF7, 0X86 }, /* -56.0db */ - { 0X00, 0X1B, 0X81, 0X6A }, /* -55.5db */ - { 0X00, 0X1D, 0X22, 0XA4 }, /* -55.0db */ - { 0X00, 0X1E, 0XDC, 0X98 }, /* -54.5db */ - { 0X00, 0X20, 0XB0, 0XBC }, /* -54.0db */ - { 0X00, 0X22, 0XA0, 0X9D }, /* -53.5db */ - { 0X00, 0X24, 0XAD, 0XE0 }, /* -53.0db */ - { 0X00, 0X26, 0XDA, 0X43 }, /* -52.5db */ - { 0X00, 0X29, 0X27, 0X9D }, /* -52.0db */ - { 0X00, 0X2B, 0X97, 0XE3 }, /* -51.5db */ - { 0X00, 0X2E, 0X2D, 0X27 }, /* -51.0db */ - { 0X00, 0X30, 0XE9, 0X9A }, /* -50.5db */ - { 0X00, 0X33, 0XCF, 0X8D }, /* -50.0db */ - { 0X00, 0X36, 0XE1, 0X78 }, /* -49.5db */ - { 0X00, 0X3A, 0X21, 0XF3 }, /* -49.0db */ - { 0X00, 0X3D, 0X93, 0XC3 }, /* -48.5db */ - { 0X00, 0X41, 0X39, 0XD3 }, /* -48.0db */ - { 0X00, 0X45, 0X17, 0X3B }, /* -47.5db */ - { 0X00, 0X49, 0X2F, 0X44 }, /* -47.0db */ - { 0X00, 0X4D, 0X85, 0X66 }, /* -46.5db */ - { 0X00, 0X52, 0X1D, 0X50 }, /* -46.0db */ - { 0X00, 0X56, 0XFA, 0XE8 }, /* -45.5db */ - { 0X00, 0X5C, 0X22, 0X4E }, /* -45.0db */ - { 0X00, 0X61, 0X97, 0XE1 }, /* -44.5db */ - { 0X00, 0X67, 0X60, 0X44 }, /* -44.0db */ - { 0X00, 0X6D, 0X80, 0X60 }, /* -43.5db */ - { 0X00, 0X73, 0XFD, 0X65 }, /* -43.0db */ - { 0X00, 0X7A, 0XDC, 0XD7 }, /* -42.5db */ - { 0X00, 0X82, 0X24, 0X8A }, /* -42.0db */ - { 0X00, 0X89, 0XDA, 0XAB }, /* -41.5db */ - { 0X00, 0X92, 0X05, 0XC6 }, /* -41.0db */ - { 0X00, 0X9A, 0XAC, 0XC8 }, /* -40.5db */ - { 0X00, 0XA3, 0XD7, 0X0A }, /* -40.0db */ - { 0X00, 0XAD, 0X8C, 0X52 }, /* -39.5db */ - { 0X00, 0XB7, 0XD4, 0XDD }, /* -39.0db */ - { 0X00, 0XC2, 0XB9, 0X65 }, /* -38.5db */ - { 0X00, 0XCE, 0X43, 0X28 }, /* -38.0db */ - { 0X00, 0XDA, 0X7B, 0XF1 }, /* -37.5db */ - { 0X00, 0XE7, 0X6E, 0X1E }, /* -37.0db */ - { 0X00, 0XF5, 0X24, 0XAC }, /* -36.5db */ - { 0X01, 0X03, 0XAB, 0X3D }, /* -36.0db */ - { 0X01, 0X13, 0X0E, 0X24 }, /* -35.5db */ - { 0X01, 0X23, 0X5A, 0X71 }, /* -35.0db */ - { 0X01, 0X34, 0X9D, 0XF8 }, /* -34.5db */ - { 0X01, 0X46, 0XE7, 0X5D }, /* -34.0db */ - { 0X01, 0X5A, 0X46, 0X27 }, /* -33.5db */ - { 0X01, 0X6E, 0XCA, 0XC5 }, /* -33.0db */ - { 0X01, 0X84, 0X86, 0X9F }, /* -32.5db */ - { 0X01, 0X9B, 0X8C, 0X27 }, /* -32.0db */ - { 0X01, 0XB3, 0XEE, 0XE5 }, /* -31.5db */ - { 0X01, 0XCD, 0XC3, 0X8C }, /* -31.0db */ - { 0X01, 0XE9, 0X20, 0X05 }, /* -30.5db */ - { 0X02, 0X06, 0X1B, 0X89 }, /* -30.0db */ - { 0X02, 0X24, 0XCE, 0XB0 }, /* -29.5db */ - { 0X02, 0X45, 0X53, 0X85 }, /* -29.0db */ - { 0X02, 0X67, 0XC5, 0XA2 }, /* -28.5db */ - { 0X02, 0X8C, 0X42, 0X3F }, /* -28.0db */ - { 0X02, 0XB2, 0XE8, 0X55 }, /* -27.5db */ - { 0X02, 0XDB, 0XD8, 0XAD }, /* -27.0db */ - { 0X03, 0X07, 0X36, 0X05 }, /* -26.5db */ - { 0X03, 0X35, 0X25, 0X29 }, /* -26.0db */ - { 0X03, 0X65, 0XCD, 0X13 }, /* -25.5db */ - { 0X03, 0X99, 0X57, 0X0C }, /* -25.0db */ - { 0X03, 0XCF, 0XEE, 0XCF }, /* -24.5db */ - { 0X04, 0X09, 0XC2, 0XB0 }, /* -24.0db */ - { 0X04, 0X47, 0X03, 0XC1 }, /* -23.5db */ - { 0X04, 0X87, 0XE5, 0XFB }, /* -23.0db */ - { 0X04, 0XCC, 0XA0, 0X6D }, /* -22.5db */ - { 0X05, 0X15, 0X6D, 0X68 }, /* -22.0db */ - { 0X05, 0X62, 0X8A, 0XB3 }, /* -21.5db */ - { 0X05, 0XB4, 0X39, 0XBC }, /* -21.0db */ - { 0X06, 0X0A, 0XBF, 0XD4 }, /* -20.5db */ - { 0X06, 0X66, 0X66, 0X66 }, /* -20.0db */ - { 0X06, 0XC7, 0X7B, 0X36 }, /* -19.5db */ - { 0X07, 0X2E, 0X50, 0XA6 }, /* -19.0db */ - { 0X07, 0X9B, 0X3D, 0XF6 }, /* -18.5db */ - { 0X08, 0X0E, 0X9F, 0X96 }, /* -18.0db */ - { 0X08, 0X88, 0XD7, 0X6D }, /* -17.5db */ - { 0X09, 0X0A, 0X4D, 0X2F }, /* -17.0db */ - { 0X09, 0X93, 0X6E, 0XB8 }, /* -16.5db */ - { 0X0A, 0X24, 0XB0, 0X62 }, /* -16.0db */ - { 0X0A, 0XBE, 0X8D, 0X70 }, /* -15.5db */ - { 0X0B, 0X61, 0X88, 0X71 }, /* -15.0db */ - { 0X0C, 0X0E, 0X2B, 0XB0 }, /* -14.5db */ - { 0X0C, 0XC5, 0X09, 0XAB }, /* -14.0db */ - { 0X0D, 0X86, 0XBD, 0X8D }, /* -13.5db */ - { 0X0E, 0X53, 0XEB, 0XB3 }, /* -13.0db */ - { 0X0F, 0X2D, 0X42, 0X38 }, /* -12.5db */ - { 0X10, 0X13, 0X79, 0X87 }, /* -12.0db */ - { 0X11, 0X07, 0X54, 0XF9 }, /* -11.5db */ - { 0X12, 0X09, 0XA3, 0X7A }, /* -11.0db */ - { 0X13, 0X1B, 0X40, 0X39 }, /* -10.5db */ - { 0X14, 0X3D, 0X13, 0X62 }, /* -10.0db */ - { 0X15, 0X70, 0X12, 0XE1 }, /* -9.5db */ - { 0X16, 0XB5, 0X43, 0X37 }, /* -9.0db */ - { 0X18, 0X0D, 0XB8, 0X54 }, /* -8.5db */ - { 0X19, 0X7A, 0X96, 0X7F }, /* -8.0db */ - { 0X1A, 0XFD, 0X13, 0X54 }, /* -7.5db */ - { 0X1C, 0X96, 0X76, 0XC6 }, /* -7.0db */ - { 0X1E, 0X48, 0X1C, 0X37 }, /* -6.5db */ - { 0X20, 0X13, 0X73, 0X9E }, /* -6.0db */ - { 0X21, 0XFA, 0X02, 0XBF }, /* -5.5db */ - { 0X23, 0XFD, 0X66, 0X78 }, /* -5.0db */ - { 0X26, 0X1F, 0X54, 0X1C }, /* -4.5db */ - { 0X28, 0X61, 0X9A, 0XE9 }, /* -4.0db */ - { 0X2A, 0XC6, 0X25, 0X91 }, /* -3.5db */ - { 0X2D, 0X4E, 0XFB, 0XD5 }, /* -3.0db */ - { 0X2F, 0XFE, 0X44, 0X48 }, /* -2.5db */ - { 0X32, 0XD6, 0X46, 0X17 }, /* -2.0db */ - { 0X35, 0XD9, 0X6B, 0X02 }, /* -1.5db */ - { 0X39, 0X0A, 0X41, 0X5F }, /* -1.0db */ - { 0X3C, 0X6B, 0X7E, 0X4F }, /* -0.5db */ - { 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */ - { 0X43, 0XCA, 0XD0, 0X22 }, /* 0.5db */ - { 0X47, 0XCF, 0X26, 0X7D }, /* 1.0db */ - { 0X4C, 0X10, 0X6B, 0XA5 }, /* 1.5db */ - { 0X50, 0X92, 0X3B, 0XE3 }, /* 2.0db */ - { 0X55, 0X58, 0X6A, 0X46 }, /* 2.5db */ - { 0X5A, 0X67, 0X03, 0XDF }, /* 3.0db */ - { 0X5F, 0XC2, 0X53, 0X32 }, /* 3.5db */ - { 0X65, 0X6E, 0XE3, 0XDB }, /* 4.0db */ - { 0X6B, 0X71, 0X86, 0X68 }, /* 4.5db */ - { 0X71, 0XCF, 0X54, 0X71 }, /* 5.0db */ - { 0X78, 0X8D, 0XB4, 0XE9 }, /* 5.5db */ - { 0XFF, 0XFF, 0XFF, 0XFF }, /* 6.0db */ -}; #endif diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index a52afb423b46..e87bd15a8b43 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -126,6 +126,8 @@ source "sound/soc/xtensa/Kconfig" # Supported codecs source "sound/soc/codecs/Kconfig" +source "sound/soc/sdw_utils/Kconfig" + # generic frame-work source "sound/soc/generic/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index fd61847dd1eb..775bb38c2ed4 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -75,3 +75,4 @@ obj-$(CONFIG_SND_SOC) += uniphier/ obj-$(CONFIG_SND_SOC) += ux500/ obj-$(CONFIG_SND_SOC) += xilinx/ obj-$(CONFIG_SND_SOC) += xtensa/ +obj-$(CONFIG_SND_SOC) += sdw_utils/ diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig index 30590a23ad63..88391e4c17e3 100644 --- a/sound/soc/amd/acp/Kconfig +++ b/sound/soc/amd/acp/Kconfig @@ -13,6 +13,10 @@ config SND_SOC_AMD_ACP_COMMON This option enables common modules for Audio-Coprocessor i.e. ACP IP block on AMD platforms. +config SND_SOC_ACPI_AMD_MATCH + tristate + select SND_SOC_ACPI if ACPI + if SND_SOC_AMD_ACP_COMMON config SND_SOC_AMD_ACP_PDM @@ -115,6 +119,24 @@ config SND_SOC_AMD_SOF_MACH help This option enables SOF sound card support for ACP audio. +config SND_SOC_AMD_SOF_SDW_MACH + tristate "AMD SOF Soundwire Machine Driver Support" + depends on X86 && PCI && ACPI + depends on SOUNDWIRE + select SND_SOC_SDW_UTILS + select SND_SOC_DMIC + select SND_SOC_RT711_SDW + select SND_SOC_RT711_SDCA_SDW + select SND_SOC_RT1316_SDW + select SND_SOC_RT715_SDW + select SND_SOC_RT715_SDCA_SDW + help + This option enables SOF sound card support for SoundWire enabled + AMD platforms along with ACP PDM controller. + Say Y if you want to enable SoundWire based machine driver support + on AMD platform. + If unsure select "N". + endif # SND_SOC_AMD_ACP_COMMON config SND_AMD_SOUNDWIRE_ACPI diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index b068bf1f920e..82cf5d180b3a 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -22,6 +22,8 @@ snd-acp70-y := acp70.o snd-acp-mach-y := acp-mach-common.o snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o snd-acp-sof-mach-y := acp-sof-mach.o +snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o +snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o @@ -38,3 +40,5 @@ obj-$(CONFIG_SND_AMD_SOUNDWIRE_ACPI) += snd-amd-sdw-acpi.o obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o obj-$(CONFIG_SND_SOC_AMD_SOF_MACH) += snd-acp-sof-mach.o +obj-$(CONFIG_SND_SOC_ACPI_AMD_MATCH) += snd-soc-acpi-amd-match.o +obj-$(CONFIG_SND_SOC_AMD_SOF_SDW_MACH) += snd-acp-sdw-sof-mach.o diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c new file mode 100644 index 000000000000..3419675e45a9 --- /dev/null +++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c @@ -0,0 +1,742 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright(c) 2024 Advanced Micro Devices, Inc. + +/* + * acp-sdw-sof-mach - ASoC Machine driver for AMD SoundWire platforms + */ + +#include <linux/bitmap.h> +#include <linux/device.h> +#include <linux/dmi.h> +#include <linux/module.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "soc_amd_sdw_common.h" +#include "../../codecs/rt711.h" + +static unsigned long sof_sdw_quirk = RT711_JD1; +static int quirk_override = -1; +module_param_named(quirk, quirk_override, int, 0444); +MODULE_PARM_DESC(quirk, "Board-specific quirk override"); + +static void log_quirks(struct device *dev) +{ + if (SOC_JACK_JDSRC(sof_sdw_quirk)) + dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", + SOC_JACK_JDSRC(sof_sdw_quirk)); + if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC) + dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n"); +} + +static int sof_sdw_quirk_cb(const struct dmi_system_id *id) +{ + sof_sdw_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_sdw_quirk_table[] = { + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AMD"), + DMI_MATCH(DMI_PRODUCT_NAME, "Birman-PHX"), + }, + .driver_data = (void *)RT711_JD2, + }, + {} +}; + +static struct snd_soc_dai_link_component platform_component[] = { + { + /* name might be overridden during probe */ + .name = "0000:04:00.5", + } +}; + +static const struct snd_soc_ops sdw_ops = { + .startup = asoc_sdw_startup, + .prepare = asoc_sdw_prepare, + .trigger = asoc_sdw_trigger, + .hw_params = asoc_sdw_hw_params, + .hw_free = asoc_sdw_hw_free, + .shutdown = asoc_sdw_shutdown, +}; + +/* + * get BE dailink number and CPU DAI number based on sdw link adr. + * Since some sdw slaves may be aggregated, the CPU DAI number + * may be larger than the number of BE dailinks. + */ +static int get_dailink_info(struct device *dev, + const struct snd_soc_acpi_link_adr *adr_link, + int *sdw_be_num, int *codecs_num) +{ + bool group_visited[AMD_SDW_MAX_GROUPS]; + int i; + int j; + + *sdw_be_num = 0; + + if (!adr_link) + return -EINVAL; + + for (i = 0; i < AMD_SDW_MAX_GROUPS; i++) + group_visited[i] = false; + + for (; adr_link->num_adr; adr_link++) { + const struct snd_soc_acpi_endpoint *endpoint; + struct asoc_sdw_codec_info *codec_info; + int stream; + u64 adr; + + /* make sure the link mask has a single bit set */ + if (!is_power_of_2(adr_link->mask)) + return -EINVAL; + + for (i = 0; i < adr_link->num_adr; i++) { + adr = adr_link->adr_d[i].adr; + codec_info = asoc_sdw_find_codec_info_part(adr); + if (!codec_info) + return -EINVAL; + + *codecs_num += codec_info->dai_num; + + if (!adr_link->adr_d[i].name_prefix) { + dev_err(dev, "codec 0x%llx does not have a name prefix\n", + adr_link->adr_d[i].adr); + return -EINVAL; + } + + endpoint = adr_link->adr_d[i].endpoints; + if (endpoint->aggregated && !endpoint->group_id) { + dev_err(dev, "invalid group id on link %x\n", + adr_link->mask); + return -EINVAL; + } + + for (j = 0; j < codec_info->dai_num; j++) { + /* count DAI number for playback and capture */ + for_each_pcm_streams(stream) { + if (!codec_info->dais[j].direction[stream]) + continue; + + /* count BE for each non-aggregated slave or group */ + if (!endpoint->aggregated || + !group_visited[endpoint->group_id]) + (*sdw_be_num)++; + } + } + + if (endpoint->aggregated) + group_visited[endpoint->group_id] = true; + } + } + return 0; +} + +static int fill_sdw_codec_dlc(struct device *dev, + const struct snd_soc_acpi_link_adr *adr_link, + struct snd_soc_dai_link_component *codec, + int adr_index, int dai_index) +{ + u64 adr = adr_link->adr_d[adr_index].adr; + struct asoc_sdw_codec_info *codec_info; + + codec_info = asoc_sdw_find_codec_info_part(adr); + if (!codec_info) + return -EINVAL; + + codec->name = asoc_sdw_get_codec_name(dev, codec_info, adr_link, adr_index); + if (!codec->name) + return -ENOMEM; + + codec->dai_name = codec_info->dais[dai_index].dai_name; + dev_err(dev, "codec->dai_name:%s\n", codec->dai_name); + return 0; +} + +static int set_codec_init_func(struct snd_soc_card *card, + const struct snd_soc_acpi_link_adr *adr_link, + struct snd_soc_dai_link *dai_links, + bool playback, int group_id, int adr_index, int dai_index) +{ + int i = adr_index; + + do { + /* + * Initialize the codec. If codec is part of an aggregated + * group (group_id>0), initialize all codecs belonging to + * same group. + * The first link should start with adr_link->adr_d[adr_index] + * because that is the device that we want to initialize and + * we should end immediately if it is not aggregated (group_id=0) + */ + for ( ; i < adr_link->num_adr; i++) { + struct asoc_sdw_codec_info *codec_info; + + codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; + + /* The group_id is > 0 iff the codec is aggregated */ + if (adr_link->adr_d[i].endpoints->group_id != group_id) + continue; + if (codec_info->dais[dai_index].init) + codec_info->dais[dai_index].init(card, + dai_links, + codec_info, + playback); + + if (!group_id) + return 0; + } + + i = 0; + adr_link++; + } while (adr_link->mask); + + return 0; +} + +/* + * check endpoint status in slaves and gather link ID for all slaves in + * the same group to generate different CPU DAI. Now only support + * one sdw link with all slaves set with only single group id. + * + * one slave on one sdw link with aggregated = 0 + * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI + * + * two or more slaves on one sdw link with aggregated = 1 + * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs + */ +static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, + struct device *dev, int *cpu_dai_id, int *cpu_dai_num, + int *codec_num, unsigned int *group_id, + int adr_index) +{ + int i; + + if (!adr_link->adr_d[adr_index].endpoints->aggregated) { + cpu_dai_id[0] = ffs(adr_link->mask) - 1; + *cpu_dai_num = 1; + *codec_num = 1; + *group_id = 0; + return 0; + } + + *codec_num = 0; + *cpu_dai_num = 0; + *group_id = adr_link->adr_d[adr_index].endpoints->group_id; + + /* Count endpoints with the same group_id in the adr_link */ + for (; adr_link && adr_link->num_adr; adr_link++) { + unsigned int link_codecs = 0; + + for (i = 0; i < adr_link->num_adr; i++) { + if (adr_link->adr_d[i].endpoints->aggregated && + adr_link->adr_d[i].endpoints->group_id == *group_id) + link_codecs++; + } + + if (link_codecs) { + *codec_num += link_codecs; + + if (*cpu_dai_num >= ACP63_SDW_MAX_CPU_DAIS) { + dev_err(dev, "cpu_dai_id array overflowed\n"); + return -EINVAL; + } + + cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1; + } + } + + return 0; +} + +static int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev) +{ + switch (sdw_link_id) { + case AMD_SDW0: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO0_RX; + break; + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_TX; + break; + case SOC_SDW_AMP_IN_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO1_RX; + break; + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW0_AUDIO2_RX; + break; + default: + dev_err(dev, "Invalid be id:%d\n", be_id); + return -EINVAL; + } + break; + case AMD_SDW1: + switch (be_id) { + case SOC_SDW_JACK_OUT_DAI_ID: + case SOC_SDW_AMP_OUT_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_TX; + break; + case SOC_SDW_JACK_IN_DAI_ID: + case SOC_SDW_AMP_IN_DAI_ID: + case SOC_SDW_DMIC_DAI_ID: + *cpu_pin_id = ACP63_SW1_AUDIO0_RX; + break; + default: + dev_err(dev, "invalid be_id:%d\n", be_id); + return -EINVAL; + } + break; + default: + dev_err(dev, "Invalid link id:%d\n", sdw_link_id); + return -EINVAL; + } + return 0; +} + +static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; + +static int create_sdw_dailink(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + const struct snd_soc_acpi_link_adr *adr_link, + struct snd_soc_codec_conf **codec_conf, + int *be_id, int adr_index, int dai_index) +{ + 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 device *dev = card->dev; + const struct snd_soc_acpi_link_adr *adr_link_next; + struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *cpus; + struct asoc_sdw_codec_info *codec_info; + int cpu_dai_id[ACP63_SDW_MAX_CPU_DAIS]; + int cpu_dai_num; + unsigned int group_id; + unsigned int sdw_link_id; + int codec_dlc_index = 0; + int codec_num; + int stream; + int i = 0; + int j, k; + int ret; + int cpu_pin_id; + + ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, + &group_id, adr_index); + if (ret) + return ret; + codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); + if (!codecs) + return -ENOMEM; + + sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, + sizeof(*sdw_codec_ch_maps), GFP_KERNEL); + if (!sdw_codec_ch_maps) + return -ENOMEM; + + /* generate codec name on different links in the same group */ + j = adr_index; + for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && + i < cpu_dai_num; adr_link_next++) { + /* skip the link excluded by this processed group */ + if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1) + continue; + + /* j reset after loop, adr_index only applies to first link */ + for (k = 0 ; (j < adr_link_next->num_adr) && (k < codec_num) ; j++, k++) { + const struct snd_soc_acpi_endpoint *endpoints; + + endpoints = adr_link_next->adr_d[j].endpoints; + if (group_id && (!endpoints->aggregated || + endpoints->group_id != group_id)) + continue; + + /* sanity check */ + if (*codec_conf >= card->codec_conf + card->num_configs) { + dev_err(dev, "codec_conf array overflowed\n"); + return -EINVAL; + } + + ret = fill_sdw_codec_dlc(dev, adr_link_next, + &codecs[codec_dlc_index], + j, dai_index); + if (ret) + return ret; + (*codec_conf)->dlc = codecs[codec_dlc_index]; + (*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix; + + sdw_codec_ch_maps[codec_dlc_index].cpu = i; + sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index; + + codec_dlc_index++; + (*codec_conf)++; + } + j = 0; + + /* check next link to create codec dai in the processed group */ + i++; + } + + /* find codec info to create BE DAI */ + codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[adr_index].adr); + if (!codec_info) + return -EINVAL; + + ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic; + + sdw_link_id = (adr_link->adr_d[adr_index].adr) >> 48; + for_each_pcm_streams(stream) { + char *name, *cpu_name; + int playback, capture; + static const char * const sdw_stream_name[] = { + "SDW%d-PIN%d-PLAYBACK", + "SDW%d-PIN%d-CAPTURE", + "SDW%d-PIN%d-PLAYBACK-%s", + "SDW%d-PIN%d-CAPTURE-%s", + }; + + if (!codec_info->dais[dai_index].direction[stream]) + continue; + + *be_id = codec_info->dais[dai_index].dailink[stream]; + if (*be_id < 0) { + dev_err(dev, "Invalid dailink id %d\n", *be_id); + return -EINVAL; + } + switch (amd_ctx->acp_rev) { + case ACP63_PCI_REV: + ret = get_acp63_cpu_pin_id(sdw_link_id, *be_id, &cpu_pin_id, dev); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + /* create stream name according to first link id */ + if (ctx->append_dai_type) { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream + 2], sdw_link_id, cpu_pin_id, + type_strings[codec_info->dais[dai_index].dai_type]); + } else { + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], sdw_link_id, cpu_pin_id); + } + if (!name) + return -ENOMEM; + + cpus = devm_kcalloc(dev, cpu_dai_num, sizeof(*cpus), GFP_KERNEL); + if (!cpus) + return -ENOMEM; + /* + * generate CPU DAI name base on the sdw link ID and + * cpu pin id according to sdw dai driver. + */ + for (k = 0; k < cpu_dai_num; k++) { + cpu_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW%d Pin%d", sdw_link_id, cpu_pin_id); + if (!cpu_name) + return -ENOMEM; + + cpus[k].dai_name = cpu_name; + } + + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); + capture = (stream == SNDRV_PCM_STREAM_CAPTURE); + asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, + playback, capture, + cpus, cpu_dai_num, + platform_component, ARRAY_SIZE(platform_component), + codecs, codec_num, + asoc_sdw_rtd_init, &sdw_ops); + /* + * SoundWire DAILINKs use 'stream' functions and Bank Switch operations + * based on wait_for_completion(), tag them as 'nonatomic'. + */ + (*dai_links)->nonatomic = true; + (*dai_links)->ch_maps = sdw_codec_ch_maps; + + ret = set_codec_init_func(card, adr_link, *dai_links, + playback, group_id, adr_index, dai_index); + if (ret < 0) { + dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id); + return ret; + } + + (*dai_links)++; + } + return 0; +} + +static int create_dmic_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id) +{ + struct device *dev = card->dev; + int ret; + + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec", + 0, 1, // DMIC only supports capture + "acp-sof-dmic", platform_component->name, + ARRAY_SIZE(platform_component), + "dmic-codec", "dmic-hifi", + asoc_sdw_dmic_init, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + +static int sof_card_dai_links_create(struct snd_soc_card *card) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); + int sdw_be_num = 0, dmic_num = 0; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; + struct snd_soc_codec_conf *codec_conf; + int codec_conf_num = 0; + bool group_generated[AMD_SDW_MAX_GROUPS] = { }; + struct snd_soc_dai_link *dai_links; + struct asoc_sdw_codec_info *codec_info; + int num_links; + int i, j, be_id = 0; + int ret; + + ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); + if (ret < 0) { + dev_err(dev, "failed to get sdw link info %d\n", ret); + return ret; + } + + /* enable dmic */ + if (sof_sdw_quirk & ASOC_SDW_ACP_DMIC || mach_params->dmic_num) + dmic_num = 1; + + dev_dbg(dev, "sdw %d, dmic %d", sdw_be_num, dmic_num); + + /* allocate BE dailinks */ + num_links = sdw_be_num + dmic_num; + dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); + if (!dai_links) + return -ENOMEM; + + /* allocate codec conf, will be populated when dailinks are created */ + codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), + GFP_KERNEL); + if (!codec_conf) + return -ENOMEM; + + card->dai_link = dai_links; + card->num_links = num_links; + card->codec_conf = codec_conf; + card->num_configs = codec_conf_num; + + /* SDW */ + if (!sdw_be_num) + goto DMIC; + + for (; adr_link->num_adr; adr_link++) { + /* + * If there are two or more different devices on the same sdw link, we have to + * append the codec type to the dai link name to prevent duplicated dai link name. + * The same type devices on the same sdw link will be in the same + * snd_soc_acpi_adr_device array. They won't be described in different adr_links. + */ + for (i = 0; i < adr_link->num_adr; i++) { + /* find codec info to get dai_num */ + codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; + if (codec_info->dai_num > 1) { + ctx->append_dai_type = true; + goto out; + } + for (j = 0; j < i; j++) { + if ((SDW_PART_ID(adr_link->adr_d[i].adr) != + SDW_PART_ID(adr_link->adr_d[j].adr)) || + (SDW_MFG_ID(adr_link->adr_d[i].adr) != + SDW_MFG_ID(adr_link->adr_d[j].adr))) { + ctx->append_dai_type = true; + goto out; + } + } + } + } +out: + + /* generate DAI links by each sdw link */ + for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { + for (i = 0; i < adr_link->num_adr; i++) { + const struct snd_soc_acpi_endpoint *endpoint; + + endpoint = adr_link->adr_d[i].endpoints; + + /* this group has been generated */ + if (endpoint->aggregated && + group_generated[endpoint->group_id]) + continue; + + /* find codec info to get dai_num */ + codec_info = asoc_sdw_find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; + + for (j = 0; j < codec_info->dai_num ; j++) { + int current_be_id; + + ret = create_sdw_dailink(card, &dai_links, adr_link, + &codec_conf, ¤t_be_id, + i, j); + if (ret < 0) { + dev_err(dev, + "failed to create dai link %d on 0x%x\n", + j, codec_info->part_id); + return ret; + } + /* Update the be_id to match the highest ID used for SDW link */ + if (be_id < current_be_id) + be_id = current_be_id; + } + + if (endpoint->aggregated) + group_generated[endpoint->group_id] = true; + } + } + +DMIC: + /* dmic */ + if (dmic_num > 0) { + if (ctx->ignore_internal_dmic) { + dev_warn(dev, "Ignoring ACP DMIC\n"); + } else { + be_id = SOC_SDW_DMIC_DAI_ID; + ret = create_dmic_dailinks(card, &dai_links, &be_id); + if (ret) + return ret; + } + } + + WARN_ON(dai_links != card->dai_link + card->num_links); + return 0; +} + +/* SoC card */ +static const char sdw_card_long_name[] = "AMD Soundwire SOF"; + +static int mc_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); + struct snd_soc_card *card; + struct amd_mc_ctx *amd_ctx; + struct asoc_sdw_mc_private *ctx; + int amp_num = 0, i; + int ret; + + amd_ctx = devm_kzalloc(&pdev->dev, sizeof(*amd_ctx), GFP_KERNEL); + if (!amd_ctx) + return -ENOMEM; + + amd_ctx->acp_rev = mach->mach_params.subsystem_rev; + amd_ctx->max_sdw_links = ACP63_SDW_MAX_LINKS; + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); + ctx->private = amd_ctx; + card = &ctx->card; + card->dev = &pdev->dev; + card->name = "amd-soundwire", + card->owner = THIS_MODULE, + card->late_probe = asoc_sdw_card_late_probe, + + snd_soc_card_set_drvdata(card, ctx); + + dmi_check_system(sof_sdw_quirk_table); + + if (quirk_override != -1) { + dev_info(card->dev, "Overriding quirk 0x%lx => 0x%x\n", + sof_sdw_quirk, quirk_override); + sof_sdw_quirk = quirk_override; + } + + log_quirks(card->dev); + + ctx->mc_quirk = sof_sdw_quirk; + /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ + for (i = 0; i < ctx->codec_info_list_count; i++) + codec_info_list[i].amp_num = 0; + + ret = sof_card_dai_links_create(card); + if (ret < 0) + return ret; + + /* + * the default amp_num is zero for each codec and + * amp_num will only be increased for active amp + * codecs on used platform + */ + for (i = 0; i < ctx->codec_info_list_count; i++) + amp_num += codec_info_list[i].amp_num; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + " cfg-amp:%d", amp_num); + if (!card->components) + return -ENOMEM; + + card->long_name = sdw_card_long_name; + + /* Register the card */ + ret = devm_snd_soc_register_card(card->dev, card); + if (ret) { + dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); + asoc_sdw_mc_dailink_exit_loop(card); + return ret; + } + + platform_set_drvdata(pdev, card); + + return ret; +} + +static void mc_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + asoc_sdw_mc_dailink_exit_loop(card); +} + +static const struct platform_device_id mc_id_table[] = { + { "amd_sof_sdw", }, + {} +}; +MODULE_DEVICE_TABLE(platform, mc_id_table); + +static struct platform_driver sof_sdw_driver = { + .driver = { + .name = "amd_sof_sdw", + .pm = &snd_soc_pm_ops, + }, + .probe = mc_probe, + .remove_new = mc_remove, + .id_table = mc_id_table, +}; + +module_platform_driver(sof_sdw_driver); + +MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver"); +MODULE_AUTHOR("Vijendar Mukunda <[email protected]"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amd_sof_sdw"); +MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); diff --git a/sound/soc/amd/acp/amd-acp63-acpi-match.c b/sound/soc/amd/acp/amd-acp63-acpi-match.c new file mode 100644 index 000000000000..be9367913073 --- /dev/null +++ b/sound/soc/amd/acp/amd-acp63-acpi-match.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * amd-acp63-acpi-match.c - tables and support for ACP 6.3 platform + * ACPI enumeration. + * + * Copyright 2024 Advanced Micro Devices, Inc. + */ + +#include <sound/soc-acpi.h> +#include "../mach-config.h" + +static const struct snd_soc_acpi_endpoint single_endpoint = { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0 +}; + +static const struct snd_soc_acpi_endpoint spk_l_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 0, + .group_id = 1 +}; + +static const struct snd_soc_acpi_endpoint spk_r_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 1, + .group_id = 1 +}; + +static const struct snd_soc_acpi_adr_device rt711_rt1316_group_adr[] = { + { + .adr = 0x000030025D071101ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + }, + { + .adr = 0x000030025D131601ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "rt1316-1" + }, + { + .adr = 0x000032025D131601ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1316-2" + }, +}; + +static const struct snd_soc_acpi_adr_device rt714_adr[] = { + { + .adr = 0x130025d071401ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt714" + } +}; + +static const struct snd_soc_acpi_link_adr acp63_4_in_1_sdca[] = { + { .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_rt1316_group_adr), + .adr_d = rt711_rt1316_group_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt714_adr), + .adr_d = rt714_adr, + }, + {} +}; + +struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[] = { + { + .link_mask = BIT(0) | BIT(1), + .links = acp63_4_in_1_sdca, + .drv_name = "amd_sof_sdw", + .sof_tplg_filename = "sof-acp_6_3-rt711-l0-rt1316-l0-rt714-l1.tplg", + .fw_filename = "sof-acp_6_3.ri", + }, + {}, +}; +EXPORT_SYMBOL(snd_soc_acpi_amd_acp63_sof_sdw_machines); + +MODULE_DESCRIPTION("AMD ACP6.3 tables and support for ACPI enumeration"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("[email protected]"); diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h new file mode 100644 index 000000000000..f1bd5a7afc8e --- /dev/null +++ b/sound/soc/amd/acp/soc_amd_sdw_common.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved + */ + +/* + * soc_amd_sdw_common.h - prototypes for common helpers + */ + +#ifndef SOC_AMD_SDW_COMMON_H +#define SOC_AMD_SDW_COMMON_H + +#include <linux/bits.h> +#include <linux/types.h> +#include <sound/soc.h> +#include <sound/soc_sdw_utils.h> + +#define ACP63_SDW_MAX_CPU_DAIS 8 +#define ACP63_SDW_MAX_LINKS 2 + +#define AMD_SDW_MAX_GROUPS 9 +#define ACP63_PCI_REV 0x63 +#define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) +#define ASOC_SDW_FOUR_SPK BIT(4) +#define ASOC_SDW_ACP_DMIC BIT(5) + +#define AMD_SDW0 0 +#define AMD_SDW1 1 +#define ACP63_SW0_AUDIO0_TX 0 +#define ACP63_SW0_AUDIO1_TX 1 +#define ACP63_SW0_AUDIO2_TX 2 + +#define ACP63_SW0_AUDIO0_RX 3 +#define ACP63_SW0_AUDIO1_RX 4 +#define ACP63_SW0_AUDIO2_RX 5 + +#define ACP63_SW1_AUDIO0_TX 0 +#define ACP63_SW1_AUDIO0_RX 1 + +struct amd_mc_ctx { + unsigned int acp_rev; + unsigned int max_sdw_links; +}; + +#endif diff --git a/sound/soc/amd/mach-config.h b/sound/soc/amd/mach-config.h index 7af0f9cf3921..32aa8a6931f4 100644 --- a/sound/soc/amd/mach-config.h +++ b/sound/soc/amd/mach-config.h @@ -23,6 +23,7 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_amd_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_vangogh_sof_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_sof_sdw_machines[]; struct config_entry { u32 flags; diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c index 551738abd1a5..de9e43185555 100644 --- a/sound/soc/codecs/ak4613.c +++ b/sound/soc/codecs/ak4613.c @@ -840,14 +840,14 @@ static void ak4613_parse_of(struct ak4613_priv *priv, /* Input 1 - 2 */ for (i = 0; i < 2; i++) { snprintf(prop, sizeof(prop), "asahi-kasei,in%d-single-end", i + 1); - if (!of_get_property(np, prop, NULL)) + if (!of_property_read_bool(np, prop)) priv->ic |= 1 << i; } /* Output 1 - 6 */ for (i = 0; i < 6; i++) { snprintf(prop, sizeof(prop), "asahi-kasei,out%d-single-end", i + 1); - if (!of_get_property(np, prop, NULL)) + if (!of_property_read_bool(np, prop)) priv->oc |= 1 << i; } diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c index 94a66a325303..29891c1f6bec 100644 --- a/sound/soc/codecs/cs42l42-sdw.c +++ b/sound/soc/codecs/cs42l42-sdw.c @@ -323,15 +323,15 @@ static int cs42l42_sdw_read_prop(struct sdw_slave *peripheral) prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; /* DP1 - capture */ - ports[0].num = CS42L42_SDW_CAPTURE_PORT, - ports[0].type = SDW_DPN_FULL, - ports[0].ch_prep_timeout = 10, + ports[0].num = CS42L42_SDW_CAPTURE_PORT; + ports[0].type = SDW_DPN_FULL; + ports[0].ch_prep_timeout = 10; prop->src_dpn_prop = &ports[0]; /* DP2 - playback */ - ports[1].num = CS42L42_SDW_PLAYBACK_PORT, - ports[1].type = SDW_DPN_FULL, - ports[1].ch_prep_timeout = 10, + ports[1].num = CS42L42_SDW_PLAYBACK_PORT; + ports[1].type = SDW_DPN_FULL; + ports[1].ch_prep_timeout = 10; prop->sink_dpn_prop = &ports[1]; return 0; diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index be4037890fdb..cb4ca80f36d2 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -1415,7 +1415,7 @@ static const char * const bypass_mux_text[] = { static SOC_ENUM_SINGLE_DECL(bypass_enum, SND_SOC_NOPM, 0, bypass_mux_text); static const struct snd_kcontrol_new bypass_ctrl = SOC_DAPM_ENUM("Switch", bypass_enum); -static const struct snd_soc_dapm_widget digital_hp_widgets[] = { +static const struct snd_soc_dapm_widget hp_widgets[] = { SND_SOC_DAPM_MUX("Bypass Switch", SND_SOC_NOPM, 0, 0, &bypass_ctrl), SND_SOC_DAPM_OUTPUT("HPOUTA"), SND_SOC_DAPM_OUTPUT("HPOUTB"), @@ -1447,19 +1447,16 @@ static const struct snd_soc_dapm_widget digital_hp_widgets[] = { CS43130_PDN_HP_SHIFT, 1, cs43130_dac_event, (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD)), -}; -static const struct snd_soc_dapm_widget analog_hp_widgets[] = { +/* Some devices have some extra analog widgets */ +#define NUM_ANALOG_WIDGETS 1 + SND_SOC_DAPM_DAC_E("Analog Playback", NULL, CS43130_HP_OUT_CTL_1, CS43130_HP_IN_EN_SHIFT, 0, cs43130_hpin_event, (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD)), }; -static struct snd_soc_dapm_widget all_hp_widgets[ - ARRAY_SIZE(digital_hp_widgets) + - ARRAY_SIZE(analog_hp_widgets)]; - -static const struct snd_soc_dapm_route digital_hp_routes[] = { +static const struct snd_soc_dapm_route hp_routes[] = { {"ASPIN PCM", NULL, "ASP PCM Playback"}, {"ASPIN DoP", NULL, "ASP DoP Playback"}, {"XSPIN DoP", NULL, "XSP DoP Playback"}, @@ -1472,15 +1469,12 @@ static const struct snd_soc_dapm_route digital_hp_routes[] = { {"Bypass Switch", "Internal", "HiFi DAC"}, {"HPOUTA", NULL, "Bypass Switch"}, {"HPOUTB", NULL, "Bypass Switch"}, -}; -static const struct snd_soc_dapm_route analog_hp_routes[] = { +/* Some devices have some extra analog routes */ +#define NUM_ANALOG_ROUTES 1 {"Bypass Switch", "Alternative", "Analog Playback"}, }; -static struct snd_soc_dapm_route all_hp_routes[ - ARRAY_SIZE(digital_hp_routes) + - ARRAY_SIZE(analog_hp_routes)]; static const unsigned int cs43130_asp_src_rates[] = { 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000 @@ -2398,7 +2392,23 @@ static int cs43130_probe(struct snd_soc_component *component) return 0; } -static struct snd_soc_component_driver soc_component_dev_cs43130 = { +static const struct snd_soc_component_driver soc_component_dev_cs43130_digital = { + .probe = cs43130_probe, + .controls = cs43130_snd_controls, + .num_controls = ARRAY_SIZE(cs43130_snd_controls), + .set_sysclk = cs43130_component_set_sysclk, + .set_pll = cs43130_set_pll, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + /* Don't take into account the ending analog widgets and routes */ + .dapm_widgets = hp_widgets, + .num_dapm_widgets = ARRAY_SIZE(hp_widgets) - NUM_ANALOG_WIDGETS, + .dapm_routes = hp_routes, + .num_dapm_routes = ARRAY_SIZE(hp_routes) - NUM_ANALOG_ROUTES, +}; + +static const struct snd_soc_component_driver soc_component_dev_cs43130_analog = { .probe = cs43130_probe, .controls = cs43130_snd_controls, .num_controls = ARRAY_SIZE(cs43130_snd_controls), @@ -2407,6 +2417,10 @@ static struct snd_soc_component_driver soc_component_dev_cs43130 = { .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, + .dapm_widgets = hp_widgets, + .num_dapm_widgets = ARRAY_SIZE(hp_widgets), + .dapm_routes = hp_routes, + .num_dapm_routes = ARRAY_SIZE(hp_routes), }; static const struct regmap_config cs43130_regmap = { @@ -2479,6 +2493,7 @@ static int cs43130_handle_device_data(struct cs43130_private *cs43130) static int cs43130_i2c_probe(struct i2c_client *client) { + const struct snd_soc_component_driver *component_driver; struct cs43130_private *cs43130; int ret; unsigned int reg; @@ -2596,39 +2611,15 @@ static int cs43130_i2c_probe(struct i2c_client *client) switch (cs43130->dev_id) { case CS43130_CHIP_ID: case CS43131_CHIP_ID: - memcpy(all_hp_widgets, digital_hp_widgets, - sizeof(digital_hp_widgets)); - memcpy(all_hp_widgets + ARRAY_SIZE(digital_hp_widgets), - analog_hp_widgets, sizeof(analog_hp_widgets)); - memcpy(all_hp_routes, digital_hp_routes, - sizeof(digital_hp_routes)); - memcpy(all_hp_routes + ARRAY_SIZE(digital_hp_routes), - analog_hp_routes, sizeof(analog_hp_routes)); - - soc_component_dev_cs43130.dapm_widgets = - all_hp_widgets; - soc_component_dev_cs43130.num_dapm_widgets = - ARRAY_SIZE(all_hp_widgets); - soc_component_dev_cs43130.dapm_routes = - all_hp_routes; - soc_component_dev_cs43130.num_dapm_routes = - ARRAY_SIZE(all_hp_routes); + component_driver = &soc_component_dev_cs43130_analog; break; case CS43198_CHIP_ID: case CS4399_CHIP_ID: - soc_component_dev_cs43130.dapm_widgets = - digital_hp_widgets; - soc_component_dev_cs43130.num_dapm_widgets = - ARRAY_SIZE(digital_hp_widgets); - soc_component_dev_cs43130.dapm_routes = - digital_hp_routes; - soc_component_dev_cs43130.num_dapm_routes = - ARRAY_SIZE(digital_hp_routes); + component_driver = &soc_component_dev_cs43130_digital; break; } - ret = devm_snd_soc_register_component(cs43130->dev, - &soc_component_dev_cs43130, + ret = devm_snd_soc_register_component(cs43130->dev, component_driver, cs43130_dai, ARRAY_SIZE(cs43130_dai)); if (ret < 0) { dev_err(cs43130->dev, diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index b246694ebb4f..60877116c0ef 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -805,6 +805,7 @@ static void es8326_jack_button_handler(struct work_struct *work) SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2); button_to_report = 0; } + es8326_disable_micbias(es8326->component); } mutex_unlock(&es8326->lock); } @@ -878,7 +879,6 @@ static void es8326_jack_detect_handler(struct work_struct *work) regmap_write(es8326->regmap, ES8326_INT_SOURCE, 0x00); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x00); - es8326_enable_micbias(es8326->component); usleep_range(50000, 70000); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x10, 0x10); @@ -897,6 +897,7 @@ static void es8326_jack_detect_handler(struct work_struct *work) dev_dbg(comp->dev, "button pressed\n"); regmap_write(es8326->regmap, ES8326_INT_SOURCE, (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON)); + es8326_enable_micbias(es8326->component); queue_delayed_work(system_wq, &es8326->button_press_work, 10); goto exit; } @@ -1067,6 +1068,7 @@ static void es8326_init(struct snd_soc_component *component) regmap_write(es8326->regmap, ES8326_ADC_MUTE, 0x0f); regmap_write(es8326->regmap, ES8326_CLK_DIV_LRCK, 0xff); + es8326_disable_micbias(es8326->component); msleep(200); regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9); diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 73a588289408..76900274acf3 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2297,36 +2297,37 @@ static int wsa_macro_vi_feed_mixer_put(struct snd_kcontrol *kcontrol, struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); u32 enable = ucontrol->value.integer.value[0]; u32 spk_tx_id = mixer->shift; + u32 dai_id = widget->shift; if (enable) { if (spk_tx_id == WSA_MACRO_TX0 && !test_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { set_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]++; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]++; } if (spk_tx_id == WSA_MACRO_TX1 && !test_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { set_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]++; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]++; } } else { if (spk_tx_id == WSA_MACRO_TX0 && test_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { clear_bit(WSA_MACRO_TX0, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]--; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]--; } if (spk_tx_id == WSA_MACRO_TX1 && test_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI])) { + &wsa->active_ch_mask[dai_id])) { clear_bit(WSA_MACRO_TX1, - &wsa->active_ch_mask[WSA_MACRO_AIF_VI]); - wsa->active_ch_cnt[WSA_MACRO_AIF_VI]--; + &wsa->active_ch_mask[dai_id]); + wsa->active_ch_cnt[dai_id]--; } } snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL); diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index f50f196d700d..ce2e88e066f3 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -2828,7 +2828,9 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component) } if (dev->of_node) { - devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, dai_clk_hw); + if (ret) + return ret; } else { ret = devm_clk_hw_register_clkdev(dev, dai_clk_hw, init.name, dev_name(dev)); diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index c421906a0694..4ab15be69f3a 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -63,10 +63,6 @@ struct sti_spdif_audio { struct sti_sas_dev_data { const struct regmap_config *regmap; const struct snd_soc_dai_ops *dac_ops; /* DAC function callbacks */ - const struct snd_soc_dapm_widget *dapm_widgets; /* dapms declaration */ - const int num_dapm_widgets; /* dapms declaration */ - const struct snd_soc_dapm_route *dapm_routes; /* route declaration */ - const int num_dapm_routes; /* route declaration */ }; /* driver data structure */ @@ -324,10 +320,6 @@ static const struct regmap_config stih407_sas_regmap = { static const struct sti_sas_dev_data stih407_data = { .regmap = &stih407_sas_regmap, .dac_ops = &stih407_dac_ops, - .dapm_widgets = stih407_sas_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets), - .dapm_routes = stih407_sas_route, - .num_dapm_routes = ARRAY_SIZE(stih407_sas_route), }; static struct snd_soc_dai_driver sti_sas_dai[] = { @@ -386,12 +378,16 @@ static int sti_sas_component_probe(struct snd_soc_component *component) return sti_sas_init_sas_registers(component, drvdata); } -static struct snd_soc_component_driver sti_sas_driver = { +static const struct snd_soc_component_driver sti_sas_driver = { .probe = sti_sas_component_probe, .resume = sti_sas_resume, .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, + .dapm_widgets = stih407_sas_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(stih407_sas_dapm_widgets), + .dapm_routes = stih407_sas_route, + .num_dapm_routes = ARRAY_SIZE(stih407_sas_route), }; static const struct of_device_id sti_sas_dev_match[] = { @@ -446,13 +442,6 @@ static int sti_sas_driver_probe(struct platform_device *pdev) sti_sas_dai[STI_SAS_DAI_ANALOG_OUT].ops = drvdata->dev_data->dac_ops; - /* Set dapms*/ - sti_sas_driver.dapm_widgets = drvdata->dev_data->dapm_widgets; - sti_sas_driver.num_dapm_widgets = drvdata->dev_data->num_dapm_widgets; - - sti_sas_driver.dapm_routes = drvdata->dev_data->dapm_routes; - sti_sas_driver.num_dapm_routes = drvdata->dev_data->num_dapm_routes; - /* Store context */ dev_set_drvdata(&pdev->dev, drvdata); diff --git a/sound/soc/codecs/tas2781-comlib.c b/sound/soc/codecs/tas2781-comlib.c index 1fbf4560f5cc..58abbc098a91 100644 --- a/sound/soc/codecs/tas2781-comlib.c +++ b/sound/soc/codecs/tas2781-comlib.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// TAS2781 Common functions for HDA and ASoC Audio drivers +// TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers // // Copyright 2023 - 2024 Texas Instruments, Inc. // @@ -64,8 +64,8 @@ static int tasdevice_change_chn_book(struct tasdevice_priv *tas_priv, */ ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0); if (ret < 0) { - dev_err(tas_priv->dev, "%s, E=%d\n", - __func__, ret); + dev_err(tas_priv->dev, "%s, E=%d channel:%d\n", + __func__, ret, chn); goto out; } } diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index e79d613745b4..8a57c045afdd 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -30,6 +30,7 @@ #include <sound/soc.h> #include <sound/tas2781.h> #include <sound/tlv.h> +#include <sound/tas2563-tlv.h> #include <sound/tas2781-tlv.h> #include <asm/unaligned.h> diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h index 37bff16e88dd..35f3d48bd7dd 100644 --- a/sound/soc/codecs/wcd937x.h +++ b/sound/soc/codecs/wcd937x.h @@ -484,10 +484,25 @@ #define WCD937X_MAX_MICBIAS 3 #define WCD937X_MAX_BULK_SUPPLY 4 -#define WCD937X_MAX_TX_SWR_PORTS 4 -#define WCD937X_MAX_SWR_PORTS 5 #define WCD937X_MAX_SWR_CH_IDS 15 +enum wcd937x_tx_sdw_ports { + WCD937X_ADC_1_PORT = 1, + WCD937X_ADC_2_3_PORT, + WCD937X_DMIC_0_3_MBHC_PORT, + WCD937X_DMIC_4_6_PORT, + WCD937X_MAX_TX_SWR_PORTS = WCD937X_DMIC_4_6_PORT, +}; + +enum wcd937x_rx_sdw_ports { + WCD937X_HPH_PORT = 1, + WCD937X_CLSH_PORT, + WCD937X_COMP_PORT, + WCD937X_LO_PORT, + WCD937X_DSD_PORT, + WCD937X_MAX_SWR_PORTS = WCD937X_DSD_PORT, +}; + struct wcd937x_sdw_ch_info { int port_num; unsigned int ch_mask; @@ -581,13 +596,6 @@ enum { WCD937X_NUM_IRQS, }; -enum wcd937x_tx_sdw_ports { - WCD937X_ADC_1_PORT = 1, - WCD937X_ADC_2_3_PORT, - WCD937X_DMIC_0_3_MBHC_PORT, - WCD937X_DMIC_4_6_PORT, -}; - enum wcd937x_tx_sdw_channels { WCD937X_ADC1, WCD937X_ADC2, @@ -602,14 +610,6 @@ enum wcd937x_tx_sdw_channels { WCD937X_DMIC6, }; -enum wcd937x_rx_sdw_ports { - WCD937X_HPH_PORT = 1, - WCD937X_CLSH_PORT, - WCD937X_COMP_PORT, - WCD937X_LO_PORT, - WCD937X_DSD_PORT, -}; - enum wcd937x_rx_sdw_channels { WCD937X_HPH_L, WCD937X_HPH_R, diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index 12b32d5dc580..aa92f1bfc921 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -29,7 +29,6 @@ #define WCD938X_MAX_SUPPLY (4) #define WCD938X_MBHC_MAX_BUTTONS (8) #define TX_ADC_MAX (4) -#define WCD938X_TX_MAX_SWR_PORTS (5) #define WCD938X_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ @@ -39,8 +38,6 @@ SNDRV_PCM_RATE_176400) #define WCD938X_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \ SNDRV_PCM_FMTBIT_S24_LE) -/* Convert from vout ctl to micbias voltage in mV */ -#define WCD_VOUT_CTL_TO_MICB(v) (1000 + v * 50) #define SWR_CLK_RATE_0P6MHZ (600000) #define SWR_CLK_RATE_1P2MHZ (1200000) #define SWR_CLK_RATE_2P4MHZ (2400000) @@ -48,8 +45,6 @@ #define SWR_CLK_RATE_9P6MHZ (9600000) #define SWR_CLK_RATE_11P2896MHZ (1128960) -#define WCD938X_DRV_NAME "wcd938x_codec" -#define WCD938X_VERSION_1_0 (1) #define EAR_RX_PATH_AUX (1) #define ADC_MODE_VAL_HIFI 0x01 @@ -72,7 +67,6 @@ /* Z value compared in milliOhm */ #define WCD938X_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000)) #define WCD938X_MBHC_ZDET_CONST (86 * 16384) -#define WCD938X_MBHC_MOISTURE_RREF R_24_KOHM #define WCD_MBHC_HS_V_MAX 1600 #define WCD938X_EAR_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \ @@ -90,18 +84,6 @@ enum { }; enum { - TX_HDR12 = 0, - TX_HDR34, - TX_HDR_MAX, -}; - -enum { - WCD_RX1, - WCD_RX2, - WCD_RX3 -}; - -enum { /* INTR_CTRL_INT_MASK_0 */ WCD938X_IRQ_MBHC_BUTTON_PRESS_DET = 0, WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h index b2ad98026ae2..fb6a0e4ef337 100644 --- a/sound/soc/codecs/wcd938x.h +++ b/sound/soc/codecs/wcd938x.h @@ -585,8 +585,6 @@ #define WCD938X_DIGITAL_DEM_BYPASS_DATA3 (0x34D8) #define WCD938X_MAX_REGISTER (WCD938X_DIGITAL_DEM_BYPASS_DATA3) -#define WCD938X_MAX_SWR_PORTS 5 -#define WCD938X_MAX_TX_SWR_PORTS 4 #define WCD938X_MAX_SWR_CH_IDS 15 struct wcd938x_sdw_ch_info { @@ -606,6 +604,7 @@ enum wcd938x_tx_sdw_ports { /* DMIC0_0, DMIC0_1, DMIC1_0, DMIC1_1 */ WCD938X_DMIC_0_3_MBHC_PORT, WCD938X_DMIC_4_7_PORT, + WCD938X_MAX_TX_SWR_PORTS = WCD938X_DMIC_4_7_PORT, }; enum wcd938x_tx_sdw_channels { @@ -630,6 +629,7 @@ enum wcd938x_rx_sdw_ports { WCD938X_COMP_PORT, WCD938X_LO_PORT, WCD938X_DSD_PORT, + WCD938X_MAX_SWR_PORTS = WCD938X_DSD_PORT, }; enum wcd938x_rx_sdw_channels { diff --git a/sound/soc/codecs/wcd939x.h b/sound/soc/codecs/wcd939x.h index 1571c2120cfc..3204fb10b58d 100644 --- a/sound/soc/codecs/wcd939x.h +++ b/sound/soc/codecs/wcd939x.h @@ -842,9 +842,6 @@ #define WCD939X_DSD_HPHR_CFG5 (0x35a6) #define WCD939X_MAX_REGISTER (WCD939X_DSD_HPHR_CFG5) -#define WCD939X_MAX_SWR_PORTS (6) -#define WCD939X_MAX_RX_SWR_PORTS (6) -#define WCD939X_MAX_TX_SWR_PORTS (4) #define WCD939X_MAX_SWR_CH_IDS (15) struct wcd939x_sdw_ch_info { @@ -863,6 +860,7 @@ enum wcd939x_tx_sdw_ports { WCD939X_ADC_DMIC_1_2_PORT, WCD939X_DMIC_0_3_MBHC_PORT, WCD939X_DMIC_3_7_PORT, + WCD939X_MAX_TX_SWR_PORTS = WCD939X_DMIC_3_7_PORT, }; enum wcd939x_tx_sdw_channels { @@ -888,6 +886,8 @@ enum wcd939x_rx_sdw_ports { WCD939X_LO_PORT, WCD939X_DSD_PORT, WCD939X_HIFI_PCM_PORT, + WCD939X_MAX_RX_SWR_PORTS = WCD939X_HIFI_PCM_PORT, + WCD939X_MAX_SWR_PORTS = WCD939X_MAX_RX_SWR_PORTS, }; enum wcd939x_rx_sdw_channels { diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index fb9e92f08d98..dd2d6661adc7 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -386,33 +386,32 @@ enum wsa_port_ids { /* 4 ports */ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = { - { - /* DAC */ - .num = 1, + [WSA881X_PORT_DAC] = { + .num = WSA881X_PORT_DAC + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* COMP */ - .num = 2, + }, + [WSA881X_PORT_COMP] = { + .num = WSA881X_PORT_COMP + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* BOOST */ - .num = 3, + }, + [WSA881X_PORT_BOOST] = { + .num = WSA881X_PORT_BOOST + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* VISENSE */ - .num = 4, + }, + [WSA881X_PORT_VISENSE] = { + .num = WSA881X_PORT_VISENSE + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, @@ -422,17 +421,20 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = { }; static const struct sdw_port_config wsa881x_pconfig[WSA881X_MAX_SWR_PORTS] = { - { - .num = 1, + [WSA881X_PORT_DAC] = { + .num = WSA881X_PORT_DAC + 1, .ch_mask = 0x1, - }, { - .num = 2, + }, + [WSA881X_PORT_COMP] = { + .num = WSA881X_PORT_COMP + 1, .ch_mask = 0xf, - }, { - .num = 3, + }, + [WSA881X_PORT_BOOST] = { + .num = WSA881X_PORT_BOOST + 1, .ch_mask = 0x3, - }, { /* IV feedback */ - .num = 4, + }, + [WSA881X_PORT_VISENSE] = { + .num = WSA881X_PORT_VISENSE + 1, .ch_mask = 0x3, }, }; @@ -680,7 +682,6 @@ struct wsa881x_priv { * For backwards compatibility. */ unsigned int sd_n_val; - int version; int active_ports; bool port_prepared[WSA881X_MAX_SWR_PORTS]; bool port_enable[WSA881X_MAX_SWR_PORTS]; @@ -691,7 +692,6 @@ static void wsa881x_init(struct wsa881x_priv *wsa881x) struct regmap *rm = wsa881x->regmap; unsigned int val = 0; - regmap_read(rm, WSA881X_CHIP_ID1, &wsa881x->version); regmap_register_patch(wsa881x->regmap, wsa881x_rev_2_0, ARRAY_SIZE(wsa881x_rev_2_0)); diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index 3e4fdaa3f44f..47da5674d7c9 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c @@ -438,8 +438,6 @@ struct wsa883x_priv { struct gpio_desc *sd_n; bool port_prepared[WSA883X_MAX_SWR_PORTS]; bool port_enable[WSA883X_MAX_SWR_PORTS]; - int version; - int variant; int active_ports; int dev_mode; int comp_offset; @@ -482,33 +480,32 @@ static const struct soc_enum wsa_dev_mode_enum = /* 4 ports */ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA883X_MAX_SWR_PORTS] = { - { - /* DAC */ - .num = 1, + [WSA883X_PORT_DAC] = { + .num = WSA883X_PORT_DAC + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* COMP */ - .num = 2, + }, + [WSA883X_PORT_COMP] = { + .num = WSA883X_PORT_COMP + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* BOOST */ - .num = 3, + }, + [WSA883X_PORT_BOOST] = { + .num = WSA883X_PORT_BOOST + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { - /* VISENSE */ - .num = 4, + }, + [WSA883X_PORT_VISENSE] = { + .num = WSA883X_PORT_VISENSE + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, @@ -518,17 +515,20 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA883X_MAX_SWR_PORTS] = { }; static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = { - { - .num = 1, + [WSA883X_PORT_DAC] = { + .num = WSA883X_PORT_DAC + 1, .ch_mask = 0x1, - }, { - .num = 2, + }, + [WSA883X_PORT_COMP] = { + .num = WSA883X_PORT_COMP + 1, .ch_mask = 0xf, - }, { - .num = 3, + }, + [WSA883X_PORT_BOOST] = { + .num = WSA883X_PORT_BOOST + 1, .ch_mask = 0x3, - }, { /* IV feedback */ - .num = 4, + }, + [WSA883X_PORT_VISENSE] = { + .num = WSA883X_PORT_VISENSE + 1, .ch_mask = 0x3, }, }; @@ -997,33 +997,36 @@ static const struct reg_sequence reg_init[] = { {WSA883X_GMAMP_SUP1, 0xE2}, }; -static void wsa883x_init(struct wsa883x_priv *wsa883x) +static int wsa883x_init(struct wsa883x_priv *wsa883x) { struct regmap *regmap = wsa883x->regmap; - int variant, version; + int variant, version, ret; - regmap_read(regmap, WSA883X_OTP_REG_0, &variant); - wsa883x->variant = variant & WSA883X_ID_MASK; + ret = regmap_read(regmap, WSA883X_OTP_REG_0, &variant); + if (ret) + return ret; + variant = variant & WSA883X_ID_MASK; - regmap_read(regmap, WSA883X_CHIP_ID0, &version); - wsa883x->version = version; + ret = regmap_read(regmap, WSA883X_CHIP_ID0, &version); + if (ret) + return ret; - switch (wsa883x->variant) { + switch (variant) { case WSA8830: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8830\n", - wsa883x->version); + version); break; case WSA8835: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8835\n", - wsa883x->version); + version); break; case WSA8832: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8832\n", - wsa883x->version); + version); break; case WSA8835_V2: dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8835_V2\n", - wsa883x->version); + version); break; default: break; @@ -1034,12 +1037,14 @@ static void wsa883x_init(struct wsa883x_priv *wsa883x) /* Initial settings */ regmap_multi_reg_write(regmap, reg_init, ARRAY_SIZE(reg_init)); - if (wsa883x->variant == WSA8830 || wsa883x->variant == WSA8832) { + if (variant == WSA8830 || variant == WSA8832) { wsa883x->comp_offset = COMP_OFFSET3; regmap_update_bits(regmap, WSA883X_DRE_CTL_0, WSA883X_DRE_OFFSET_MASK, wsa883x->comp_offset); } + + return 0; } static int wsa883x_update_status(struct sdw_slave *slave, @@ -1048,7 +1053,7 @@ static int wsa883x_update_status(struct sdw_slave *slave, struct wsa883x_priv *wsa883x = dev_get_drvdata(&slave->dev); if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0) - wsa883x_init(wsa883x); + return wsa883x_init(wsa883x); return 0; } diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c index 89eb5e03a617..8db1380d1f10 100644 --- a/sound/soc/codecs/wsa884x.c +++ b/sound/soc/codecs/wsa884x.c @@ -703,7 +703,6 @@ struct wsa884x_priv { struct reset_control *sd_reset; bool port_prepared[WSA884X_MAX_SWR_PORTS]; bool port_enable[WSA884X_MAX_SWR_PORTS]; - unsigned int variant; int active_ports; int dev_mode; bool hw_init; @@ -782,42 +781,47 @@ static const struct soc_enum wsa884x_dev_mode_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa884x_dev_mode_text), wsa884x_dev_mode_text); static struct sdw_dpn_prop wsa884x_sink_dpn_prop[WSA884X_MAX_SWR_PORTS] = { - { + [WSA884X_PORT_DAC] = { .num = WSA884X_PORT_DAC + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_COMP] = { .num = WSA884X_PORT_COMP + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_BOOST] = { .num = WSA884X_PORT_BOOST + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_PBR] = { .num = WSA884X_PORT_PBR + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_VISENSE] = { .num = WSA884X_PORT_VISENSE + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, .max_ch = 1, .simple_ch_prep_sm = true, .read_only_wordlength = true, - }, { + }, + [WSA884X_PORT_CPS] = { .num = WSA884X_PORT_CPS + 1, .type = SDW_DPN_SIMPLE, .min_ch = 1, @@ -828,22 +832,27 @@ static struct sdw_dpn_prop wsa884x_sink_dpn_prop[WSA884X_MAX_SWR_PORTS] = { }; static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = { - { + [WSA884X_PORT_DAC] = { .num = WSA884X_PORT_DAC + 1, .ch_mask = 0x1, - }, { + }, + [WSA884X_PORT_COMP] = { .num = WSA884X_PORT_COMP + 1, .ch_mask = 0xf, - }, { + }, + [WSA884X_PORT_BOOST] = { .num = WSA884X_PORT_BOOST + 1, .ch_mask = 0x3, - }, { + }, + [WSA884X_PORT_PBR] = { .num = WSA884X_PORT_PBR + 1, .ch_mask = 0x1, - }, { + }, + [WSA884X_PORT_VISENSE] = { .num = WSA884X_PORT_VISENSE + 1, .ch_mask = 0x3, - }, { + }, + [WSA884X_PORT_CPS] = { .num = WSA884X_PORT_CPS + 1, .ch_mask = 0x3, }, @@ -1465,7 +1474,7 @@ static void wsa884x_init(struct wsa884x_priv *wsa884x) unsigned int variant = 0; if (!regmap_read(wsa884x->regmap, WSA884X_OTP_REG_0, &variant)) - wsa884x->variant = variant & WSA884X_OTP_REG_0_ID_MASK; + variant = variant & WSA884X_OTP_REG_0_ID_MASK; regmap_multi_reg_write(wsa884x->regmap, wsa884x_reg_init, ARRAY_SIZE(wsa884x_reg_init)); @@ -1474,7 +1483,7 @@ static void wsa884x_init(struct wsa884x_priv *wsa884x) wo_ctl_0 |= FIELD_PREP(WSA884X_ANA_WO_CTL_0_DAC_CM_CLAMP_EN_MASK, WSA884X_ANA_WO_CTL_0_DAC_CM_CLAMP_EN_MODE_SPEAKER); /* Assume that compander is enabled by default unless it is haptics sku */ - if (wsa884x->variant == WSA884X_OTP_ID_WSA8845H) + if (variant == WSA884X_OTP_ID_WSA8845H) wo_ctl_0 |= FIELD_PREP(WSA884X_ANA_WO_CTL_0_PA_AUX_GAIN_MASK, WSA884X_ANA_WO_CTL_0_PA_AUX_18_DB); else diff --git a/sound/soc/fsl/lpc3xxx-i2s.c b/sound/soc/fsl/lpc3xxx-i2s.c index af995ca081a3..c65c17dfa174 100644 --- a/sound/soc/fsl/lpc3xxx-i2s.c +++ b/sound/soc/fsl/lpc3xxx-i2s.c @@ -39,7 +39,7 @@ static void __lpc3xxx_find_clkdiv(u32 *clkx, u32 *clky, int freq, int xbytes, u3 { u32 i2srate; u32 idxx, idyy; - u32 savedbitclkrate, diff, trate, baseclk; + u32 diff, trate, baseclk; /* Adjust rate for sample size (bits) and 2 channels and offset for * divider in clock output @@ -53,14 +53,12 @@ static void __lpc3xxx_find_clkdiv(u32 *clkx, u32 *clky, int freq, int xbytes, u3 /* Find the best divider */ *clkx = *clky = 0; - savedbitclkrate = 0; diff = ~0; for (idxx = 1; idxx < 0xFF; idxx++) { for (idyy = 1; idyy < 0xFF; idyy++) { trate = (baseclk * idxx) / idyy; if (abs(trate - i2srate) < diff) { diff = abs(trate - i2srate); - savedbitclkrate = trate; *clkx = idxx; *clky = idyy; } @@ -190,8 +188,7 @@ static int lpc3xxx_i2s_hw_params(struct snd_pcm_substream *substream, __lpc3xxx_find_clkdiv(&clkx, &clky, i2s_info_p->freq, xfersize, i2s_info_p->clkrate); - dev_dbg(dev, "Stream : %s\n", - substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture"); + dev_dbg(dev, "Stream : %s\n", snd_pcm_direction_name(substream->stream)); dev_dbg(dev, "Desired clock rate : %d\n", i2s_info_p->freq); dev_dbg(dev, "Base clock rate : %d\n", i2s_info_p->clkrate); dev_dbg(dev, "Transfer size (bytes) : %d\n", xfersize); @@ -260,7 +257,7 @@ static int lpc3xxx_i2s_dai_probe(struct snd_soc_dai *dai) return 0; } -const struct snd_soc_dai_ops lpc3xxx_i2s_dai_ops = { +static const struct snd_soc_dai_ops lpc3xxx_i2s_dai_ops = { .probe = lpc3xxx_i2s_dai_probe, .startup = lpc3xxx_i2s_startup, .shutdown = lpc3xxx_i2s_shutdown, @@ -270,7 +267,7 @@ const struct snd_soc_dai_ops lpc3xxx_i2s_dai_ops = { .set_fmt = lpc3xxx_i2s_set_dai_fmt, }; -struct snd_soc_dai_driver lpc3xxx_i2s_dai_driver = { +static struct snd_soc_dai_driver lpc3xxx_i2s_dai_driver = { .playback = { .channels_min = 1, .channels_max = 2, diff --git a/sound/soc/fsl/lpc3xxx-pcm.c b/sound/soc/fsl/lpc3xxx-pcm.c index c0d499b9b8ba..e6abaf63895a 100644 --- a/sound/soc/fsl/lpc3xxx-pcm.c +++ b/sound/soc/fsl/lpc3xxx-pcm.c @@ -52,7 +52,7 @@ static const struct snd_dmaengine_pcm_config lpc3xxx_dmaengine_pcm_config = { .prealloc_buffer_size = 128 * 1024, }; -const struct snd_soc_component_driver lpc3xxx_soc_platform_driver = { +static const struct snd_soc_component_driver lpc3xxx_soc_platform_driver = { .name = "lpc32xx-pcm", }; diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index af8b9d098d2d..931b430fa983 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -184,7 +184,7 @@ static int psc_i2s_of_probe(struct platform_device *op) /* Check for the codec handle. If it is not present then we * are done */ - if (!of_get_property(op->dev.of_node, "codec-handle", NULL)) + if (!of_property_present(op->dev.of_node, "codec-handle")) return 0; /* Due to errata in the dma mode; need to line up enabling diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c index e9e5e235a8a6..df2487b700cc 100644 --- a/sound/soc/generic/test-component.c +++ b/sound/soc/generic/test-component.c @@ -181,14 +181,6 @@ static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct return 0; } -static int test_dai_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - mile_stone(dai); - - return 0; -} - static const u64 test_dai_formats = /* * Select below from Sound Card, not auto @@ -228,7 +220,6 @@ static const struct snd_soc_dai_ops test_verbose_ops = { .hw_params = test_dai_hw_params, .hw_free = test_dai_hw_free, .trigger = test_dai_trigger, - .bespoke_trigger = test_dai_bespoke_trigger, .auto_selectable_formats = &test_dai_formats, .num_auto_selectable_formats = 1, }; diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index f1faa5dd2a4f..3d59d6982763 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -656,6 +656,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE + select SND_SOC_SDW_UTILS select SND_SOC_MAX98363 select SND_SOC_MAX98373_I2C select SND_SOC_MAX98373_SDW diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index dc6fe110f279..5bd8dc2d166a 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -35,15 +35,6 @@ snd-soc-skl_nau88l25_ssm4567-y := skl_nau88l25_ssm4567.o snd-soc-ehl-rt5660-y := ehl_rt5660.o snd-soc-sof-ssp-amp-y := sof_ssp_amp.o snd-soc-sof-sdw-y += sof_sdw.o \ - sof_sdw_maxim.o sof_sdw_rt_amp.o \ - bridge_cs35l56.o \ - sof_sdw_rt5682.o sof_sdw_rt700.o \ - sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ - sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \ - sof_sdw_rt_dmic.o \ - sof_sdw_cs42l42.o sof_sdw_cs42l43.o \ - sof_sdw_cs_amp.o \ - sof_sdw_dmic.o \ sof_sdw_hdmi.o obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o obj-$(CONFIG_SND_SOC_INTEL_SOF_CS42L42_MACH) += snd-soc-sof_cs42l42.o diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e5feaef669d1..d258728d64cf 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -11,7 +11,6 @@ #include <linux/module.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> -#include <sound/soc.h> #include <sound/soc-acpi.h> #include "sof_sdw_common.h" #include "../../codecs/rt711.h" @@ -23,24 +22,24 @@ MODULE_PARM_DESC(quirk, "Board-specific quirk override"); static void log_quirks(struct device *dev) { - if (SOF_JACK_JDSRC(sof_sdw_quirk)) + if (SOC_SDW_JACK_JDSRC(sof_sdw_quirk)) dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", - SOF_JACK_JDSRC(sof_sdw_quirk)); - if (sof_sdw_quirk & SOF_SDW_FOUR_SPK) - dev_err(dev, "quirk SOF_SDW_FOUR_SPK enabled but no longer supported\n"); + SOC_SDW_JACK_JDSRC(sof_sdw_quirk)); + if (sof_sdw_quirk & SOC_SDW_FOUR_SPK) + dev_err(dev, "quirk SOC_SDW_FOUR_SPK enabled but no longer supported\n"); if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n"); - if (sof_sdw_quirk & SOF_SDW_PCH_DMIC) - dev_dbg(dev, "quirk SOF_SDW_PCH_DMIC enabled\n"); + if (sof_sdw_quirk & SOC_SDW_PCH_DMIC) + dev_dbg(dev, "quirk SOC_SDW_PCH_DMIC enabled\n"); if (SOF_SSP_GET_PORT(sof_sdw_quirk)) dev_dbg(dev, "SSP port %ld\n", SOF_SSP_GET_PORT(sof_sdw_quirk)); - if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) - dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n"); - if (sof_sdw_quirk & SOF_CODEC_SPKR) - dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n"); - if (sof_sdw_quirk & SOF_SIDECAR_AMPS) - dev_dbg(dev, "quirk SOF_SIDECAR_AMPS enabled\n"); + if (sof_sdw_quirk & SOC_SDW_NO_AGGREGATION) + dev_err(dev, "quirk SOC_SDW_NO_AGGREGATION enabled but no longer supported\n"); + if (sof_sdw_quirk & SOC_SDW_CODEC_SPKR) + dev_dbg(dev, "quirk SOC_SDW_CODEC_SPKR enabled\n"); + if (sof_sdw_quirk & SOC_SDW_SIDECAR_AMPS) + dev_dbg(dev, "quirk SOC_SDW_SIDECAR_AMPS enabled\n"); } static int sof_sdw_quirk_cb(const struct dmi_system_id *id) @@ -57,7 +56,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), }, - .driver_data = (void *)SOF_SDW_PCH_DMIC, + .driver_data = (void *)SOC_SDW_PCH_DMIC, }, { .callback = sof_sdw_quirk_cb, @@ -99,7 +98,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), }, - .driver_data = (void *)SOF_SDW_PCH_DMIC, + .driver_data = (void *)SOC_SDW_PCH_DMIC, }, /* TigerLake devices */ { @@ -111,7 +110,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | RT711_JD1 | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | SOF_SSP_PORT(SOF_I2S_SSP2)), }, { @@ -159,7 +158,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | SOF_BT_OFFLOAD_SSP(2) | SOF_SSP_BT_OFFLOAD_PRESENT), }, @@ -170,7 +169,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC), + SOC_SDW_PCH_DMIC), }, { /* @@ -185,7 +184,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | RT711_JD1), }, { @@ -199,7 +198,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "8709"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | RT711_JD1), }, { @@ -210,7 +209,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | RT711_JD1), }, { @@ -221,7 +220,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | RT711_JD1), }, { @@ -232,7 +231,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | RT711_JD2_100K), }, { @@ -243,7 +242,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | RT711_JD2_100K), }, /* TigerLake-SDCA devices */ @@ -293,7 +292,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Brya"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | + SOC_SDW_PCH_DMIC | SOF_BT_OFFLOAD_SSP(2) | SOF_SSP_BT_OFFLOAD_PRESENT), }, @@ -501,7 +500,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_PRODUCT_NAME, "Rex"), }, - .driver_data = (void *)(SOF_SDW_PCH_DMIC | + .driver_data = (void *)(SOC_SDW_PCH_DMIC | SOF_BT_OFFLOAD_SSP(1) | SOF_SSP_BT_OFFLOAD_PRESENT), }, @@ -529,7 +528,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE3") }, - .driver_data = (void *)(SOF_SIDECAR_AMPS), + .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS), }, { .callback = sof_sdw_quirk_cb, @@ -537,7 +536,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CE4") }, - .driver_data = (void *)(SOF_SIDECAR_AMPS), + .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS), }, {} }; @@ -549,900 +548,15 @@ static struct snd_soc_dai_link_component platform_component[] = { } }; -static const struct snd_soc_dapm_widget generic_dmic_widgets[] = { - SND_SOC_DAPM_MIC("DMIC", NULL), -}; - -static const struct snd_soc_dapm_widget generic_jack_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), -}; - -static const struct snd_kcontrol_new generic_jack_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), -}; - -static const struct snd_soc_dapm_widget generic_spk_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -static const struct snd_kcontrol_new generic_spk_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - -static const struct snd_soc_dapm_widget maxim_widgets[] = { - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), -}; - -static const struct snd_kcontrol_new maxim_controls[] = { - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), -}; - -static const struct snd_soc_dapm_widget rt700_widgets[] = { - SND_SOC_DAPM_HP("Headphones", NULL), - SND_SOC_DAPM_MIC("AMIC", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -static const struct snd_kcontrol_new rt700_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphones"), - SOC_DAPM_PIN_SWITCH("AMIC"), - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - -/* these wrappers are only needed to avoid typecast compilation errors */ -int sdw_startup(struct snd_pcm_substream *substream) -{ - return sdw_startup_stream(substream); -} - -int sdw_prepare(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct sdw_stream_runtime *sdw_stream; - struct snd_soc_dai *dai; - - /* Find stream from first CPU DAI */ - dai = snd_soc_rtd_to_cpu(rtd, 0); - - sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); - if (IS_ERR(sdw_stream)) { - dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); - return PTR_ERR(sdw_stream); - } - - return sdw_prepare_stream(sdw_stream); -} - -int sdw_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct sdw_stream_runtime *sdw_stream; - struct snd_soc_dai *dai; - int ret; - - /* Find stream from first CPU DAI */ - dai = snd_soc_rtd_to_cpu(rtd, 0); - - sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); - if (IS_ERR(sdw_stream)) { - dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); - return PTR_ERR(sdw_stream); - } - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - case SNDRV_PCM_TRIGGER_RESUME: - ret = sdw_enable_stream(sdw_stream); - break; - - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - ret = sdw_disable_stream(sdw_stream); - break; - default: - ret = -EINVAL; - break; - } - - if (ret) - dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret); - - return ret; -} - -int sdw_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_link_ch_map *ch_maps; - int ch = params_channels(params); - unsigned int ch_mask; - int num_codecs; - int step; - int i; - - if (!rtd->dai_link->ch_maps) - return 0; - - /* Identical data will be sent to all codecs in playback */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ch_mask = GENMASK(ch - 1, 0); - step = 0; - } else { - num_codecs = rtd->dai_link->num_codecs; - - if (ch < num_codecs || ch % num_codecs != 0) { - dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n", - ch, num_codecs); - return -EINVAL; - } - - ch_mask = GENMASK(ch / num_codecs - 1, 0); - step = hweight_long(ch_mask); - - } - - /* - * The captured data will be combined from each cpu DAI if the dai - * link has more than one codec DAIs. Set codec channel mask and - * ASoC will set the corresponding channel numbers for each cpu dai. - */ - for_each_link_ch_maps(rtd->dai_link, i, ch_maps) - ch_maps->ch_mask = ch_mask << (i * step); - - return 0; -} - -int sdw_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct sdw_stream_runtime *sdw_stream; - struct snd_soc_dai *dai; - - /* Find stream from first CPU DAI */ - dai = snd_soc_rtd_to_cpu(rtd, 0); - - sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); - if (IS_ERR(sdw_stream)) { - dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); - return PTR_ERR(sdw_stream); - } - - return sdw_deprepare_stream(sdw_stream); -} - -void sdw_shutdown(struct snd_pcm_substream *substream) -{ - sdw_shutdown_stream(substream); -} - static const struct snd_soc_ops sdw_ops = { - .startup = sdw_startup, - .prepare = sdw_prepare, - .trigger = sdw_trigger, - .hw_params = sdw_hw_params, - .hw_free = sdw_hw_free, - .shutdown = sdw_shutdown, -}; - -static struct sof_sdw_codec_info codec_info_list[] = { - { - .part_id = 0x700, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt700-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .rtd_init = rt700_rtd_init, - .controls = rt700_controls, - .num_controls = ARRAY_SIZE(rt700_controls), - .widgets = rt700_widgets, - .num_widgets = ARRAY_SIZE(rt700_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x711, - .version_id = 3, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt711-sdca-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = sof_sdw_rt_sdca_jack_init, - .exit = sof_sdw_rt_sdca_jack_exit, - .rtd_init = rt_sdca_jack_rtd_init, - .controls = generic_jack_controls, - .num_controls = ARRAY_SIZE(generic_jack_controls), - .widgets = generic_jack_widgets, - .num_widgets = ARRAY_SIZE(generic_jack_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x711, - .version_id = 2, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt711-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = sof_sdw_rt711_init, - .exit = sof_sdw_rt711_exit, - .rtd_init = rt711_rtd_init, - .controls = generic_jack_controls, - .num_controls = ARRAY_SIZE(generic_jack_controls), - .widgets = generic_jack_widgets, - .num_widgets = ARRAY_SIZE(generic_jack_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x712, - .version_id = 3, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt712-sdca-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = sof_sdw_rt_sdca_jack_init, - .exit = sof_sdw_rt_sdca_jack_exit, - .rtd_init = rt_sdca_jack_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 = {true, false}, - .dai_name = "rt712-sdca-aif2", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .init = sof_sdw_rt_amp_init, - .exit = sof_sdw_rt_amp_exit, - .rtd_init = rt712_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 = 2, - }, - { - .part_id = 0x1712, - .version_id = 3, - .dais = { - { - .direction = {false, true}, - .dai_name = "rt712-sdca-dmic-aif1", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt_dmic_rtd_init, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x713, - .version_id = 3, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt712-sdca-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = sof_sdw_rt_sdca_jack_init, - .exit = sof_sdw_rt_sdca_jack_exit, - .rtd_init = rt_sdca_jack_rtd_init, - .controls = generic_jack_controls, - .num_controls = ARRAY_SIZE(generic_jack_controls), - .widgets = generic_jack_widgets, - .num_widgets = ARRAY_SIZE(generic_jack_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x1713, - .version_id = 3, - .dais = { - { - .direction = {false, true}, - .dai_name = "rt712-sdca-dmic-aif1", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt_dmic_rtd_init, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x1308, - .acpi_id = "10EC1308", - .dais = { - { - .direction = {true, false}, - .dai_name = "rt1308-aif", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .init = sof_sdw_rt_amp_init, - .exit = sof_sdw_rt_amp_exit, - .rtd_init = rt_amp_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 = 1, - .ops = &sof_sdw_rt1308_i2s_ops, - }, - { - .part_id = 0x1316, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt1316-aif", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, - .init = sof_sdw_rt_amp_init, - .exit = sof_sdw_rt_amp_exit, - .rtd_init = rt_amp_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 = 1, - }, - { - .part_id = 0x1318, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt1318-aif", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, - .init = sof_sdw_rt_amp_init, - .exit = sof_sdw_rt_amp_exit, - .rtd_init = rt_amp_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 = 1, - }, - { - .part_id = 0x714, - .version_id = 3, - .ignore_pch_dmic = true, - .dais = { - { - .direction = {false, true}, - .dai_name = "rt715-sdca-aif2", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt_dmic_rtd_init, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x715, - .version_id = 3, - .ignore_pch_dmic = true, - .dais = { - { - .direction = {false, true}, - .dai_name = "rt715-sdca-aif2", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt_dmic_rtd_init, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x714, - .version_id = 2, - .ignore_pch_dmic = true, - .dais = { - { - .direction = {false, true}, - .dai_name = "rt715-aif2", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt_dmic_rtd_init, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x715, - .version_id = 2, - .ignore_pch_dmic = true, - .dais = { - { - .direction = {false, true}, - .dai_name = "rt715-aif2", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt_dmic_rtd_init, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x722, - .version_id = 3, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt722-sdca-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = sof_sdw_rt_sdca_jack_init, - .exit = sof_sdw_rt_sdca_jack_exit, - .rtd_init = rt_sdca_jack_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 = {true, false}, - .dai_name = "rt722-sdca-aif2", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - /* No feedback capability is provided by rt722-sdca codec driver*/ - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .init = sof_sdw_rt_amp_init, - .exit = sof_sdw_rt_amp_exit, - .rtd_init = rt722_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), - }, - { - .direction = {false, true}, - .dai_name = "rt722-sdca-aif3", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt_dmic_rtd_init, - }, - }, - .dai_num = 3, - }, - { - .part_id = 0x8373, - .dais = { - { - .direction = {true, true}, - .dai_name = "max98373-aif1", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, - .init = sof_sdw_maxim_init, - .rtd_init = maxim_spk_rtd_init, - .controls = maxim_controls, - .num_controls = ARRAY_SIZE(maxim_controls), - .widgets = maxim_widgets, - .num_widgets = ARRAY_SIZE(maxim_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x8363, - .dais = { - { - .direction = {true, false}, - .dai_name = "max98363-aif1", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .init = sof_sdw_maxim_init, - .rtd_init = maxim_spk_rtd_init, - .controls = maxim_controls, - .num_controls = ARRAY_SIZE(maxim_controls), - .widgets = maxim_widgets, - .num_widgets = ARRAY_SIZE(maxim_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x5682, - .dais = { - { - .direction = {true, true}, - .dai_name = "rt5682-sdw", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .rtd_init = rt5682_rtd_init, - .controls = generic_jack_controls, - .num_controls = ARRAY_SIZE(generic_jack_controls), - .widgets = generic_jack_widgets, - .num_widgets = ARRAY_SIZE(generic_jack_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x3556, - .dais = { - { - .direction = {true, true}, - .dai_name = "cs35l56-sdw1", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, - .init = sof_sdw_cs_amp_init, - .rtd_init = cs_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 = 1, - }, - { - .part_id = 0x4242, - .dais = { - { - .direction = {true, true}, - .dai_name = "cs42l42-sdw", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .rtd_init = cs42l42_rtd_init, - .controls = generic_jack_controls, - .num_controls = ARRAY_SIZE(generic_jack_controls), - .widgets = generic_jack_widgets, - .num_widgets = ARRAY_SIZE(generic_jack_widgets), - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x4243, - .codec_name = "cs42l43-codec", - .count_sidecar = bridge_cs35l56_count_sidecar, - .add_sidecar = bridge_cs35l56_add_sidecar, - .dais = { - { - .direction = {true, false}, - .dai_name = "cs42l43-dp5", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .rtd_init = cs42l43_hs_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 = "cs42l43-dp1", - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = cs42l43_dmic_rtd_init, - .widgets = generic_dmic_widgets, - .num_widgets = ARRAY_SIZE(generic_dmic_widgets), - }, - { - .direction = {false, true}, - .dai_name = "cs42l43-dp2", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_UNUSED_DAI_ID, SDW_JACK_IN_DAI_ID}, - }, - { - .direction = {true, false}, - .dai_name = "cs42l43-dp6", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .init = sof_sdw_cs42l43_spk_init, - .rtd_init = cs42l43_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), - .quirk = SOF_CODEC_SPKR | SOF_SIDECAR_AMPS, - }, - }, - .dai_num = 4, - }, - { - .part_id = 0xaaaa, /* generic codec mockup */ - .version_id = 0, - .dais = { - { - .direction = {true, true}, - .dai_name = "sdw-mockup-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0xaa55, /* headset codec mockup */ - .version_id = 0, - .dais = { - { - .direction = {true, true}, - .dai_name = "sdw-mockup-aif1", - .dai_type = SOF_SDW_DAI_TYPE_JACK, - .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x55aa, /* amplifier mockup */ - .version_id = 0, - .dais = { - { - .direction = {true, true}, - .dai_name = "sdw-mockup-aif1", - .dai_type = SOF_SDW_DAI_TYPE_AMP, - .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, - }, - }, - .dai_num = 1, - }, - { - .part_id = 0x5555, - .version_id = 0, - .dais = { - { - .dai_name = "sdw-mockup-aif1", - .direction = {false, true}, - .dai_type = SOF_SDW_DAI_TYPE_MIC, - .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - }, - }, - .dai_num = 1, - }, + .startup = asoc_sdw_startup, + .prepare = asoc_sdw_prepare, + .trigger = asoc_sdw_trigger, + .hw_params = asoc_sdw_hw_params, + .hw_free = asoc_sdw_hw_free, + .shutdown = asoc_sdw_shutdown, }; -static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr) -{ - unsigned int part_id, sdw_version; - int i; - - part_id = SDW_PART_ID(adr); - sdw_version = SDW_VERSION(adr); - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) - /* - * A codec info is for all sdw version with the part id if - * version_id is not specified in the codec info. - */ - if (part_id == codec_info_list[i].part_id && - (!codec_info_list[i].version_id || - sdw_version == codec_info_list[i].version_id)) - return &codec_info_list[i]; - - return NULL; - -} - -static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id) -{ - int i; - - if (!acpi_id[0]) - return NULL; - - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) - if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN)) - return &codec_info_list[i]; - - return NULL; -} - -static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name, - int *dai_index) -{ - int i, j; - - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - for (j = 0; j < codec_info_list[i].dai_num; j++) { - if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { - *dai_index = j; - return &codec_info_list[i]; - } - } - } - - return NULL; -} - -static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, - int *be_id, char *name, int playback, int capture, - struct snd_soc_dai_link_component *cpus, int cpus_num, - struct snd_soc_dai_link_component *codecs, int codecs_num, - int (*init)(struct snd_soc_pcm_runtime *rtd), - const struct snd_soc_ops *ops) -{ - dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id); - dai_links->id = (*be_id)++; - dai_links->name = name; - dai_links->platforms = platform_component; - dai_links->num_platforms = ARRAY_SIZE(platform_component); - dai_links->no_pcm = 1; - dai_links->cpus = cpus; - dai_links->num_cpus = cpus_num; - dai_links->codecs = codecs; - dai_links->num_codecs = codecs_num; - dai_links->dpcm_playback = playback; - dai_links->dpcm_capture = capture; - dai_links->init = init; - dai_links->ops = ops; -} - -static int init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, - int *be_id, char *name, int playback, int capture, - const char *cpu_dai_name, - const char *codec_name, const char *codec_dai_name, - int (*init)(struct snd_soc_pcm_runtime *rtd), - const struct snd_soc_ops *ops) -{ - struct snd_soc_dai_link_component *dlc; - - /* Allocate two DLCs one for the CPU, one for the CODEC */ - dlc = devm_kcalloc(dev, 2, sizeof(*dlc), GFP_KERNEL); - if (!dlc || !name || !cpu_dai_name || !codec_name || !codec_dai_name) - return -ENOMEM; - - dlc[0].dai_name = cpu_dai_name; - - dlc[1].name = codec_name; - dlc[1].dai_name = codec_dai_name; - - init_dai_link(dev, dai_links, be_id, name, playback, capture, - &dlc[0], 1, &dlc[1], 1, init, ops); - - return 0; -} - -static bool is_unique_device(const struct snd_soc_acpi_link_adr *adr_link, - unsigned int sdw_version, - unsigned int mfg_id, - unsigned int part_id, - unsigned int class_id, - int index_in_link) -{ - int i; - - for (i = 0; i < adr_link->num_adr; i++) { - unsigned int sdw1_version, mfg1_id, part1_id, class1_id; - u64 adr; - - /* skip itself */ - if (i == index_in_link) - continue; - - adr = adr_link->adr_d[i].adr; - - sdw1_version = SDW_VERSION(adr); - mfg1_id = SDW_MFG_ID(adr); - part1_id = SDW_PART_ID(adr); - class1_id = SDW_CLASS_ID(adr); - - if (sdw_version == sdw1_version && - mfg_id == mfg1_id && - part_id == part1_id && - class_id == class1_id) - return false; - } - - return true; -} - -static const char *get_codec_name(struct device *dev, - const struct sof_sdw_codec_info *codec_info, - const struct snd_soc_acpi_link_adr *adr_link, - int adr_index) -{ - u64 adr = adr_link->adr_d[adr_index].adr; - unsigned int sdw_version = SDW_VERSION(adr); - unsigned int link_id = SDW_DISCO_LINK_ID(adr); - unsigned int unique_id = SDW_UNIQUE_ID(adr); - unsigned int mfg_id = SDW_MFG_ID(adr); - unsigned int part_id = SDW_PART_ID(adr); - unsigned int class_id = SDW_CLASS_ID(adr); - - if (codec_info->codec_name) - return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); - else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, - class_id, adr_index)) - return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x", - link_id, mfg_id, part_id, class_id); - else - return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x", - link_id, mfg_id, part_id, class_id, unique_id); - - return NULL; -} - -static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - struct sof_sdw_codec_info *codec_info; - struct snd_soc_dai *dai; - int dai_index; - int ret; - int i; - - for_each_rtd_codec_dais(rtd, i, dai) { - codec_info = find_codec_info_dai(dai->name, &dai_index); - if (!codec_info) - return -EINVAL; - - /* - * A codec dai can be connected to different dai links for capture and playback, - * but we only need to call the rtd_init function once. - * The rtd_init for each codec dai is independent. So, the order of rtd_init - * doesn't matter. - */ - if (codec_info->dais[dai_index].rtd_init_done) - continue; - - /* - * Add card controls and dapm widgets for the first codec dai. - * The controls and widgets will be used for all codec dais. - */ - - if (i > 0) - goto skip_add_controls_widgets; - - if (codec_info->dais[dai_index].controls) { - ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls, - codec_info->dais[dai_index].num_controls); - if (ret) { - dev_err(card->dev, "%#x controls addition failed: %d\n", - codec_info->part_id, ret); - return ret; - } - } - if (codec_info->dais[dai_index].widgets) { - ret = snd_soc_dapm_new_controls(&card->dapm, - codec_info->dais[dai_index].widgets, - codec_info->dais[dai_index].num_widgets); - if (ret) { - dev_err(card->dev, "%#x widgets addition failed: %d\n", - codec_info->part_id, ret); - return ret; - } - } - -skip_add_controls_widgets: - if (codec_info->dais[dai_index].rtd_init) { - ret = codec_info->dais[dai_index].rtd_init(rtd, dai); - if (ret) - return ret; - } - codec_info->dais[dai_index].rtd_init_done = true; - } - - return 0; -} - struct sof_sdw_endpoint { struct list_head list; @@ -1451,8 +565,8 @@ struct sof_sdw_endpoint { const char *name_prefix; bool include_sidecar; - struct sof_sdw_codec_info *codec_info; - const struct sof_sdw_dai_info *dai_info; + struct asoc_sdw_codec_info *codec_info; + const struct asoc_sdw_dai_info *dai_info; }; struct sof_sdw_dailink { @@ -1509,7 +623,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, int *num_devs) { struct device *dev = card->dev; - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(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; @@ -1529,7 +643,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, for (i = 0; i < adr_link->num_adr; i++) { const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i]; - struct sof_sdw_codec_info *codec_info; + struct asoc_sdw_codec_info *codec_info; const char *codec_name; if (!adr_dev->name_prefix) { @@ -1538,13 +652,13 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, return -EINVAL; } - codec_info = find_codec_info_part(adr_dev->adr); + codec_info = asoc_sdw_find_codec_info_part(adr_dev->adr); if (!codec_info) return -EINVAL; - ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; + ctx->ignore_internal_dmic |= codec_info->ignore_internal_dmic; - codec_name = get_codec_name(dev, codec_info, adr_link, i); + codec_name = asoc_sdw_get_codec_name(dev, codec_info, adr_link, i); if (!codec_name) return -ENOMEM; @@ -1563,7 +677,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, for (j = 0; j < adr_dev->num_endpoints; j++) { const struct snd_soc_acpi_endpoint *adr_end; - const struct sof_sdw_dai_info *dai_info; + const struct asoc_sdw_dai_info *dai_info; struct sof_sdw_dailink *sof_dai; int stream; @@ -1630,7 +744,8 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *be_id, struct snd_soc_codec_conf **codec_conf) { struct device *dev = card->dev; - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; struct sof_sdw_endpoint *sof_end; int stream; int ret; @@ -1709,7 +824,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, if (cur_link != sof_end->link_mask) { int link_num = ffs(sof_end->link_mask) - 1; - int pin_num = ctx->sdw_pin_index[link_num]++; + int pin_num = intel_ctx->sdw_pin_index[link_num]++; cur_link = sof_end->link_mask; @@ -1734,9 +849,10 @@ static int create_sdw_dailink(struct snd_soc_card *card, playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); capture = (stream == SNDRV_PCM_STREAM_CAPTURE); - init_dai_link(dev, *dai_links, be_id, name, playback, capture, - cpus, num_cpus, codecs, num_codecs, - sof_sdw_rtd_init, &sdw_ops); + asoc_sdw_init_dai_link(dev, *dai_links, be_id, name, playback, capture, + cpus, num_cpus, platform_component, + ARRAY_SIZE(platform_component), codecs, num_codecs, + asoc_sdw_rtd_init, &sdw_ops); /* * SoundWire DAILINKs use 'stream' functions and Bank Switch operations @@ -1763,11 +879,12 @@ static int create_sdw_dailinks(struct snd_soc_card *card, struct sof_sdw_dailink *sof_dais, struct snd_soc_codec_conf **codec_conf) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; int ret, i; for (i = 0; i < SDW_MAX_LINKS; i++) - ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; + intel_ctx->sdw_pin_index[i] = SOC_SDW_INTEL_BIDIR_PDI_BASE; /* generate DAI links by each sdw link */ while (sof_dais->initialised) { @@ -1790,7 +907,7 @@ static int create_sdw_dailinks(struct snd_soc_card *card, static int create_ssp_dailinks(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, int *be_id, - struct sof_sdw_codec_info *ssp_info, + struct asoc_sdw_codec_info *ssp_info, unsigned long ssp_mask) { struct device *dev = card->dev; @@ -1805,10 +922,12 @@ static int create_ssp_dailinks(struct snd_soc_card *card, int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; - ret = init_simple_dai_link(dev, *dai_links, be_id, name, - playback, capture, cpu_dai_name, - codec_name, ssp_info->dais[0].dai_name, - NULL, ssp_info->ops); + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, + playback, capture, cpu_dai_name, + platform_component->name, + ARRAY_SIZE(platform_component), codec_name, + ssp_info->dais[0].dai_name, NULL, + ssp_info->ops); if (ret) return ret; @@ -1828,20 +947,24 @@ static int create_dmic_dailinks(struct snd_soc_card *card, struct device *dev = card->dev; int ret; - ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic01", - 0, 1, // DMIC only supports capture - "DMIC01 Pin", "dmic-codec", "dmic-hifi", - sof_sdw_dmic_init, NULL); + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic01", + 0, 1, // DMIC only supports capture + "DMIC01 Pin", platform_component->name, + ARRAY_SIZE(platform_component), + "dmic-codec", "dmic-hifi", + asoc_sdw_dmic_init, NULL); if (ret) return ret; (*dai_links)++; - ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic16k", - 0, 1, // DMIC only supports capture - "DMIC16k Pin", "dmic-codec", "dmic-hifi", - /* don't call sof_sdw_dmic_init() twice */ - NULL, NULL); + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "dmic16k", + 0, 1, // DMIC only supports capture + "DMIC16k Pin", platform_component->name, + ARRAY_SIZE(platform_component), + "dmic-codec", "dmic-hifi", + /* don't call asoc_sdw_dmic_init() twice */ + NULL, NULL); if (ret) return ret; @@ -1855,7 +978,8 @@ static int create_hdmi_dailinks(struct snd_soc_card *card, int hdmi_num) { struct device *dev = card->dev; - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; int i, ret; for (i = 0; i < hdmi_num; i++) { @@ -1863,7 +987,7 @@ static int create_hdmi_dailinks(struct snd_soc_card *card, char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); char *codec_name, *codec_dai_name; - if (ctx->hdmi.idisp_codec) { + if (intel_ctx->hdmi.idisp_codec) { codec_name = "ehdaudio0D2"; codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, "intel-hdmi-hifi%d", i + 1); @@ -1872,10 +996,12 @@ static int create_hdmi_dailinks(struct snd_soc_card *card, codec_dai_name = "snd-soc-dummy-dai"; } - ret = init_simple_dai_link(dev, *dai_links, be_id, name, - 1, 0, // HDMI only supports playback - cpu_dai_name, codec_name, codec_dai_name, - i == 0 ? sof_sdw_hdmi_init : NULL, NULL); + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, + 1, 0, // HDMI only supports playback + cpu_dai_name, platform_component->name, + ARRAY_SIZE(platform_component), + codec_name, codec_dai_name, + i == 0 ? sof_sdw_hdmi_init : NULL, NULL); if (ret) return ret; @@ -1895,9 +1021,11 @@ static int create_bt_dailinks(struct snd_soc_card *card, char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); int ret; - ret = init_simple_dai_link(dev, *dai_links, be_id, name, - 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, - snd_soc_dummy_dlc.dai_name, NULL, NULL); + ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name, + 1, 1, cpu_dai_name, platform_component->name, + ARRAY_SIZE(platform_component), + snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name, + NULL, NULL); if (ret) return ret; @@ -1911,10 +1039,11 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct device *dev = card->dev; struct snd_soc_acpi_mach *mach = dev_get_platdata(card->dev); int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0; - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; struct snd_soc_codec_conf *codec_conf; - struct sof_sdw_codec_info *ssp_info; + struct asoc_sdw_codec_info *ssp_info; struct sof_sdw_endpoint *sof_ends; struct sof_sdw_dailink *sof_dais; int num_devs = 0; @@ -1956,14 +1085,14 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) * system only when I2S mode is supported, not sdw mode. * Here check ACPI ID to confirm I2S is supported. */ - ssp_info = find_codec_info_acpi(mach->id); + ssp_info = asoc_sdw_find_codec_info_acpi(mach->id); if (ssp_info) { ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); ssp_num = hweight_long(ssp_mask); } if (mach_params->codec_mask & IDISP_CODEC_MASK) - ctx->hdmi.idisp_codec = true; + intel_ctx->hdmi.idisp_codec = true; if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) hdmi_num = SOF_TGL_HDMI_COUNT; @@ -1971,7 +1100,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) hdmi_num = SOF_PRE_TGL_HDMI_COUNT; /* enable dmic01 & dmic16k */ - if (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) + if (sof_sdw_quirk & SOC_SDW_PCH_DMIC || mach_params->dmic_num) dmic_num = 2; if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) @@ -1979,7 +1108,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d, bt: %d\n", sdw_be_num, ssp_num, dmic_num, - ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num); + intel_ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num); codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); if (!codec_conf) { @@ -2018,7 +1147,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) /* dmic */ if (dmic_num > 0) { - if (ctx->ignore_pch_dmic) { + if (ctx->ignore_internal_dmic) { dev_warn(dev, "Ignoring PCH DMIC\n"); } else { ret = create_dmic_dailinks(card, &dai_links, &be_id); @@ -2052,88 +1181,41 @@ err_dai: static int sof_sdw_card_late_probe(struct snd_soc_card *card) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; int ret = 0; - int i; - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - if (codec_info_list[i].codec_card_late_probe) { - ret = codec_info_list[i].codec_card_late_probe(card); - - if (ret < 0) - return ret; - } - } + ret = asoc_sdw_card_late_probe(card); + if (ret < 0) + return ret; - if (ctx->hdmi.idisp_codec) + if (intel_ctx->hdmi.idisp_codec) ret = sof_sdw_hdmi_card_late_probe(card); return ret; } -/* helper to get the link that the codec DAI is used */ -static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card, - const char *dai_name) -{ - struct snd_soc_dai_link *dai_link; - int i; - int j; - - for_each_card_prelinks(card, i, dai_link) { - for (j = 0; j < dai_link->num_codecs; j++) { - /* Check each codec in a link */ - if (!strcmp(dai_link->codecs[j].dai_name, dai_name)) - return dai_link; - } - } - return NULL; -} - -static void mc_dailink_exit_loop(struct snd_soc_card *card) -{ - struct snd_soc_dai_link *dai_link; - int ret; - int i, j; - - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - for (j = 0; j < codec_info_list[i].dai_num; j++) { - codec_info_list[i].dais[j].rtd_init_done = false; - /* Check each dai in codec_info_lis to see if it is used in the link */ - if (!codec_info_list[i].dais[j].exit) - continue; - /* - * We don't need to call .exit function if there is no matched - * dai link found. - */ - dai_link = mc_find_codec_dai_used(card, - codec_info_list[i].dais[j].dai_name); - if (dai_link) { - /* Do the .exit function if the codec dai is used in the link */ - ret = codec_info_list[i].dais[j].exit(card, dai_link); - if (ret) - dev_warn(card->dev, - "codec exit failed %d\n", - ret); - break; - } - } - } -} - static int mc_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); struct snd_soc_card *card; - struct mc_private *ctx; + struct asoc_sdw_mc_private *ctx; + struct intel_mc_ctx *intel_ctx; int amp_num = 0, i; int ret; dev_dbg(&pdev->dev, "Entry\n"); + intel_ctx = devm_kzalloc(&pdev->dev, sizeof(*intel_ctx), GFP_KERNEL); + if (!intel_ctx) + return -ENOMEM; + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; + ctx->private = intel_ctx; + ctx->codec_info_list_count = asoc_sdw_get_codec_info_list_count(); card = &ctx->card; card->dev = &pdev->dev; card->name = "soundwire"; @@ -2152,8 +1234,9 @@ static int mc_probe(struct platform_device *pdev) log_quirks(card->dev); + ctx->mc_quirk = sof_sdw_quirk; /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + for (i = 0; i < ctx->codec_info_list_count; i++) codec_info_list[i].amp_num = 0; if (mach->mach_params.subsystem_id_set) { @@ -2171,7 +1254,7 @@ static int mc_probe(struct platform_device *pdev) * amp_num will only be increased for active amp * codecs on used platform */ - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + for (i = 0; i < ctx->codec_info_list_count; i++) amp_num += codec_info_list[i].amp_num; card->components = devm_kasprintf(card->dev, GFP_KERNEL, @@ -2192,7 +1275,7 @@ static int mc_probe(struct platform_device *pdev) ret = devm_snd_soc_register_card(card->dev, card); if (ret) { dev_err_probe(card->dev, ret, "snd_soc_register_card failed %d\n", ret); - mc_dailink_exit_loop(card); + asoc_sdw_mc_dailink_exit_loop(card); return ret; } @@ -2205,7 +1288,7 @@ static void mc_remove(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); - mc_dailink_exit_loop(card); + asoc_sdw_mc_dailink_exit_loop(card); } static const struct platform_device_id mc_id_table[] = { @@ -2232,3 +1315,4 @@ MODULE_AUTHOR("Rander Wang <[email protected]>"); MODULE_AUTHOR("Pierre-Louis Bossart <[email protected]>"); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); +MODULE_IMPORT_NS(SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 2a3145d1feb6..02f3eebd019d 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -12,18 +12,12 @@ #include <linux/bits.h> #include <linux/types.h> #include <sound/soc.h> +#include <sound/soc_sdw_utils.h> #include "sof_hdmi_common.h" -#define MAX_NO_PROPS 2 #define MAX_HDMI_NUM 4 -#define SDW_UNUSED_DAI_ID -1 -#define SDW_JACK_OUT_DAI_ID 0 -#define SDW_JACK_IN_DAI_ID 1 -#define SDW_AMP_OUT_DAI_ID 2 -#define SDW_AMP_IN_DAI_ID 3 -#define SDW_DMIC_DAI_ID 4 -#define SDW_MAX_CPU_DAIS 16 -#define SDW_INTEL_BIDIR_PDI_BASE 2 +#define SOC_SDW_MAX_CPU_DAIS 16 +#define SOC_SDW_INTEL_BIDIR_PDI_BASE 2 #define SDW_MAX_LINKS 4 @@ -44,27 +38,14 @@ enum { SOF_I2S_SSP5 = BIT(5), }; -#define SOF_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) /* Deprecated and no longer supported by the code */ -#define SOF_SDW_FOUR_SPK BIT(4) +#define SOC_SDW_FOUR_SPK BIT(4) #define SOF_SDW_TGL_HDMI BIT(5) -#define SOF_SDW_PCH_DMIC BIT(6) +#define SOC_SDW_PCH_DMIC BIT(6) #define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7) #define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0)) /* Deprecated and no longer supported by the code */ -#define SOF_SDW_NO_AGGREGATION BIT(14) -/* If a CODEC has an optional speaker output, this quirk will enable it */ -#define SOF_CODEC_SPKR BIT(15) -/* - * If the CODEC has additional devices attached directly to it. - * - * For the cs42l43: - * - 0 - No speaker output - * - SOF_CODEC_SPKR - CODEC internal speaker - * - SOF_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker - * - SOF_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported - */ -#define SOF_SIDECAR_AMPS BIT(16) +#define SOC_SDW_NO_AGGREGATION BIT(14) /* BT audio offload: reserve 3 bits for future */ #define SOF_BT_OFFLOAD_SSP_SHIFT 15 @@ -73,150 +54,17 @@ enum { (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK) #define SOF_SSP_BT_OFFLOAD_PRESENT BIT(18) -#define SOF_SDW_DAI_TYPE_JACK 0 -#define SOF_SDW_DAI_TYPE_AMP 1 -#define SOF_SDW_DAI_TYPE_MIC 2 - -#define SOF_SDW_MAX_DAI_NUM 8 - -struct sof_sdw_codec_info; - -struct sof_sdw_dai_info { - const bool direction[2]; /* playback & capture support */ - const char *dai_name; - const int dai_type; - const int dailink[2]; /* dailink id for each direction */ - const struct snd_kcontrol_new *controls; - const int num_controls; - const struct snd_soc_dapm_widget *widgets; - const int num_widgets; - int (*init)(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); - int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - int (*rtd_init)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); - bool rtd_init_done; /* Indicate that the rtd_init callback is done */ - unsigned long quirk; -}; - -struct sof_sdw_codec_info { - const int part_id; - const int version_id; - const char *codec_name; - int amp_num; - const u8 acpi_id[ACPI_ID_LEN]; - const bool ignore_pch_dmic; - const struct snd_soc_ops *ops; - struct sof_sdw_dai_info dais[SOF_SDW_MAX_DAI_NUM]; - const int dai_num; - - int (*codec_card_late_probe)(struct snd_soc_card *card); - - int (*count_sidecar)(struct snd_soc_card *card, - int *num_dais, int *num_devs); - int (*add_sidecar)(struct snd_soc_card *card, - struct snd_soc_dai_link **dai_links, - struct snd_soc_codec_conf **codec_conf); -}; - -struct mc_private { - struct snd_soc_card card; - struct snd_soc_jack sdw_headset; +struct intel_mc_ctx { struct sof_hdmi_private hdmi; - struct device *headset_codec_dev; /* only one headset per card */ - struct device *amp_dev1, *amp_dev2; /* To store SDW Pin index for each SoundWire link */ unsigned int sdw_pin_index[SDW_MAX_LINKS]; - bool append_dai_type; - bool ignore_pch_dmic; }; extern unsigned long sof_sdw_quirk; -int sdw_startup(struct snd_pcm_substream *substream); -int sdw_prepare(struct snd_pcm_substream *substream); -int sdw_trigger(struct snd_pcm_substream *substream, int cmd); -int sdw_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params); -int sdw_hw_free(struct snd_pcm_substream *substream); -void sdw_shutdown(struct snd_pcm_substream *substream); - /* generic HDMI support */ int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd); int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card); -/* DMIC support */ -int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd); - -/* RT711 support */ -int sof_sdw_rt711_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); -int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - -/* RT711-SDCA support */ -int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); -int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - -/* RT1308 I2S support */ -extern const struct snd_soc_ops sof_sdw_rt1308_i2s_ops; - -/* generic amp support */ -int sof_sdw_rt_amp_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); -int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - -/* MAXIM codec support */ -int sof_sdw_maxim_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); - -/* CS42L43 support */ -int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); - -/* CS AMP support */ -int bridge_cs35l56_count_sidecar(struct snd_soc_card *card, - int *num_dais, int *num_devs); -int bridge_cs35l56_add_sidecar(struct snd_soc_card *card, - struct snd_soc_dai_link **dai_links, - struct snd_soc_codec_conf **codec_conf); -int bridge_cs35l56_spk_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); - -int sof_sdw_cs_amp_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); - -/* dai_link init callbacks */ - -int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); -int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); - #endif diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c index f34fabdf9d93..4084119a9a5f 100644 --- a/sound/soc/intel/boards/sof_sdw_hdmi.c +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -17,23 +17,25 @@ int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd) { - struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - ctx->hdmi.hdmi_comp = dai->component; + intel_ctx->hdmi.hdmi_comp = dai->component; return 0; } int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + struct intel_mc_ctx *intel_ctx = (struct intel_mc_ctx *)ctx->private; - if (!ctx->hdmi.idisp_codec) + if (!intel_ctx->hdmi.idisp_codec) return 0; - if (!ctx->hdmi.hdmi_comp) + if (!intel_ctx->hdmi.hdmi_comp) return -EINVAL; - return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp); + return hda_dsp_hdmi_build_controls(card, intel_ctx->hdmi.hdmi_comp); } diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index 40a74a19c508..91e146e2487d 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -12,6 +12,7 @@ snd-soc-acpi-intel-match-y := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-matc soc-acpi-intel-rpl-match.o soc-acpi-intel-mtl-match.o \ soc-acpi-intel-arl-match.o \ soc-acpi-intel-lnl-match.o \ + soc-acpi-intel-ptl-match.o \ soc-acpi-intel-hda-match.o \ soc-acpi-intel-sdw-mockup-match.o diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c new file mode 100644 index 000000000000..90f97a44b607 --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * soc-acpi-intel-ptl-match.c - tables and support for PTL ACPI enumeration. + * + * Copyright (c) 2024, Intel Corporation. + * + */ + +#include <sound/soc-acpi.h> +#include <sound/soc-acpi-intel-match.h> +#include "soc-acpi-intel-sdw-mockup-match.h" + +struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[] = { + {}, +}; +EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ptl_machines); + +static const struct snd_soc_acpi_endpoint single_endpoint = { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, +}; + +/* + * RT722 is a multi-function codec, three endpoints are created for + * its headset, amp and dmic functions. + */ +static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { + { + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { + { + .adr = 0x000030025D071101ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + } +}; + +static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = { + { + .adr = 0x000030025d072201ull, + .num_endpoints = ARRAY_SIZE(rt722_endpoints), + .endpoints = rt722_endpoints, + .name_prefix = "rt722" + } +}; + +static const struct snd_soc_acpi_adr_device rt722_3_single_adr[] = { + { + .adr = 0x000330025d072201ull, + .num_endpoints = ARRAY_SIZE(rt722_endpoints), + .endpoints = rt722_endpoints, + .name_prefix = "rt722" + } +}; + +static const struct snd_soc_acpi_link_adr ptl_rt722_only[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt722_0_single_adr), + .adr_d = rt722_0_single_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr ptl_rt722_l3[] = { + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt722_3_single_adr), + .adr_d = rt722_3_single_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr ptl_rvp[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + {} +}; + +/* this table is used when there is no I2S codec present */ +struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = { + /* mockup tests need to be first */ + { + .link_mask = GENMASK(3, 0), + .links = sdw_mockup_headset_2amps_mic, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt711-rt1308-rt715.tplg", + }, + { + .link_mask = BIT(0) | BIT(1) | BIT(3), + .links = sdw_mockup_headset_1amp_mic, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt711-rt1308-mono-rt715.tplg", + }, + { + .link_mask = GENMASK(2, 0), + .links = sdw_mockup_mic_headset_1amp, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt715-rt711-rt1308-mono.tplg", + }, + { + .link_mask = BIT(0), + .links = ptl_rvp, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt711.tplg", + }, + { + .link_mask = BIT(0), + .links = ptl_rt722_only, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt722.tplg", + }, + { + .link_mask = BIT(3), + .links = ptl_rt722_l3, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-ptl-rt722.tplg", + }, + {}, +}; +EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ptl_sdw_machines); diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 8b323fb19925..db00704e206d 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -1108,9 +1108,7 @@ static int mt8192_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data) err_headset_codec: of_node_put(speaker_codec); err_speaker_codec: - if (hdmi_codec) - of_node_put(hdmi_codec); - + of_node_put(hdmi_codec); return ret; } diff --git a/sound/soc/sdw_utils/Kconfig b/sound/soc/sdw_utils/Kconfig new file mode 100644 index 000000000000..d915083c3889 --- /dev/null +++ b/sound/soc/sdw_utils/Kconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +config SND_SOC_SDW_UTILS + tristate + help + This option enables to use SoundWire common helper functions and + SoundWire codec helper functions in machine driver. diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile new file mode 100644 index 000000000000..28229ed96ffb --- /dev/null +++ b/sound/soc/sdw_utils/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \ + soc_sdw_rt700.o soc_sdw_rt711.o \ + soc_sdw_rt712_sdca.o soc_sdw_rt722_sdca.o \ + soc_sdw_rt5682.o soc_sdw_rt_sdca_jack_common.o \ + soc_sdw_rt_amp.o \ + soc_sdw_bridge_cs35l56.o \ + soc_sdw_cs42l42.o soc_sdw_cs42l43.o \ + soc_sdw_cs_amp.o \ + soc_sdw_maxim.o +obj-$(CONFIG_SND_SOC_SDW_UTILS) += snd-soc-sdw-utils.o diff --git a/sound/soc/intel/boards/bridge_cs35l56.c b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c index c3995e724aed..fcc3ef685af7 100644 --- a/sound/soc/intel/boards/bridge_cs35l56.c +++ b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c @@ -1,6 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only -// -// Intel SOF Machine Driver with Cirrus Logic CS35L56 Smart Amp +// This file incorporates work covered by the following copyright notice: +// Copyright (c) 2024 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. + +/* + * soc_sdw_bridge_cs35l56 - codec helper functions for handling CS35L56 Smart AMP + */ #include <linux/module.h> #include <linux/platform_device.h> @@ -9,7 +14,7 @@ #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/soc-acpi.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static const struct snd_soc_dapm_widget bridge_widgets[] = { SND_SOC_DAPM_SPK("Bridge Speaker", NULL), @@ -25,7 +30,7 @@ static const char * const bridge_cs35l56_name_prefixes[] = { "AMPR", }; -static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd) +static int asoc_sdw_bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; int i, ret; @@ -73,7 +78,7 @@ static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd) return 0; } -static const struct snd_soc_pcm_stream bridge_params = { +static const struct snd_soc_pcm_stream asoc_sdw_bridge_params = { .formats = SNDRV_PCM_FMTBIT_S16_LE, .rate_min = 48000, .rate_max = 48000, @@ -81,7 +86,7 @@ static const struct snd_soc_pcm_stream bridge_params = { .channels_max = 2, }; -SND_SOC_DAILINK_DEFS(bridge_dai, +SND_SOC_DAILINK_DEFS(asoc_sdw_bridge_dai, DAILINK_COMP_ARRAY(COMP_CODEC("cs42l43-codec", "cs42l43-asp")), DAILINK_COMP_ARRAY(COMP_CODEC("spi-cs35l56-left", "cs35l56-asp1"), COMP_CODEC("spi-cs35l56-right", "cs35l56-asp1")), @@ -89,28 +94,33 @@ SND_SOC_DAILINK_DEFS(bridge_dai, static const struct snd_soc_dai_link bridge_dai_template = { .name = "cs42l43-cs35l56", - .init = bridge_cs35l56_asp_init, - .c2c_params = &bridge_params, + .init = asoc_sdw_bridge_cs35l56_asp_init, + .c2c_params = &asoc_sdw_bridge_params, .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBC_CFC, - SND_SOC_DAILINK_REG(bridge_dai), + SND_SOC_DAILINK_REG(asoc_sdw_bridge_dai), }; -int bridge_cs35l56_count_sidecar(struct snd_soc_card *card, - int *num_dais, int *num_devs) +int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card, + int *num_dais, int *num_devs) { - if (sof_sdw_quirk & SOF_SIDECAR_AMPS) { + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + + if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS) { (*num_dais)++; (*num_devs) += ARRAY_SIZE(bridge_cs35l56_name_prefixes); } return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_count_sidecar, SND_SOC_SDW_UTILS); -int bridge_cs35l56_add_sidecar(struct snd_soc_card *card, - struct snd_soc_dai_link **dai_links, - struct snd_soc_codec_conf **codec_conf) +int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf) { - if (sof_sdw_quirk & SOF_SIDECAR_AMPS) { + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + + if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS) { **dai_links = bridge_dai_template; for (int i = 0; i < ARRAY_SIZE(bridge_cs35l56_name_prefixes); i++) { @@ -124,14 +134,18 @@ int bridge_cs35l56_add_sidecar(struct snd_soc_card *card, return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_add_sidecar, SND_SOC_SDW_UTILS); -int bridge_cs35l56_spk_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) +int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) { - if (sof_sdw_quirk & SOF_SIDECAR_AMPS) + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + + if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS) info->amp_num += ARRAY_SIZE(bridge_cs35l56_name_prefixes); return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_spk_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/sdw_utils/soc_sdw_cs42l42.c index fc18e4aa3dbe..78a6cb059ac0 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l42.c +++ b/sound/soc/sdw_utils/soc_sdw_cs42l42.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2023 Intel Corporation - +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_cs42l42 - Helpers to handle CS42L42 from generic machine driver + * soc_sdw_cs42l42 - Helpers to handle CS42L42 from generic machine driver */ #include <linux/device.h> @@ -15,7 +16,7 @@ #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> #include <sound/jack.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static const struct snd_soc_dapm_route cs42l42_map[] = { /* HP jack connectors - unknown if we have jack detection */ @@ -36,10 +37,10 @@ static struct snd_soc_jack_pin cs42l42_jack_pins[] = { }, }; -int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; - struct mc_private *ctx = snd_soc_card_get_drvdata(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; @@ -87,4 +88,4 @@ int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return ret; } -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); +EXPORT_SYMBOL_NS(asoc_sdw_cs42l42_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/sdw_utils/soc_sdw_cs42l43.c index b7e2750c1074..adb1c008e871 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l43.c +++ b/sound/soc/sdw_utils/soc_sdw_cs42l43.c @@ -1,9 +1,11 @@ // 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. /* - * sof_sdw_cs42l43 - Helpers to handle CS42L43 from generic machine driver + * soc_sdw_cs42l43 - Helpers to handle CS42L43 from generic machine driver */ #include <linux/device.h> #include <linux/errno.h> @@ -16,7 +18,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static const struct snd_soc_dapm_route cs42l43_hs_map[] = { { "Headphone", NULL, "cs42l43 AMP3_OUT" }, @@ -37,7 +39,7 @@ static const struct snd_soc_dapm_route cs42l43_dmic_map[] = { { "cs42l43 PDM2_DIN", NULL, "DMIC" }, }; -static struct snd_soc_jack_pin sof_jack_pins[] = { +static struct snd_soc_jack_pin soc_jack_pins[] = { { .pin = "Headphone", .mask = SND_JACK_HEADPHONE, @@ -48,10 +50,10 @@ static struct snd_soc_jack_pin sof_jack_pins[] = { }, }; -int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_jack *jack = &ctx->sdw_headset; struct snd_soc_card *card = rtd->card; int ret; @@ -73,8 +75,8 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, - jack, sof_jack_pins, - ARRAY_SIZE(sof_jack_pins)); + jack, soc_jack_pins, + ARRAY_SIZE(soc_jack_pins)); if (ret) { dev_err(card->dev, "Failed to create jack: %d\n", ret); return ret; @@ -98,13 +100,15 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai return ret; } +EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_hs_rtd_init, SND_SOC_SDW_UTILS); -int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_cs42l43_spk_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); int ret; - if (!(sof_sdw_quirk & SOF_SIDECAR_AMPS)) { + if (!(ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS)) { /* Will be set by the bridge code in this case */ card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:cs42l43-spk", @@ -120,11 +124,12 @@ int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *da return ret; } +EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_rtd_init, SND_SOC_SDW_UTILS); -int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) +int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) { /* Do init on playback link only. */ if (!playback) @@ -132,10 +137,11 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, info->amp_num++; - return bridge_cs35l56_spk_init(card, dai_links, info, playback); + return asoc_sdw_bridge_cs35l56_spk_init(card, dai_links, info, playback); } +EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_init, SND_SOC_SDW_UTILS); -int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; @@ -152,4 +158,4 @@ int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *d return ret; } - +EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_dmic_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/sdw_utils/soc_sdw_cs_amp.c index 10e08207619a..58b059b68016 100644 --- a/sound/soc/intel/boards/sof_sdw_cs_amp.c +++ b/sound/soc/sdw_utils/soc_sdw_cs_amp.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2023 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_cs_amp - Helpers to handle CS35L56 from generic machine driver + * soc_sdw_cs_amp - Helpers to handle CS35L56 from generic machine driver */ #include <linux/device.h> @@ -10,11 +12,11 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dai.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> #define CODEC_NAME_SIZE 8 -int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { const char *dai_name = rtd->dai_link->codecs->dai_name; struct snd_soc_card *card = rtd->card; @@ -44,11 +46,12 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_rtd_init, SND_SOC_SDW_UTILS); -int sof_sdw_cs_amp_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) +int asoc_sdw_cs_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) { /* Do init on playback link only. */ if (!playback) @@ -58,3 +61,4 @@ int sof_sdw_cs_amp_init(struct snd_soc_card *card, return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_cs_amp_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_dmic.c b/sound/soc/sdw_utils/soc_sdw_dmic.c index 19df0f7a1d85..fc2aae985084 100644 --- a/sound/soc/intel/boards/sof_sdw_dmic.c +++ b/sound/soc/sdw_utils/soc_sdw_dmic.c @@ -1,14 +1,16 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2020 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_dmic - Helpers to handle dmic from generic machine driver + * soc_sdw_dmic - Helpers to handle dmic from generic machine driver */ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static const struct snd_soc_dapm_widget dmic_widgets[] = { SND_SOC_DAPM_MIC("SoC DMIC", NULL), @@ -19,7 +21,7 @@ static const struct snd_soc_dapm_route dmic_map[] = { {"DMic", NULL, "SoC DMIC"}, }; -int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd) +int asoc_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; int ret; @@ -40,4 +42,4 @@ int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd) return ret; } - +EXPORT_SYMBOL_NS(asoc_sdw_dmic_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/sdw_utils/soc_sdw_maxim.c index b7f73177867f..cdcd8df37e1d 100644 --- a/sound/soc/intel/boards/sof_sdw_maxim.c +++ b/sound/soc/sdw_utils/soc_sdw_maxim.c @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2020 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. // -// sof_sdw_maxim - Helpers to handle maxim codecs +// soc_sdw_maxim - Helpers to handle maxim codecs // codec devices from generic machine driver #include <linux/device.h> @@ -10,18 +12,18 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static int maxim_part_id; -#define SOF_SDW_PART_ID_MAX98363 0x8363 -#define SOF_SDW_PART_ID_MAX98373 0x8373 +#define SOC_SDW_PART_ID_MAX98363 0x8363 +#define SOC_SDW_PART_ID_MAX98373 0x8373 static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { { "Left Spk", NULL, "Left BE_OUT" }, { "Right Spk", NULL, "Right BE_OUT" }, }; -int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; @@ -41,8 +43,9 @@ int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return ret; } +EXPORT_SYMBOL_NS(asoc_sdw_maxim_spk_rtd_init, SND_SOC_SDW_UTILS); -static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable) +static int asoc_sdw_mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; @@ -75,40 +78,40 @@ static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enabl return 0; } -static int mx8373_sdw_prepare(struct snd_pcm_substream *substream) +static int asoc_sdw_mx8373_prepare(struct snd_pcm_substream *substream) { int ret; /* according to soc_pcm_prepare dai link prepare is called first */ - ret = sdw_prepare(substream); + ret = asoc_sdw_prepare(substream); if (ret < 0) return ret; - return mx8373_enable_spk_pin(substream, true); + return asoc_sdw_mx8373_enable_spk_pin(substream, true); } -static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream) +static int asoc_sdw_mx8373_hw_free(struct snd_pcm_substream *substream) { int ret; /* according to soc_pcm_hw_free dai link free is called first */ - ret = sdw_hw_free(substream); + ret = asoc_sdw_hw_free(substream); if (ret < 0) return ret; - return mx8373_enable_spk_pin(substream, false); + return asoc_sdw_mx8373_enable_spk_pin(substream, false); } static const struct snd_soc_ops max_98373_sdw_ops = { - .startup = sdw_startup, - .prepare = mx8373_sdw_prepare, - .trigger = sdw_trigger, - .hw_params = sdw_hw_params, - .hw_free = mx8373_sdw_hw_free, - .shutdown = sdw_shutdown, + .startup = asoc_sdw_startup, + .prepare = asoc_sdw_mx8373_prepare, + .trigger = asoc_sdw_trigger, + .hw_params = asoc_sdw_hw_params, + .hw_free = asoc_sdw_mx8373_hw_free, + .shutdown = asoc_sdw_shutdown, }; -static int mx8373_sdw_late_probe(struct snd_soc_card *card) +static int asoc_sdw_mx8373_sdw_late_probe(struct snd_soc_card *card) { struct snd_soc_dapm_context *dapm = &card->dapm; @@ -118,22 +121,22 @@ static int mx8373_sdw_late_probe(struct snd_soc_card *card) return snd_soc_dapm_sync(dapm); } -int sof_sdw_maxim_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) +int asoc_sdw_maxim_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) { info->amp_num++; maxim_part_id = info->part_id; switch (maxim_part_id) { - case SOF_SDW_PART_ID_MAX98363: + case SOC_SDW_PART_ID_MAX98363: /* Default ops are set in function init_dai_link. * called as part of function create_sdw_dailink */ break; - case SOF_SDW_PART_ID_MAX98373: - info->codec_card_late_probe = mx8373_sdw_late_probe; + case SOC_SDW_PART_ID_MAX98373: + info->codec_card_late_probe = asoc_sdw_mx8373_sdw_late_probe; dai_links->ops = &max_98373_sdw_ops; break; default: @@ -142,3 +145,4 @@ int sof_sdw_maxim_init(struct snd_soc_card *card, } return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_maxim_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/sdw_utils/soc_sdw_rt5682.c index 67737815d016..80b4caa92667 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/sdw_utils/soc_sdw_rt5682.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2020 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt5682 - Helpers to handle RT5682 from generic machine driver + * soc_sdw_rt5682 - Helpers to handle RT5682 from generic machine driver */ #include <linux/device.h> @@ -15,7 +17,7 @@ #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> #include <sound/jack.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static const struct snd_soc_dapm_route rt5682_map[] = { /*Headphones*/ @@ -35,10 +37,10 @@ static struct snd_soc_jack_pin rt5682_jack_pins[] = { }, }; -int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; - struct mc_private *ctx = snd_soc_card_get_drvdata(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; @@ -86,4 +88,4 @@ int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return ret; } -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); +EXPORT_SYMBOL_NS(asoc_sdw_rt5682_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/sdw_utils/soc_sdw_rt700.c index 0db730071be2..4dbeeeca3434 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/sdw_utils/soc_sdw_rt700.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2020 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt700 - Helpers to handle RT700 from generic machine driver + * soc_sdw_rt700 - Helpers to handle RT700 from generic machine driver */ #include <linux/device.h> @@ -13,7 +15,7 @@ #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> #include <sound/jack.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static const struct snd_soc_dapm_route rt700_map[] = { /* Headphones */ @@ -33,10 +35,10 @@ static struct snd_soc_jack_pin rt700_jack_pins[] = { }, }; -int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; - struct mc_private *ctx = snd_soc_card_get_drvdata(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; @@ -83,4 +85,4 @@ int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return ret; } -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); +EXPORT_SYMBOL_NS(asoc_sdw_rt700_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/sdw_utils/soc_sdw_rt711.c index 60ff4d88e2dc..38b4126dd45f 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/sdw_utils/soc_sdw_rt711.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2020 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt711 - Helpers to handle RT711 from generic machine driver + * soc_sdw_rt711 - Helpers to handle RT711 from generic machine driver */ #include <linux/device.h> @@ -15,21 +17,21 @@ #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> #include <sound/jack.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> /* * Note this MUST be called before snd_soc_register_card(), so that the props * are in place before the codec component driver's probe function parses them. */ -static int rt711_add_codec_device_props(struct device *sdw_dev) +static int rt711_add_codec_device_props(struct device *sdw_dev, unsigned long quirk) { - struct property_entry props[MAX_NO_PROPS] = {}; + struct property_entry props[SOC_SDW_MAX_NO_PROPS] = {}; struct fwnode_handle *fwnode; int ret; - if (!SOF_JACK_JDSRC(sof_sdw_quirk)) + if (!SOC_SDW_JACK_JDSRC(quirk)) return 0; - props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_JACK_JDSRC(sof_sdw_quirk)); + props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOC_SDW_JACK_JDSRC(quirk)); fwnode = fwnode_create_software_node(props, NULL); if (IS_ERR(fwnode)) @@ -59,10 +61,10 @@ static struct snd_soc_jack_pin rt711_jack_pins[] = { }, }; -int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; - struct mc_private *ctx = snd_soc_card_get_drvdata(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; @@ -110,10 +112,11 @@ int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return ret; } +EXPORT_SYMBOL_NS(asoc_sdw_rt711_rtd_init, SND_SOC_SDW_UTILS); -int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) +int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); if (!ctx->headset_codec_dev) return 0; @@ -123,13 +126,14 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_rt711_exit, SND_SOC_SDW_UTILS); -int sof_sdw_rt711_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) +int asoc_sdw_rt711_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *sdw_dev; int ret; @@ -144,7 +148,7 @@ int sof_sdw_rt711_init(struct snd_soc_card *card, if (!sdw_dev) return -EPROBE_DEFER; - ret = rt711_add_codec_device_props(sdw_dev); + ret = rt711_add_codec_device_props(sdw_dev, ctx->mc_quirk); if (ret < 0) { put_device(sdw_dev); return ret; @@ -153,4 +157,4 @@ int sof_sdw_rt711_init(struct snd_soc_card *card, return 0; } -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); +EXPORT_SYMBOL_NS(asoc_sdw_rt711_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c index 788796461885..5127210b9a03 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/sdw_utils/soc_sdw_rt712_sdca.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2023 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt712_sdca - Helpers to handle RT712-SDCA from generic machine driver + * soc_sdw_rt712_sdca - Helpers to handle RT712-SDCA from generic machine driver */ #include <linux/device.h> @@ -13,7 +15,7 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> /* * dapm routes for rt712 spk will be registered dynamically according @@ -26,7 +28,7 @@ static const struct snd_soc_dapm_route rt712_spk_map[] = { { "Speaker", NULL, "rt712 SPOR" }, }; -int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; @@ -43,4 +45,4 @@ int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return ret; } - +EXPORT_SYMBOL_NS(asoc_sdw_rt712_spk_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c index 083d281bd052..6a402172289f 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/sdw_utils/soc_sdw_rt722_sdca.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2023 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt722_sdca - Helpers to handle RT722-SDCA from generic machine driver + * soc_sdw_rt722_sdca - Helpers to handle RT722-SDCA from generic machine driver */ #include <linux/device.h> @@ -13,13 +15,13 @@ #include <sound/soc.h> #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> static const struct snd_soc_dapm_route rt722_spk_map[] = { { "Speaker", NULL, "rt722 SPK" }, }; -int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; @@ -36,4 +38,4 @@ int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return ret; } - +EXPORT_SYMBOL_NS(asoc_sdw_rt722_spk_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/sdw_utils/soc_sdw_rt_amp.c index d1c0f91ce589..42be01405ab4 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_amp.c +++ b/sound/soc/sdw_utils/soc_sdw_rt_amp.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2022 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt_amp - Helpers to handle RT1308/RT1316/RT1318 from generic machine driver + * soc_sdw_rt_amp - Helpers to handle RT1308/RT1316/RT1318 from generic machine driver */ #include <linux/device.h> @@ -14,9 +16,9 @@ #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> #include <linux/dmi.h> -#include "sof_sdw_common.h" -#include "sof_sdw_amp_coeff_tables.h" -#include "../../codecs/rt1308.h" +#include <sound/soc_sdw_utils.h> +#include "soc_sdw_rt_amp_coeff_tables.h" +#include "../codecs/rt1308.h" #define CODEC_NAME_SIZE 7 @@ -173,7 +175,7 @@ static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_ return rt1318_map; } -int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; const struct snd_soc_dapm_route *rt_amp_map; @@ -199,6 +201,7 @@ int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai return ret; } +EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_spk_rtd_init, SND_SOC_SDW_UTILS); static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -233,13 +236,14 @@ static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, } /* machine stream operations */ -const struct snd_soc_ops sof_sdw_rt1308_i2s_ops = { +const struct snd_soc_ops soc_sdw_rt1308_i2s_ops = { .hw_params = rt1308_i2s_hw_params, }; +EXPORT_SYMBOL_NS(soc_sdw_rt1308_i2s_ops, SND_SOC_SDW_UTILS); -int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) +int asoc_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); if (ctx->amp_dev1) { device_remove_software_node(ctx->amp_dev1); @@ -253,13 +257,14 @@ int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_ return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_exit, SND_SOC_SDW_UTILS); -int sof_sdw_rt_amp_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) +int asoc_sdw_rt_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *sdw_dev1, *sdw_dev2; int ret; @@ -295,3 +300,4 @@ int sof_sdw_rt_amp_init(struct snd_soc_card *card, return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h b/sound/soc/sdw_utils/soc_sdw_rt_amp_coeff_tables.h index 4a3e6fdbd623..4803d134d071 100644 --- a/sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h +++ b/sound/soc/sdw_utils/soc_sdw_rt_amp_coeff_tables.h @@ -2,11 +2,11 @@ */ /* - * sof_sdw_amp_coeff_tables.h - related coefficients for amplifier parameters + * soc_sdw_rt_amp_coeff_tables.h - related coefficients for RTK amplifier parameters */ -#ifndef SND_SOC_SOF_SDW_AMP_COEFF_H -#define SND_SOC_SOF_SDW_AMP_COEFF_H +#ifndef SND_SOC_SDW_RT_SDW_AMP_COEFF_H +#define SND_SOC_SDW_RT_SDW_AMP_COEFF_H #define RT1308_MAX_BQ_REG 480 #define RT1316_MAX_BQ_REG 580 diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/sdw_utils/soc_sdw_rt_dmic.c index ea7c1a4bc566..7f24806d809d 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_dmic.c +++ b/sound/soc/sdw_utils/soc_sdw_rt_dmic.c @@ -1,18 +1,19 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2024 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver + * soc_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver */ #include <linux/device.h> #include <linux/errno.h> #include <sound/soc.h> #include <sound/soc-acpi.h> -#include "sof_board_helpers.h" -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> -int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt_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; @@ -39,4 +40,4 @@ int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) return 0; } -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); +EXPORT_SYMBOL_NS(asoc_sdw_rt_dmic_rtd_init, SND_SOC_SDW_UTILS); diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c index 4254e30ee4c3..3e6211dc1599 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c @@ -1,8 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: // Copyright (c) 2020 Intel Corporation +// Copyright (c) 2024 Advanced Micro Devices, Inc. /* - * sof_sdw_rt711_sdca - Helpers to handle RT711-SDCA from generic machine driver + * soc_sdw_rt711_sdca - Helpers to handle RT711-SDCA from generic machine driver */ #include <linux/device.h> @@ -15,22 +17,22 @@ #include <sound/soc-acpi.h> #include <sound/soc-dapm.h> #include <sound/jack.h> -#include "sof_sdw_common.h" +#include <sound/soc_sdw_utils.h> /* * Note this MUST be called before snd_soc_register_card(), so that the props * are in place before the codec component driver's probe function parses them. */ -static int rt_sdca_jack_add_codec_device_props(struct device *sdw_dev) +static int rt_sdca_jack_add_codec_device_props(struct device *sdw_dev, unsigned long quirk) { - struct property_entry props[MAX_NO_PROPS] = {}; + struct property_entry props[SOC_SDW_MAX_NO_PROPS] = {}; struct fwnode_handle *fwnode; int ret; - if (!SOF_JACK_JDSRC(sof_sdw_quirk)) + if (!SOC_SDW_JACK_JDSRC(quirk)) return 0; - props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOF_JACK_JDSRC(sof_sdw_quirk)); + props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", SOC_SDW_JACK_JDSRC(quirk)); fwnode = fwnode_create_software_node(props, NULL); if (IS_ERR(fwnode)) @@ -83,10 +85,10 @@ static const char * const need_sdca_suffix[] = { "rt711", "rt713" }; -int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) +int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; - struct mc_private *ctx = snd_soc_card_get_drvdata(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; @@ -160,15 +162,16 @@ int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *d return ret; } +EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_rtd_init, SND_SOC_SDW_UTILS); -int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) +int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); if (!ctx->headset_codec_dev) return 0; - if (!SOF_JACK_JDSRC(sof_sdw_quirk)) + if (!SOC_SDW_JACK_JDSRC(ctx->mc_quirk)) return 0; device_remove_software_node(ctx->headset_codec_dev); @@ -177,13 +180,14 @@ int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link return 0; } +EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_exit, SND_SOC_SDW_UTILS); -int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) +int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *sdw_dev; int ret; @@ -198,7 +202,7 @@ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, if (!sdw_dev) return -EPROBE_DEFER; - ret = rt_sdca_jack_add_codec_device_props(sdw_dev); + ret = rt_sdca_jack_add_codec_device_props(sdw_dev, ctx->mc_quirk); if (ret < 0) { put_device(sdw_dev); return ret; @@ -207,4 +211,4 @@ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, return 0; } -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); +EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_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 new file mode 100644 index 000000000000..6183629d1754 --- /dev/null +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -0,0 +1,990 @@ +// SPDX-License-Identifier: GPL-2.0-only +// This file incorporates work covered by the following copyright notice: +// Copyright (c) 2020 Intel Corporation +// Copyright(c) 2024 Advanced Micro Devices, Inc. +/* + * soc-sdw-utils.c - common SoundWire machine driver helper functions + */ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc_sdw_utils.h> + +static const struct snd_soc_dapm_widget generic_dmic_widgets[] = { + SND_SOC_DAPM_MIC("DMIC", NULL), +}; + +static const struct snd_soc_dapm_widget generic_jack_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_kcontrol_new generic_jack_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget generic_spk_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new generic_spk_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static const struct snd_soc_dapm_widget maxim_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_kcontrol_new maxim_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static const struct snd_soc_dapm_widget rt700_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_MIC("AMIC", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new rt700_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("AMIC"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +struct asoc_sdw_codec_info codec_info_list[] = { + { + .part_id = 0x700, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt700-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .rtd_init = asoc_sdw_rt700_rtd_init, + .controls = rt700_controls, + .num_controls = ARRAY_SIZE(rt700_controls), + .widgets = rt700_widgets, + .num_widgets = ARRAY_SIZE(rt700_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x711, + .version_id = 3, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt711-sdca-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .init = asoc_sdw_rt_sdca_jack_init, + .exit = asoc_sdw_rt_sdca_jack_exit, + .rtd_init = asoc_sdw_rt_sdca_jack_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x711, + .version_id = 2, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt711-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .init = asoc_sdw_rt711_init, + .exit = asoc_sdw_rt711_exit, + .rtd_init = asoc_sdw_rt711_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x712, + .version_id = 3, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt712-sdca-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .init = asoc_sdw_rt_sdca_jack_init, + .exit = asoc_sdw_rt_sdca_jack_exit, + .rtd_init = asoc_sdw_rt_sdca_jack_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 = {true, false}, + .dai_name = "rt712-sdca-aif2", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_rt_amp_init, + .exit = asoc_sdw_rt_amp_exit, + .rtd_init = asoc_sdw_rt712_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 = 2, + }, + { + .part_id = 0x1712, + .version_id = 3, + .dais = { + { + .direction = {false, true}, + .dai_name = "rt712-sdca-dmic-aif1", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x713, + .version_id = 3, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt712-sdca-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .init = asoc_sdw_rt_sdca_jack_init, + .exit = asoc_sdw_rt_sdca_jack_exit, + .rtd_init = asoc_sdw_rt_sdca_jack_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x1713, + .version_id = 3, + .dais = { + { + .direction = {false, true}, + .dai_name = "rt712-sdca-dmic-aif1", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x1308, + .acpi_id = "10EC1308", + .dais = { + { + .direction = {true, false}, + .dai_name = "rt1308-aif", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_rt_amp_init, + .exit = asoc_sdw_rt_amp_exit, + .rtd_init = asoc_sdw_rt_amp_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 = 1, + .ops = &soc_sdw_rt1308_i2s_ops, + }, + { + .part_id = 0x1316, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt1316-aif", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + .init = asoc_sdw_rt_amp_init, + .exit = asoc_sdw_rt_amp_exit, + .rtd_init = asoc_sdw_rt_amp_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 = 1, + }, + { + .part_id = 0x1318, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt1318-aif", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + .init = asoc_sdw_rt_amp_init, + .exit = asoc_sdw_rt_amp_exit, + .rtd_init = asoc_sdw_rt_amp_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 = 1, + }, + { + .part_id = 0x714, + .version_id = 3, + .ignore_internal_dmic = true, + .dais = { + { + .direction = {false, true}, + .dai_name = "rt715-sdca-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x715, + .version_id = 3, + .ignore_internal_dmic = true, + .dais = { + { + .direction = {false, true}, + .dai_name = "rt715-sdca-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x714, + .version_id = 2, + .ignore_internal_dmic = true, + .dais = { + { + .direction = {false, true}, + .dai_name = "rt715-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x715, + .version_id = 2, + .ignore_internal_dmic = true, + .dais = { + { + .direction = {false, true}, + .dai_name = "rt715-aif2", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x722, + .version_id = 3, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt722-sdca-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .init = asoc_sdw_rt_sdca_jack_init, + .exit = asoc_sdw_rt_sdca_jack_exit, + .rtd_init = asoc_sdw_rt_sdca_jack_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 = {true, false}, + .dai_name = "rt722-sdca-aif2", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + /* No feedback capability is provided by rt722-sdca codec driver*/ + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_rt_amp_init, + .exit = asoc_sdw_rt_amp_exit, + .rtd_init = asoc_sdw_rt722_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), + }, + { + .direction = {false, true}, + .dai_name = "rt722-sdca-aif3", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_rt_dmic_rtd_init, + }, + }, + .dai_num = 3, + }, + { + .part_id = 0x8373, + .dais = { + { + .direction = {true, true}, + .dai_name = "max98373-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + .init = asoc_sdw_maxim_init, + .rtd_init = asoc_sdw_maxim_spk_rtd_init, + .controls = maxim_controls, + .num_controls = ARRAY_SIZE(maxim_controls), + .widgets = maxim_widgets, + .num_widgets = ARRAY_SIZE(maxim_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x8363, + .dais = { + { + .direction = {true, false}, + .dai_name = "max98363-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_maxim_init, + .rtd_init = asoc_sdw_maxim_spk_rtd_init, + .controls = maxim_controls, + .num_controls = ARRAY_SIZE(maxim_controls), + .widgets = maxim_widgets, + .num_widgets = ARRAY_SIZE(maxim_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x5682, + .dais = { + { + .direction = {true, true}, + .dai_name = "rt5682-sdw", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .rtd_init = asoc_sdw_rt5682_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x3556, + .dais = { + { + .direction = {true, true}, + .dai_name = "cs35l56-sdw1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + .init = asoc_sdw_cs_amp_init, + .rtd_init = asoc_sdw_cs_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 = 1, + }, + { + .part_id = 0x4242, + .dais = { + { + .direction = {true, true}, + .dai_name = "cs42l42-sdw", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + .rtd_init = asoc_sdw_cs42l42_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x4243, + .codec_name = "cs42l43-codec", + .count_sidecar = asoc_sdw_bridge_cs35l56_count_sidecar, + .add_sidecar = asoc_sdw_bridge_cs35l56_add_sidecar, + .dais = { + { + .direction = {true, false}, + .dai_name = "cs42l43-dp5", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .rtd_init = asoc_sdw_cs42l43_hs_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 = "cs42l43-dp1", + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + .rtd_init = asoc_sdw_cs42l43_dmic_rtd_init, + .widgets = generic_dmic_widgets, + .num_widgets = ARRAY_SIZE(generic_dmic_widgets), + }, + { + .direction = {false, true}, + .dai_name = "cs42l43-dp2", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + }, + { + .direction = {true, false}, + .dai_name = "cs42l43-dp6", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, + .init = asoc_sdw_cs42l43_spk_init, + .rtd_init = asoc_sdw_cs42l43_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), + .quirk = SOC_SDW_CODEC_SPKR | SOC_SDW_SIDECAR_AMPS, + }, + }, + .dai_num = 4, + }, + { + .part_id = 0xaaaa, /* generic codec mockup */ + .version_id = 0, + .dais = { + { + .direction = {true, true}, + .dai_name = "sdw-mockup-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0xaa55, /* headset codec mockup */ + .version_id = 0, + .dais = { + { + .direction = {true, true}, + .dai_name = "sdw-mockup-aif1", + .dai_type = SOC_SDW_DAI_TYPE_JACK, + .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID}, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x55aa, /* amplifier mockup */ + .version_id = 0, + .dais = { + { + .direction = {true, true}, + .dai_name = "sdw-mockup-aif1", + .dai_type = SOC_SDW_DAI_TYPE_AMP, + .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID}, + }, + }, + .dai_num = 1, + }, + { + .part_id = 0x5555, + .version_id = 0, + .dais = { + { + .dai_name = "sdw-mockup-aif1", + .direction = {false, true}, + .dai_type = SOC_SDW_DAI_TYPE_MIC, + .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID}, + }, + }, + .dai_num = 1, + }, +}; +EXPORT_SYMBOL_NS(codec_info_list, SND_SOC_SDW_UTILS); + +int asoc_sdw_get_codec_info_list_count(void) +{ + return ARRAY_SIZE(codec_info_list); +}; +EXPORT_SYMBOL_NS(asoc_sdw_get_codec_info_list_count, SND_SOC_SDW_UTILS); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr) +{ + unsigned int part_id, sdw_version; + int i; + + part_id = SDW_PART_ID(adr); + sdw_version = SDW_VERSION(adr); + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + /* + * A codec info is for all sdw version with the part id if + * version_id is not specified in the codec info. + */ + if (part_id == codec_info_list[i].part_id && + (!codec_info_list[i].version_id || + sdw_version == codec_info_list[i].version_id)) + return &codec_info_list[i]; + + return NULL; +} +EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_part, SND_SOC_SDW_UTILS); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id) +{ + int i; + + if (!acpi_id[0]) + return NULL; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN)) + return &codec_info_list[i]; + + return NULL; +} +EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_acpi, SND_SOC_SDW_UTILS); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, int *dai_index) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + for (j = 0; j < codec_info_list[i].dai_num; j++) { + if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { + *dai_index = j; + return &codec_info_list[i]; + } + } + } + + return NULL; +} +EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, SND_SOC_SDW_UTILS); + +int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct asoc_sdw_codec_info *codec_info; + struct snd_soc_dai *dai; + int dai_index; + int ret; + int i; + + for_each_rtd_codec_dais(rtd, i, dai) { + codec_info = asoc_sdw_find_codec_info_dai(dai->name, &dai_index); + if (!codec_info) + return -EINVAL; + + /* + * A codec dai can be connected to different dai links for capture and playback, + * but we only need to call the rtd_init function once. + * The rtd_init for each codec dai is independent. So, the order of rtd_init + * doesn't matter. + */ + if (codec_info->dais[dai_index].rtd_init_done) + continue; + + /* + * Add card controls and dapm widgets for the first codec dai. + * The controls and widgets will be used for all codec dais. + */ + + if (i > 0) + goto skip_add_controls_widgets; + + if (codec_info->dais[dai_index].controls) { + ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls, + codec_info->dais[dai_index].num_controls); + if (ret) { + dev_err(card->dev, "%#x controls addition failed: %d\n", + codec_info->part_id, ret); + return ret; + } + } + if (codec_info->dais[dai_index].widgets) { + ret = snd_soc_dapm_new_controls(&card->dapm, + codec_info->dais[dai_index].widgets, + codec_info->dais[dai_index].num_widgets); + if (ret) { + dev_err(card->dev, "%#x widgets addition failed: %d\n", + codec_info->part_id, ret); + return ret; + } + } + +skip_add_controls_widgets: + if (codec_info->dais[dai_index].rtd_init) { + ret = codec_info->dais[dai_index].rtd_init(rtd, dai); + if (ret) + return ret; + } + codec_info->dais[dai_index].rtd_init_done = true; + } + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_rtd_init, SND_SOC_SDW_UTILS); + +/* these wrappers are only needed to avoid typecast compilation errors */ +int asoc_sdw_startup(struct snd_pcm_substream *substream) +{ + return sdw_startup_stream(substream); +} +EXPORT_SYMBOL_NS(asoc_sdw_startup, SND_SOC_SDW_UTILS); + +int asoc_sdw_prepare(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct sdw_stream_runtime *sdw_stream; + struct snd_soc_dai *dai; + + /* Find stream from first CPU DAI */ + dai = snd_soc_rtd_to_cpu(rtd, 0); + + sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); + if (IS_ERR(sdw_stream)) { + dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); + return PTR_ERR(sdw_stream); + } + + return sdw_prepare_stream(sdw_stream); +} +EXPORT_SYMBOL_NS(asoc_sdw_prepare, SND_SOC_SDW_UTILS); + +int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct sdw_stream_runtime *sdw_stream; + struct snd_soc_dai *dai; + int ret; + + /* Find stream from first CPU DAI */ + dai = snd_soc_rtd_to_cpu(rtd, 0); + + sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); + if (IS_ERR(sdw_stream)) { + dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); + return PTR_ERR(sdw_stream); + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + ret = sdw_enable_stream(sdw_stream); + break; + + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + ret = sdw_disable_stream(sdw_stream); + break; + default: + ret = -EINVAL; + break; + } + + if (ret) + dev_err(rtd->dev, "%s trigger %d failed: %d\n", __func__, cmd, ret); + + return ret; +} +EXPORT_SYMBOL_NS(asoc_sdw_trigger, SND_SOC_SDW_UTILS); + +int asoc_sdw_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_link_ch_map *ch_maps; + int ch = params_channels(params); + unsigned int ch_mask; + int num_codecs; + int step; + int i; + + if (!rtd->dai_link->ch_maps) + return 0; + + /* Identical data will be sent to all codecs in playback */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ch_mask = GENMASK(ch - 1, 0); + step = 0; + } else { + num_codecs = rtd->dai_link->num_codecs; + + if (ch < num_codecs || ch % num_codecs != 0) { + dev_err(rtd->dev, "Channels number %d is invalid when codec number = %d\n", + ch, num_codecs); + return -EINVAL; + } + + ch_mask = GENMASK(ch / num_codecs - 1, 0); + step = hweight_long(ch_mask); + } + + /* + * The captured data will be combined from each cpu DAI if the dai + * link has more than one codec DAIs. Set codec channel mask and + * ASoC will set the corresponding channel numbers for each cpu dai. + */ + for_each_link_ch_maps(rtd->dai_link, i, ch_maps) + ch_maps->ch_mask = ch_mask << (i * step); + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_hw_params, SND_SOC_SDW_UTILS); + +int asoc_sdw_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct sdw_stream_runtime *sdw_stream; + struct snd_soc_dai *dai; + + /* Find stream from first CPU DAI */ + dai = snd_soc_rtd_to_cpu(rtd, 0); + + sdw_stream = snd_soc_dai_get_stream(dai, substream->stream); + if (IS_ERR(sdw_stream)) { + dev_err(rtd->dev, "no stream found for DAI %s\n", dai->name); + return PTR_ERR(sdw_stream); + } + + return sdw_deprepare_stream(sdw_stream); +} +EXPORT_SYMBOL_NS(asoc_sdw_hw_free, SND_SOC_SDW_UTILS); + +void asoc_sdw_shutdown(struct snd_pcm_substream *substream) +{ + sdw_shutdown_stream(substream); +} +EXPORT_SYMBOL_NS(asoc_sdw_shutdown, SND_SOC_SDW_UTILS); + +static bool asoc_sdw_is_unique_device(const struct snd_soc_acpi_link_adr *adr_link, + unsigned int sdw_version, + unsigned int mfg_id, + unsigned int part_id, + unsigned int class_id, + int index_in_link) +{ + int i; + + for (i = 0; i < adr_link->num_adr; i++) { + unsigned int sdw1_version, mfg1_id, part1_id, class1_id; + u64 adr; + + /* skip itself */ + if (i == index_in_link) + continue; + + adr = adr_link->adr_d[i].adr; + + sdw1_version = SDW_VERSION(adr); + mfg1_id = SDW_MFG_ID(adr); + part1_id = SDW_PART_ID(adr); + class1_id = SDW_CLASS_ID(adr); + + if (sdw_version == sdw1_version && + mfg_id == mfg1_id && + part_id == part1_id && + class_id == class1_id) + return false; + } + + return true; +} + +const char *asoc_sdw_get_codec_name(struct device *dev, + const struct asoc_sdw_codec_info *codec_info, + const struct snd_soc_acpi_link_adr *adr_link, + int adr_index) +{ + u64 adr = adr_link->adr_d[adr_index].adr; + unsigned int sdw_version = SDW_VERSION(adr); + unsigned int link_id = SDW_DISCO_LINK_ID(adr); + unsigned int unique_id = SDW_UNIQUE_ID(adr); + unsigned int mfg_id = SDW_MFG_ID(adr); + unsigned int part_id = SDW_PART_ID(adr); + unsigned int class_id = SDW_CLASS_ID(adr); + + if (codec_info->codec_name) + return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); + else if (asoc_sdw_is_unique_device(adr_link, sdw_version, mfg_id, part_id, + class_id, adr_index)) + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x", + link_id, mfg_id, part_id, class_id); + else + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x", + link_id, mfg_id, part_id, class_id, unique_id); + + return NULL; +} +EXPORT_SYMBOL_NS(asoc_sdw_get_codec_name, SND_SOC_SDW_UTILS); + +/* helper to get the link that the codec DAI is used */ +struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card, + const char *dai_name) +{ + struct snd_soc_dai_link *dai_link; + int i; + int j; + + for_each_card_prelinks(card, i, dai_link) { + for (j = 0; j < dai_link->num_codecs; j++) { + /* Check each codec in a link */ + if (!strcmp(dai_link->codecs[j].dai_name, dai_name)) + return dai_link; + } + } + return NULL; +} +EXPORT_SYMBOL_NS(asoc_sdw_mc_find_codec_dai_used, SND_SOC_SDW_UTILS); + +void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card) +{ + struct snd_soc_dai_link *dai_link; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); + int ret; + int i, j; + + for (i = 0; i < ctx->codec_info_list_count; i++) { + for (j = 0; j < codec_info_list[i].dai_num; j++) { + codec_info_list[i].dais[j].rtd_init_done = false; + /* Check each dai in codec_info_lis to see if it is used in the link */ + if (!codec_info_list[i].dais[j].exit) + continue; + /* + * We don't need to call .exit function if there is no matched + * dai link found. + */ + dai_link = asoc_sdw_mc_find_codec_dai_used(card, + codec_info_list[i].dais[j].dai_name); + if (dai_link) { + /* Do the .exit function if the codec dai is used in the link */ + ret = codec_info_list[i].dais[j].exit(card, dai_link); + if (ret) + dev_warn(card->dev, + "codec exit failed %d\n", + ret); + break; + } + } + } +} +EXPORT_SYMBOL_NS(asoc_sdw_mc_dailink_exit_loop, SND_SOC_SDW_UTILS); + +int asoc_sdw_card_late_probe(struct snd_soc_card *card) +{ + int ret = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + if (codec_info_list[i].codec_card_late_probe) { + ret = codec_info_list[i].codec_card_late_probe(card); + if (ret < 0) + return ret; + } + } + return ret; +} +EXPORT_SYMBOL_NS(asoc_sdw_card_late_probe, SND_SOC_SDW_UTILS); + +void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, + int *be_id, char *name, int playback, int capture, + struct snd_soc_dai_link_component *cpus, int cpus_num, + struct snd_soc_dai_link_component *platform_component, + int num_platforms, struct snd_soc_dai_link_component *codecs, + int codecs_num, int (*init)(struct snd_soc_pcm_runtime *rtd), + const struct snd_soc_ops *ops) +{ + dev_dbg(dev, "create dai link %s, id %d\n", name, *be_id); + dai_links->id = (*be_id)++; + dai_links->name = name; + dai_links->platforms = platform_component; + dai_links->num_platforms = num_platforms; + dai_links->no_pcm = 1; + dai_links->cpus = cpus; + dai_links->num_cpus = cpus_num; + dai_links->codecs = codecs; + dai_links->num_codecs = codecs_num; + dai_links->dpcm_playback = playback; + dai_links->dpcm_capture = capture; + dai_links->init = init; + dai_links->ops = ops; +} +EXPORT_SYMBOL_NS(asoc_sdw_init_dai_link, SND_SOC_SDW_UTILS); + +int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, + int *be_id, char *name, int playback, int capture, + const char *cpu_dai_name, const char *platform_comp_name, + int num_platforms, const char *codec_name, + const char *codec_dai_name, + int (*init)(struct snd_soc_pcm_runtime *rtd), + const struct snd_soc_ops *ops) +{ + struct snd_soc_dai_link_component *dlc; + + /* Allocate three DLCs one for the CPU, one for platform and one for the CODEC */ + dlc = devm_kcalloc(dev, 3, sizeof(*dlc), GFP_KERNEL); + if (!dlc || !name || !cpu_dai_name || !platform_comp_name || !codec_name || !codec_dai_name) + return -ENOMEM; + + dlc[0].dai_name = cpu_dai_name; + dlc[1].name = platform_comp_name; + + dlc[2].name = codec_name; + dlc[2].dai_name = codec_dai_name; + + asoc_sdw_init_dai_link(dev, dai_links, be_id, name, playback, capture, + &dlc[0], 1, &dlc[1], num_platforms, + &dlc[2], 1, init, ops); + + return 0; +} +EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, SND_SOC_SDW_UTILS); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SoundWire ASoC helpers"); diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 7bddfd5e38d6..426632996a0a 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -41,6 +41,7 @@ config SND_SOC_RCAR depends on COMMON_CLK depends on OF select SND_SIMPLE_CARD_UTILS + select SND_DMAENGINE_PCM select REGMAP_MMIO help This option enables R-Car SRU/SCU/SSIU/SSI sound support diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index afd69c6eb654..0f190abf00e7 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -262,7 +262,7 @@ int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod, int id = rsnd_mod_id(src_mod); int shift = (id % 2) ? 16 : 0; - rsnd_mod_confirm_src(src_mod); + rsnd_mod_make_sure(src_mod, RSND_MOD_SRC); rsnd_adg_get_timesel_ratio(priv, io, in_rate, out_rate, @@ -291,7 +291,7 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val) int shift = (id % 4) * 8; u32 mask = 0xFF << shift; - rsnd_mod_confirm_ssi(ssi_mod); + rsnd_mod_make_sure(ssi_mod, RSND_MOD_SSI); val = val << shift; diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 63b3c8bf0fde..15cb5e7008f9 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -660,23 +660,6 @@ static struct rsnd_dai *rsnd_dai_to_rdai(struct snd_soc_dai *dai) return rsnd_rdai_get(priv, dai->id); } -/* - * rsnd_soc_dai functions - */ -void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io) -{ - struct snd_pcm_substream *substream = io->substream; - - /* - * this function should be called... - * - * - if rsnd_dai_pointer_update() returns true - * - without spin lock - */ - - snd_pcm_period_elapsed(substream); -} - static void rsnd_dai_stream_init(struct rsnd_dai_stream *io, struct snd_pcm_substream *substream) { diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 7b499eee5080..2342bbb6fe92 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -7,6 +7,7 @@ #include <linux/delay.h> #include <linux/of_dma.h> +#include <sound/dmaengine_pcm.h> #include "rsnd.h" /* @@ -22,8 +23,6 @@ struct rsnd_dmaen { struct dma_chan *chan; - dma_cookie_t cookie; - unsigned int dma_len; }; struct rsnd_dmapp { @@ -66,20 +65,6 @@ static struct rsnd_mod mem = { /* * Audio DMAC */ -static void __rsnd_dmaen_complete(struct rsnd_mod *mod, - struct rsnd_dai_stream *io) -{ - if (rsnd_io_is_working(io)) - rsnd_dai_period_elapsed(io); -} - -static void rsnd_dmaen_complete(void *data) -{ - struct rsnd_mod *mod = data; - - rsnd_mod_interrupt(mod, __rsnd_dmaen_complete); -} - static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) @@ -98,13 +83,7 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { - struct rsnd_dma *dma = rsnd_mod_to_dma(mod); - struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); - - if (dmaen->chan) - dmaengine_terminate_async(dmaen->chan); - - return 0; + return snd_dmaengine_pcm_trigger(io->substream, SNDRV_PCM_TRIGGER_STOP); } static int rsnd_dmaen_cleanup(struct rsnd_mod *mod, @@ -120,7 +99,7 @@ static int rsnd_dmaen_cleanup(struct rsnd_mod *mod, * Let's call it under prepare */ if (dmaen->chan) - dma_release_channel(dmaen->chan); + snd_dmaengine_pcm_close_release_chan(io->substream); dmaen->chan = NULL; @@ -153,7 +132,7 @@ static int rsnd_dmaen_prepare(struct rsnd_mod *mod, return -EIO; } - return 0; + return snd_dmaengine_pcm_open(io->substream, dmaen->chan); } static int rsnd_dmaen_start(struct rsnd_mod *mod, @@ -162,12 +141,9 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, { struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); - struct snd_pcm_substream *substream = io->substream; struct device *dev = rsnd_priv_to_dev(priv); - struct dma_async_tx_descriptor *desc; struct dma_slave_config cfg = {}; enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; - int is_play = rsnd_io_is_play(io); int ret; /* @@ -195,7 +171,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, } } - cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + cfg.direction = snd_pcm_substream_to_dma_direction(io->substream); cfg.src_addr = dma->src_addr; cfg.dst_addr = dma->dst_addr; cfg.src_addr_width = buswidth; @@ -209,32 +185,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, if (ret < 0) return ret; - desc = dmaengine_prep_dma_cyclic(dmaen->chan, - substream->runtime->dma_addr, - snd_pcm_lib_buffer_bytes(substream), - snd_pcm_lib_period_bytes(substream), - is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - - if (!desc) { - dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); - return -EIO; - } - - desc->callback = rsnd_dmaen_complete; - desc->callback_param = rsnd_mod_get(dma); - - dmaen->dma_len = snd_pcm_lib_buffer_bytes(substream); - - dmaen->cookie = dmaengine_submit(desc); - if (dmaen->cookie < 0) { - dev_err(dev, "dmaengine_submit() fail\n"); - return -EIO; - } - - dma_async_issue_pending(dmaen->chan); - - return 0; + return snd_dmaengine_pcm_trigger(io->substream, SNDRV_PCM_TRIGGER_START); } struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name, @@ -307,19 +258,7 @@ static int rsnd_dmaen_pointer(struct rsnd_mod *mod, struct rsnd_dai_stream *io, snd_pcm_uframes_t *pointer) { - struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); - struct rsnd_dma *dma = rsnd_mod_to_dma(mod); - struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); - struct dma_tx_state state; - enum dma_status status; - unsigned int pos = 0; - - status = dmaengine_tx_status(dmaen->chan, dmaen->cookie, &state); - if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) { - if (state.residue > 0 && state.residue <= dmaen->dma_len) - pos = dmaen->dma_len - state.residue; - } - *pointer = bytes_to_frames(runtime, pos); + *pointer = snd_dmaengine_pcm_pointer(io->substream); return 0; } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index ff294aa2d640..3c164d8e3b16 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -576,7 +576,6 @@ int rsnd_rdai_ssi_lane_ctrl(struct rsnd_dai *rdai, #define rsnd_rdai_width_get(rdai) \ rsnd_rdai_width_ctrl(rdai, 0) int rsnd_rdai_width_ctrl(struct rsnd_dai *rdai, int width); -void rsnd_dai_period_elapsed(struct rsnd_dai_stream *io); int rsnd_dai_connect(struct rsnd_mod *mod, struct rsnd_dai_stream *io, enum rsnd_mod_type type); @@ -871,15 +870,6 @@ void rsnd_cmd_remove(struct rsnd_priv *priv); int rsnd_cmd_attach(struct rsnd_dai_stream *io, int id); void rsnd_mod_make_sure(struct rsnd_mod *mod, enum rsnd_mod_type type); -#ifdef DEBUG -#define rsnd_mod_confirm_ssi(mssi) rsnd_mod_make_sure(mssi, RSND_MOD_SSI) -#define rsnd_mod_confirm_src(msrc) rsnd_mod_make_sure(msrc, RSND_MOD_SRC) -#define rsnd_mod_confirm_dvc(mdvc) rsnd_mod_make_sure(mdvc, RSND_MOD_DVC) -#else -#define rsnd_mod_confirm_ssi(mssi) -#define rsnd_mod_confirm_src(msrc) -#define rsnd_mod_confirm_dvc(mdvc) -#endif /* * If you don't need interrupt status debug message, diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 8d2a86383ae0..b3d4e8ae07ef 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -706,7 +706,7 @@ rsnd_ssi_interrupt_out: spin_unlock(&priv->lock); if (elapsed) - rsnd_dai_period_elapsed(io); + snd_pcm_period_elapsed(io->substream); if (stop) snd_pcm_stop_xrun(io->substream); diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 9d103646973a..d0bf0487bf1b 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -52,6 +52,7 @@ #define SSIFCR_RIE BIT(2) #define SSIFCR_TFRST BIT(1) #define SSIFCR_RFRST BIT(0) +#define SSIFCR_FIFO_RST (SSIFCR_TFRST | SSIFCR_RFRST) #define SSIFSR_TDC_MASK 0x3f #define SSIFSR_TDC_SHIFT 24 @@ -130,6 +131,14 @@ struct rz_ssi_priv { bool lrckp_fsync_fall; /* LR clock polarity (SSICR.LRCKP) */ bool bckp_rise; /* Bit clock polarity (SSICR.BCKP) */ bool dma_rt; + + /* Full duplex communication support */ + struct { + unsigned int rate; + unsigned int channels; + unsigned int sample_width; + unsigned int sample_bits; + } hw_params_cache; }; static void rz_ssi_dma_complete(void *data); @@ -208,6 +217,11 @@ static bool rz_ssi_stream_is_valid(struct rz_ssi_priv *ssi, return ret; } +static inline bool rz_ssi_is_stream_running(struct rz_ssi_stream *strm) +{ + return strm->substream && strm->running; +} + static void rz_ssi_stream_init(struct rz_ssi_stream *strm, struct snd_pcm_substream *substream) { @@ -303,13 +317,53 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate, return 0; } +static void rz_ssi_set_idle(struct rz_ssi_priv *ssi) +{ + int timeout; + + /* Disable irqs */ + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN | + SSICR_RUIEN | SSICR_ROIEN, 0); + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0); + + /* Clear all error flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, + (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | + SSISR_RUIRQ), 0); + + /* Wait for idle */ + timeout = 100; + while (--timeout) { + if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ) + break; + udelay(1); + } + + if (!timeout) + dev_info(ssi->dev, "timeout waiting for SSI idle\n"); + + /* Hold FIFOs in reset */ + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, + SSIFCR_TFRST | SSIFCR_RFRST); +} + static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { bool is_play = rz_ssi_stream_is_play(ssi, strm->substream); + bool is_full_duplex; u32 ssicr, ssifcr; + is_full_duplex = rz_ssi_is_stream_running(&ssi->playback) || + rz_ssi_is_stream_running(&ssi->capture); ssicr = rz_ssi_reg_readl(ssi, SSICR); - ssifcr = rz_ssi_reg_readl(ssi, SSIFCR) & ~0xF; + ssifcr = rz_ssi_reg_readl(ssi, SSIFCR); + if (!is_full_duplex) { + ssifcr &= ~0xF; + } else { + rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); + rz_ssi_set_idle(ssi); + ssifcr &= ~SSIFCR_FIFO_RST; + } /* FIFO interrupt thresholds */ if (rz_ssi_is_dma_enabled(ssi)) @@ -322,10 +376,14 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) /* enable IRQ */ if (is_play) { ssicr |= SSICR_TUIEN | SSICR_TOIEN; - ssifcr |= SSIFCR_TIE | SSIFCR_RFRST; + ssifcr |= SSIFCR_TIE; + if (!is_full_duplex) + ssifcr |= SSIFCR_RFRST; } else { ssicr |= SSICR_RUIEN | SSICR_ROIEN; - ssifcr |= SSIFCR_RIE | SSIFCR_TFRST; + ssifcr |= SSIFCR_RIE; + if (!is_full_duplex) + ssifcr |= SSIFCR_TFRST; } rz_ssi_reg_writel(ssi, SSICR, ssicr); @@ -337,7 +395,11 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) SSISR_RUIRQ), 0); strm->running = 1; - ssicr |= is_play ? SSICR_TEN : SSICR_REN; + if (is_full_duplex) + ssicr |= SSICR_TEN | SSICR_REN; + else + ssicr |= is_play ? SSICR_TEN : SSICR_REN; + rz_ssi_reg_writel(ssi, SSICR, ssicr); return 0; @@ -345,10 +407,12 @@ static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) { - int timeout; - strm->running = 0; + if (rz_ssi_is_stream_running(&ssi->playback) || + rz_ssi_is_stream_running(&ssi->capture)) + return 0; + /* Disable TX/RX */ rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0); @@ -356,30 +420,7 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) if (rz_ssi_is_dma_enabled(ssi)) dmaengine_terminate_async(strm->dma_ch); - /* Disable irqs */ - rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TUIEN | SSICR_TOIEN | - SSICR_RUIEN | SSICR_ROIEN, 0); - rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_TIE | SSIFCR_RIE, 0); - - /* Clear all error flags */ - rz_ssi_reg_mask_setl(ssi, SSISR, - (SSISR_TOIRQ | SSISR_TUIRQ | SSISR_ROIRQ | - SSISR_RUIRQ), 0); - - /* Wait for idle */ - timeout = 100; - while (--timeout) { - if (rz_ssi_reg_readl(ssi, SSISR) & SSISR_IIRQ) - break; - udelay(1); - } - - if (!timeout) - dev_info(ssi->dev, "timeout waiting for SSI idle\n"); - - /* Hold FIFOs in reset */ - rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, - SSIFCR_TFRST | SSIFCR_RFRST); + rz_ssi_set_idle(ssi); return 0; } @@ -512,66 +553,90 @@ static int rz_ssi_pio_send(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm) static irqreturn_t rz_ssi_interrupt(int irq, void *data) { - struct rz_ssi_stream *strm = NULL; + struct rz_ssi_stream *strm_playback = NULL; + struct rz_ssi_stream *strm_capture = NULL; struct rz_ssi_priv *ssi = data; u32 ssisr = rz_ssi_reg_readl(ssi, SSISR); if (ssi->playback.substream) - strm = &ssi->playback; - else if (ssi->capture.substream) - strm = &ssi->capture; - else + strm_playback = &ssi->playback; + if (ssi->capture.substream) + strm_capture = &ssi->capture; + + if (!strm_playback && !strm_capture) return IRQ_HANDLED; /* Left over TX/RX interrupt */ if (irq == ssi->irq_int) { /* error or idle */ - if (ssisr & SSISR_TUIRQ) - strm->uerr_num++; - if (ssisr & SSISR_TOIRQ) - strm->oerr_num++; - if (ssisr & SSISR_RUIRQ) - strm->uerr_num++; - if (ssisr & SSISR_ROIRQ) - strm->oerr_num++; - - if (ssisr & (SSISR_TUIRQ | SSISR_TOIRQ | SSISR_RUIRQ | - SSISR_ROIRQ)) { - /* Error handling */ - /* You must reset (stop/restart) after each interrupt */ - rz_ssi_stop(ssi, strm); - - /* Clear all flags */ - rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | - SSISR_TUIRQ | SSISR_ROIRQ | - SSISR_RUIRQ, 0); - - /* Add/remove more data */ - strm->transfer(ssi, strm); - - /* Resume */ - rz_ssi_start(ssi, strm); + bool is_stopped = false; + int i, count; + + if (rz_ssi_is_dma_enabled(ssi)) + count = 4; + else + count = 1; + + if (ssisr & (SSISR_RUIRQ | SSISR_ROIRQ | SSISR_TUIRQ | SSISR_TOIRQ)) + is_stopped = true; + + if (ssi->capture.substream && is_stopped) { + if (ssisr & SSISR_RUIRQ) + strm_capture->uerr_num++; + if (ssisr & SSISR_ROIRQ) + strm_capture->oerr_num++; + + rz_ssi_stop(ssi, strm_capture); } + + if (ssi->playback.substream && is_stopped) { + if (ssisr & SSISR_TUIRQ) + strm_playback->uerr_num++; + if (ssisr & SSISR_TOIRQ) + strm_playback->oerr_num++; + + rz_ssi_stop(ssi, strm_playback); + } + + /* Clear all flags */ + rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | SSISR_TUIRQ | + SSISR_ROIRQ | SSISR_RUIRQ, 0); + + /* Add/remove more data */ + if (ssi->capture.substream && is_stopped) { + for (i = 0; i < count; i++) + strm_capture->transfer(ssi, strm_capture); + } + + if (ssi->playback.substream && is_stopped) { + for (i = 0; i < count; i++) + strm_playback->transfer(ssi, strm_playback); + } + + /* Resume */ + if (ssi->playback.substream && is_stopped) + rz_ssi_start(ssi, &ssi->playback); + if (ssi->capture.substream && is_stopped) + rz_ssi_start(ssi, &ssi->capture); } - if (!strm->running) + if (!rz_ssi_is_stream_running(&ssi->playback) && + !rz_ssi_is_stream_running(&ssi->capture)) return IRQ_HANDLED; /* tx data empty */ - if (irq == ssi->irq_tx) - strm->transfer(ssi, &ssi->playback); + if (irq == ssi->irq_tx && rz_ssi_is_stream_running(&ssi->playback)) + strm_playback->transfer(ssi, &ssi->playback); /* rx data full */ - if (irq == ssi->irq_rx) { - strm->transfer(ssi, &ssi->capture); + if (irq == ssi->irq_rx && rz_ssi_is_stream_running(&ssi->capture)) { + strm_capture->transfer(ssi, &ssi->capture); rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); } if (irq == ssi->irq_rt) { - struct snd_pcm_substream *substream = strm->substream; - - if (rz_ssi_stream_is_play(ssi, substream)) { - strm->transfer(ssi, &ssi->playback); + if (ssi->playback.substream) { + strm_playback->transfer(ssi, &ssi->playback); } else { - strm->transfer(ssi, &ssi->capture); + strm_capture->transfer(ssi, &ssi->capture); rz_ssi_reg_mask_setl(ssi, SSIFSR, SSIFSR_RDF, 0); } } @@ -731,9 +796,12 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_START: /* Soft Reset */ - rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); - rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); - udelay(5); + if (!rz_ssi_is_stream_running(&ssi->playback) && + !rz_ssi_is_stream_running(&ssi->capture)) { + rz_ssi_reg_mask_setl(ssi, SSIFCR, 0, SSIFCR_SSIRST); + rz_ssi_reg_mask_setl(ssi, SSIFCR, SSIFCR_SSIRST, 0); + udelay(5); + } rz_ssi_stream_init(strm, substream); @@ -824,14 +892,41 @@ static int rz_ssi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) return 0; } +static bool rz_ssi_is_valid_hw_params(struct rz_ssi_priv *ssi, unsigned int rate, + unsigned int channels, + unsigned int sample_width, + unsigned int sample_bits) +{ + if (ssi->hw_params_cache.rate != rate || + ssi->hw_params_cache.channels != channels || + ssi->hw_params_cache.sample_width != sample_width || + ssi->hw_params_cache.sample_bits != sample_bits) + return false; + + return true; +} + +static void rz_ssi_cache_hw_params(struct rz_ssi_priv *ssi, unsigned int rate, + unsigned int channels, + unsigned int sample_width, + unsigned int sample_bits) +{ + ssi->hw_params_cache.rate = rate; + ssi->hw_params_cache.channels = channels; + ssi->hw_params_cache.sample_width = sample_width; + ssi->hw_params_cache.sample_bits = sample_bits; +} + static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai); + struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream); unsigned int sample_bits = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min; unsigned int channels = params_channels(params); + unsigned int rate = params_rate(params); if (sample_bits != 16) { dev_err(ssi->dev, "Unsupported sample width: %d\n", @@ -845,8 +940,20 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - return rz_ssi_clk_setup(ssi, params_rate(params), - params_channels(params)); + if (rz_ssi_is_stream_running(&ssi->playback) || + rz_ssi_is_stream_running(&ssi->capture)) { + if (rz_ssi_is_valid_hw_params(ssi, rate, channels, + strm->sample_width, sample_bits)) + return 0; + + dev_err(ssi->dev, "Full duplex needs same HW params\n"); + return -EINVAL; + } + + rz_ssi_cache_hw_params(ssi, rate, channels, strm->sample_width, + sample_bits); + + return rz_ssi_clk_setup(ssi, rate, channels); } static const struct snd_soc_dai_ops rz_ssi_dai_ops = { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 724fe1f033b5..20248a29d167 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -326,8 +326,8 @@ static int snd_soc_rtd_add_component(struct snd_soc_pcm_runtime *rtd, } /* see for_each_rtd_components */ - rtd->components[rtd->num_components] = component; - rtd->num_components++; + rtd->num_components++; // increment flex array count at first + rtd->components[rtd->num_components - 1] = component; return 0; } @@ -494,7 +494,6 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) { struct snd_soc_pcm_runtime *rtd; - struct snd_soc_component *component; struct device *dev; int ret; int stream; @@ -521,10 +520,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( * for rtd */ rtd = devm_kzalloc(dev, - sizeof(*rtd) + - sizeof(component) * (dai_link->num_cpus + - dai_link->num_codecs + - dai_link->num_platforms), + struct_size(rtd, components, + dai_link->num_cpus + + dai_link->num_codecs + + dai_link->num_platforms), GFP_KERNEL); if (!rtd) { device_unregister(dev); @@ -3372,10 +3371,10 @@ unsigned int snd_soc_daifmt_parse_format(struct device_node *np, * SND_SOC_DAIFMT_INV_MASK area */ snprintf(prop, sizeof(prop), "%sbitclock-inversion", prefix); - bit = !!of_get_property(np, prop, NULL); + bit = of_property_read_bool(np, prop); snprintf(prop, sizeof(prop), "%sframe-inversion", prefix); - frame = !!of_get_property(np, prop, NULL); + frame = of_property_read_bool(np, prop); switch ((bit << 4) + frame) { case 0x11: @@ -3412,12 +3411,12 @@ unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, * check "[prefix]frame-master" */ snprintf(prop, sizeof(prop), "%sbitclock-master", prefix); - bit = !!of_get_property(np, prop, NULL); + bit = of_property_read_bool(np, prop); if (bit && bitclkmaster) *bitclkmaster = of_parse_phandle(np, prop, 0); snprintf(prop, sizeof(prop), "%sframe-master", prefix); - frame = !!of_get_property(np, prop, NULL); + frame = of_property_read_bool(np, prop); if (frame && framemaster) *framemaster = of_parse_phandle(np, prop, 0); diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 9e47053419c1..302ca753a1f3 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -685,26 +685,6 @@ int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, return ret; } -int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *dai; - int i, ret; - - for_each_rtd_dais(rtd, i, dai) { - if (dai->driver->ops && - dai->driver->ops->bespoke_trigger) { - ret = dai->driver->ops->bespoke_trigger(substream, - cmd, dai); - if (ret < 0) - return soc_dai_ret(dai, ret); - } - } - - return 0; -} - void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 37dccd9c1ba0..d7d6dbb9d9ea 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2751,8 +2751,7 @@ static int dapm_update_dai_unlocked(struct snd_pcm_substream *substream, if (!w) return 0; - dev_dbg(dai->dev, "Update DAI routes for %s %s\n", dai->name, - dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture"); + dev_dbg(dai->dev, "Update DAI routes for %s %s\n", dai->name, snd_pcm_direction_name(dir)); snd_soc_dapm_widget_for_each_sink_path(w, p) { ret = dapm_update_dai_chan(p, p->sink, channels); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index bad823718ae4..1edcb8d6f6ee 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -222,7 +222,7 @@ static void dpcm_create_debugfs_state(struct snd_soc_dpcm *dpcm, int stream) char *name; name = kasprintf(GFP_KERNEL, "%s:%s", dpcm->be->dai_link->name, - stream ? "capture" : "playback"); + snd_pcm_direction_name(stream)); if (name) { dpcm->debugfs_state = debugfs_create_dir( name, dpcm->fe->debugfs_dpcm_root); @@ -1278,7 +1278,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, snd_soc_dpcm_stream_unlock_irq(fe, stream); dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n", - stream ? "capture" : "playback", fe->dai_link->name, + snd_pcm_direction_name(stream), fe->dai_link->name, stream ? "<-" : "->", be->dai_link->name); dpcm_create_debugfs_state(dpcm, stream); @@ -1306,7 +1306,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, continue; dev_dbg(fe->dev, "reparent %s path %s %s %s\n", - stream ? "capture" : "playback", + snd_pcm_direction_name(stream), dpcm->fe->dai_link->name, stream ? "<-" : "->", dpcm->be->dai_link->name); @@ -1327,14 +1327,14 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) snd_soc_dpcm_stream_lock_irq(fe, stream); for_each_dpcm_be_safe(fe, stream, dpcm, d) { dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n", - stream ? "capture" : "playback", + snd_pcm_direction_name(stream), dpcm->be->dai_link->name); if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE) continue; dev_dbg(fe->dev, "freed DSP %s path %s %s %s\n", - stream ? "capture" : "playback", fe->dai_link->name, + snd_pcm_direction_name(stream), fe->dai_link->name, stream ? "<-" : "->", dpcm->be->dai_link->name); /* BEs still alive need new FE */ @@ -1441,10 +1441,10 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe, if (paths > 0) dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, - stream ? "capture" : "playback"); + snd_pcm_direction_name(stream)); else if (paths == 0) dev_dbg(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, - stream ? "capture" : "playback"); + snd_pcm_direction_name(stream)); return paths; } @@ -1487,7 +1487,7 @@ static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, continue; dev_dbg(fe->dev, "ASoC: pruning %s BE %s for %s\n", - stream ? "capture" : "playback", + snd_pcm_direction_name(stream), dpcm->be->dai_link->name, fe->dai_link->name); dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE; dpcm_set_be_update_state(dpcm->be, stream, SND_SOC_DPCM_UPDATE_BE); @@ -1605,7 +1605,7 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, if (be->dpcm[stream].users == 0) { dev_err(be->dev, "ASoC: no users %s at close - state %d\n", - stream ? "capture" : "playback", + snd_pcm_direction_name(stream), be->dpcm[stream].state); continue; } @@ -1645,7 +1645,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) if (!be_substream) { dev_err(be->dev, "ASoC: no backend %s stream\n", - stream ? "capture" : "playback"); + snd_pcm_direction_name(stream)); continue; } @@ -1656,7 +1656,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) /* first time the dpcm is open ? */ if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) { dev_err(be->dev, "ASoC: too many users %s at open %d\n", - stream ? "capture" : "playback", + snd_pcm_direction_name(stream), be->dpcm[stream].state); continue; } @@ -1669,7 +1669,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) continue; dev_dbg(be->dev, "ASoC: open %s BE %s\n", - stream ? "capture" : "playback", be->dai_link->name); + snd_pcm_direction_name(stream), be->dai_link->name); be_substream->runtime = fe_substream->runtime; err = __soc_pcm_open(be, be_substream); @@ -1677,7 +1677,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) be->dpcm[stream].users--; if (be->dpcm[stream].users < 0) dev_err(be->dev, "ASoC: no users %s at unwind %d\n", - stream ? "capture" : "playback", + snd_pcm_direction_name(stream), be->dpcm[stream].state); be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; @@ -2388,14 +2388,6 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) break; } break; - case SND_SOC_DPCM_TRIGGER_BESPOKE: - /* bespoke trigger() - handles both FE and BEs */ - - dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd %d\n", - fe->dai_link->name, cmd); - - ret = snd_soc_pcm_dai_bespoke_trigger(substream, cmd); - break; default: dev_err(fe->dev, "ASoC: invalid trigger cmd %d for %s\n", cmd, fe->dai_link->name); @@ -2525,26 +2517,12 @@ out: static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) { - struct snd_pcm_substream *substream = - snd_soc_dpcm_get_substream(fe, stream); - enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; int err; dev_dbg(fe->dev, "ASoC: runtime %s close on FE %s\n", - stream ? "capture" : "playback", fe->dai_link->name); + snd_pcm_direction_name(stream), fe->dai_link->name); - if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) { - /* call bespoke trigger - FE takes care of all BE triggers */ - dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd stop\n", - fe->dai_link->name); - - err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP); - } else { - dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n", - fe->dai_link->name); - - err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP); - } + err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP); dpcm_be_dai_hw_free(fe, stream); @@ -2558,14 +2536,11 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) { - struct snd_pcm_substream *substream = - snd_soc_dpcm_get_substream(fe, stream); struct snd_soc_dpcm *dpcm; - enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream]; int ret = 0; dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n", - stream ? "capture" : "playback", fe->dai_link->name); + snd_pcm_direction_name(stream), fe->dai_link->name); /* Only start the BE if the FE is ready */ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE || @@ -2605,23 +2580,9 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) fe->dpcm[stream].state == SND_SOC_DPCM_STATE_STOP) return 0; - if (trigger == SND_SOC_DPCM_TRIGGER_BESPOKE) { - /* call trigger on the frontend - FE takes care of all BE triggers */ - dev_dbg(fe->dev, "ASoC: bespoke trigger FE %s cmd start\n", - fe->dai_link->name); - - ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); - if (ret < 0) - goto hw_free; - } else { - dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n", - fe->dai_link->name); - - ret = dpcm_be_dai_trigger(fe, stream, - SNDRV_PCM_TRIGGER_START); - if (ret < 0) - goto hw_free; - } + ret = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_START); + if (ret < 0) + goto hw_free; return 0; diff --git a/sound/soc/sof/amd/Kconfig b/sound/soc/sof/amd/Kconfig index 2729c6eb3feb..848c031ed5fb 100644 --- a/sound/soc/sof/amd/Kconfig +++ b/sound/soc/sof/amd/Kconfig @@ -23,6 +23,7 @@ config SND_SOC_SOF_AMD_COMMON select SND_AMD_ACP_CONFIG select SND_SOC_SOF_XTENSA select SND_SOC_SOF_ACP_PROBES + select SND_SOC_ACPI_AMD_MATCH select SND_SOC_ACPI if ACPI help This option is not user-selectable but automatically handled by diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index 81bb93e98358..dbcaac84cb73 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -153,6 +153,7 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev * break; } if (mach && mach->link_mask) { + mach->mach_params.subsystem_rev = acp_data->pci_rev; mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; mach->mach_params.platform = dev_name(sdev->dev); @@ -173,6 +174,7 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev * struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev) { struct snd_sof_pdata *sof_pdata = sdev->pdata; + struct acp_dev_data *acp_data = sdev->pdata->hw_pdata; const struct sof_dev_desc *desc = sof_pdata->desc; struct snd_soc_acpi_mach *mach = NULL; @@ -186,6 +188,7 @@ struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev) } } + mach->mach_params.subsystem_rev = acp_data->pci_rev; sof_pdata->tplg_filename = mach->sof_tplg_filename; sof_pdata->fw_filename = mach->fw_filename; diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c index 74fd5f2b148b..7b122656efd1 100644 --- a/sound/soc/sof/amd/acp.c +++ b/sound/soc/sof/amd/acp.c @@ -695,6 +695,7 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev) pci_set_master(pci); adata->addr = addr; adata->reg_range = chip->reg_end_addr - chip->reg_start_addr; + adata->pci_rev = pci->revision; mutex_init(&adata->acp_lock); sdev->pdata->hw_pdata = adata; adata->smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, chip->host_bridge_id, NULL); diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index 87e79d500865..ec9170b3f068 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -251,6 +251,7 @@ struct acp_dev_data { bool is_dram_in_use; bool is_sram_in_use; bool sdw_en_stat; + unsigned int pci_rev; }; void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src, size_t bytes); diff --git a/sound/soc/sof/amd/pci-acp63.c b/sound/soc/sof/amd/pci-acp63.c index fc8984447365..54d42f83ce9e 100644 --- a/sound/soc/sof/amd/pci-acp63.c +++ b/sound/soc/sof/amd/pci-acp63.c @@ -48,6 +48,7 @@ static const struct sof_amd_acp_desc acp63_chip_info = { static const struct sof_dev_desc acp63_desc = { .machines = snd_soc_acpi_amd_acp63_sof_machines, + .alt_machines = snd_soc_acpi_amd_acp63_sof_sdw_machines, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 3396bd46b778..2c43558d96b9 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -281,6 +281,23 @@ config SND_SOC_SOF_LUNARLAKE Say Y if you have such a device. If unsure select "N". +config SND_SOC_SOF_INTEL_PTL + tristate + select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE + select SND_SOC_SOF_IPC4 + select SND_SOC_SOF_INTEL_LNL + +config SND_SOC_SOF_PANTHERLAKE + tristate "SOF support for Pantherlake" + default SND_SOC_SOF_PCI + select SND_SOC_SOF_INTEL_PTL + help + This adds support for Sound Open Firmware for Intel(R) platforms + using the Pantherlake processors. + Say Y if you have such a device. + If unsure select "N". + config SND_SOC_SOF_HDA_COMMON tristate diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index b56fa5530b8b..f40daa616803 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -34,6 +34,7 @@ snd-sof-pci-intel-icl-y := pci-icl.o icl.o snd-sof-pci-intel-tgl-y := pci-tgl.o tgl.o snd-sof-pci-intel-mtl-y := pci-mtl.o mtl.o snd-sof-pci-intel-lnl-y := pci-lnl.o lnl.o +snd-sof-pci-intel-ptl-y := pci-ptl.o obj-$(CONFIG_SND_SOC_SOF_MERRIFIELD) += snd-sof-pci-intel-tng.o obj-$(CONFIG_SND_SOC_SOF_INTEL_SKL) += snd-sof-pci-intel-skl.o @@ -43,3 +44,4 @@ obj-$(CONFIG_SND_SOC_SOF_INTEL_ICL) += snd-sof-pci-intel-icl.o obj-$(CONFIG_SND_SOC_SOF_INTEL_TGL) += snd-sof-pci-intel-tgl.o obj-$(CONFIG_SND_SOC_SOF_INTEL_MTL) += snd-sof-pci-intel-mtl.o obj-$(CONFIG_SND_SOC_SOF_INTEL_LNL) += snd-sof-pci-intel-lnl.o +obj-$(CONFIG_SND_SOC_SOF_INTEL_PTL) += snd-sof-pci-intel-ptl.o diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 1315f5bc3e31..4c88522d4048 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -69,6 +69,7 @@ static void hda_get_interfaces(struct snd_sof_dev *sdev, u32 *interface_mask) interface_mask[SOF_DAI_HOST_ACCESS] = BIT(SOF_DAI_INTEL_HDA); break; case SOF_INTEL_ACE_2_0: + case SOF_INTEL_ACE_3_0: interface_mask[SOF_DAI_DSP_ACCESS] = BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 8213debde497..3ac63ce67ab1 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -216,9 +216,7 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) /* stream found ? */ if (!hext_stream) { - dev_err(sdev->dev, "error: no free %s streams\n", - direction == SNDRV_PCM_STREAM_PLAYBACK ? - "playback" : "capture"); + dev_err(sdev->dev, "error: no free %s streams\n", snd_pcm_direction_name(direction)); return hext_stream; } diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 3c9e1d59e1ab..b74a472435b5 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -920,6 +920,7 @@ extern const struct sof_intel_dsp_desc adls_chip_info; extern const struct sof_intel_dsp_desc mtl_chip_info; extern const struct sof_intel_dsp_desc arl_s_chip_info; extern const struct sof_intel_dsp_desc lnl_chip_info; +extern const struct sof_intel_dsp_desc ptl_chip_info; /* Probes support */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 4b5665f82170..3d5a1f8b17e5 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -22,6 +22,7 @@ /* LunarLake ops */ struct snd_sof_dsp_ops sof_lnl_ops; +EXPORT_SYMBOL_NS(sof_lnl_ops, SND_SOC_SOF_INTEL_LNL); static const struct snd_sof_debugfs_map lnl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, @@ -181,6 +182,7 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) return 0; }; +EXPORT_SYMBOL_NS(sof_lnl_ops_init, SND_SOC_SOF_INTEL_LNL); /* Check if an SDW IRQ occurred */ static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) @@ -245,3 +247,28 @@ const struct sof_intel_dsp_desc lnl_chip_info = { .disable_interrupts = lnl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_2_0, }; + +const struct sof_intel_dsp_desc ptl_chip_info = { + .cores_num = 5, + .init_core_mask = BIT(0), + .host_managed_cores_mask = BIT(0), + .ipc_req = MTL_DSP_REG_HFIPCXIDR, + .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY, + .ipc_ack = MTL_DSP_REG_HFIPCXIDA, + .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, + .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, + .rom_status_reg = LNL_DSP_REG_HFDSC, + .rom_init_timeout = 300, + .ssp_count = MTL_SSP_COUNT, + .d0i3_offset = MTL_HDA_VS_D0I3C, + .read_sdw_lcount = hda_sdw_check_lcount_ext, + .enable_sdw_irq = lnl_enable_sdw_irq, + .check_sdw_irq = lnl_dsp_check_sdw_irq, + .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, + .check_ipc_irq = mtl_dsp_check_ipc_irq, + .cl_init = mtl_dsp_cl_init, + .power_down_dsp = mtl_power_down_dsp, + .disable_interrupts = lnl_dsp_disable_interrupts, + .hw_ip_version = SOF_INTEL_ACE_3_0, +}; +EXPORT_SYMBOL_NS(ptl_chip_info, SND_SOC_SOF_INTEL_LNL); diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 1bf274509ee6..2b9d22ccf345 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -245,6 +245,18 @@ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) u32 cpa; u32 pgs; int ret; + u32 dsppwrctl; + u32 dsppwrsts; + const struct sof_intel_dsp_desc *chip; + + chip = get_chip_info(sdev->pdata); + if (chip->hw_ip_version > SOF_INTEL_ACE_2_0) { + dsppwrctl = PTL_HFPWRCTL2; + dsppwrsts = PTL_HFPWRSTS2; + } else { + dsppwrctl = MTL_HFPWRCTL; + dsppwrsts = MTL_HFPWRSTS; + } /* Set the DSP subsystem power on */ snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFDSSCS, @@ -264,14 +276,14 @@ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) } /* Power up gated-DSP-0 domain in order to access the DSP shim register block. */ - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, MTL_HFPWRCTL, + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, dsppwrctl, MTL_HFPWRCTL_WPDSPHPXPG, MTL_HFPWRCTL_WPDSPHPXPG); usleep_range(1000, 1010); /* poll with timeout to check if operation successful */ pgs = MTL_HFPWRSTS_DSPHPXPGS_MASK; - ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, MTL_HFPWRSTS, dsphfpwrsts, + ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, dsppwrsts, dsphfpwrsts, (dsphfpwrsts & pgs) == pgs, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index 7acaa7e724f4..9ab4b21c960e 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -12,9 +12,11 @@ #define MTL_HFDSSCS_CPA_MASK BIT(24) #define MTL_HFSNDWIE 0x114C #define MTL_HFPWRCTL 0x1D18 +#define PTL_HFPWRCTL2 0x1D20 #define MTL_HfPWRCTL_WPIOXPG(x) BIT((x) + 8) #define MTL_HFPWRCTL_WPDSPHPXPG BIT(0) #define MTL_HFPWRSTS 0x1D1C +#define PTL_HFPWRSTS2 0x1D24 #define MTL_HFPWRSTS_DSPHPXPGS_MASK BIT(0) #define MTL_HFINTIPPTR 0x1108 #define MTL_IRQ_INTEN_L_HOST_IPC_MASK BIT(0) diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c new file mode 100644 index 000000000000..69195b5e7b1a --- /dev/null +++ b/sound/soc/sof/intel/pci-ptl.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2024 Intel Corporation. +// + +#include <linux/module.h> +#include <linux/pci.h> +#include <sound/soc-acpi.h> +#include <sound/soc-acpi-intel-match.h> +#include <sound/sof.h> +#include "../ops.h" +#include "../sof-pci-dev.h" + +/* platform specific devices */ +#include "hda.h" +#include "mtl.h" + +static const struct sof_dev_desc ptl_desc = { + .use_acpi_target_states = true, + .machines = snd_soc_acpi_intel_ptl_machines, + .alt_machines = snd_soc_acpi_intel_ptl_sdw_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = -1, + .resindex_imr_base = -1, + .irqindex_host_ipc = -1, + .chip_info = &ptl_chip_info, + .ipc_supported_mask = BIT(SOF_IPC_TYPE_4), + .ipc_default = SOF_IPC_TYPE_4, + .dspless_mode_supported = true, + .default_fw_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4/ptl", + }, + .default_lib_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/ptl", + }, + .default_tplg_path = { + [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg", + }, + .default_fw_filename = { + [SOF_IPC_TYPE_4] = "sof-ptl.ri", + }, + .nocodec_tplg_filename = "sof-ptl-nocodec.tplg", + .ops = &sof_lnl_ops, + .ops_init = sof_lnl_ops_init, +}; + +/* PCI IDs */ +static const struct pci_device_id sof_pci_ids[] = { + { PCI_DEVICE_DATA(INTEL, HDA_PTL, &ptl_desc) }, /* PTL */ + { 0, } +}; +MODULE_DEVICE_TABLE(pci, sof_pci_ids); + +/* pci_driver definition */ +static struct pci_driver snd_sof_pci_intel_ptl_driver = { + .name = "sof-audio-pci-intel-ptl", + .id_table = sof_pci_ids, + .probe = hda_pci_intel_probe, + .remove = sof_pci_remove, + .shutdown = sof_pci_shutdown, + .driver = { + .pm = &sof_pci_pm, + }, +}; +module_pci_driver(snd_sof_pci_intel_ptl_driver); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("SOF support for PantherLake platforms"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_LNL); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_MTL); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); +MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index 9328d2bbfd03..8709b750a11e 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -22,6 +22,7 @@ enum sof_intel_hw_ip_version { SOF_INTEL_CAVS_2_5, /* TigerLake, AlderLake */ SOF_INTEL_ACE_1_0, /* MeteorLake */ SOF_INTEL_ACE_2_0, /* LunarLake */ + SOF_INTEL_ACE_3_0, /* PantherLake */ }; /* diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index baad4c1445aa..35a7462d8b69 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -100,7 +100,7 @@ sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_run dpcm_end_walk_at_be); if (ret < 0) { dev_err(sdev->dev, "error: dai %s has no valid %s path\n", dai->name, - dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture"); + snd_pcm_direction_name(dir)); return ret; } diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 49be02234fc3..b9b8b64768b9 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -314,12 +314,12 @@ struct sof_token_info { /** * struct snd_sof_pcm_stream_pipeline_list - List of pipelines associated with a PCM stream - * @count: number of pipeline widgets in the @pipe_widgets array * @pipelines: array of pipelines + * @count: number of pipeline widgets in the @pipe_widgets array */ struct snd_sof_pcm_stream_pipeline_list { - u32 count; struct snd_sof_pipeline **pipelines; + u32 count; }; /* PCM stream, mapped to FW component */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 4d6a1517f9b3..843be3b6415d 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -132,16 +132,17 @@ struct snd_sof_pdata; /** * struct snd_sof_platform_stream_params - platform dependent stream parameters - * @stream_tag: Stream tag to use - * @use_phy_addr: Use the provided @phy_addr for configuration * @phy_addr: Platform dependent address to be used, if @use_phy_addr * is true + * @stream_tag: Stream tag to use + * @use_phy_addr: Use the provided @phy_addr for configuration * @no_ipc_position: Disable position update IPC from firmware + * @cont_update_posn: Continuous position update. */ struct snd_sof_platform_stream_params { + u32 phy_addr; u16 stream_tag; bool use_phy_address; - u32 phy_addr; bool no_ipc_position; bool cont_update_posn; }; @@ -411,8 +412,8 @@ struct snd_sof_debugfs_map { /* mailbox descriptor, used for host <-> DSP IPC */ struct snd_sof_mailbox { - u32 offset; size_t size; + u32 offset; }; /* IPC message descriptor for host <-> DSP IO */ @@ -424,11 +425,12 @@ struct snd_sof_ipc_msg { size_t reply_size; int reply_error; - /* notification, firmware initiated messages */ - void *rx_data; + bool ipc_complete; wait_queue_head_t waitq; - bool ipc_complete; + + /* notification, firmware initiated messages */ + void *rx_data; }; /** diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 46098e111142..a96aa308681a 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -823,7 +823,7 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* Enable i2s */ dev_dbg(cpu_dai->dev, "start I2S %s\n", - playback_flg ? "playback" : "capture"); + snd_pcm_direction_name(substream->stream)); cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN; regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG, @@ -869,7 +869,7 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: dev_dbg(cpu_dai->dev, "stop I2S %s\n", - playback_flg ? "playback" : "capture"); + snd_pcm_direction_name(substream->stream)); if (playback_flg) regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index fe4fde844d86..e93ceb7afb4c 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -85,7 +85,7 @@ static int tegra210_i2s_set_clock_rate(struct device *dev, } static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt, - bool is_playback) + int stream) { struct device *dev = compnt->dev; struct tegra210_i2s *i2s = dev_get_drvdata(dev); @@ -95,7 +95,7 @@ static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt, unsigned int cif_ctrl, stream_ctrl, i2s_ctrl, val; int err; - if (is_playback) { + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { reset_reg = TEGRA210_I2S_RX_SOFT_RESET; cif_reg = TEGRA210_I2S_RX_CIF_CTRL; stream_reg = TEGRA210_I2S_RX_CTRL; @@ -118,7 +118,7 @@ static int tegra210_i2s_sw_reset(struct snd_soc_component *compnt, 10, 10000); if (err) { dev_err(dev, "timeout: failed to reset I2S for %s\n", - is_playback ? "playback" : "capture"); + snd_pcm_direction_name(stream)); return err; } @@ -137,16 +137,16 @@ static int tegra210_i2s_init(struct snd_soc_dapm_widget *w, struct device *dev = compnt->dev; struct tegra210_i2s *i2s = dev_get_drvdata(dev); unsigned int val, status_reg; - bool is_playback; + int stream; int err; switch (w->reg) { case TEGRA210_I2S_RX_ENABLE: - is_playback = true; + stream = SNDRV_PCM_STREAM_PLAYBACK; status_reg = TEGRA210_I2S_RX_STATUS; break; case TEGRA210_I2S_TX_ENABLE: - is_playback = false; + stream = SNDRV_PCM_STREAM_CAPTURE; status_reg = TEGRA210_I2S_TX_STATUS; break; default: @@ -159,11 +159,11 @@ static int tegra210_i2s_init(struct snd_soc_dapm_widget *w, 10, 10000); if (err) { dev_err(dev, "timeout: previous I2S %s is still active\n", - is_playback ? "playback" : "capture"); + snd_pcm_direction_name(stream)); return err; } - return tegra210_i2s_sw_reset(compnt, is_playback); + return tegra210_i2s_sw_reset(compnt, stream); } static int __maybe_unused tegra210_i2s_runtime_suspend(struct device *dev) diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 4bdbcd2635ef..05d59e03b1c5 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -213,7 +213,7 @@ int tegra_pcm_construct(struct snd_soc_component *component, * Fallback for backwards-compatibility with older device trees that * have the iommus property in the virtual, top-level "sound" node. */ - if (!of_get_property(dev->of_node, "iommus", NULL)) + if (!of_property_present(dev->of_node, "iommus")) dev = rtd->card->snd_card->dev; return tegra_pcm_dma_allocate(dev, rtd, tegra_pcm_hardware.buffer_bytes_max); |